StoreBuyScreen.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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. namespace RolePlaying
  15. {
  16. /// <summary>
  17. /// Displays the gear from a particular store and allows the user to purchase them.
  18. /// </summary>
  19. class StoreBuyScreen : ListScreen<Gear>
  20. {
  21. /// <summary>
  22. /// The left-facing quantity arrow.
  23. /// </summary>
  24. private Texture2D leftQuantityArrow;
  25. /// <summary>
  26. /// The right-facing quantity arrow.
  27. /// </summary>
  28. private Texture2D rightQuantityArrow;
  29. private string nameColumnText = "Name";
  30. private const int nameColumnInterval = 80;
  31. private string powerColumnText = "Power (min, max)";
  32. private const int powerColumnInterval = 270;
  33. private string quantityColumnText = "Qty";
  34. private const int quantityColumnInterval = 340;
  35. private string priceColumnText = "Price";
  36. private const int priceColumnInterval = 120;
  37. /// <summary>
  38. /// The store whose goods are being displayed.
  39. /// </summary>
  40. private Store store;
  41. /// <summary>
  42. /// The index of the current StoreCategory.
  43. /// </summary>
  44. private int currentCategoryIndex = 0;
  45. /// <summary>
  46. /// Get the list that this screen displays.
  47. /// </summary>
  48. public override ReadOnlyCollection<Gear> GetDataList()
  49. {
  50. return
  51. store.StoreCategories[currentCategoryIndex].AvailableGear.AsReadOnly();
  52. }
  53. /// <summary>
  54. /// The selected quantity of the current entry.
  55. /// </summary>
  56. private int selectedQuantity = 0;
  57. /// <summary>
  58. /// The maximum quantity of the current entry.
  59. /// </summary>
  60. private int maximumQuantity = 0;
  61. /// <summary>
  62. /// Resets the selected quantity to the maximum value for the selected entry.
  63. /// </summary>
  64. private void ResetQuantities()
  65. {
  66. // check the indices before recalculating
  67. if ((currentCategoryIndex < 0) ||
  68. (currentCategoryIndex > store.StoreCategories.Count) ||
  69. (SelectedIndex < 0) || (SelectedIndex >=
  70. store.StoreCategories[currentCategoryIndex].AvailableGear.Count))
  71. {
  72. return;
  73. }
  74. // get the value of the selected gear
  75. Gear gear =
  76. store.StoreCategories[currentCategoryIndex].AvailableGear[SelectedIndex];
  77. if ((gear == null) || (gear.GoldValue <= 0))
  78. {
  79. selectedQuantity = maximumQuantity = 0;
  80. }
  81. selectedQuantity = 1;
  82. maximumQuantity = (int)Math.Floor(Session.Party.PartyGold /
  83. (gear.GoldValue * store.BuyMultiplier));
  84. }
  85. /// <summary>
  86. /// Move the current selection up one entry.
  87. /// </summary>
  88. protected override void MoveCursorUp()
  89. {
  90. int oldIndex = SelectedIndex;
  91. base.MoveCursorUp();
  92. if (SelectedIndex != oldIndex)
  93. {
  94. ResetQuantities();
  95. }
  96. }
  97. /// <summary>
  98. /// Move the current selection down one entry.
  99. /// </summary>
  100. protected override void MoveCursorDown()
  101. {
  102. int oldIndex = SelectedIndex;
  103. base.MoveCursorDown();
  104. if (SelectedIndex != oldIndex)
  105. {
  106. ResetQuantities();
  107. }
  108. }
  109. /// <summary>
  110. /// Decrease the selected quantity by one.
  111. /// </summary>
  112. protected override void MoveCursorLeft()
  113. {
  114. if (maximumQuantity > 0)
  115. {
  116. // decrement the quantity, looping around if necessary
  117. selectedQuantity = (selectedQuantity > 1) ?
  118. selectedQuantity - 1 : maximumQuantity;
  119. }
  120. }
  121. /// <summary>
  122. /// Increase the selected quantity by one.
  123. /// </summary>
  124. protected override void MoveCursorRight()
  125. {
  126. if (maximumQuantity > 0)
  127. {
  128. // loop to one if the selected quantity is already at maximum.
  129. selectedQuantity = selectedQuantity < maximumQuantity ?
  130. selectedQuantity + 1 : 1;
  131. }
  132. }
  133. /// <summary>
  134. /// Creates a new StoreBuyScreen object for the given store.
  135. /// </summary>
  136. public StoreBuyScreen(Store store)
  137. : base()
  138. {
  139. // check the parameter
  140. if ((store == null) || (store.StoreCategories.Count <= 0))
  141. {
  142. throw new ArgumentNullException("store");
  143. }
  144. this.store = store;
  145. // configure the menu text
  146. selectButtonText = "Purchase";
  147. backButtonText = "Back";
  148. xButtonText = String.Empty;
  149. yButtonText = String.Empty;
  150. ResetMenu();
  151. ResetQuantities();
  152. }
  153. /// <summary>
  154. /// Load the graphics content from the content manager.
  155. /// </summary>
  156. public override void LoadContent()
  157. {
  158. base.LoadContent();
  159. ContentManager content = ScreenManager.Game.Content;
  160. leftQuantityArrow =
  161. content.Load<Texture2D>(@"Textures\Buttons\QuantityArrowLeft");
  162. rightQuantityArrow =
  163. content.Load<Texture2D>(@"Textures\Buttons\QuantityArrowRight");
  164. }
  165. /// <summary>
  166. /// Respond to the triggering of the Select action.
  167. /// </summary>
  168. protected override void SelectTriggered(Gear entry)
  169. {
  170. if (entry == null)
  171. {
  172. return;
  173. }
  174. // purchase the items if possible
  175. int totalPrice = (int)Math.Floor(entry.GoldValue * selectedQuantity *
  176. store.BuyMultiplier);
  177. if (totalPrice <= Session.Party.PartyGold)
  178. {
  179. Session.Party.PartyGold -= totalPrice;
  180. Session.Party.AddToInventory(entry, selectedQuantity);
  181. }
  182. // reset the quantities - either gold has gone down or the total was bad
  183. ResetQuantities();
  184. }
  185. /// <summary>
  186. /// Switch to the previous store category.
  187. /// </summary>
  188. protected override void PageScreenLeft()
  189. {
  190. currentCategoryIndex--;
  191. if (currentCategoryIndex < 0)
  192. {
  193. currentCategoryIndex = store.StoreCategories.Count - 1;
  194. }
  195. ResetMenu();
  196. ResetQuantities();
  197. }
  198. /// <summary>
  199. /// Switch to the next store category.
  200. /// </summary>
  201. protected override void PageScreenRight()
  202. {
  203. currentCategoryIndex++;
  204. if (currentCategoryIndex >= store.StoreCategories.Count)
  205. {
  206. currentCategoryIndex = 0;
  207. }
  208. ResetMenu();
  209. ResetQuantities();
  210. }
  211. /// <summary>
  212. /// Reset the menu title and trigger button text for the current store category.
  213. /// </summary>
  214. private void ResetMenu()
  215. {
  216. // update the title the title
  217. titleText = store.StoreCategories[currentCategoryIndex].Name;
  218. // get the left trigger text
  219. int index = currentCategoryIndex - 1;
  220. if (index < 0)
  221. {
  222. index = store.StoreCategories.Count - 1;
  223. }
  224. leftTriggerText = store.StoreCategories[index].Name;
  225. // get the right trigger text
  226. index = currentCategoryIndex + 1;
  227. if (index >= store.StoreCategories.Count)
  228. {
  229. index = 0;
  230. }
  231. rightTriggerText = store.StoreCategories[index].Name;
  232. }
  233. /// <summary>
  234. /// Draw the entry at the given position in the list.
  235. /// </summary>
  236. /// <param name="contentEntry">The entry to draw.</param>
  237. /// <param name="position">The position to draw the entry at.</param>
  238. /// <param name="isSelected">If true, this item is selected.</param>
  239. protected override void DrawEntry(Gear entry, Vector2 position,
  240. bool isSelected)
  241. {
  242. // check the parameter
  243. if (entry == null)
  244. {
  245. throw new ArgumentNullException("entry");
  246. }
  247. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  248. Vector2 drawPosition = position;
  249. // draw the icon
  250. spriteBatch.Draw(entry.IconTexture, drawPosition + iconOffset, Color.White);
  251. // draw the name
  252. Color color = isSelected ? Fonts.HighlightColor : Fonts.DisplayColor;
  253. drawPosition.Y += listLineSpacing / 4;
  254. drawPosition.X += nameColumnInterval;
  255. spriteBatch.DrawString(Fonts.GearInfoFont, entry.Name, drawPosition, color);
  256. // draw the power
  257. drawPosition.X += powerColumnInterval;
  258. string powerText = entry.GetPowerText();
  259. Vector2 powerTextSize = Fonts.GearInfoFont.MeasureString(powerText);
  260. Vector2 powerPosition = drawPosition;
  261. powerPosition.Y -= (float)Math.Ceiling((powerTextSize.Y - 30f) / 2);
  262. spriteBatch.DrawString(Fonts.GearInfoFont, powerText,
  263. powerPosition, color);
  264. // draw the quantity
  265. drawPosition.X += quantityColumnInterval;
  266. int priceSingle = (int)Math.Floor(entry.GoldValue * store.BuyMultiplier);
  267. if (isSelected)
  268. {
  269. if (priceSingle <= Session.Party.PartyGold)
  270. {
  271. Vector2 quantityPosition = drawPosition;
  272. // draw the left selection arrow
  273. quantityPosition.X -= leftQuantityArrow.Width;
  274. spriteBatch.Draw(leftQuantityArrow,
  275. new Vector2(quantityPosition.X, quantityPosition.Y - 4),
  276. Color.White);
  277. quantityPosition.X += leftQuantityArrow.Width;
  278. // draw the selected quantity ratio
  279. string quantityText = selectedQuantity.ToString() + "/" +
  280. maximumQuantity.ToString();
  281. spriteBatch.DrawString(Fonts.GearInfoFont, quantityText,
  282. quantityPosition, color);
  283. quantityPosition.X +=
  284. Fonts.GearInfoFont.MeasureString(quantityText).X;
  285. // draw the right selection arrow
  286. spriteBatch.Draw(rightQuantityArrow,
  287. new Vector2(quantityPosition.X, quantityPosition.Y - 4),
  288. Color.White);
  289. quantityPosition.X += rightQuantityArrow.Width;
  290. // draw the purchase button
  291. selectButtonText = "Purchase";
  292. }
  293. else
  294. {
  295. // turn off the purchase button
  296. selectButtonText = String.Empty;
  297. }
  298. }
  299. // draw the price
  300. drawPosition.X += priceColumnInterval;
  301. string priceText = String.Empty;
  302. if (isSelected)
  303. {
  304. int totalPrice = (int)Math.Floor(entry.GoldValue * store.BuyMultiplier) *
  305. selectedQuantity;
  306. priceText = totalPrice.ToString();
  307. }
  308. else
  309. {
  310. priceText = ((int)Math.Floor(entry.GoldValue *
  311. store.BuyMultiplier)).ToString();
  312. }
  313. spriteBatch.DrawString(Fonts.GearInfoFont, priceText,
  314. 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. }