2
0

StoreBuyScreen.cs 15 KB

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