• 3 Vote(s) - 4.67 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Release Game Type Changer
#1
Hi everyone,

This is my first time posting a plugin so bare with me, I know there is a similar plugin to the one that I'm releasing but I will explain the differences before you think I copied someone else.

Basically the main problem with MW3 at the moment is its hard for custom playlists to be used with custom game types there for anyone using the God Plugin and permissions plugin it isn't trivial as to how you switch the map with the correct game type assigned in the playlist.

What I have done is created a simple chat command that accepts the map name and DSR file name, of course its the same as another plugin but bare with me, the key difference is I have ensured only the maps defined in the plugin can ever be loaded and only if they do exist will they be loaded. If a map is found along with the specified game type two server commands will be issued; one that sets the map rotation playlist and another that rotates the map using the custom playlist that was just set.

In a nutshell it works like this:
  • The plugin creates a new DSPL file in the admin folder
  • Once created it adds a new playlist line for the map and game type
  • Next it assigns the map rotation to the custom playlist
  • Finally it rotates the map

Now the main problem with setting a custom DSPL file is that you lose the custom playlist previously assigned, to fix this issue on the map pre change I have set a check that looks for this custom DSPL file and switches the map rotation back to the DSPL file you had set previously.

There are some limitations/downsides to doing this and they are:
  • The map rotation counter goes up so once the map rotates it sits at 2
  • The !nextmap command reports the same map as been next because of the custom playlist
  • You need to write the full name of maps and game types as its not smart enough to guess them for you
  • When the map changes the !mr command will rotate to the to the first map in your playlist file

Now of course I'm still new to this so there may be a way to fix this but from my investigating there isn't but if you know a fix please let me know. So without further ado add the following into your sv_config.ini file.

Code:
[GameTypeChange]
dsplfile=default
// The name of the DSPL file you have set for your map playlist

Usage:
Code:
!gametype <map name> <dsr file name>
or
!gt <map name> <dsr file name>

Example: !gt dome INF_default

Changelog:

Credits:
@Nukem - For such a great code base to work with
@Pozzuh - For the permissions plugin


