/Samples/MacOS/RolePlayingGame/Session/Party.cs

https://github.com/mauriciocirelli/MonoGame-Samples · C# · 364 lines · 217 code · 59 blank · 88 comment · 37 complexity · b8c23a17f4ee2352df99b8408035041c MD5 · raw file

  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // Party.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Collections.ObjectModel;
  13. using System.IO;
  14. using Microsoft.Xna.Framework.Content;
  15. using RolePlayingGameData;
  16. #endregion
  17. namespace RolePlaying
  18. {
  19. /// <summary>
  20. /// The group of players, under control of the user.
  21. /// </summary>
  22. public class Party
  23. {
  24. #region Party Members
  25. /// <summary>
  26. /// The ordered list of players in the party.
  27. /// </summary>
  28. /// <remarks>The first entry is the leader.</remarks>
  29. private List<Player> players = new List<Player>();
  30. /// <summary>
  31. /// The ordered list of players in the party.
  32. /// </summary>
  33. /// <remarks>The first entry is the leader.</remarks>
  34. [ContentSerializerIgnore]
  35. public List<Player> Players
  36. {
  37. get { return players; }
  38. set { players = value; }
  39. }
  40. /// <summary>
  41. /// Add a new player to the party.
  42. /// </summary>
  43. /// <param name="player">The new player.</param>
  44. /// <remarks>Instead of using the lists directly, this fixes all data.</remarks>
  45. public void JoinParty(Player player)
  46. {
  47. // check the parameter
  48. if (player == null)
  49. {
  50. throw new ArgumentNullException("player");
  51. }
  52. if (players.Contains(player))
  53. {
  54. throw new ArgumentException("The player was already in the party.");
  55. }
  56. // add the new player to the list
  57. players.Add(player);
  58. // add the initial gold
  59. partyGold += player.Gold;
  60. // only as NPCs are players allowed to have their own gold
  61. player.Gold = 0;
  62. // add the player's inventory items
  63. foreach (ContentEntry<Gear> contentEntry in player.Inventory)
  64. {
  65. AddToInventory(contentEntry.Content, contentEntry.Count);
  66. }
  67. // only as NPCs are players allowed to have their own non-equipped gear
  68. player.Inventory.Clear();
  69. }
  70. /// <summary>
  71. /// Gives the experience amount specified to all party members.
  72. /// </summary>
  73. public void GiveExperience(int experience)
  74. {
  75. // check the parameters
  76. if (experience < 0)
  77. {
  78. throw new ArgumentOutOfRangeException("experience");
  79. }
  80. else if (experience == 0)
  81. {
  82. return;
  83. }
  84. List<Player> leveledUpPlayers = null;
  85. foreach (Player player in players)
  86. {
  87. int oldLevel = player.CharacterLevel;
  88. player.Experience += experience;
  89. if (player.CharacterLevel > oldLevel)
  90. {
  91. if (leveledUpPlayers == null)
  92. {
  93. leveledUpPlayers = new List<Player>();
  94. }
  95. leveledUpPlayers.Add(player);
  96. }
  97. }
  98. if ((leveledUpPlayers != null) && (leveledUpPlayers.Count > 0))
  99. {
  100. Session.ScreenManager.AddScreen(new LevelUpScreen(leveledUpPlayers));
  101. }
  102. }
  103. #endregion
  104. #region Inventory
  105. /// <summary>
  106. /// The items held by the party.
  107. /// </summary>
  108. private List<ContentEntry<Gear>> inventory = new List<ContentEntry<Gear>>();
  109. /// <summary>
  110. /// The items held by the party.
  111. /// </summary>
  112. [ContentSerializerIgnore]
  113. public ReadOnlyCollection<ContentEntry<Gear>> Inventory
  114. {
  115. get { return inventory.AsReadOnly(); }
  116. }
  117. /// <summary>
  118. /// Add the given gear, in the given quantity, to the party's inventory.
  119. /// </summary>
  120. public void AddToInventory(Gear gear, int count)
  121. {
  122. // check the parameters
  123. if ((gear == null) || (count <= 0))
  124. {
  125. return;
  126. }
  127. // search for an existing entry
  128. ContentEntry<Gear> existingEntry = inventory.Find(
  129. delegate(ContentEntry<Gear> entry)
  130. {
  131. return (entry.Content == gear);
  132. });
  133. // increment the existing entry, if any
  134. if (existingEntry != null)
  135. {
  136. existingEntry.Count += count;
  137. return;
  138. }
  139. // no existing entry - create a new entry
  140. ContentEntry<Gear> newEntry = new ContentEntry<Gear>();
  141. newEntry.Content = gear;
  142. newEntry.Count = count;
  143. newEntry.ContentName = gear.AssetName;
  144. if (newEntry.ContentName.StartsWith(@"Gear\"))
  145. {
  146. newEntry.ContentName = newEntry.ContentName.Substring(5);
  147. }
  148. inventory.Add(newEntry);
  149. }
  150. /// <summary>
  151. /// Remove the given quantity of the given gear from the party's inventory.
  152. /// </summary>
  153. /// <returns>True if the quantity specified could be removed.</returns>
  154. public bool RemoveFromInventory(Gear gear, int count)
  155. {
  156. // check the parameters
  157. if (gear == null)
  158. {
  159. throw new ArgumentNullException("gear");
  160. }
  161. if (count <= 0)
  162. {
  163. throw new ArgumentOutOfRangeException("count");
  164. }
  165. // search for an existing entry
  166. ContentEntry<Gear> existingEntry = inventory.Find(
  167. delegate(ContentEntry<Gear> entry)
  168. {
  169. return (entry.Content == gear);
  170. });
  171. // no existing entry, so this is moot
  172. if (existingEntry == null)
  173. {
  174. return false;
  175. }
  176. // decrement the existing entry
  177. existingEntry.Count -= count;
  178. bool fullRemoval = (existingEntry.Count >= 0);
  179. // if the entry is empty, then remove it
  180. if (existingEntry.Count <= 0)
  181. {
  182. inventory.Remove(existingEntry);
  183. }
  184. return fullRemoval;
  185. }
  186. /// <summary>
  187. /// The gold held by the party.
  188. /// </summary>
  189. private int partyGold;
  190. /// <summary>
  191. /// The gold held by the party.
  192. /// </summary>
  193. [ContentSerializer(Optional = true)]
  194. public int PartyGold
  195. {
  196. get { return partyGold; }
  197. set { partyGold = value; }
  198. }
  199. #endregion
  200. #region Quest Data
  201. /// <summary>
  202. /// The name and kill-count of monsters killed in the active quest.
  203. /// </summary>
  204. /// <remarks>
  205. /// Used to determine if the requirements for the active quest have been met.
  206. /// </remarks>
  207. private Dictionary<string, int> monsterKills = new Dictionary<string, int>();
  208. /// <summary>
  209. /// The name and kill-count of monsters killed in the active quest.
  210. /// </summary>
  211. /// <remarks>
  212. /// Used to determine if the requirements for the active quest have been met.
  213. /// </remarks>
  214. public Dictionary<string, int> MonsterKills
  215. {
  216. get { return monsterKills; }
  217. }
  218. /// <summary>
  219. /// Add a new monster-kill to the party's records.
  220. /// </summary>
  221. public void AddMonsterKill(Monster monster)
  222. {
  223. if (monsterKills.ContainsKey(monster.AssetName))
  224. {
  225. monsterKills[monster.AssetName]++;
  226. }
  227. else
  228. {
  229. monsterKills.Add(monster.AssetName, 1);
  230. }
  231. }
  232. #endregion
  233. #region Initialization
  234. /// <summary>
  235. /// Creates a new Party object from the game-start description.
  236. /// </summary>
  237. public Party(GameStartDescription gameStartDescription,
  238. ContentManager contentManager)
  239. {
  240. // check the parameters
  241. if (gameStartDescription == null)
  242. {
  243. throw new ArgumentNullException("gameStartDescription");
  244. }
  245. if (contentManager == null)
  246. {
  247. throw new ArgumentNullException("contentManager");
  248. }
  249. // load the players
  250. foreach (string contentName in gameStartDescription.PlayerContentNames)
  251. {
  252. JoinParty(contentManager.Load<Player>(
  253. Path.Combine(@"Characters\Players", contentName)).Clone()
  254. as Player);
  255. }
  256. }
  257. /// <summary>
  258. /// Create a new Party object from serialized party data.
  259. /// </summary>
  260. public Party(PartySaveData partyData, ContentManager contentManager)
  261. {
  262. // check the parameters
  263. if (partyData == null)
  264. {
  265. throw new ArgumentNullException("partyData");
  266. }
  267. if (contentManager == null)
  268. {
  269. throw new ArgumentNullException("contentManager");
  270. }
  271. // load the players
  272. foreach (PlayerSaveData playerData in partyData.players)
  273. {
  274. Player player =
  275. contentManager.Load<Player>(playerData.assetName).Clone() as Player;
  276. player.CharacterLevel = playerData.characterLevel;
  277. player.Experience = playerData.experience;
  278. player.EquippedEquipment.Clear();
  279. foreach (string equipmentAssetName in playerData.equipmentAssetNames)
  280. {
  281. player.Equip(contentManager.Load<Equipment>(equipmentAssetName));
  282. }
  283. player.StatisticsModifiers = playerData.statisticsModifiers;
  284. JoinParty(player);
  285. }
  286. // load the party inventory
  287. inventory.Clear();
  288. inventory.AddRange(partyData.inventory);
  289. foreach (ContentEntry<Gear> entry in inventory)
  290. {
  291. entry.Content = contentManager.Load<Gear>(
  292. Path.Combine(@"Gear", entry.ContentName));
  293. }
  294. // set the party gold
  295. partyGold = partyData.partyGold;
  296. // load the monster kills
  297. for (int i = 0; i < partyData.monsterKillNames.Count; i++)
  298. {
  299. monsterKills.Add(partyData.monsterKillNames[i],
  300. partyData.monsterKillCounts[i]);
  301. }
  302. }
  303. #endregion
  304. }
  305. }