PageRenderTime 68ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/fCraft/Commands/FunCommands.cs

https://github.com/EpicClowny/LegendCraft
C# | 2392 lines | 2202 code | 150 blank | 40 comment | 571 complexity | 4bb490604a5537b1ecf0c23a6954ea71 MD5 | raw file
  1. //Copyright (C) <2012> <Jon Baker, Glenn MariĂŤn and Lao Tszy>
  2. //This program is free software: you can redistribute it and/or modify
  3. //it under the terms of the GNU General Public License as published by
  4. //the Free Software Foundation, either version 3 of the License, or
  5. //(at your option) any later version.
  6. //This program is distributed in the hope that it will be useful,
  7. //but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. //GNU General Public License for more details.
  10. //You should have received a copy of the GNU General Public License
  11. //along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Linq;
  15. using System.Text;
  16. using System.Threading;
  17. using RandomMaze;
  18. namespace fCraft
  19. {
  20. internal static class FunCommands
  21. {
  22. internal static void Init()
  23. {
  24. CommandManager.RegisterCommand(CdRandomMaze);
  25. CommandManager.RegisterCommand(CdMazeCuboid);
  26. CommandManager.RegisterCommand(CdFirework);
  27. CommandManager.RegisterCommand(CdLife);
  28. CommandManager.RegisterCommand(CdPossess);
  29. CommandManager.RegisterCommand(CdUnpossess);
  30. CommandManager.RegisterCommand(CdThrow);
  31. CommandManager.RegisterCommand(CdInsult);
  32. CommandManager.RegisterCommand(CdFFAStatistics);
  33. CommandManager.RegisterCommand(CdFreeForAll);
  34. CommandManager.RegisterCommand(CdTDStatistics);
  35. CommandManager.RegisterCommand(CdTeamDeathMatch);
  36. CommandManager.RegisterCommand(CdInfection);
  37. CommandManager.RegisterCommand(CdSetModel);
  38. CommandManager.RegisterCommand(CdBot);
  39. CommandManager.RegisterCommand(CdCTF);
  40. Player.Moving += PlayerMoved;
  41. }
  42. public static string[] validEntities =
  43. {
  44. "chicken",
  45. "creeper",
  46. "croc",
  47. "humanoid",
  48. "human",
  49. "pig",
  50. "printer",
  51. "sheep",
  52. "skeleton",
  53. "spider",
  54. "zombie"
  55. };
  56. public static void PlayerMoved(object sender, fCraft.Events.PlayerMovingEventArgs e)
  57. {
  58. if (e.Player.Info.IsFrozen || e.Player.SpectatedPlayer != null || !e.Player.SpeedMode)
  59. return;
  60. Vector3I oldPos = e.OldPosition.ToBlockCoords();
  61. Vector3I newPos = e.NewPosition.ToBlockCoords();
  62. //check if has moved 1 whole block
  63. if (newPos.X == oldPos.X + 1 || newPos.X == oldPos.X - 1 || newPos.Y == oldPos.Y + 1 || newPos.Y == oldPos.Y - 1)
  64. {
  65. Server.Players.Message("Old: " + newPos.ToString());
  66. Vector3I move = newPos - oldPos;
  67. int AccelerationFactor = 4;
  68. Vector3I acceleratedNewPos = oldPos + move * AccelerationFactor;
  69. //do not forget to check for all the null pointers here - TODO
  70. Map m = e.Player.World.Map;
  71. //check if can move through all the blocks along the path
  72. Vector3F normal = move.Normalize();
  73. Vector3I prevBlockPos = e.OldPosition.ToBlockCoords();
  74. for (int i = 1; i <= AccelerationFactor * move.Length; ++i)
  75. {
  76. Vector3I pos = (oldPos + i * normal).Round();
  77. if (prevBlockPos == pos) //didnt yet hit the next block
  78. continue;
  79. if (!m.InBounds(pos) || m.GetBlock(pos) != Block.Air) //got out of bounds or some solid block
  80. {
  81. acceleratedNewPos = (oldPos + normal * (i - 1)).Round();
  82. break;
  83. }
  84. prevBlockPos = pos;
  85. }
  86. //teleport keeping the same orientation
  87. //Server.Players.Message("New: "+ acceleratedNewPos.ToString());
  88. e.Player.Send(PacketWriter.MakeSelfTeleport(new Position((short)(acceleratedNewPos.X * 32), (short)(acceleratedNewPos.Y * 32), e.Player.Position.Z, e.NewPosition.R, e.NewPosition.L)));
  89. }
  90. }
  91. #region LegendCraft
  92. /* Copyright (c) <2012-2014> <LeChosenOne, DingusBungus>
  93. Permission is hereby granted, free of charge, to any person obtaining a copy
  94. of this software and associated documentation files (the "Software"), to deal
  95. in the Software without restriction, including without limitation the rights
  96. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  97. copies of the Software, and to permit persons to whom the Software is
  98. furnished to do so, subject to the following conditions:
  99. The above copyright notice and this permission notice shall be included in
  100. all copies or substantial portions of the Software.
  101. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  102. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  103. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  104. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  105. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  106. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  107. THE SOFTWARE.*/
  108. static readonly CommandDescriptor CdBot = new CommandDescriptor
  109. {
  110. Name = "Bot",
  111. Permissions = new Permission[] { Permission.Bots },
  112. Category = CommandCategory.Fun,
  113. IsConsoleSafe = false,
  114. Usage = "/Bot <create / remove / removeAll / model / close / explode / list / summon / stop / move / fly>",
  115. Help = "Commands for manipulating bots. For help and usage for the individual options, use /help bot <option>.",
  116. HelpSections = new Dictionary<string, string>{
  117. { "create", "&H/Bot create <botname> <model>\n&S" +
  118. "Creates a new bot with the given name. Valid models are chicken, creeper, croc, human, pig, printer, sheep, skeleton, spider, or zombie." },
  119. { "remove", "&H/Bot remove <botname>\n&S" +
  120. "Removes the given bot." },
  121. { "removeall", "&H/Bot removeAll\n&S" +
  122. "Removes all bots from the server."},
  123. { "model", "&H/Bot model <bot name> <model>\n&S" +
  124. "Changes the model of a bot to the given model. Valid models are chicken, creeper, croc, human, pig, printer, sheep, skeleton, spider, or zombie."},
  125. { "clone", "&H/Bot clone <bot> <player>\n&S" +
  126. "Changes the skin of a bot to the skin of the given player. Leave the player parameter blank to reset the skin. Bot's model must be human. Use /bot changeModel to change the bot's model."},
  127. { "explode", "&H/Bot explode <bot>\n&S" +
  128. "Epically explodes a bot, removing it from the server."},
  129. { "list", "&H/Bot list\n&S" +
  130. "Prints out a list of all the bots on the server."},
  131. { "summon", "&H/Bot summon <botname>\n&S" +
  132. "Summons a bot from anywhere to your current position."},
  133. { "move", "&H/Bot move <botname> <player>\n&S" +
  134. "Moves the bot to a specific player."},
  135. { "fly", "&H/Bot fly <botname>\n&S" +
  136. "Toggles whether the bot can fly or not."},
  137. { "stop", "&H/Bot stop <botname>\n&S" +
  138. "Stops the bot from doing any of its movement actions."}
  139. },
  140. Handler = BotHandler,
  141. };
  142. static void BotHandler(Player player, Command cmd)
  143. {
  144. if (!player.ClassiCube || !Heartbeat.ClassiCube())
  145. {
  146. player.Message("Bots can only be used on ClassiCube servers and clients!");
  147. return;
  148. }
  149. string option = cmd.Next(); //take in the option arg
  150. if (string.IsNullOrEmpty(option)) //empty? return, otherwise continue
  151. {
  152. CdBot.PrintUsage(player);
  153. return;
  154. }
  155. //certain options that take in specific params are in here, the rest are in the switch-case
  156. if (option.ToLower() == "list")
  157. {
  158. player.Message("_Bots on {0}_", ConfigKey.ServerName.GetString());
  159. foreach (Bot botCheck in Server.Bots)
  160. {
  161. player.Message(botCheck.Name + " on " + botCheck.World.Name);
  162. }
  163. return;
  164. }
  165. else if (option.ToLower() == "removeall")
  166. {
  167. Server.Bots.ForEach(botToRemove =>
  168. {
  169. botToRemove.removeBot();
  170. });
  171. player.Message("All bots removed from the server.");
  172. return;
  173. }
  174. else if (option.ToLower() == "move")
  175. {
  176. string targetBot = cmd.Next();
  177. if (string.IsNullOrEmpty(targetBot))
  178. {
  179. CdBot.PrintUsage(player);
  180. return;
  181. }
  182. string targetPlayer = cmd.Next();
  183. if (string.IsNullOrEmpty(targetPlayer))
  184. {
  185. CdBot.PrintUsage(player);
  186. return;
  187. }
  188. Bot targetB = player.World.FindBot(targetBot);
  189. Player targetP = player.World.FindPlayerExact(targetPlayer);
  190. if (targetP == null)
  191. {
  192. player.Message("Could not find {0} on {1}! Please make sure you spelled their name correctly.", targetPlayer, player.World);
  193. return;
  194. }
  195. if (targetB == null)
  196. {
  197. player.Message("Could not find {0} on {1}! Please make sure you spelled their name correctly.", targetBot, player.World);
  198. return;
  199. }
  200. player.Message("{0} is now moving!", targetB.Name);
  201. targetB.isMoving = true;
  202. targetB.NewPosition = targetP.Position;
  203. targetB.OldPosition = targetB.Position;
  204. targetB.timeCheck.Start();
  205. return;
  206. }
  207. else if (option.ToLower() == "follow")
  208. {
  209. string targetBot = cmd.Next();
  210. if (string.IsNullOrEmpty(targetBot))
  211. {
  212. CdBot.PrintUsage(player);
  213. return;
  214. }
  215. string targetPlayer = cmd.Next();
  216. if (string.IsNullOrEmpty(targetPlayer))
  217. {
  218. CdBot.PrintUsage(player);
  219. return;
  220. }
  221. Bot targetB = player.World.FindBot(targetBot);
  222. Player targetP = player.World.FindPlayerExact(targetPlayer);
  223. if (targetP == null)
  224. {
  225. player.Message("Could not find {0} on {1}! Please make sure you spelled their name correctly.", targetPlayer, player.World);
  226. return;
  227. }
  228. if (targetB == null)
  229. {
  230. player.Message("Could not find {0} on {1}! Please make sure you spelled their name correctly.", targetBot, player.World);
  231. return;
  232. }
  233. player.Message("{0} is now following {1}!", targetB.Name, targetP.Name);
  234. targetB.isMoving = true;
  235. targetB.followTarget = targetP;
  236. targetB.OldPosition = targetB.Position;
  237. targetB.timeCheck.Start();
  238. return;
  239. }
  240. //finally away from the special cases
  241. string botName = cmd.Next(); //take in bot name arg
  242. if (string.IsNullOrEmpty(botName)) //null check
  243. {
  244. CdBot.PrintUsage(player);
  245. return;
  246. }
  247. Bot bot = new Bot();
  248. if (option != "create")//since the bot wouldn't exist for "create", we must check the bot for all cases other than "create"
  249. {
  250. bot = Server.FindBot(botName.ToLower()); //Find the bot and assign to bot var
  251. if (bot == null) //If null, return and yell at user
  252. {
  253. player.Message("Could not find {0}! Please make sure you spelled the bot's name correctly. To view all the bots, type /Bot list.", botName);
  254. return;
  255. }
  256. }
  257. //now to the cases - additional args should be taken in at the individual cases
  258. switch (option.ToLower())
  259. {
  260. case "create":
  261. string requestedModel = cmd.Next();
  262. if (string.IsNullOrEmpty(requestedModel))
  263. {
  264. player.Message("Usage is /Bot create <bot name> <bot model>. Valid models are chicken, creeper, croc, human, pig, printer, sheep, skeleton, spider, or zombie.");
  265. return;
  266. }
  267. if (!validEntities.Contains(requestedModel))
  268. {
  269. player.Message("That wasn't a valid bot model! Valid models are chicken, creeper, croc, human, pig, printer, sheep, skeleton, spider, or zombie.");
  270. return;
  271. }
  272. //if a botname has already been chosen, ask player for a new name
  273. var matchingNames = from b in Server.Bots
  274. where b.Name.ToLower() == botName.ToLower()
  275. select b;
  276. if (matchingNames.Count() > 0)
  277. {
  278. player.Message("A bot with that name already exists! To view all bots, type /bot list.");
  279. return;
  280. }
  281. player.Message("Successfully created a bot.");
  282. Bot botCreate = new Bot();
  283. botCreate.setBot(botName, player.World, player.Position, LegendCraft.getNewID());
  284. botCreate.createBot();
  285. botCreate.changeBotModel(requestedModel);
  286. break;
  287. case "remove":
  288. player.Message("{0} was removed from the server.", bot.Name);
  289. bot.removeBot();
  290. break;
  291. case "fly":
  292. if (bot.isFlying)
  293. {
  294. player.Message("{0} can no longer fly.", bot.Name);
  295. bot.isFlying = false;
  296. break;
  297. }
  298. player.Message("{0} can now fly!", bot.Name);
  299. bot.isFlying = true;
  300. break;
  301. case "model":
  302. if (bot.Skin != "steve")
  303. {
  304. player.Message("Bots cannot change model with a skin! Use '/bot clone' to reset a bot's skin.");
  305. return;
  306. }
  307. string model = cmd.Next();
  308. if (string.IsNullOrEmpty(model))
  309. {
  310. player.Message("Usage is /Bot model <bot> <model>. Valid models are chicken, creeper, croc, human, pig, printer, sheep, skeleton, spider, or zombie.");
  311. break;
  312. }
  313. if(model == "human")//lazy parse
  314. {
  315. model = "humanoid";
  316. }
  317. if (!validEntities.Contains(model))
  318. {
  319. player.Message("Please use a valid model name! Valid models are chicken, creeper, croc, human, pig, printer, sheep, skeleton, spider, or zombie.");
  320. break;
  321. }
  322. player.Message("Changed bot model to {0}.", model);
  323. bot.changeBotModel(model);
  324. break;
  325. case "clone":
  326. if (bot.Model != "humanoid")
  327. {
  328. player.Message("A bot must be a human in order to have a skin. Use '/bot model <bot> <model>' to change a bot's model.");
  329. return;
  330. }
  331. string playerToClone = cmd.Next();
  332. if (string.IsNullOrEmpty(playerToClone))
  333. {
  334. player.Message("{0}'s skin was reset!", bot.Name);
  335. bot.Clone("steve");
  336. break;
  337. }
  338. PlayerInfo targetPlayer = PlayerDB.FindPlayerInfoExact(playerToClone);
  339. if (targetPlayer == null)
  340. {
  341. player.Message("That player doesn't exists! Please use a valid playername for the skin of the bot.");
  342. break;
  343. }
  344. player.Message("{0}'s skin was updated!", bot.Name);
  345. bot.Clone(playerToClone);
  346. break;
  347. case "explode":
  348. Server.Message("{0} exploded!", bot.Name);
  349. bot.explodeBot(player);
  350. break;
  351. case "summon":
  352. if (player.World != bot.World)
  353. {
  354. bot.tempRemoveBot(); //remove the entity
  355. bot.World = player.World; //update variables
  356. bot.Position = player.Position;
  357. bot.updateBotPosition(); //replace the entity
  358. }
  359. else
  360. {
  361. bot.Position = player.Position;
  362. bot.teleportBot(player.Position);
  363. }
  364. if (bot.Model != "human")
  365. {
  366. bot.changeBotModel(bot.Model); //replace the model, if the model is set
  367. }
  368. if (bot.Skin != "steve")
  369. {
  370. bot.Clone(bot.Skin); //replace the skin, if a skin is set
  371. }
  372. break;
  373. case "stop":
  374. player.Message("{0} is no longer moving.", bot.Name);
  375. bot.isMoving = false;
  376. bot.timeCheck.Stop();
  377. bot.timeCheck.Reset();
  378. bot.followTarget = null;
  379. break;
  380. default:
  381. CdBot.PrintUsage(player);
  382. break;
  383. }
  384. }
  385. static readonly CommandDescriptor CdSetModel = new CommandDescriptor
  386. {
  387. Name = "SetModel",
  388. Permissions = new Permission[] { Permission.EditPlayerDB },
  389. Category = CommandCategory.Fun,
  390. IsConsoleSafe = false,
  391. Usage = "/SetModel [Player] [Model]",
  392. Help = "Changes the model of a target player Valid models are chicken, creeper, croc, human, pig, printer, sheep, skeleton, spider, or zombie. If the model is empty, the player's model will reset.",
  393. Handler = ModelHandler,
  394. };
  395. static void ModelHandler(Player player, Command cmd)
  396. {
  397. string target = cmd.Next();
  398. if(string.IsNullOrEmpty(target))
  399. {
  400. CdSetModel.PrintUsage(player);
  401. return;
  402. }
  403. Player targetPlayer = Server.FindPlayerOrPrintMatches(player, target, false, true);
  404. if (targetPlayer == null)
  405. {
  406. return;
  407. }
  408. string model = cmd.Next();
  409. if (string.IsNullOrEmpty(model))
  410. {
  411. player.Message("Reset the model for {0}.", targetPlayer.Name);
  412. targetPlayer.Model = player.Name; //reset the model to the player's name
  413. return;
  414. }
  415. if (model == "human")//execute super lazy parse
  416. {
  417. model = "humanoid";
  418. }
  419. if (!validEntities.Contains(model))
  420. {
  421. player.Message("Please choose a valid model! Valid models are chicken, creeper, croc, human, pig, printer, sheep, skeleton, spider, or zombie.");
  422. return;
  423. }
  424. player.Message("{0} has been changed into a {1}!", targetPlayer.Name, model);
  425. targetPlayer.Model = model;
  426. return;
  427. }
  428. static readonly CommandDescriptor CdTroll = new CommandDescriptor //Troll is an old command from 800craft that i have rehashed because of its popularity
  429. { //The original command and the idea for the command were done by Jonty800 and Rebelliousdude.
  430. Name = "Troll",
  431. Permissions = new Permission[] { Permission.Moderation },
  432. Category = CommandCategory.Chat | CommandCategory.Fun,
  433. IsConsoleSafe = true,
  434. Usage = "/Troll (playername) (message-type) (message)",
  435. Help = "Allows you impersonate others in the chat. Available chat types are msg, st, ac, pm, rq, and leave.",
  436. NotRepeatable = true,
  437. Handler = Troll,
  438. };
  439. static void Troll(Player p, Command c)
  440. {
  441. string name = c.Next();
  442. string chatType = c.Next();
  443. string msg = c.NextAll();
  444. if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(chatType))
  445. {
  446. p.Message("Use like : /Troll (playername) (chat-type) (message)");
  447. return;
  448. }
  449. Player tgt = Server.FindPlayerOrPrintMatches(p, name, false, true);
  450. if (tgt == null) { return; }
  451. switch (chatType)
  452. {
  453. default:
  454. p.Message("The available chat types are: st, ac, pm, msg, rq and leave");
  455. break;
  456. case "leave":
  457. Server.Message("&SPlayer {0}&S left the server.", tgt.ClassyName);
  458. break;
  459. case "ragequit":
  460. case "rq":
  461. string quitMsg = "";
  462. if (msg.Length > 1) { quitMsg = ": &C" + msg; }
  463. Server.Message("{0}&4 Ragequit from the server{1}", tgt.ClassyName, quitMsg);
  464. Server.Message("&SPlayer {0}&S left the server.", tgt.ClassyName);
  465. break;
  466. case "st":
  467. case "staffchat":
  468. case "staff":
  469. if (string.IsNullOrEmpty(msg))
  470. {
  471. p.Message("The st option requires a message: /troll (player) st (message)");
  472. return;
  473. }
  474. Server.Message("&P(staff){0}&P: {1}", tgt.ClassyName, msg);
  475. break;
  476. case "pm":
  477. case "privatemessage":
  478. case "private":
  479. case "whisper":
  480. if (string.IsNullOrEmpty(msg))
  481. {
  482. p.Message("The pm option requires a message: /troll (player) pm (message)");
  483. return;
  484. }
  485. Server.Message("&Pfrom {0}: {1}", tgt.Name, msg);
  486. break;
  487. case "ac":
  488. case "adminchat":
  489. case "admin":
  490. if (string.IsNullOrEmpty(msg))
  491. {
  492. p.Message("The ac option requires a message: /troll (player) ac (message)");
  493. return;
  494. }
  495. Server.Message("&9(Admin){0}&P: {1}", tgt.ClassyName, msg);
  496. break;
  497. case "msg":
  498. case "message":
  499. case "global":
  500. case "server":
  501. if (string.IsNullOrEmpty(msg))
  502. {
  503. p.Message("The msg option requires a message: /troll (player) msg (message)");
  504. return;
  505. }
  506. Server.Message("{0}&f: {1}", tgt.ClassyName, msg);
  507. break;
  508. }
  509. return;
  510. }
  511. #region Gamemodes
  512. static readonly CommandDescriptor CdCTF = new CommandDescriptor
  513. {
  514. Name = "CTF",
  515. Aliases = new[] { "CaptureTheFlag" },
  516. Category = CommandCategory.World,
  517. Permissions = new Permission[] { Permission.Games },
  518. IsConsoleSafe = false,
  519. Usage = "/CTF [Start | Stop | SetSpawn | SetFlag | Help]",
  520. Help = "Manage the CTF Game!",
  521. Handler = CTFHandler
  522. };
  523. private static void CTFHandler(Player player, Command cmd)
  524. {
  525. string option = cmd.Next();
  526. if (String.IsNullOrEmpty(option))
  527. {
  528. player.Message("Please select an option in the CTF menu!");
  529. return;
  530. }
  531. World world = player.World;
  532. switch (option.ToLower())
  533. {
  534. case "begin":
  535. case "start":
  536. if (world.blueCTFSpawn == new Vector3I(0, 0, 0) || world.redCTFSpawn == new Vector3I(0, 0, 0))
  537. {
  538. player.Message("&cYou must assign spawn points before the game starts! Use /CTF SetSpawn <red | blue>");
  539. return;
  540. }
  541. if (world.blueFlag == new Vector3I(0, 0, 0) || world.redFlag == new Vector3I(0, 0, 0))
  542. {
  543. player.Message("&cYou must set the flags before play! Use /CTF SetFlag <red | blue>");
  544. return;
  545. }
  546. if (world.Players.Count() < 2)
  547. {
  548. player.Message("&cYou need at least 2 players to play CTF");
  549. return;
  550. }
  551. try
  552. {
  553. foreach (Player p in player.World.Players)
  554. {
  555. p.JoinWorld(player.World, WorldChangeReason.Rejoin);
  556. }
  557. CTF.GetInstance(world);
  558. CTF.Start();
  559. }
  560. catch (Exception e)
  561. {
  562. Logger.Log(LogType.Error, "Error: " + e + e.Message);
  563. }
  564. break;
  565. case "end":
  566. case "stop":
  567. if (world.gameMode != GameMode.CaptureTheFlag)
  568. {
  569. player.Message("&cThere is no game of CTF currently going on!");
  570. break;
  571. }
  572. CTF.Stop(player);
  573. break;
  574. case "setspawn":
  575. if (world.gameMode != GameMode.NULL)
  576. {
  577. player.Message("&cYou cannot change spawns during the game!");
  578. return;
  579. }
  580. string team = cmd.Next();
  581. if (String.IsNullOrEmpty(team))
  582. {
  583. player.Message("&cPlease select a team to set a spawn for!");
  584. break;
  585. }
  586. if (team.ToLower() == "red")
  587. {
  588. world.redCTFSpawn = new Vector3I(player.Position.ToBlockCoords().X, player.Position.ToBlockCoords().Y, player.Position.ToBlockCoords().Z + 2);
  589. player.Message("&aRed team spawn set.");
  590. break;
  591. }
  592. else if (team.ToLower() == "blue")
  593. {
  594. world.blueCTFSpawn = new Vector3I(player.Position.ToBlockCoords().X, player.Position.ToBlockCoords().Y, player.Position.ToBlockCoords().Z + 2);
  595. player.Message("&aBlue team spawn set.");
  596. break;
  597. }
  598. else
  599. {
  600. player.Message("&cYou may only select the 'Blue' or 'Red' team!");
  601. break;
  602. }
  603. case "setflag":
  604. if (world.gameMode != GameMode.NULL)
  605. {
  606. player.Message("&cYou cannot change flags during the game!");
  607. return;
  608. }
  609. string flag = cmd.Next();
  610. if (String.IsNullOrEmpty(flag))
  611. {
  612. player.Message("&cPlease select a flag color to set!");
  613. break;
  614. }
  615. if (flag.ToLower() == "red")
  616. {
  617. //select red flag
  618. player.Message("&fPlease select where you wish to place the &cred&f flag. The &cred&f flag must be red wool.");
  619. player.Info.placingRedFlag = true;
  620. break;
  621. }
  622. else if (flag.ToLower() == "blue")
  623. {
  624. player.Message("&fPlease select where you wish to place the &9blue&f flag. The &9blue&f flag must be blue wool.");
  625. player.Info.placingBlueFlag = true;
  626. break;
  627. }
  628. else
  629. {
  630. player.Message("&cYou may only select a 'Blue' or 'Red' colored flag!");
  631. break;
  632. }
  633. case "help":
  634. case "rules":
  635. player.Message("Start: Starts the CTF game.");
  636. player.Message("Stop: Ends the CTF game.");
  637. player.Message("SetSpawn: Usage is /CTF SetSpawn <Red|Blue>. The spawn for each team will be set at your feet. Both spawns must be set for the game to begin.");
  638. player.Message("SetFlag: Usage is /CTF SetFlag <Red|Blue>. The next block clicked will be the corresponding team's flag. The blue flag must be a blue wool block, and the red flag must be a red wool block.");
  639. break;
  640. default:
  641. CdCTF.PrintUsage(player);
  642. break;
  643. }
  644. }
  645. static readonly CommandDescriptor CdInfection = new CommandDescriptor
  646. {
  647. Name = "Infection",
  648. Aliases = new[] { "ZombieSurvival", "zs" },
  649. Category = CommandCategory.World,
  650. Permissions = new Permission[] { Permission.Games },
  651. IsConsoleSafe = false,
  652. Usage = "/Infection [start | stop | custom | help]",
  653. Help = "Manage the Infection Gamemode!",
  654. Handler = InfectionHandler
  655. };
  656. private static void InfectionHandler(Player player, Command cmd)
  657. {
  658. string Option = cmd.Next();
  659. World world = player.World;
  660. if (string.IsNullOrEmpty(Option))
  661. {
  662. CdInfection.PrintUsage(player);
  663. return;
  664. }
  665. if (Option.ToLower() == "start")
  666. {
  667. if (world == WorldManager.MainWorld)
  668. {
  669. player.Message("&SInfection games cannot be played on the main world");
  670. return;
  671. }
  672. if (world.gameMode != GameMode.NULL)
  673. {
  674. player.Message("&SThere is already a game going on");
  675. return;
  676. }
  677. if (player.World.CountPlayers(true) < 2)
  678. {
  679. player.Message("&SThere must be at least &W2&S players on this world to play Infection");
  680. return;
  681. }
  682. else
  683. {
  684. try
  685. {
  686. player.World.Hax = false;
  687. foreach (Player p in player.World.Players)
  688. {
  689. p.JoinWorld(player.World, WorldChangeReason.Rejoin);
  690. }
  691. fCraft.Games.Infection.GetInstance(world);
  692. fCraft.Games.Infection.Start();
  693. }
  694. catch (Exception e)
  695. {
  696. Logger.Log(LogType.Error, "Error: " + e + e.Message);
  697. }
  698. return;
  699. }
  700. }
  701. if (Option.ToLower() == "stop")
  702. {
  703. if (world.gameMode == GameMode.Infection)
  704. {
  705. fCraft.Games.Infection.Stop(player);
  706. return;
  707. }
  708. else
  709. {
  710. player.Message("&SNo games of Infection are going on.");
  711. return;
  712. }
  713. }
  714. if (Option.ToLower() == "custom")
  715. {
  716. string stringLimit = cmd.Next();
  717. string stringDelay = cmd.Next();
  718. int intLimit, intDelay;
  719. if (String.IsNullOrEmpty(stringLimit) || String.IsNullOrEmpty(stringDelay))
  720. {
  721. player.Message("Usage for '/infection custom' is '/infection custom TimeLimit TimeDelay'.");
  722. }
  723. if (!int.TryParse(stringLimit, out intLimit))
  724. {
  725. player.Message("Please select a number for the time limit.");
  726. return;
  727. }
  728. if (!int.TryParse(stringDelay, out intDelay))
  729. {
  730. player.Message("Please select a number for the time delay.");
  731. return;
  732. }
  733. if (world == WorldManager.MainWorld)
  734. {
  735. player.Message("&SInfection games cannot be played on the main world");
  736. return;
  737. }
  738. if (world.gameMode != GameMode.NULL)
  739. {
  740. player.Message("&SThere is already a game going on");
  741. return;
  742. }
  743. if (player.World.CountPlayers(true) < 2)
  744. {
  745. player.Message("&SThere must be at least &W2&S players on this world to play Infection");
  746. return;
  747. }
  748. if (intLimit > 900 || intLimit < 60)
  749. {
  750. player.Message("&SThe game must be between 60 and 900 seconds! (1 and 15 minutes)");
  751. return;
  752. }
  753. if (intDelay > 60 || intDelay < 11)
  754. {
  755. player.Message("&SThe game delay must be greater than 10 seconds, but less than 60 seconds!");
  756. return;
  757. }
  758. else
  759. {
  760. try
  761. {
  762. player.World.Hax = false;
  763. foreach (Player p in player.World.Players)
  764. {
  765. p.JoinWorld(player.World, WorldChangeReason.Rejoin);
  766. }
  767. fCraft.Games.Infection.GetInstance(world);
  768. fCraft.Games.Infection.Custom(intLimit, intDelay);
  769. }
  770. catch (Exception e)
  771. {
  772. Logger.Log(LogType.Error, "Error: " + e + e.Message);
  773. }
  774. return;
  775. }
  776. }
  777. if (Option.ToLower() == "help")
  778. {
  779. player.Message("&SStart: Will begin a game of infection on the current world.\n" +
  780. "&SStop: Will end a game of infection on the current world.\n" +
  781. "&SCustom: Determines factors in the next Infection game. Factors are TimeLimit and TimeDelay. TimeDelay must be greater than 10.\n" +
  782. "&fExample: '/Infection Custom 100 12' would start an Infection game with a game length of 100 seconds, and it will begin in 12 seconds.\n"
  783. );
  784. }
  785. else
  786. {
  787. CdInfection.PrintUsage(player);
  788. return;
  789. }
  790. }
  791. static readonly CommandDescriptor CdTeamDeathMatch = new CommandDescriptor
  792. {
  793. Name = "TeamDeathMatch", //I think I resolved all of the bugs...
  794. Aliases = new[] { "td", "tdm" },
  795. Category = CommandCategory.World,
  796. Permissions = new Permission[] { Permission.Games },
  797. IsConsoleSafe = false,
  798. Usage = "/TeamDeathMatch [Start | Stop | Time | Score | ScoreLimit | TimeLimit | TimeDelay | Settings | Red | Blue | ManualTeams | About | Help]",
  799. Help = "Manage the TDM Gamemode!",
  800. Handler = TDHandler
  801. };
  802. private static void TDHandler(Player player, Command cmd) //For TDM Game: starting/ending game, customizing game options, viewing score, etc.
  803. {
  804. string Option = cmd.Next();
  805. World world = player.World;
  806. if (string.IsNullOrEmpty(Option))
  807. {
  808. CdTeamDeathMatch.PrintUsage(player);
  809. return;
  810. }
  811. if (Option.ToLower() == "start" || Option.ToLower() == "on") //starts the game
  812. {
  813. if (world == WorldManager.MainWorld)
  814. {
  815. player.Message("TDM games cannot be played on the main world");
  816. return;
  817. }
  818. if (world.gameMode != GameMode.NULL)
  819. {
  820. player.Message("There is already a game going on");
  821. return;
  822. }
  823. if (player.World.CountPlayers(true) < 2)
  824. {
  825. player.Message("There needs to be at least &W2&S players to play TDM");
  826. return;
  827. }
  828. if (TeamDeathMatch.blueSpawn == Position.Zero || TeamDeathMatch.redSpawn == Position.Zero)
  829. {
  830. player.Message("You must first assign the team's spawn points with &H/TD SetSpawn (Red/Blue)");
  831. return;
  832. }
  833. else
  834. {
  835. player.World.Hax = false;
  836. foreach (Player p in player.World.Players)
  837. {
  838. p.JoinWorld(player.World, WorldChangeReason.Rejoin);
  839. }
  840. TeamDeathMatch.GetInstance(player.World);
  841. TeamDeathMatch.Start();
  842. return;
  843. }
  844. }
  845. if (Option.ToLower() == "stop" || Option.ToLower() == "off") //stops the game
  846. {
  847. if (TeamDeathMatch.isOn)
  848. {
  849. TeamDeathMatch.Stop(player);
  850. return;
  851. }
  852. else
  853. {
  854. player.Message("No games of Team DeathMatch are going on");
  855. return;
  856. }
  857. }
  858. if (Option.ToLower() == "manualteams")
  859. {
  860. string option = cmd.Next();
  861. if (string.IsNullOrEmpty(option) || option.Length < 2 || option.Length > 9)
  862. {
  863. player.Message("Use like: /TD ManualTeams (On/Off)");
  864. return;
  865. }
  866. if (option.ToLower() == "off" || option.ToLower() == "auto" || option.ToLower() == "automatic")
  867. {
  868. if (!TeamDeathMatch.manualTeams)
  869. {
  870. player.Message("The team assign option is already set to &wAuto");
  871. return;
  872. }
  873. TeamDeathMatch.manualTeams = false;
  874. player.Message("The team assign option has been set to &WAuto&s.");
  875. return;
  876. }
  877. if (option.ToLower() == "on" || option.ToLower() == "manual")
  878. {
  879. if (TeamDeathMatch.manualTeams)
  880. {
  881. player.Message("The team assign option is already set to &wManual");
  882. return;
  883. }
  884. TeamDeathMatch.manualTeams = true;
  885. player.Message("The team assign option has been set to &WManual&s.");
  886. return;
  887. }
  888. }
  889. if (TeamDeathMatch.isOn && (Option.ToLower() == "timelimit" || Option.ToLower() == "scorelimit" || Option.ToLower() == "timedelay"))
  890. {
  891. player.Message("You cannot adjust game settings while a game is going on");
  892. return;
  893. }
  894. if (!TeamDeathMatch.isOn && (Option.ToLower() == "timelimit" || Option.ToLower() == "scorelimit" || Option.ToLower() == "timedelay"))
  895. {
  896. if (Option.ToLower() == "timelimit") //option to change the length of the game (5m default)
  897. {
  898. string time = cmd.Next();
  899. if (time == null)
  900. {
  901. player.Message("Use the syntax: /TD timelimit (whole number of minutes)\n&HNote: The acceptable times are from 1-20 minutes");
  902. return;
  903. }
  904. int timeLimit = 0;
  905. bool parsed = Int32.TryParse(time, out timeLimit);
  906. if (!parsed)
  907. {
  908. player.Message("Enter a whole number of minutes. For example: /TD timelimit 5");
  909. return;
  910. }
  911. if (timeLimit < 1 || timeLimit > 20)
  912. {
  913. player.Message("The accepted times are between 1 and 20 minutes");
  914. return;
  915. }
  916. else
  917. {
  918. TeamDeathMatch.timeLimit = (timeLimit * 60);
  919. player.Message("The time limit has been changed to &W{0}&S minutes", timeLimit);
  920. return;
  921. }
  922. }
  923. if (Option.ToLower() == "timedelay") //option to set the time delay for TDM games (20s default)
  924. {
  925. if (TeamDeathMatch.manualTeams)
  926. {
  927. player.Message("The manual team assign option is enabled so the delay is 30 seconds to enable team assigning");
  928. return;
  929. }
  930. string time = cmd.Next();
  931. if (time == null)
  932. {
  933. player.Message("Use the syntax: /TD timedelay (whole number of seconds)\n&HNote: The acceptable times incriment by 10 from 10 to 60");
  934. return;
  935. }
  936. int timeDelay = 0;
  937. bool parsed = Int32.TryParse(time, out timeDelay);
  938. if (!parsed)
  939. {
  940. player.Message("Enter a whole number of minutes. For example: /TD timedelay 20");
  941. return;
  942. }
  943. if (timeDelay != 10 && timeDelay != 20 && timeDelay != 30 && timeDelay != 40 && timeDelay != 50 && timeDelay != 60)
  944. {
  945. player.Message("The accepted times are 10, 20, 30, 40, 50, and 60 seconds");
  946. return;
  947. }
  948. else
  949. {
  950. TeamDeathMatch.timeDelay = timeDelay;
  951. player.Message("The time delay has been changed to &W{0}&s seconds", timeDelay);
  952. return;
  953. }
  954. }
  955. if (Option.ToLower() == "scorelimit") //changes the score limit (30 default)
  956. {
  957. string score = cmd.Next();
  958. if (score == null)
  959. {
  960. player.Message("Use the syntax: /TD scorelimit (whole number)\n&HNote: The acceptable scores are from 5-300 points");
  961. return;
  962. }
  963. int scoreLimit = 0;
  964. bool parsed = Int32.TryParse(score, out scoreLimit);
  965. if (!parsed)
  966. {
  967. player.Message("Enter a whole number score. For example: /TD scorelimit 50");
  968. return;
  969. }
  970. if (scoreLimit < 5 || scoreLimit > 300)
  971. {
  972. player.Message("The accepted scores are from 5-300 points");
  973. return;
  974. }
  975. else
  976. {
  977. TeamDeathMatch.scoreLimit = scoreLimit;
  978. player.Message("The score limit has been changed to &W{0}&s points", scoreLimit);
  979. return;
  980. }
  981. }
  982. }
  983. if (Option.ToLower() == "red")
  984. {
  985. string target = cmd.Next();
  986. if (target == null)
  987. {
  988. player.Message("Use like: /TD Red <PlayerName>");
  989. return;
  990. }
  991. Player targetP = Server.FindPlayerOrPrintMatches(player, target, true, true);
  992. if (targetP == null) return;
  993. if (player.World.gameMode == GameMode.TeamDeathMatch && !TeamDeathMatch.isOn)
  994. {
  995. TeamDeathMatch.AssignRed(targetP);
  996. return;
  997. }
  998. else
  999. {
  1000. player.Message("You can only assign teams during the delay of a Team DeathMatch Game.");
  1001. return;
  1002. }
  1003. }
  1004. if (Option.ToLower() == "blue")
  1005. {
  1006. string target = cmd.Next();
  1007. if (target == null)
  1008. {
  1009. player.Message("Use like: /TD Blue <PlayerName>");
  1010. return;
  1011. }
  1012. Player targetP = Server.FindPlayerOrPrintMatches(player, target, true, true);
  1013. if (targetP == null) return;
  1014. if (player.World.gameMode == GameMode.TeamDeathMatch && !TeamDeathMatch.isOn)
  1015. {
  1016. TeamDeathMatch.AssignBlue(targetP);
  1017. return;
  1018. }
  1019. else
  1020. {
  1021. player.Message("You can only assign teams during the delay of a Team DeathMatch Game.");
  1022. return;
  1023. }
  1024. }
  1025. if (Option.ToLower() == "setspawn")
  1026. {
  1027. string team = cmd.Next();
  1028. if (string.IsNullOrEmpty(team) || team.Length < 1)
  1029. {
  1030. player.Message("Use like: /TD SetSpawn (Red/Blue)");
  1031. return;
  1032. }
  1033. if (TeamDeathMatch.isOn)
  1034. {
  1035. player.Message("You cannot change the spawn during the game!");
  1036. return;
  1037. }
  1038. if (!TeamDeathMatch.isOn && player.World != WorldManager.MainWorld)
  1039. {
  1040. switch (team.ToLower())
  1041. {
  1042. default:
  1043. player.Message("Use like: /TD SetSpawn (Red/Blue)");
  1044. return;
  1045. case "red":
  1046. TeamDeathMatch.redSpawn = player.Position;
  1047. player.Message("&SSpawn for the &cRed&S team set.");
  1048. return;
  1049. case "blue":
  1050. TeamDeathMatch.blueSpawn = player.Position;
  1051. player.Message("&SSpawn for the &1Blue&S team set.");
  1052. return;
  1053. }
  1054. }
  1055. else
  1056. {
  1057. if (player.World == WorldManager.MainWorld) { player.Message("You cannot play TDM on the main world"); return; }
  1058. else if (TeamDeathMatch.isOn)
  1059. {
  1060. player.Message("You can only set the team spawns during the delay or before the game");
  1061. return;
  1062. }
  1063. }
  1064. }
  1065. if (Option.ToLower() == "score") //scoreboard for the matchs, different messages for when the game has ended. //td score
  1066. {
  1067. int red = TeamDeathMatch.redScore;
  1068. int blue = TeamDeathMatch.blueScore;
  1069. if (red > blue)
  1070. {
  1071. if (player.Info.isOnRedTeam)
  1072. {
  1073. player.Message("&sYour team is winning {0} to {1}", red, blue);
  1074. return;
  1075. }
  1076. if (player.Info.isOnBlueTeam)
  1077. {
  1078. player.Message("&sYour team is losing {0} to {1}", red, blue);
  1079. return;
  1080. }
  1081. else
  1082. {
  1083. player.Message("&sThe &cRed Team&s won {0} to {1}", red, blue);
  1084. return;
  1085. }
  1086. }
  1087. if (red < blue)
  1088. {
  1089. if (player.Info.isOnBlueTeam)
  1090. {
  1091. player.Message("&sYour team is winning {0} to {1}", blue, red);
  1092. return;
  1093. }
  1094. if (player.Info.isOnRedTeam)
  1095. {
  1096. player.Message("&sYour team is losing {0} to {1}", blue, red);
  1097. return;
  1098. }
  1099. else
  1100. {
  1101. player.Message("&sThe &1Blue Team&s won {0} to {1}", blue, red);
  1102. return;
  1103. }
  1104. }
  1105. if (red == blue)
  1106. {
  1107. if (player.Info.isPlayingTD)
  1108. {
  1109. player.Message("&sThe teams are tied at {0}!", blue);
  1110. return;
  1111. }
  1112. else
  1113. {
  1114. player.Message("&sThe teams tied at {0}!", blue);
  1115. return;
  1116. }
  1117. }
  1118. }
  1119. if (Option.ToLower() == "about") //td about
  1120. {
  1121. player.Message("&cTeam Deathmatch&S is a team game where all players are assigned to a red or blue team. Players cannot shoot players on their own team. The game will start the gun physics and do /gun for you. The game keeps score and notifications come up about the score and time left every 30 seconds. The Score Limit, Time Delay, Time Limit, and Team Assigning are customizable. Detailed help is on &H/TD Help"
  1122. + "\n&SDeveloped for &5Legend&WCraft&S by &fDingus&0Bungus&S 2013 - Based on the template of ZombieGame.cs written by Jonty800.");
  1123. return;
  1124. }
  1125. if (Option.ToLower() == "settings") //shows the current settings for the game (time limit, time delay, score limit, team assigning)
  1126. {
  1127. if (!TeamDeathMatch.manualTeams)
  1128. {
  1129. player.Message("The Current Settings For TDM: Auto Team Assign: &cOn&s | Time Delay: &c{0}&ss | Time Limit: &c{1}&sm | Score Limit: &c{2}&s points",
  1130. TeamDeathMatch.timeDelay, (TeamDeathMatch.timeLimit / 60), TeamDeathMatch.scoreLimit);
  1131. return;
  1132. }
  1133. if (TeamDeathMatch.manualTeams)
  1134. {
  1135. player.Message("The Current Settings For TDM: Auto Team Assign: &cOff&s | Time Delay: &c30&ss | Time Limit: &c{1}&sm | Score Limit: &c{2}&s points",
  1136. TeamDeathMatch.timeDelay, (TeamDeathMatch.timeLimit / 60), TeamDeathMatch.scoreLimit);
  1137. return;
  1138. }
  1139. }
  1140. if (Option.ToLower() == "help") //detailed help for the cmd
  1141. {
  1142. player.Message("Showing Option Descriptions for /TD (Option):"
  1143. + "\n&HTime &f- Tells how much time left in the game"
  1144. + "\n&HScore &f- Tells the score of the game (or last game played)"
  1145. + "\n&HSetSpawn [Red/Blue] &f- Sets the teams spawns"
  1146. + "\n&HScoreLimit [number] &f- Sets score limit (Whole Numbers from 5-300)"
  1147. + "\n&HTimeLimit [time(m)] &f- Sets end time (Whole minutes from 1-15)"
  1148. + "\n&HTimeDelay [time(s)] &f- Sets start delay (10 second incriments from 10-60)"
  1149. + "\n&HManualTeams [On/Off] &f- Create teams manually/automatically"
  1150. + "\n&HRed [PlayerName] &f- Assigns the given player to the red team"
  1151. + "\n&HBlue [PlayerName] &f - Assigns the given player to the blue team"
  1152. + "\n&HSettings&f - Shows the current TDM settings"
  1153. + "\n&HAbout&f - General description and credits");
  1154. return;
  1155. }
  1156. if (Option.ToLower() == "time" || Option.ToLower() == "timeleft")
  1157. {
  1158. if (player.Info.isPlayingTD)
  1159. {
  1160. player.Message("&fThere are &W{0}&f seconds left in the game.", TeamDeathMatch.timeLeft);
  1161. return;
  1162. }
  1163. else
  1164. {
  1165. player.Message("&fThere are no games of Team DeathMatch going on.");
  1166. return;
  1167. }
  1168. }
  1169. else
  1170. {
  1171. CdTeamDeathMatch.PrintUsage(player);
  1172. return;
  1173. }
  1174. }
  1175. static readonly CommandDescriptor CdFreeForAll = new CommandDescriptor
  1176. {
  1177. Name = "FreeForAll", //I think I resolved all of the bugs...
  1178. Aliases = new[] { "ffa" },
  1179. Category = CommandCategory.World,
  1180. Permissions = new Permission[] { Permission.Games },
  1181. IsConsoleSafe = false,
  1182. Usage = "/FFA [Start | Stop | Time | Score | ScoreLimit | TimeLimit | TimeDelay | TNT | Settings | About | Help]",
  1183. Help = "Manage the Free-For-All Gamemode!",
  1184. Handler = FFAHandler
  1185. };
  1186. private static void FFAHandler(Player player, Command cmd) //For FFA Game: starting/ending game, customizing game options, viewing score, etc.
  1187. {
  1188. string Option = cmd.Next();
  1189. World world = player.World;
  1190. if (string.IsNullOrEmpty(Option))
  1191. {
  1192. CdFreeForAll.PrintUsage(player);
  1193. return;
  1194. }
  1195. if (Option.ToLower() == "start" || Option.ToLower() == "on") //starts the game
  1196. {
  1197. if (world == WorldManager.MainWorld)
  1198. {
  1199. player.Message("FFA games cannot be played on the main world");
  1200. return;
  1201. }
  1202. if (world.gameMode != GameMode.NULL)
  1203. {
  1204. player.Message("There is already a game of FFA going on");
  1205. return;
  1206. }
  1207. if (player.World.CountPlayers(true) < 2)
  1208. {
  1209. player.Message("There needs to be at least &W2&S players to play FFA");
  1210. return;
  1211. }
  1212. else
  1213. {
  1214. //restart, without hax
  1215. player.World.Hax = false;
  1216. foreach (Player p in player.World.Players)
  1217. {
  1218. p.JoinWorld(player.World, WorldChangeReason.Rejoin);
  1219. }
  1220. FFA.GetInstance(player.World);
  1221. FFA.Start();
  1222. return;
  1223. }
  1224. }
  1225. if (Option.ToLower() == "stop" || Option.ToLower() == "off") //stops the game
  1226. {
  1227. if (FFA.isOn())
  1228. {
  1229. FFA.stoppedEarly = true;
  1230. FFA.Stop(player);
  1231. return;
  1232. }
  1233. else
  1234. {
  1235. player.Message("No games of FFA are going on");
  1236. return;
  1237. }
  1238. }
  1239. if (FFA.isOn() && (Option.ToLower() == "timelimit" || Option.ToLower() == "scorelimit" || Option.ToLower() == "timedelay" || Option.ToLower() == "tnt"))
  1240. {
  1241. player.Message("You cannot adjust game settings while a game is going on");
  1242. return;
  1243. }
  1244. if (!FFA.isOn() && (Option.ToLower() == "timelimit" || Option.ToLower() == "scorelimit" || Option.ToLower() == "timedelay" || Option.ToLower() == "tnt"))
  1245. {
  1246. if (Option.ToLower() == "timelimit") //option to change the length of the game (5m default)
  1247. {
  1248. string time = cmd.Next();
  1249. if (time == null)
  1250. {
  1251. player.Message("Use the syntax: /FFA timelimit (whole number of minutes)\n&HNote: The acceptable times are from 1-20 minutes");
  1252. return;
  1253. }
  1254. int timeLimit = 0;
  1255. bool parsed = Int32.TryParse(time, out timeLimit);
  1256. if (!parsed)
  1257. {
  1258. player.Message("Enter a whole number of minutes. For example: /FFA timelimit 5");
  1259. return;
  1260. }
  1261. if (timeLimit < 1 || timeLimit > 20)
  1262. {
  1263. player.Message("The accepted times are between 1 and 20 minutes");
  1264. return;
  1265. }
  1266. else
  1267. {
  1268. FFA.timeLimit = (timeLimit * 60);
  1269. player.Message("The time limit has been changed to &W{0}&S minutes", timeLimit);
  1270. return;
  1271. }
  1272. }
  1273. if (Option.ToLower() == "timedelay") //option to set the time delay for TDM games (20s default)
  1274. {
  1275. string time = cmd.Next();
  1276. if (time == null)
  1277. {
  1278. player.Message("Use the syntax: /FFA timedelay (whole number of seconds)\n&HNote: The acceptable times incriment by 10 from 10 to 60");
  1279. return;
  1280. }
  1281. int timeDelay = 0;
  1282. bool parsed = Int32.TryParse(time, out timeDelay);
  1283. if (!parsed)
  1284. {
  1285. player.Message("Enter a whole number of minutes. For example: /FFA timedelay 20");
  1286. return;
  1287. }
  1288. if (timeDelay != 10 && timeDelay != 20 && timeDelay != 30 && timeDelay != 40 && timeDelay != 50 && timeDelay != 60)
  1289. {
  1290. player.Message("The accepted times are 10, 20, 30, 40, 50, and 60 seconds");
  1291. return;
  1292. }
  1293. else
  1294. {
  1295. FFA.timeDelay = timeDelay;
  1296. player.Message("The time delay has been changed to &W{0}&s seconds", timeDelay);
  1297. return;
  1298. }
  1299. }
  1300. if (Option.ToLower() == "scorelimit") //changes the score limit (30 default)
  1301. {
  1302. string score = cmd.Next();
  1303. if (score == null)
  1304. {
  1305. player.Message("Use the syntax: /FFA scorelimit (whole number)\n&HNote: The acceptable scores are from 5-300 points");
  1306. return;
  1307. }
  1308. int scoreLimit = 0;
  1309. bool parsed = Int32.TryParse(score, out scoreLimit);
  1310. if (!parsed)
  1311. {
  1312. player.Message("Enter a whole number score. For example: /FFA scorelimit 50");
  1313. return;
  1314. }
  1315. if (scoreLimit < 5 || scoreLimit > 300)
  1316. {
  1317. player.Message("The accepted scores are from 5-300 points");
  1318. return;
  1319. }
  1320. else
  1321. {
  1322. FFA.scoreLimit = scoreLimit;
  1323. player.Message("The score limit has been changed to &W{0}&s points", scoreLimit);
  1324. return;
  1325. }
  1326. }
  1327. if (Option.ToLower() == "tnt")
  1328. {
  1329. if (!FFA.tntAllowed)
  1330. {
  1331. player.Message("&WTNT blasts are now scored in FFA");
  1332. FFA.tntAllowed = true;
  1333. return;
  1334. }
  1335. player.Message("&WTNT blasts are no longer scored in FFA");
  1336. FFA.tntAllowed = false;
  1337. return;
  1338. }
  1339. }
  1340. if (Option.ToLower() == "score") //score for the matches
  1341. {
  1342. Player leader = FFA.GetScoreList()[0];
  1343. int leadScore = leader.Info.gameKillsFFA;
  1344. int secondScore = FFA.GetScoreList()[1].Info.gameKillsFFA;
  1345. player.Message("&f{0}&f is winning &c{1}&f to &c{2}.", leader.ClassyName, leadScore, secondScore);
  1346. return;
  1347. }
  1348. if (Option.ToLower() == "about") //FFA about
  1349. {
  1350. player.Message("&cFree For All&S is a gun game where it is everyone versus everyone. The game will start the gun physics and do /gun for you (also unhides players). The game keeps score and notifications come up about the score and time left every 30 seconds. The Score Limit, Time Delay, and Time Limit are customizable. Detailed help is on &H/FFA Help"
  1351. + "\n&SDeveloped for &5Legend&WCraft&S by &fDingus&0Bungus&S 2013 - Based on the template of ZombieGame.cs written by Jonty800.");
  1352. return;
  1353. }
  1354. if (Option.ToLower() == "settings") //shows the current settings for the game (time limit, time delay, score limit)
  1355. {
  1356. player.Message("The Current Settings For FFA: Time Delay: &c{0}&ss | Time Limit: &c{1}&sm | Score Limit: &c{2}&s points",
  1357. FFA.timeDelay, (FFA.timeLimit / 60), FFA.scoreLimit);
  1358. return;
  1359. }
  1360. if (Option.ToLower() == "help") //detailed help for the cmd
  1361. {
  1362. player.Message("Showing Option Descriptions for /FFA (Option):"
  1363. + "\n&HStart &f- Starts a game of FFA on the current world"
  1364. + "\n&HStop &f- Stops a game of FFA"
  1365. + "\n&HTime &f- Tells how much time left in the game"
  1366. + "\n&HScoreLimit [number] &f- Sets score limit (Whole Numbers from 5-300)"
  1367. + "\n&HTimeLimit [time(m)] &f- Sets end time (Whole minutes from 1-15)"
  1368. + "\n&HTimeDelay [time(s)] &f- Sets start delay (10 second incriments from 10-60)"
  1369. + "\n&HSettings&f - Shows the current game settings"
  1370. + "\n&HAbout&f - General description and credits");
  1371. return;
  1372. }
  1373. if (Option.ToLower() == "time" || Option.ToLower() == "timeleft")
  1374. {
  1375. if (player.Info.isPlayingFFA)
  1376. {
  1377. player.Message("&fThere are &W{0}&f seconds left in the game.", FFA.timeLeft);
  1378. return;
  1379. }
  1380. else
  1381. {
  1382. player.Message("&fThere are no games of FFA going on.");
  1383. return;
  1384. }
  1385. }
  1386. else
  1387. {
  1388. CdFreeForAll.PrintUsage(player);
  1389. return;
  1390. }
  1391. }
  1392. static readonly CommandDescriptor CdTDStatistics = new CommandDescriptor
  1393. {
  1394. Name = "TDStatistics",
  1395. Aliases = new[] { "tdstats" },
  1396. Category = CommandCategory.Fun,
  1397. Permissions = new Permission[] { Permission.Chat },
  1398. IsConsoleSafe = false,
  1399. Usage = "/TDStats (AllTime|TopKills|TopDeaths|Help)\n&HNote: Leave Blank For Current Game Stats.",
  1400. Handler = TDStatisticsHandler
  1401. };
  1402. private static void TDStatisticsHandler(Player player, Command cmd)
  1403. {
  1404. string option = cmd.Next();
  1405. double TDMKills = player.Info.gameKills; //for use in division (for precision)
  1406. double TDMDeaths = player.Info.gameDeaths;
  1407. if (string.IsNullOrEmpty(option)) //user does /TDstats
  1408. {
  1409. double gameKDR = 0;
  1410. if (TDMDeaths == 0 && TDMKills == 0)
  1411. {
  1412. gameKDR = 0;
  1413. }
  1414. else if (TDMKills == 0 && TDMDeaths > 0)
  1415. {
  1416. gameKDR = 0;
  1417. }
  1418. else if (TDMDeaths == 0 && TDMKills > 0)
  1419. {
  1420. gameKDR = player.Info.gameKills;
  1421. }
  1422. else if (TDMDeaths > 0 && TDMKills > 0)
  1423. {
  1424. gameKDR = TDMKills / TDMDeaths;
  1425. }
  1426. if (player.Info.isPlayingTD)
  1427. {
  1428. player.Message("&sYou have &W{0}&s Kills and &W{1}&s Deaths. Your Kill/Death Ratio is &W{2:0.00}&s.", player.Info.gameDeaths, player.Info.gameDeaths, gameKDR);
  1429. }
  1430. else
  1431. {
  1432. player.Message("&sYou had &W{0}&s Kills and &W{1}&s Deaths. Your Kill/Death Ratio was &W{2:0.00}&s.", player.Info.gameKills, player.Info.gameDeaths, gameKDR);
  1433. }
  1434. return;
  1435. }
  1436. else
  1437. {
  1438. switch (option.ToLower())
  1439. {
  1440. default:
  1441. if (option.Length < 2)
  1442. {
  1443. player.Message("Invalid /TDStats option. Do &H/TDStats Help&s for all /TDStats options.");
  1444. return;
  1445. }
  1446. PlayerInfo tar = PlayerDB.FindPlayerInfoOrPrintMatches(player, option);
  1447. if (tar == null) { return; }
  1448. else
  1449. {
  1450. double tarKills = tar.gameKills;
  1451. double tarDeaths = tar.gameDeaths; //for use in division (for precision)
  1452. double gameKDR = 0;
  1453. string opt = cmd.Next();
  1454. if (opt == null)
  1455. {
  1456. player.Message("By default, checking TDM game stats for {0}", tar.ClassyName);
  1457. if (tarKills == 0)
  1458. {
  1459. gameKDR = 0;
  1460. }
  1461. else if (tarDeaths == 0 && tarKills > 0)
  1462. {
  1463. gameKDR = tarKills;
  1464. }
  1465. else if (tarDeaths > 0 && tarKills > 0)
  1466. {
  1467. gameKDR = tarKills / tarDeaths;
  1468. }
  1469. if (tar.isPlayingTD)
  1470. {
  1471. player.Message("&s{0}&S has &W{1}&s Kills and &W{2}&s Deaths. Their Kill/Death Ratio is &W{3:0.00}&s.", tar.ClassyName, tarKills, tarDeaths, gameKDR);
  1472. }
  1473. else
  1474. {
  1475. player.Message("&s{0}&S had &W{1}&s Kills and &W{2}&s Deaths. Their Kill/Death Ratio was &W{3:0.00}&s.", tar.ClassyName, tarKills, tarDeaths, gameKDR);
  1476. }
  1477. return;
  1478. }
  1479. switch (opt.ToLower())
  1480. {
  1481. default:
  1482. player.Message("By default, checking game stats for {0}", tar.ClassyName);
  1483. if (tarKills == 0)
  1484. {
  1485. gameKDR = 0;
  1486. }
  1487. else if (tarDeaths == 0 && tarKills > 0)
  1488. {
  1489. gameKDR = tarKills;
  1490. }
  1491. else if (tarDeaths > 0 && tarKills > 0)
  1492. {
  1493. gameKDR = tarKills / tarDeaths;
  1494. }
  1495. if (tar.isPlayingTD)
  1496. {
  1497. player.Message("&s{0}&S has &W{1}&s Kills and &W{2}&s Deaths. Their Kill/Death Ratio is &W{3:0.00}&s.", tar.ClassyName, tarKills, tarDeaths, gameKDR);
  1498. }
  1499. else
  1500. {
  1501. player.Message("&s{0}&S had &W{1}&s Kills and &W{2}&s Deaths. Their Kill/Death Ratio was &W{3:0.00}&s.", tar.ClassyName, tarKills, tarDeaths, gameKDR);
  1502. }
  1503. break;
  1504. case "alltime":
  1505. double alltimeKDR = 0;
  1506. double dubKills = tar.totalKillsTDM;
  1507. double dubDeaths = tar.totalDeathsTDM;
  1508. if (tar.totalKillsTDM == 0)
  1509. {
  1510. alltimeKDR = 0;
  1511. }
  1512. else if (dubDeaths == 0 && dubKills > 0)
  1513. {
  1514. alltimeKDR = dubKills;
  1515. }
  1516. else if (dubDeaths > 0 && dubKills > 0)
  1517. {
  1518. alltimeKDR = dubKills / dubDeaths;
  1519. }
  1520. player.Message("&sIn all &WTeam Deathmatch&S games {0}&S has played, they have gotten: &W{1}&S Kills and &W{2}&s Deaths giving them a Kill/Death ratio of &W{3:0.00}&S.",
  1521. tar.ClassyName, dubKills, dubDeaths, alltimeKDR);
  1522. break;
  1523. }
  1524. }
  1525. return;
  1526. case "alltime": //user does /TDstats alltime
  1527. double allKills = player.Info.totalKillsTDM;
  1528. double allDeaths = player.Info.totalDeathsTDM; //for use in the division for KDR (int / int = int, so no precision), why we convert to double here
  1529. double totalKDR = 0;
  1530. if (player.Info.totalDeathsTDM == 0 && player.Info.totalKillsTDM == 0)
  1531. {
  1532. totalKDR = 0;
  1533. }
  1534. else if (player.Info.totalDeathsTDM == 0 && player.Info.totalKillsTDM > 0)
  1535. {
  1536. totalKDR = player.Info.totalKillsTDM;
  1537. }
  1538. else if (player.Info.totalKillsTDM == 0 && player.Info.totalDeathsTDM > 0)
  1539. {
  1540. totalKDR = 0;
  1541. }
  1542. else if (player.Info.totalKillsTDM > 0 && player.Info.totalDeathsTDM > 0)
  1543. {
  1544. totalKDR = allKills / allDeaths;
  1545. }
  1546. player.Message("&sIn all &WTeam Deathmatch&S games you have played, you have gotten: &W{0}&S Kills and &W{1}&s Deaths giving you a Kill/Death ratio of &W{2:0.00}&S.",
  1547. player.Info.totalKillsTDM, player.Info.totalDeathsTDM, totalKDR);
  1548. return;
  1549. case "topkills": //user does /TDstats topkills
  1550. List<PlayerInfo> TDPlayers = new List<PlayerInfo>(PlayerDB.PlayerInfoList.ToArray().OrderBy(r => r.totalKillsTDM).Reverse());
  1551. player.Message("&HShowing the players with the most all-time TDM Kills:");
  1552. if (TDPlayers.Count() < 10)
  1553. {
  1554. for (int i = 0; i < TDPlayers.Count(); i++)
  1555. {
  1556. player.Message("{0}&s - {1} Kills", TDPlayers[i].ClassyName, TDPlayers[i].totalKillsTDM);
  1557. }
  1558. }
  1559. else
  1560. {
  1561. for (int i = 0; i < 10; i++)
  1562. {
  1563. player.Message("{0}&s - {1} Kills", TDPlayers[i].ClassyName, TDPlayers[i].totalKillsTDM);
  1564. }
  1565. }
  1566. return;
  1567. case "topdeaths": //user does /TDstats topdeaths
  1568. List<PlayerInfo> TDPlayers2 = new List<PlayerInfo>(PlayerDB.PlayerInfoList.ToArray().OrderBy(r => r.totalDeathsTDM).Reverse());
  1569. player.Message("&HShowing the players with the most all-time TDM Deaths:");
  1570. if (TDPlayers2.Count() < 10)
  1571. {
  1572. for (int i = 0; i < TDPlayers2.Count(); i++)
  1573. {
  1574. player.Message("{0}&s - {1} Deaths", TDPlayers2[i].ClassyName, TDPlayers2[i].totalDeathsTDM);
  1575. }
  1576. }
  1577. else
  1578. {
  1579. for (int i = 0; i < 10; i++)
  1580. {
  1581. player.Message("{0}&s - {1} Deaths", TDPlayers2[i].ClassyName, TDPlayers2[i].totalDeathsTDM);
  1582. }
  1583. }
  1584. return;
  1585. case "scoreboard": //user does /TDstats scoreboard
  1586. List<PlayerInfo> TDPlayersRed = new List<PlayerInfo>(PlayerDB.PlayerInfoList.Where(r => r.isPlayingTD).Where(r => r.isOnRedTeam).ToArray().OrderBy(r => r.totalKillsTDM).Reverse());
  1587. List<PlayerInfo> TDPlayersBlue = new List<PlayerInfo>(PlayerDB.PlayerInfoList.Where(r => r.isPlayingTD).Where(r => r.isOnBlueTeam).ToArray().OrderBy(r => r.totalKillsTDM).Reverse());
  1588. if (TeamDeathMatch.redScore >= TeamDeathMatch.blueScore)
  1589. {
  1590. player.Message("&CRed Team &f{0}&1:", TeamDeathMatch.redScore);
  1591. for (int i = 0; i < TDPlayersRed.Count(); i++)
  1592. {
  1593. string sbNameRed = TDPlayersRed[i].Name;
  1594. if (TDPlayersRed[i].Name.Contains('@'))
  1595. {
  1596. sbNameRed = TDPlayersRed[i].Name.Split('@')[0];
  1597. }
  1598. player.Message("&C{0} &f| &c{1} &fKills - &c{2} &fDeaths",
  1599. sbNameRed, TDPlayersRed[i].gameKills, TDPlayersRed[i].gameDeaths);
  1600. }
  1601. player.Message("&f--------------------------------------------");
  1602. player.Message("&1Blue Team &f{0}&1:", TeamDeathMatch.blueScore);
  1603. for (int i = 0; i < TDPlayersBlue.Count(); i++)
  1604. {
  1605. string sbNameBlue = TDPlayersBlue[i].Name;
  1606. if (TDPlayersBlue[i].Name.Contains('@'))
  1607. {
  1608. sbNameBlue = TDPlayersBlue[i].Name.Split('@')[0];
  1609. }
  1610. player.Message("&1{0} &f| &c{1} &fKills - &c{2} &fDeaths",
  1611. sbNameBlue, TDPlayersBlue[i].gameKills, TDPlayersBlue[i].gameDeaths);
  1612. }
  1613. }
  1614. if (TeamDeathMatch.redScore < TeamDeathMatch.blueScore)
  1615. {
  1616. player.Message("&1Blue Team &f{0}&1:", TeamDeathMatch.blueScore);
  1617. for (int i = 0; i < TDPlayersBlue.Count(); i++)
  1618. {
  1619. string sbNameBlue = TDPlayersBlue[i].Name;
  1620. if (TDPlayersBlue[i].Name.Contains('@'))
  1621. {
  1622. sbNameBlue = TDPlayersBlue[i].Name.Split('@')[0];
  1623. }
  1624. player.Message("&1{0} &f| &c{1} &fKills - &c{2} &fDeaths",
  1625. sbNameBlue, TDPlayersBlue[i].gameKills, TDPlayersBlue[i].gameDeaths);
  1626. }
  1627. player.Message("&f--------------------------------------------");
  1628. player.Message("&CRed Team &f{0}&1:", TeamDeathMatch.redScore);
  1629. for (int i = 0; i < TDPlayersRed.Count(); i++)
  1630. {
  1631. string sbNameRed = TDPlayersRed[i].Name;
  1632. if (TDPlayersRed[i].Name.Contains('@'))
  1633. {
  1634. sbNameRed = TDPlayersRed[i].Name.Split('@')[0];
  1635. }
  1636. player.Message("&C{0} &f| &c{1} &fKills - &c{2} &fDeaths",
  1637. sbNameRed, TDPlayersRed[i].gameKills, TDPlayersRed[i].gameDeaths);
  1638. }
  1639. }
  1640. return;
  1641. case "help": //user does /TDstats help
  1642. player.Message("&HDetailed help for the /TDStats (options):");
  1643. player.Message("&HAllTime&S - Shows your all time TD stats.");
  1644. player.Message("&HTopKills&S - Show the players with the most all time kills");
  1645. player.Message("&HTopDeaths&S - Show the players with the most all time Deaths.");
  1646. player.Message("&HScoreBoard&S - Shows a scoreboard of the current TDM game.");
  1647. player.Message("&H(PlayerName) (Alltime|Game) - Shows the alltime or game stats of a player");
  1648. player.Message("&HNote: Leave Blank For Current Game Stats");
  1649. return;
  1650. }
  1651. }
  1652. }
  1653. static readonly CommandDescriptor CdFFAStatistics = new CommandDescriptor
  1654. {
  1655. Name = "FFAStatistics",
  1656. Aliases = new[] { "ffastats" },
  1657. Category = CommandCategory.Fun,
  1658. Permissions = new Permission[] { Permission.Chat },
  1659. IsConsoleSafe = false,
  1660. Usage = "/FFAStats (AllTime|TopKills|TopDeaths|ScoreBoard|Help)\n&HNote: Leave Blank For Current Game Stats. Can look up others stats "
  1661. + " by using /FFAStats (PlayerName) (AllTime) where alltime is Optional (left blank gives current game stats).",
  1662. Handler = FFAStatsHandler
  1663. };
  1664. private static void FFAStatsHandler(Player player, Command cmd)
  1665. {
  1666. string option = cmd.Next();
  1667. double FFAKills = player.Info.gameKillsFFA; //for use in division (for precision)
  1668. double FFADeaths = player.Info.gameDeathsFFA;
  1669. if (string.IsNullOrEmpty(option)) //user does /FFAstats
  1670. {
  1671. double gameKDR = 0;
  1672. if (FFAKills == 0 && FFAKills == 0)
  1673. {
  1674. gameKDR = 0;
  1675. }
  1676. else if (FFAKills == 0 && FFADeaths > 0)
  1677. {
  1678. gameKDR = 0;
  1679. }
  1680. else if (FFADeaths == 0 && FFAKills > 0)
  1681. {
  1682. gameKDR = player.Info.gameKillsFFA;
  1683. }
  1684. else if (FFADeaths > 0 && FFAKills > 0)
  1685. {
  1686. gameKDR = FFAKills / FFADeaths;
  1687. }
  1688. if (player.Info.isPlayingFFA)
  1689. {
  1690. player.Message("&sYou have &W{0}&s Kills and &W{1}&s Deaths. Your Kill/Death Ratio is &W{2:0.00}&s.", player.Info.gameKillsFFA, player.Info.gameDeathsFFA, gameKDR); //use int forms for display
  1691. }
  1692. else
  1693. {
  1694. player.Message("&sYou had &W{0}&s Kills and &W{1}&s Deaths. Your Kill/Death Ratio was &W{2:0.00}&s.", player.Info.gameKillsFFA, player.Info.gameDeathsFFA, gameKDR);
  1695. }
  1696. return;
  1697. }
  1698. else
  1699. {
  1700. switch (option.ToLower())
  1701. {
  1702. default:
  1703. if (option.Length < 2)
  1704. {
  1705. player.Message("Invalid /FFAStats option. Do &H/FFAStats Help&s for all /FFAStats options.");
  1706. return;
  1707. }
  1708. PlayerInfo tar = PlayerDB.FindPlayerInfoOrPrintMatches(player, option);
  1709. if (tar == null) { return; }
  1710. else
  1711. {
  1712. double tarKills = tar.gameKillsFFA;
  1713. double tarDeaths = tar.gameDeathsFFA; //for use in division (for precision)
  1714. double gameKDR = 0;
  1715. string opt = cmd.Next();
  1716. if (opt == null)
  1717. {
  1718. player.Message("By default, checking FFA game stats for {0}", tar.ClassyName);
  1719. if (tarKills == 0)
  1720. {
  1721. gameKDR = 0;
  1722. }
  1723. else if (tarDeaths == 0 && tarKills > 0)
  1724. {
  1725. gameKDR = tarKills;
  1726. }
  1727. else if (tarDeaths > 0 && tarKills > 0)
  1728. {
  1729. gameKDR = tarKills / tarDeaths;
  1730. }
  1731. if (tar.isPlayingFFA)
  1732. {
  1733. player.Message("&s{0}&S has &W{1}&s Kills and &W{2}&s Deaths. Their Kill/Death Ratio is &W{3:0.00}&s.", tar.ClassyName, tarKills, tarDeaths, gameKDR);
  1734. }
  1735. else
  1736. {
  1737. player.Message("&s{0}&S had &W{1}&s Kills and &W{2}&s Deaths. Their Kill/Death Ratio was &W{3:0.00}&s.", tar.ClassyName, tarKills, tarDeaths, gameKDR);
  1738. }
  1739. return;
  1740. }
  1741. switch (opt.ToLower())
  1742. {
  1743. default:
  1744. player.Message("By default, checking game stats for {0}", tar.ClassyName);
  1745. if (tarKills == 0)
  1746. {
  1747. gameKDR = 0;
  1748. }
  1749. else if (tarDeaths == 0 && tarKills > 0)
  1750. {
  1751. gameKDR = tarKills;
  1752. }
  1753. else if (tarDeaths > 0 && tarKills > 0)
  1754. {
  1755. gameKDR = tarKills / tarDeaths;
  1756. }
  1757. if (tar.isPlayingFFA)
  1758. {
  1759. player.Message("&s{0}&S has &W{1}&s Kills and &W{2}&s Deaths. Their Kill/Death Ratio is &W{3:0.00}&s.", tar.ClassyName, tarKills, tarDeaths, gameKDR);
  1760. }
  1761. else
  1762. {
  1763. player.Message("&s{0}&S had &W{1}&s Kills and &W{2}&s Deaths. Their Kill/Death Ratio was &W{3:0.00}&s.", tar.ClassyName, tarKills, tarDeaths, gameKDR);
  1764. }
  1765. break;
  1766. case "alltime":
  1767. double alltimeKDR = 0;
  1768. double dubKills = tar.totalKillsFFA;
  1769. double dubDeaths = tar.totalDeathsFFA;
  1770. if (dubKills == 0)
  1771. {
  1772. alltimeKDR = 0;
  1773. }
  1774. else if (dubDeaths == 0 && dubKills > 0)
  1775. {
  1776. alltimeKDR = dubKills;
  1777. }
  1778. else if (dubDeaths > 0 && dubKills > 0)
  1779. {
  1780. alltimeKDR = dubKills / dubDeaths;
  1781. }
  1782. player.Message("&sIn all &WFree For All&S games {0}&S has played, they have gotten: &W{1}&S Kills and &W{2}&s Deaths giving them a Kill/Death ratio of &W{3:0.00}&S.",
  1783. tar.ClassyName, dubKills, dubDeaths, alltimeKDR);
  1784. break;
  1785. }
  1786. }
  1787. return;
  1788. case "alltime": //user does /FFAstats alltime
  1789. double allKills = player.Info.totalKillsFFA;
  1790. double allDeaths = player.Info.totalDeathsFFA; //for use in the division for KDR (int / int = int, so no precision), why we convert to double here
  1791. double totalKDR = 0;
  1792. if (allDeaths == 0 && allKills == 0)
  1793. {
  1794. totalKDR = 0;
  1795. }
  1796. else if (allDeaths == 0 && allKills > 0)
  1797. {
  1798. totalKDR = player.Info.totalKillsTDM;
  1799. }
  1800. else if (allKills == 0 && allDeaths > 0)
  1801. {
  1802. totalKDR = 0;
  1803. }
  1804. else if (allKills > 0 && allDeaths > 0)
  1805. {
  1806. totalKDR = allKills / allDeaths;
  1807. }
  1808. player.Message("&sIn all &WFree For All&S games you have played, you have gotten: &W{0}&S Kills and &W{1}&s Deaths giving you a Kill/Death ratio of &W{2:0.00}&S.",
  1809. allKills, allDeaths, totalKDR);
  1810. return;
  1811. case "topkills": //user does /FFAstats topkills
  1812. List<PlayerInfo> FFAPlayers = new List<PlayerInfo>(PlayerDB.PlayerInfoList.ToArray().OrderBy(r => r.totalKillsFFA).Reverse());
  1813. player.Message("&HShowing the players with the most all-time FFA Kills:");
  1814. if (FFAPlayers.Count() < 10)
  1815. {
  1816. for (int i = 0; i < FFAPlayers.Count(); i++)
  1817. {
  1818. player.Message("{0}&s - {1} Kills", FFAPlayers[i].ClassyName, FFAPlayers[i].totalKillsFFA);
  1819. }
  1820. }
  1821. else
  1822. {
  1823. for (int i = 0; i < 10; i++)
  1824. {
  1825. player.Message("{0}&s - {1} Kills", FFAPlayers[i].ClassyName, FFAPlayers[i].totalKillsFFA);
  1826. }
  1827. }
  1828. return;
  1829. case "topdeaths": //user does /FFAstats topdeaths
  1830. List<PlayerInfo> FFAPlayers2 = new List<PlayerInfo>(PlayerDB.PlayerInfoList.ToArray().OrderBy(r => r.totalDeathsFFA).Reverse());
  1831. player.Message("&HShowing the players with the most all-time TDM Deaths:");
  1832. if (FFAPlayers2.Count() < 10)
  1833. {
  1834. for (int i = 0; i < FFAPlayers2.Count(); i++)
  1835. {
  1836. player.Message("{0}&s - {1} Deaths", FFAPlayers2[i].ClassyName, FFAPlayers2[i].totalDeathsFFA);
  1837. }
  1838. }
  1839. else
  1840. {
  1841. for (int i = 0; i < 10; i++)
  1842. {
  1843. player.Message("{0}&s - {1} Deaths", FFAPlayers2[i].ClassyName, FFAPlayers2[i].totalDeathsFFA);
  1844. }
  1845. }
  1846. return;
  1847. case "scoreboard": //user does /FFAstats scoreboard
  1848. if (!FFA.isOn())
  1849. {
  1850. player.Message("There are no games of FFA going on");
  1851. return;
  1852. }
  1853. List<PlayerInfo> FFAScoreBoard = new List<PlayerInfo>(PlayerDB.PlayerInfoList.Where(r => r.isPlayingFFA).ToArray().OrderBy(r => r.gameKillsFFA).Reverse());
  1854. for (int i = 0; i < FFAScoreBoard.Count(); i++)
  1855. {
  1856. string sbName = FFAScoreBoard[i].Name;
  1857. string color = "&c";
  1858. if (FFAScoreBoard[i].Name.Contains('@'))
  1859. {
  1860. sbName = FFAScoreBoard[i].Name.Split('@')[0];
  1861. }
  1862. if (FFAScoreBoard.Count() > 3 && i > 2)
  1863. {
  1864. color = "&f";
  1865. }
  1866. player.Message("{3}{0} &f| &c{1} &fKills - &c{2} &fDeaths",
  1867. sbName, FFAScoreBoard[i].gameKillsFFA, FFAScoreBoard[i].gameDeathsFFA, color);
  1868. }
  1869. return;
  1870. case "help": //user does /FFAstats help
  1871. player.Message("&HDetailed help for the /FFAStats (options):");
  1872. player.Message("&HAllTime&S - Shows your all time FFA stats");
  1873. player.Message("&HTopKills&S - Show the players with the most all time kills");
  1874. player.Message("&HTopDeaths&S - Show the players with the most all time Deaths");
  1875. player.Message("&HScoreBoard&S - Shows a scoreboard of the current FFA game");
  1876. player.Message("&H(PlayerName) (Alltime|Game) - Shows the alltime or game stats of a player");
  1877. player.Message("&HNote: Leave Blank For Current Game Stats");
  1878. return;
  1879. }
  1880. }
  1881. }
  1882. #endregion
  1883. static readonly CommandDescriptor CdInsult = new CommandDescriptor
  1884. {
  1885. Name = "Insult",
  1886. Aliases = new string[] { "MakeFun", "MF" },
  1887. Category = CommandCategory.Chat | CommandCategory.Fun,
  1888. Permissions = new Permission[] { Permission.HighFive },
  1889. IsConsoleSafe = true,
  1890. Usage = "/Insult playername",
  1891. Help = "Takes a random insult from a list and insults a player.",
  1892. NotRepeatable = true,
  1893. Handler = InsultHandler,
  1894. };
  1895. static void InsultHandler(Player player, Command cmd)
  1896. {
  1897. List<String> insults;
  1898. string name = cmd.Next();
  1899. Random randomizer = new Random();
  1900. insults = new List<String>()
  1901. {
  1902. "{0}&s shit on {1}&s's mom's face.",
  1903. "{0}&s spit in {1}&s's drink.",
  1904. "{0}&s threw a chair at {1}&s.",
  1905. "{0}&s rubbed their ass on {1}&s",
  1906. "{0}&s flicked off {1}&s.",
  1907. "{0}&s pulled down their pants and flashed {1}&s.",
  1908. "{0}&s went into {1}&s's house on their birthday, locked them in the closet, and ate their birthday dinner.",
  1909. "{0}&s went up to {1}&s and said 'mama, mama, mama, mama, mommy, mommy, mommy, mommy, ma, ma, ma, ma, mum, mum, mum, mum. Hi! hehehehe'",
  1910. "{0}&s asked {1}&s if they were single, just to hear them say a painful 'yes'...",
  1911. "{0}&s shoved a pineapple up {1}&s's ass",
  1912. "{0}&s beat {1}&s with a cane.",
  1913. "{0}&s put {1}&s in a boiling pot and started chanting.",
  1914. "{0}&s ate cheetos then wiped their hands all over {1}&s's white clothes",
  1915. "{0}&s sprayed {1}&s's crotch with water, then pointed and laughed.",
  1916. "{0}&s tied up {1}&s and ate their last candy bar right in front of them.",
  1917. "{0}&s gave {1}&s a wet willy.",
  1918. "{0}&s gave {1}&s a wedgie.",
  1919. "{0}&s gave {1}&s counterfeit money and then called the Secret Service on them.",
  1920. "{0}&s beats {1}&s with a statue of Dingus.",
  1921. "{0}&s shot {1}&s in the knee with an arrow.",
  1922. "{0}&s called {1}&s a disfigured, bearded clam.",
  1923. "{0}&s flipped a table onto {1}&s.",
  1924. "{0}&s smashed {1}&s over the head with their vintage record.",
  1925. "{0}&s dropped a piano on {1}&s.",
  1926. "{0}&s burned {1}&s with a cigarette.",
  1927. "{0}&s incinerated {1}&s with a Kamehameha!"
  1928. };
  1929. int index = randomizer.Next(0, insults.Count);
  1930. double time = (DateTime.Now - player.Info.LastUsedInsult).TotalSeconds;
  1931. if (name == null || name.Length < 1)
  1932. {
  1933. player.Message("/Insult (PlayerName)");
  1934. return;
  1935. }
  1936. Player target = Server.FindPlayerOrPrintMatches(player, name, false, true);
  1937. if (target == null)
  1938. return;
  1939. if (target == player)
  1940. {
  1941. player.Message("You cannot /insult yourself.");
  1942. return;
  1943. }
  1944. double timeLeft = Math.Round(20 - time);
  1945. if (time < 20)
  1946. {
  1947. player.Message("You cannot use this command for another " + timeLeft + " second(s).");
  1948. return;
  1949. }
  1950. else
  1951. {
  1952. Server.Message(insults[index], player.ClassyName, target.ClassyName);
  1953. player.Info.LastUsedInsult = DateTime.Now;
  1954. return;
  1955. }
  1956. }
  1957. static readonly CommandDescriptor CdThrow = new CommandDescriptor
  1958. {
  1959. Name = "Throw",
  1960. Aliases = new string[] { "Toss" },
  1961. Category = CommandCategory.Chat | CommandCategory.Fun,
  1962. Permissions = new Permission[] { Permission.Mute },
  1963. IsConsoleSafe = true,
  1964. Usage = "/Throw playername",
  1965. Help = "Throw's a player.",
  1966. NotRepeatable = true,
  1967. Handler = ThrowHandler,
  1968. };
  1969. static void ThrowHandler(Player player, Command cmd)
  1970. {
  1971. string name = cmd.Next();
  1972. string item = cmd.Next();
  1973. if (name == null)
  1974. {
  1975. player.Message("Please enter a name");
  1976. return;
  1977. }
  1978. Player target = Server.FindPlayerOrPrintMatches(player, name, false, true);
  1979. if (target == null) return;
  1980. if (target.Immortal)
  1981. {
  1982. player.Message("&SYou failed to throw {0}&S, they are immortal", target.ClassyName);
  1983. return;
  1984. }
  1985. if (target == player)
  1986. {
  1987. player.Message("&sYou can't throw yourself... It's just physically impossible...");
  1988. return;
  1989. }
  1990. double time = (DateTime.Now - player.Info.LastUsedThrow).TotalSeconds;
  1991. if (time < 10)
  1992. {
  1993. player.Message("&WYou can use /Throw again in " + Math.Round(10 - time) + " seconds.");
  1994. return;
  1995. }
  1996. Random random = new Random();
  1997. int randomNumber = random.Next(1, 4);
  1998. player.Info.LastUsedThrow = DateTime.Now;
  1999. if (randomNumber == 1)
  2000. if (player.Can(Permission.Slap, target.Info.Rank))
  2001. {
  2002. Position slap = new Position(target.Position.Z, target.Position.X, (target.World.Map.Bounds.YMax) * 32);
  2003. target.TeleportTo(slap);
  2004. Server.Players.CanSee(target).Except(target).Message("&SPlayer {0}&S was &eThrown&s by {1}&S.", target.ClassyName, player.ClassyName);
  2005. IRC.PlayerSomethingMessage(player, "thrown", target, null);
  2006. target.Message("&sYou were &eThrown&s by {0}&s.", player.ClassyName);
  2007. return;
  2008. }
  2009. else
  2010. {
  2011. player.Message("&sYou can only Throw players ranked {0}&S or lower",
  2012. player.Info.Rank.GetLimit(Permission.Slap).ClassyName);
  2013. player.Message("{0}&S is ranked {1}", target.ClassyName, target.Info.Rank.ClassyName);
  2014. }
  2015. if (randomNumber == 2)
  2016. if (player.Can(Permission.Slap, target.Info.Rank))
  2017. {
  2018. Position slap = new Position(target.Position.X, target.Position.Z, (target.World.Map.Bounds.YMax) * 32);
  2019. target.TeleportTo(slap);
  2020. Server.Players.CanSee(target).Except(target).Message("&sPlayer {0}&s was &eThrown&s by {1}&s.", target.ClassyName, player.ClassyName);
  2021. IRC.PlayerSomethingMessage(player, "thrown", target, null);
  2022. target.Message("&sYou were &eThrown&s by {0}&s.", player.ClassyName);
  2023. return;
  2024. }
  2025. else
  2026. {
  2027. player.Message("&sYou can only Throw players ranked {0}&S or lower",
  2028. player.Info.Rank.GetLimit(Permission.Slap).ClassyName);
  2029. player.Message("{0}&S is ranked {1}", target.ClassyName, target.Info.Rank.ClassyName);
  2030. }
  2031. if (randomNumber == 3)
  2032. if (player.Can(Permission.Slap, target.Info.Rank))
  2033. {
  2034. Position slap = new Position(target.Position.Z, target.Position.Y, (target.World.Map.Bounds.XMax) * 32);
  2035. target.TeleportTo(slap);
  2036. Server.Players.CanSee(target).Except(target).Message("&sPlayer {0}&s was &eThrown&s by {1}&s.", target.ClassyName, player.ClassyName);
  2037. IRC.PlayerSomethingMessage(player, "thrown", target, null);
  2038. target.Message("&sYou were &eThrown&s by {0}&s.", player.ClassyName);
  2039. return;
  2040. }
  2041. else
  2042. {
  2043. player.Message("&sYou can only Throw players ranked {0}&S or lower",
  2044. player.Info.Rank.GetLimit(Permission.Slap).ClassyName);
  2045. player.Message("{0}&S is ranked {1}", target.ClassyName, target.Info.Rank.ClassyName);
  2046. }
  2047. if (randomNumber == 4)
  2048. if (player.Can(Permission.Slap, target.Info.Rank))
  2049. {
  2050. Position slap = new Position(target.Position.Y, target.Position.Z, (target.World.Map.Bounds.XMax) * 32);
  2051. target.TeleportTo(slap);
  2052. Server.Players.CanSee(target).Except(target).Message("&sPlayer {0}&s was &eThrown&s by {1}&s.", target.ClassyName, player.ClassyName);
  2053. IRC.PlayerSomethingMessage(player, "thrown", target, null);
  2054. target.Message("&sYou were &eThrown&s by {0}&s.", player.ClassyName);
  2055. return;
  2056. }
  2057. else
  2058. {
  2059. player.Message("&sYou can only Throw players ranked {0}&S or lower",
  2060. player.Info.Rank.GetLimit(Permission.Slap).ClassyName);
  2061. player.Message("{0}&S is ranked {1}", target.ClassyName, target.Info.Rank.ClassyName);
  2062. }
  2063. }
  2064. #endregion
  2065. #region Possess / UnPossess
  2066. static readonly CommandDescriptor CdPossess = new CommandDescriptor
  2067. {
  2068. Name = "Possess",
  2069. Category = CommandCategory.Fun,
  2070. Permissions = new[] { Permission.Possess },
  2071. Usage = "/Possess PlayerName",
  2072. Handler = PossessHandler
  2073. };
  2074. static void PossessHandler(Player player, Command cmd)
  2075. {
  2076. string targetName = cmd.Next();
  2077. if (targetName == null)
  2078. {
  2079. CdPossess.PrintUsage(player);
  2080. return;
  2081. }
  2082. Player target = Server.FindPlayerOrPrintMatches(player, targetName, false, true);
  2083. if (target == null) return;
  2084. if (target.Immortal)
  2085. {
  2086. player.Message("You cannot possess {0}&S, they are immortal", target.ClassyName);
  2087. return;
  2088. }
  2089. if (target == player)
  2090. {
  2091. player.Message("You cannot possess yourself.");
  2092. return;
  2093. }
  2094. if (!player.Can(Permission.Possess, target.Info.Rank))
  2095. {
  2096. player.Message("You may only possess players ranked {0}&S or lower.",
  2097. player.Info.Rank.GetLimit(Permission.Possess).ClassyName);
  2098. player.Message("{0}&S is ranked {1}",
  2099. target.ClassyName, target.Info.Rank.ClassyName);
  2100. return;
  2101. }
  2102. if (!player.Possess(target))
  2103. {
  2104. player.Message("Already possessing {0}", target.ClassyName);
  2105. }
  2106. }
  2107. static readonly CommandDescriptor CdUnpossess = new CommandDescriptor
  2108. {
  2109. Name = "unpossess",
  2110. Category = CommandCategory.Fun,
  2111. Permissions = new[] { Permission.Possess },
  2112. NotRepeatable = true,
  2113. Usage = "/Unpossess target",
  2114. Handler = UnpossessHandler
  2115. };
  2116. static void UnpossessHandler(Player player, Command cmd)
  2117. {
  2118. string targetName = cmd.Next();
  2119. if (targetName == null)
  2120. {
  2121. CdUnpossess.PrintUsage(player);
  2122. return;
  2123. }
  2124. Player target = Server.FindPlayerOrPrintMatches(player, targetName, true, true);
  2125. if (target == null) return;
  2126. if (!player.StopPossessing(target))
  2127. {
  2128. player.Message("You are not currently possessing anyone.");
  2129. }
  2130. }
  2131. #endregion
  2132. static readonly CommandDescriptor CdLife = new CommandDescriptor
  2133. {
  2134. Name = "Life",
  2135. Category = CommandCategory.Fun,
  2136. Permissions = new[] { Permission.DrawAdvanced },
  2137. IsConsoleSafe = false,
  2138. NotRepeatable = true,
  2139. Usage = "/Life <command> [params]",
  2140. Help = "&SGoogle \"Conwey's Game of Life\"\n'&H/Life help'&S for more usage info\n(c) 2012 LaoTszy",
  2141. UsableByFrozenPlayers = false,
  2142. Handler = LifeHandlerFunc,
  2143. };
  2144. static readonly CommandDescriptor CdFirework = new CommandDescriptor
  2145. {
  2146. Name = "Firework",
  2147. Category = CommandCategory.Fun,
  2148. Permissions = new[] { Permission.Fireworks },
  2149. IsConsoleSafe = false,
  2150. NotRepeatable = false,
  2151. Usage = "/Firework",
  2152. Help = "&SToggles Firework Mode on/off for yourself. " +
  2153. "All Gold blocks will be replaced with fireworks if " +
  2154. "firework physics are enabled for the current world.",
  2155. UsableByFrozenPlayers = false,
  2156. Handler = FireworkHandler
  2157. };
  2158. static void FireworkHandler(Player player, Command cmd)
  2159. {
  2160. if (player.fireworkMode)
  2161. {
  2162. player.fireworkMode = false;
  2163. player.Message("Firework Mode has been turned off.");
  2164. return;
  2165. }
  2166. else
  2167. {
  2168. player.fireworkMode = true;
  2169. player.Message("Firework Mode has been turned on. " +
  2170. "All Gold blocks are now being replaced with Fireworks.");
  2171. }
  2172. }
  2173. static readonly CommandDescriptor CdRandomMaze = new CommandDescriptor
  2174. {
  2175. Name = "RandomMaze",
  2176. Aliases = new string[] { "3dmaze" },
  2177. Category = CommandCategory.Fun,
  2178. Permissions = new Permission[] { Permission.DrawAdvanced },
  2179. RepeatableSelection = true,
  2180. Help =
  2181. "Choose the size (width, length and height) and it will draw a random maze at the chosen point. " +
  2182. "Optional parameters tell if the lifts are to be drawn and if hint blocks (log) are to be added. \n(C) 2012 Lao Tszy",
  2183. Usage = "/randommaze <width> <length> <height> [nolifts] [hints]",
  2184. Handler = MazeHandler
  2185. };
  2186. static readonly CommandDescriptor CdMazeCuboid = new CommandDescriptor
  2187. {
  2188. Name = "MazeCuboid",
  2189. Aliases = new string[] { "Mc", "Mz", "Maze" },
  2190. Category = CommandCategory.Fun,
  2191. Permissions = new Permission[] { Permission.DrawAdvanced },
  2192. RepeatableSelection = true,
  2193. Help =
  2194. "Draws a cuboid with the current brush and with a random maze inside.(C) 2012 Lao Tszy",
  2195. Usage = "/MazeCuboid [block type]",
  2196. Handler = MazeCuboidHandler,
  2197. };
  2198. private static void MazeHandler(Player p, Command cmd)
  2199. {
  2200. try
  2201. {
  2202. RandomMazeDrawOperation op = new RandomMazeDrawOperation(p, cmd);
  2203. BuildingCommands.DrawOperationBegin(p, cmd, op);
  2204. }
  2205. catch (Exception e)
  2206. {
  2207. Logger.Log(LogType.Error, "Error: " + e.Message);
  2208. }
  2209. }
  2210. private static void MazeCuboidHandler(Player p, Command cmd)
  2211. {
  2212. try
  2213. {
  2214. MazeCuboidDrawOperation op = new MazeCuboidDrawOperation(p);
  2215. BuildingCommands.DrawOperationBegin(p, cmd, op);
  2216. }
  2217. catch (Exception e)
  2218. {
  2219. Logger.Log(LogType.Error, "Error: " + e.Message);
  2220. }
  2221. }
  2222. private static void LifeHandlerFunc(Player p, Command cmd)
  2223. {
  2224. try
  2225. {
  2226. if (!cmd.HasNext)
  2227. {
  2228. p.Message("&H/Life <command> <params>. Commands are Help, Create, Delete, Start, Stop, Set, List, Print");
  2229. p.Message("Type /Life help <command> for more information");
  2230. return;
  2231. }
  2232. LifeHandler.ProcessCommand(p, cmd);
  2233. }
  2234. catch (Exception e)
  2235. {
  2236. p.Message("Error: " + e.Message);
  2237. }
  2238. }
  2239. }
  2240. }