StoreBuyScreen.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // StoreBuyScreen.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 Microsoft.Xna.Framework;
  14. using Microsoft.Xna.Framework.Graphics;
  15. using Microsoft.Xna.Framework.Content;
  16. using RolePlayingGameData;
  17. #endregion
  18. namespace RolePlaying
  19. {
  20. /// <summary>
  21. /// Displays the gear from a particular store and allows the user to purchase them.
  22. /// </summary>
  23. class StoreBuyScreen : ListScreen<Gear>
  24. {
  25. #region Graphics Data
  26. /// <summary>
  27. /// The left-facing quantity arrow.
  28. /// </summary>
  29. private Texture2D leftQuantityArrow;
  30. /// <summary>
  31. /// The right-facing quantity arrow.
  32. /// </summary>
  33. private Texture2D rightQuantityArrow;
  34. #endregion
  35. #region Columns
  36. private string nameColumnText = "Name";
  37. private const int nameColumnInterval = 80;
  38. private string powerColumnText = "Power (min, max)";
  39. private const int powerColumnInterval = 270;
  40. private string quantityColumnText = "Qty";
  41. private const int quantityColumnInterval = 340;
  42. private string priceColumnText = "Price";
  43. private const int priceColumnInterval = 120;
  44. #endregion
  45. #region Data Access
  46. /// <summary>
  47. /// The store whose goods are being displayed.
  48. /// </summary>
  49. private Store store;
  50. /// <summary>
  51. /// The index of the current StoreCategory.
  52. /// </summary>
  53. private int currentCategoryIndex = 0;
  54. /// <summary>
  55. /// Get the list that this screen displays.
  56. /// </summary>
  57. public override ReadOnlyCollection<Gear> GetDataList()
  58. {
  59. return
  60. store.StoreCategories[currentCategoryIndex].AvailableGear.AsReadOnly();
  61. }
  62. /// <summary>
  63. /// The selected quantity of the current entry.
  64. /// </summary>
  65. private int selectedQuantity = 0;
  66. /// <summary>
  67. /// The maximum quantity of the current entry.
  68. /// </summary>
  69. private int maximumQuantity = 0;
  70. /// <summary>
  71. /// Resets the selected quantity to the maximum value for the selected entry.
  72. /// </summary>
  73. private void ResetQuantities()
  74. {
  75. // check the indices before recalculating
  76. if ((currentCategoryIndex < 0) ||
  77. (currentCategoryIndex > store.StoreCategories.Count) ||
  78. (SelectedIndex < 0) || (SelectedIndex >=
  79. store.StoreCategories[currentCategoryIndex].AvailableGear.Count))
  80. {
  81. return;
  82. }
  83. // get the value of the selected gear
  84. Gear gear =
  85. store.StoreCategories[currentCategoryIndex].AvailableGear[SelectedIndex];
  86. if ((gear == null) || (gear.GoldValue <= 0))
  87. {
  88. selectedQuantity = maximumQuantity = 0;
  89. }
  90. selectedQuantity = 1;
  91. maximumQuantity = (int)Math.Floor(Session.Party.PartyGold /
  92. (gear.GoldValue * store.BuyMultiplier));
  93. }
  94. #endregion
  95. #region List Navigation
  96. /// <summary>
  97. /// Move the current selection up one entry.
  98. /// </summary>
  99. protected override void MoveCursorUp()
  100. {
  101. int oldIndex = SelectedIndex;
  102. base.MoveCursorUp();
  103. if (SelectedIndex != oldIndex)
  104. {
  105. ResetQuantities();
  106. }
  107. }
  108. /// <summary>
  109. /// Move the current selection down one entry.
  110. /// </summary>
  111. protected override void MoveCursorDown()
  112. {
  113. int oldIndex = SelectedIndex;
  114. base.MoveCursorDown();
  115. if (SelectedIndex != oldIndex)
  116. {
  117. ResetQuantities();
  118. }
  119. }
  120. /// <summary>
  121. /// Decrease the selected quantity by one.
  122. /// </summary>
  123. protected override void MoveCursorLeft()
  124. {
  125. if (maximumQuantity > 0)
  126. {
  127. // decrement the quantity, looping around if necessary
  128. selectedQuantity = (selectedQuantity > 1) ?
  129. selectedQuantity - 1 : maximumQuantity;
  130. }
  131. }
  132. /// <summary>
  133. /// Increase the selected quantity by one.
  134. /// </summary>
  135. protected override void MoveCursorRight()
  136. {
  137. if (maximumQuantity > 0)
  138. {
  139. // loop to one if the selected quantity is already at maximum.
  140. selectedQuantity = selectedQuantity < maximumQuantity ?
  141. selectedQuantity + 1 : 1;
  142. }
  143. }
  144. #endregion
  145. #region Initialization
  146. /// <summary>
  147. /// Creates a new StoreBuyScreen object for the given store.
  148. /// </summary>
  149. public StoreBuyScreen(Store store)
  150. : base()
  151. {
  152. // check the parameter
  153. if ((store == null) || (store.StoreCategories.Count <= 0))
  154. {
  155. throw new ArgumentNullException("store");
  156. }
  157. this.store = store;
  158. // configure the menu text
  159. selectButtonText = "Purchase";
  160. backButtonText = "Back";
  161. xButtonText = String.Empty;
  162. yButtonText = String.Empty;
  163. ResetMenu();
  164. ResetQuantities();
  165. }
  166. /// <summary>
  167. /// Load the graphics content from the content manager.
  168. /// </summary>
  169. public override void LoadContent()
  170. {
  171. base.LoadContent();
  172. ContentManager content = ScreenManager.Game.Content;
  173. leftQuantityArrow =
  174. content.Load<Texture2D>(@"Textures\Buttons\QuantityArrowLeft");
  175. rightQuantityArrow =
  176. content.Load<Texture2D>(@"Textures\Buttons\QuantityArrowRight");
  177. }
  178. #endregion
  179. #region Input Handling
  180. /// <summary>
  181. /// Respond to the triggering of the Select action.
  182. /// </summary>
  183. protected override void SelectTriggered(Gear entry)
  184. {
  185. if (entry == null)
  186. {
  187. return;
  188. }
  189. // purchase the items if possible
  190. int totalPrice = (int)Math.Floor(entry.GoldValue * selectedQuantity *
  191. store.BuyMultiplier);
  192. if (totalPrice <= Session.Party.PartyGold)
  193. {
  194. Session.Party.PartyGold -= totalPrice;
  195. Session.Party.AddToInventory(entry, selectedQuantity);
  196. }
  197. // reset the quantities - either gold has gone down or the total was bad
  198. ResetQuantities();
  199. }
  200. /// <summary>
  201. /// Switch to the previous store category.
  202. /// </summary>
  203. protected override void PageScreenLeft()
  204. {
  205. currentCategoryIndex--;
  206. if (currentCategoryIndex < 0)
  207. {
  208. currentCategoryIndex = store.StoreCategories.Count - 1;
  209. }
  210. ResetMenu();
  211. ResetQuantities();
  212. }
  213. /// <summary>
  214. /// Switch to the next store category.
  215. /// </summary>
  216. protected override void PageScreenRight()
  217. {
  218. currentCategoryIndex++;
  219. if (currentCategoryIndex >= store.StoreCategories.Count)
  220. {
  221. currentCategoryIndex = 0;
  222. }
  223. ResetMenu();
  224. ResetQuantities();
  225. }
  226. /// <summary>
  227. /// Reset the menu title and trigger button text for the current store category.
  228. /// </summary>
  229. private void ResetMenu()
  230. {
  231. // update the title the title
  232. titleText = store.StoreCategories[currentCategoryIndex].Name;
  233. // get the left trigger text
  234. int index = currentCategoryIndex - 1;
  235. if (index < 0)
  236. {
  237. index = store.StoreCategories.Count - 1;
  238. }
  239. leftTriggerText = store.StoreCategories[index].Name;
  240. // get the right trigger text
  241. index = currentCategoryIndex + 1;
  242. if (index >= store.StoreCategories.Count)
  243. {
  244. index = 0;
  245. }
  246. rightTriggerText = store.StoreCategories[index].Name;
  247. }
  248. #endregion
  249. #region Drawing
  250. /// <summary>
  251. /// Draw the entry at the given position in the list.
  252. /// </summary>
  253. /// <param name="contentEntry">The entry to draw.</param>
  254. /// <param name="position">The position to draw the entry at.</param>
  255. /// <param name="isSelected">If true, this item is selected.</param>
  256. protected override void DrawEntry(Gear entry, Vector2 position,
  257. bool isSelected)
  258. {
  259. // check the parameter
  260. if (entry == null)
  261. {
  262. throw new ArgumentNullException("entry");
  263. }
  264. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  265. Vector2 drawPosition = position;
  266. // draw the icon
  267. spriteBatch.Draw(entry.IconTexture, drawPosition + iconOffset, Color.White);
  268. // draw the name
  269. Color color = isSelected ? Fonts.HighlightColor : Fonts.DisplayColor;
  270. drawPosition.Y += listLineSpacing / 4;
  271. drawPosition.X += nameColumnInterval;
  272. spriteBatch.DrawString(Fonts.GearInfoFont, entry.Name, drawPosition, color);
  273. // draw the power
  274. drawPosition.X += powerColumnInterval;
  275. string powerText = entry.GetPowerText();
  276. Vector2 powerTextSize = Fonts.GearInfoFont.MeasureString(powerText);
  277. Vector2 powerPosition = drawPosition;
  278. powerPosition.Y -= (float)Math.Ceiling((powerTextSize.Y - 30f) / 2);
  279. spriteBatch.DrawString(Fonts.GearInfoFont, powerText,
  280. powerPosition, color);
  281. // draw the quantity
  282. drawPosition.X += quantityColumnInterval;
  283. int priceSingle = (int)Math.Floor(entry.GoldValue * store.BuyMultiplier);
  284. if (isSelected)
  285. {
  286. if (priceSingle <= Session.Party.PartyGold)
  287. {
  288. Vector2 quantityPosition = drawPosition;
  289. // draw the left selection arrow
  290. quantityPosition.X -= leftQuantityArrow.Width;
  291. spriteBatch.Draw(leftQuantityArrow,
  292. new Vector2(quantityPosition.X, quantityPosition.Y - 4),
  293. Color.White);
  294. quantityPosition.X += leftQuantityArrow.Width;
  295. // draw the selected quantity ratio
  296. string quantityText = selectedQuantity.ToString() + "/" +
  297. maximumQuantity.ToString();
  298. spriteBatch.DrawString(Fonts.GearInfoFont, quantityText,
  299. quantityPosition, color);
  300. quantityPosition.X +=
  301. Fonts.GearInfoFont.MeasureString(quantityText).X;
  302. // draw the right selection arrow
  303. spriteBatch.Draw(rightQuantityArrow,
  304. new Vector2(quantityPosition.X, quantityPosition.Y - 4),
  305. Color.White);
  306. quantityPosition.X += rightQuantityArrow.Width;
  307. // draw the purchase button
  308. selectButtonText = "Purchase";
  309. }
  310. else
  311. {
  312. // turn off the purchase button
  313. selectButtonText = String.Empty;
  314. }
  315. }
  316. // draw the price
  317. drawPosition.X += priceColumnInterval;
  318. string priceText = String.Empty;
  319. if (isSelected)
  320. {
  321. int totalPrice = (int)Math.Floor(entry.GoldValue * store.BuyMultiplier) *
  322. selectedQuantity;
  323. priceText = totalPrice.ToString();
  324. }
  325. else
  326. {
  327. priceText = ((int)Math.Floor(entry.GoldValue *
  328. store.BuyMultiplier)).ToString();
  329. }
  330. spriteBatch.DrawString(Fonts.GearInfoFont, priceText,
  331. drawPosition, color);
  332. }
  333. /// <summary>
  334. /// Draw the description of the selected item.
  335. /// </summary>
  336. protected override void DrawSelectedDescription(Gear entry)
  337. {
  338. // check the parameter
  339. if (entry == null)
  340. {
  341. throw new ArgumentNullException("entry");
  342. }
  343. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  344. Vector2 position = descriptionTextPosition;
  345. // draw the description
  346. // -- it's up to the content owner to fit the description
  347. string text = entry.Description;
  348. if (!String.IsNullOrEmpty(text))
  349. {
  350. spriteBatch.DrawString(Fonts.DescriptionFont, text, position,
  351. Fonts.DescriptionColor);
  352. position.Y += Fonts.DescriptionFont.LineSpacing;
  353. }
  354. // draw the modifiers
  355. Equipment equipment = entry as Equipment;
  356. if (equipment != null)
  357. {
  358. text = equipment.OwnerBuffStatistics.GetModifierString();
  359. if (!String.IsNullOrEmpty(text))
  360. {
  361. spriteBatch.DrawString(Fonts.DescriptionFont, text, position,
  362. Fonts.DescriptionColor);
  363. position.Y += Fonts.DescriptionFont.LineSpacing;
  364. }
  365. }
  366. // draw the restrictions
  367. text = entry.GetRestrictionsText();
  368. if (!String.IsNullOrEmpty(text))
  369. {
  370. spriteBatch.DrawString(Fonts.DescriptionFont, text, position,
  371. Fonts.DescriptionColor);
  372. position.Y += Fonts.DescriptionFont.LineSpacing;
  373. }
  374. }
  375. /// <summary>
  376. /// Draw the column headers above the list.
  377. /// </summary>
  378. protected override void DrawColumnHeaders()
  379. {
  380. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  381. Vector2 position = listEntryStartPosition;
  382. position.X += nameColumnInterval;
  383. if (!String.IsNullOrEmpty(nameColumnText))
  384. {
  385. spriteBatch.DrawString(Fonts.CaptionFont, nameColumnText, position,
  386. Fonts.CaptionColor);
  387. }
  388. position.X += powerColumnInterval;
  389. if (!String.IsNullOrEmpty(powerColumnText))
  390. {
  391. spriteBatch.DrawString(Fonts.CaptionFont, powerColumnText, position,
  392. Fonts.CaptionColor);
  393. }
  394. position.X += quantityColumnInterval;
  395. if (!String.IsNullOrEmpty(quantityColumnText))
  396. {
  397. spriteBatch.DrawString(Fonts.CaptionFont, quantityColumnText, position,
  398. Fonts.CaptionColor);
  399. }
  400. position.X += priceColumnInterval;
  401. if (!String.IsNullOrEmpty(priceColumnText))
  402. {
  403. spriteBatch.DrawString(Fonts.CaptionFont, priceColumnText, position,
  404. Fonts.CaptionColor);
  405. }
  406. }
  407. #endregion
  408. }
  409. }