Source:
CSHARP Code
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using Addon;
  6.  
  7. namespace GameTypeChanger
  8. {
  9. public class GameTypeChanger : CPlugin
  10. {
  11. // The array that aliases can be stored in
  12. public Dictionary<string, IList> aliases = new Dictionary<string, IList>();
  13.  
  14. // General variables
  15. public bool isDLC = false;
  16. public string mapName;
  17. public string gameType;
  18.  
  19. /// <summary>
  20. /// Executes when a client connects to the MW3 server.
  21. ///
  22. /// When a client does connect a list of map aliases will be constructed that will be used to
  23. /// determine if a chosen map is part of the DLC packs or a standard map that comes packaged
  24. /// with the game on a clean install.
  25. /// </summary>
  26. public override void OnServerLoad()
  27. {
  28. ServerPrint("\n Game type changer plugin loaded. Author: SgtLegend. Version 1.3\n");
  29.  
  30. // Create the map alias array
  31. aliases.Add("maps", new List<AliasListing>() {
  32. // Standard maps
  33. new AliasListing() { name = "lockdown", value = "std:mp_alpha" },
  34. new AliasListing() { name = "bootleg", value = "std:mp_bootleg" },
  35. new AliasListing() { name = "mission", value = "std:mp_bravo" },
  36. new AliasListing() { name = "carbon", value = "std:mp_carbon" },
  37. new AliasListing() { name = "dome", value = "std:mp_dome" },
  38. new AliasListing() { name = "downturn", value = "std:mp_exchange" },
  39. new AliasListing() { name = "hardhat", value = "std:mp_hardhat" },
  40. new AliasListing() { name = "interchange", value = "std:mp_interchange" },
  41. new AliasListing() { name = "fallen", value = "std:mp_lambeth" },
  42. new AliasListing() { name = "bakaara", value = "std:mp_mogadishu" },
  43. new AliasListing() { name = "resistance", value = "std:mp_paris" },
  44. new AliasListing() { name = "arkaden", value = "std:mp_plaza2" },
  45. new AliasListing() { name = "outpost", value = "std:mp_radar" },
  46. new AliasListing() { name = "seatown", value = "std:mp_seatown" },
  47. new AliasListing() { name = "underground", value = "std:mp_underground" },
  48. new AliasListing() { name = "village", value = "std:mp_village" },
  49.  
  50. // DLC maps
  51. new AliasListing() { name = "aground", value = "dlc:mp_aground_ss" },
  52. new AliasListing() { name = "blackbox", value = "dlc:mp_morningwood" },
  53. new AliasListing() { name = "boardwalk", value = "dlc:mp_Boardwalk" },
  54. new AliasListing() { name = "decommission", value = "dlc:mp_Shipbreaker" },
  55. new AliasListing() { name = "erosion", value = "dlc:mp_courtyard_ss" },
  56. new AliasListing() { name = "foundation", value = "dlc:mp_Foundation" },
  57. new AliasListing() { name = "getaway", value = "dlc:mp_hillside_ss" },
  58. new AliasListing() { name = "gulch", value = "dlc:mp_gulch" },
  59. new AliasListing() { name = "liberation", value = "dlc:mp_park" },
  60. new AliasListing() { name = "lookout", value = "dlc:mp_restrepo_ss" },
  61. new AliasListing() { name = "terminal", value = "dlc:mp_terminal_cls" },
  62. new AliasListing() { name = "oasis", value = "dlc:mp_Qadeem" },
  63. new AliasListing() { name = "offshore", value = "dlc:mp_roughneck" },
  64. new AliasListing() { name = "overwatch", value = "dlc:mp_overwatch" },
  65. new AliasListing() { name = "parish", value = "dlc:mp_NOLA" },
  66. new AliasListing() { name = "piazza", value = "dlc:mp_italy" },
  67. new AliasListing() { name = "sanctuary", value = "dlc:mp_meteora" }
  68. });
  69.  
  70. // Get and set all the directories in the zone folder
  71. string[] zoneDirectories = Directory.GetDirectories("zone");
  72. List<string> directories = new List<string>();
  73.  
  74. foreach (string directory in zoneDirectories)
  75. {
  76. if (!directory.Contains("dlc"))
  77. directories.Add(directory);
  78. }
  79.  
  80. aliases.Add("zones", directories);
  81. }
  82.  
  83. /// <summary>
  84. /// Listens for when a client types in the chat, currently it listens for "!gametype" and "!gt"
  85. /// which are two pre-defined chat commands that can be assigned using the permissions plugin
  86. /// otherwise everyone will be able to use them.
  87. /// </summary>
  88. /// <param name="Message"></param>
  89. /// <param name="Client"></param>
  90. /// <returns></returns>
  91. public override ChatType OnSay(string Message, ServerClient Client)
  92. {
  93. if (Message.StartsWith("!gametype") || Message.StartsWith("!gt"))
  94. {
  95. string[] split = Message.Split(' ');
  96.  
  97. // Do we have enough arguments?
  98. if (split.Length < 3)
  99. {
  100. TellClient(Client.ClientNum, "^1Usage: ^7!" + split[0] + " <map name> <dsr name>", true);
  101. return ChatType.ChatNone;
  102. }
  103.  
  104. // Set the map name and game type
  105. mapName = split[1].ToLower();
  106. gameType = split[2];
  107.  
  108. // Are the required arguments empty?
  109. if (string.IsNullOrEmpty(mapName) || string.IsNullOrEmpty(gameType))
  110. {
  111. TellClient(Client.ClientNum, (string.IsNullOrEmpty(mapName) ? "^1Enter a map name" : "^1Enter a game type DSR name"), true);
  112. return ChatType.ChatNone;
  113. }
  114.  
  115. // Sort through all the maps specified in the alias list and determine if the map name
  116. // the user has entered matches something in that list
  117. setMapNameAndIsDLC();
  118.  
  119. // Check if the specified map exists on the server and also check if the game type given
  120. // is on that exists within the admin folder
  121. bool isMapValid = checkIfTheMapExists();
  122. bool isGameTypeValid = File.Exists(@"admin\" + gameType + ".dsr");
  123.  
  124. if (!isMapValid || !isGameTypeValid)
  125. {
  126. TellClient(Client.ClientNum, string.Format("^1Invalid ^7{0} ^1given!", (!isMapValid ? "map name" : "game type")), true);
  127. return ChatType.ChatNone;
  128. }
  129.  
  130. // Check if the custom playlist file we created still exists, if it does we need to
  131. // delete it off the server so the normal playlist can continue to work after the map
  132. // has been changed
  133. if (File.Exists(@"admin\gametypechanger.dspl"))
  134. {
  135. File.Delete(@"admin\gametypechanger.dspl");
  136. }
  137.  
  138. // Create the new playlist file that we can use to force the game type
  139. createDSPLFileAndMessageTheAdmins();
  140.  
  141. return ChatType.ChatNone;
  142. }
  143.  
  144. return ChatType.ChatContinue;
  145. }
  146.  
  147. /// <summary>
  148. /// When the map changes the custom DSPL file we set will take control of the map rotation so we
  149. /// need to switch it back to the original DSPL file.
  150. ///
  151. /// There is a downside to this which is that we have to incur another map rotation call which now
  152. /// increments the total to "2" rotations.
  153. ///
  154. /// Resets the variables that may still have values from the last change.
  155. /// </summary>
  156. public override void OnMapChange()
  157. {
  158. isDLC = false;
  159. mapName = string.Empty;
  160. gameType = string.Empty;
  161.  
  162. if (File.Exists(@"admin\gametypechanger.dspl"))
  163. {
  164. ServerCommand("sv_maprotation " + GetServerCFG("GameTypeChange", "dsplfile", "default"));
  165. }
  166. }
  167.  
  168. /// <summary>
  169. /// Loops through all the pre-defined maps that were constructed while the server was connecting to
  170. /// the server and tries to determine which map the user has chosen using the switch game type commands
  171. /// </summary>
  172. private void setMapNameAndIsDLC()
  173. {
  174. foreach (AliasListing map in aliases["maps"])
  175. {
  176. string[] mapDetails = map.value.Split(':');
  177.  
  178. // Check if the given map name matches the current map name
  179. if (mapName == map.name || mapName == mapDetails[1])
  180. {
  181. mapName = mapDetails[1];
  182. isDLC = (mapDetails[0] == "dlc");
  183. break;
  184. }
  185. }
  186. }
  187.  
  188. /// <summary>
  189. /// Checks if the given map exists on the server using the list of directories that we discovered
  190. /// in the zone folder earlier.
  191. /// </summary>
  192. /// <returns></returns>
  193. private bool checkIfTheMapExists()
  194. {
  195. if ((isDLC && File.Exists(@"zone\dlc\" + mapName + ".ff")) || !isDLC)
  196. {
  197. if (!isDLC)
  198. {
  199. foreach (string directory in aliases["zones"])
  200. {
  201. if (File.Exists(directory + @"\" + mapName + ".ff"))
  202. return true;
  203. }
  204. }
  205. else
  206. {
  207. return true;
  208. }
  209. }
  210.  
  211. return false;
  212. }
  213.  
  214. /// <summary>
  215. /// It also create the custom DSPL file needed to set the user selected map and game type set via
  216. /// the commands.
  217. ///
  218. /// Lets all the admins on the server know the map was just changed using "!gametype" or "!gt" and
  219. /// what game type was loaded during the change.
  220. /// </summary>
  221. private void createDSPLFileAndMessageTheAdmins()
  222. {
  223. using (StreamWriter file = new StreamWriter(@"admin\gametypechanger.dspl", true))
  224. {
  225. file.WriteLine(string.Format("{0},{1},1", mapName, gameType));
  226.  
  227. // Issue the server command to change the map
  228. ServerCommand("sv_maprotation gametypechanger");
  229. ServerCommand("start_map_rotate");
  230.  
  231. // Display a server message to let the user know the map and game type has changed. Admins ONLY!
  232. string adminXUIDs = GetServerCFG("Permission", "Admin_xuids", "");
  233. List<ServerClient> clients = GetClients();
  234.  
  235. if (!string.IsNullOrEmpty(adminXUIDs))
  236. {
  237. foreach (ServerClient client in clients)
  238. {
  239. if (adminXUIDs.Contains(client.XUID))
  240. TellClient(client.ClientNum, string.Format("^5Map changed to ^7{0} ^5using ^7{1} as the game type", mapName, gameType), true);
  241. }
  242. }
  243. }
  244. }
  245. }
  246.  
  247. /// <summary>
  248. /// A re-usable structure array that can be used for map aliases etc...
  249. /// </summary>
  250. public struct AliasListing
  251. {
  252. public string name, value;
  253. }
  254. }


Thanks for reading and hope you enjoy it!

.zip   GameTypeChanger-v1.3.zip (Size: 4.5 KB / Downloads: 181)
.zip   GameTypeChanger-v1.2.zip (Size: 4.16 KB / Downloads: 66)
.zip   GameTypeChanger-v1.1.zip (Size: 4.16 KB / Downloads: 26)
.zip   GameTypeChanger-v0.1.zip (Size: 3.19 KB / Downloads: 19)
I now host all my MW3 projects on my private GIT repo
[-] The following 9 users say Thank You to SgtLegend for this post:
  • 99IRock, DidUknowiPwn, master131, Nekochan, nouri.reza, Nukem, OzonE, Pozzuh, surtek
  Reply
#2
Dayum, pretty good for your first post. XML commented code too, nice, nice. Keep up the good work.
[Image: 30xhrep.png]

A casual conversation between barata and I about Nukem.
  Reply
#3
Thanks, I have another plugin that I will release in about 2-3 days time
  Reply
#4
Nice job senor. (fancy spanish n)
Do not take life too seriously. You will never get out of it alive.
[Image: UGPjFJa.jpg]
  Reply
#5
I realy like ur plugin, but when I try to write "!gt dome tdm" it writes me smth like that: "Invalid mapname".
What's wrong?
  Reply
#6
(01-10-2013, 06:27)SMIRNOFF2096 Wrote: I realy like ur plugin, but when I try to write "!gt dome tdm" it writes me smth like that: "Invalid mapname".
What's wrong?

The only reason for that message to appear is if the map doesn't exist in your zone/english folder, just for my sanity could you please ensure that zone/english/mp_dome.ff does exist as I'm not sure if any other folders ever exist within the zone folder.
I now host all my MW3 projects on my private GIT repo
  Reply
#7
You should add more folder names.
Like zone/japanese, zone/russian, zone/swedish etc
C++/Obj-C developer. Neko engine wip
Steam: Click
  Reply
#8
(01-10-2013, 09:38)SailorMoon Wrote: You should add more folder names.
Like zone/japanese, zone/russian, zone/swedish etc

Is there a public list of these folder names as I would feel better with a 100% correct list in front of me to use
I now host all my MW3 projects on my private GIT repo
  Reply
#9
(01-10-2013, 09:50)SgtLegend Wrote:
(01-10-2013, 09:38)SailorMoon Wrote: You should add more folder names.
Like zone/japanese, zone/russian, zone/swedish etc

Is there a public list of these folder names as I would feel better with a 100% correct list in front of me to use

Look in steam, MW3 > Properties > Languages
C++/Obj-C developer. Neko engine wip
Steam: Click
  Reply
#10
(01-10-2013, 10:24)SailorMoon Wrote:
(01-10-2013, 09:50)SgtLegend Wrote:
(01-10-2013, 09:38)SailorMoon Wrote: You should add more folder names.
Like zone/japanese, zone/russian, zone/swedish etc

Is there a public list of these folder names as I would feel better with a 100% correct list in front of me to use

Look in steam, MW3 > Properties > Languages

Actually thought of a much more full proof way of detecting the folders, will release an update soon.
I now host all my MW3 projects on my private GIT repo
  Reply


Possibly Related Threads...
Thread Author Replies Views Last Post
  What game have you bought in the last week? RaZ 12 2,355 12-05-2013, 16:29
Last Post: Nekochan
  [GAME]The Letter Game Bandarigoda123 65 7,582 08-08-2013, 21:05
Last Post: AZUMIKKEL
  [Release] AntiRage for Infected Game Mode yokai134 17 6,132 08-04-2013, 22:22
Last Post: yokai134
  ESTRANGED best indie game I've seen so far Arteq 0 901 08-03-2013, 14:03
Last Post: Arteq
  [HELP] bo2 - FD1 - dis-attach the console from the game masis 8 2,078 07-17-2013, 23:01
Last Post: surtek
Smile [Release] Map & Game Type Changer Plugin (Fixed) 30mba 31 9,837 07-10-2013, 16:27
Last Post: 26hz
  Selling steam account for a game! Strentin 3 1,371 06-18-2013, 07:49
Last Post: xfxtroll
  Help Using chat outside in game Bandarigoda123 1 967 06-09-2013, 12:46
Last Post: Nekochan
  Help Game Not Reading Mod? Killjoy 6 1,839 06-08-2013, 14:49
Last Post: Killjoy
Brick Lesson 3: Making game in C++ Nekochan 2 1,448 06-03-2013, 15:25
Last Post: Nekochan

Forum Jump:


Users browsing this thread: 1 Guest(s)