#region File Description
//-----------------------------------------------------------------------------
// ChestScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using RolePlayingGameData;
#endregion
namespace RolePlaying
{
class ChestScreen : InventoryScreen
{
#region Graphics Data
///
/// The left-facing quantity arrow.
///
private Texture2D leftQuantityArrow;
///
/// The right-facing quantity arrow.
///
private Texture2D rightQuantityArrow;
#endregion
#region Columns
private const int nameColumnInterval = 80;
private const int powerColumnInterval = 270;
private const int quantityColumnInterval = 450;
#endregion
#region Data Access
///
/// The chest entry that is displayed here.
///
private MapEntry chestEntry;
///
/// Retrieve the list of gear shown in this menu.
///
///
public override ReadOnlyCollection> GetDataList()
{
if ((chestEntry == null) || (chestEntry.Content == null))
{
return null;
}
return chestEntry.Content.Entries.AsReadOnly();
}
///
/// The selected quantity of the current entry.
///
private int selectedQuantity = 0;
///
/// Resets the selected quantity to the maximum value for the selected entry.
///
private void ResetSelectedQuantity()
{
// safety-check on the chest
if ((chestEntry == null) || (chestEntry.Content == null))
{
selectedQuantity = 0;
return;
}
// set the quantity to the maximum
if (IsGoldSelected)
{
selectedQuantity = chestEntry.Content.Gold;
}
else if ((SelectedGearIndex >= 0) &&
(SelectedGearIndex < chestEntry.Content.Entries.Count))
{
selectedQuantity = chestEntry.Content[SelectedGearIndex].Count;
}
}
#endregion
#region List Navigation
///
/// If true, the phantom ContentEntry for the chest's gold is selected
///
public bool IsGoldSelected
{
get
{
return ((chestEntry != null) && (chestEntry.Content != null) &&
(chestEntry.Content.Gold > 0) && (SelectedIndex == 0));
}
}
///
/// Retrieve the zero-based selection of the gear in the chestEntry.Content.
///
///
/// If there is gold in the chestEntry.Content, its phantom ContentEntry shifts
/// ListScreen.SelectedIndex by one. If IsGoldSelected is true, this property
/// return -1.
///
public int SelectedGearIndex
{
get
{
return ((chestEntry != null) && (chestEntry.Content != null) &&
(chestEntry.Content.Gold > 0)) ? SelectedIndex - 1 : SelectedIndex;
}
}
///
/// Move the current selection up one entry.
///
protected override void MoveCursorUp()
{
base.MoveCursorUp();
ResetSelectedQuantity();
}
///
/// Move the current selection down one entry.
///
protected override void MoveCursorDown()
{
base.MoveCursorDown();
ResetSelectedQuantity();
}
///
/// Decrease the selected quantity by one.
///
protected override void MoveCursorLeft()
{
// decrement the quantity, looping around if necessary
if (selectedQuantity > 0)
{
selectedQuantity--;
}
else if (IsGoldSelected)
{
selectedQuantity = chestEntry.Content.Gold;
}
else if (SelectedGearIndex < chestEntry.Content.Entries.Count)
{
selectedQuantity = chestEntry.Content[SelectedGearIndex].Count;
}
}
///
/// Increase the selected quantity by one.
///
protected override void MoveCursorRight()
{
int maximumQuantity = 0;
// get the maximum quantity for the selected entry
if (IsGoldSelected)
{
maximumQuantity = chestEntry.Content.Gold;
}
else if (SelectedGearIndex < chestEntry.Content.Entries.Count)
{
maximumQuantity = chestEntry.Content[SelectedGearIndex].Count;
}
else
{
return;
}
// loop to zero if the selected quantity is already at maximum.
selectedQuantity = selectedQuantity < maximumQuantity ?
selectedQuantity + 1 : 0;
}
#endregion
#region Initialization
///
/// Creates a new ChestScreen object.
///
/// The chest entry shown in the screen
public ChestScreen(MapEntry chestEntry)
: base(true)
{
// check the parameter
if ((chestEntry == null) || (chestEntry.Content == null))
{
throw new ArgumentNullException("chestEntry.Content");
}
this.chestEntry = chestEntry;
// clean up any empty entries
this.chestEntry.Content.Entries.RemoveAll(
delegate(ContentEntry contentEntry)
{
return (contentEntry.Count <= 0);
});
// sort the chest entries by name
this.chestEntry.Content.Entries.Sort(
delegate(ContentEntry gearEntry1, ContentEntry gearEntry2)
{
// handle null values
if ((gearEntry1 == null) || (gearEntry1.Content == null))
{
return ((gearEntry2 == null) || (gearEntry2.Content == null) ?
0 : 1);
}
else if ((gearEntry2 == null) || (gearEntry2.Content == null))
{
return -1;
}
// sort by name
return gearEntry1.Content.Name.CompareTo(gearEntry2.Content.Name);
});
// set up the initial selected-quantity values
ResetSelectedQuantity();
// configure the menu strings
titleText = chestEntry.Content.Name;
selectButtonText = "Take";
backButtonText = "Close";
xButtonText = String.Empty;
yButtonText = "Take All";
leftTriggerText = String.Empty;
rightTriggerText = String.Empty;
}
///
/// Load the graphics content from the content manager.
///
public override void LoadContent()
{
base.LoadContent();
ContentManager content = ScreenManager.Game.Content;
leftQuantityArrow =
content.Load(@"Textures\Buttons\QuantityArrowLeft");
rightQuantityArrow =
content.Load(@"Textures\Buttons\QuantityArrowRight");
}
#endregion
#region Input Handling
///
/// Allows the screen to handle user input.
///
public override void HandleInput()
{
// if the chestEntry.Content is empty, exit immediately
if (chestEntry.Content.IsEmpty)
{
BackTriggered();
return;
}
if (InputManager.IsActionTriggered(InputManager.Action.CursorUp))
{
MoveCursorUp();
}
else if (InputManager.IsActionTriggered(InputManager.Action.CursorDown))
{
MoveCursorDown();
}
else if (InputManager.IsActionTriggered(InputManager.Action.IncreaseAmount))
{
MoveCursorRight();
}
else if (InputManager.IsActionTriggered(InputManager.Action.DecreaseAmount))
{
MoveCursorLeft();
}
// Close is pressed
else if (InputManager.IsActionTriggered(InputManager.Action.Back))
{
BackTriggered();
}
// Take is pressed
else if (InputManager.IsActionTriggered(InputManager.Action.Ok))
{
if (IsGoldSelected)
{
SelectTriggered(null);
}
else
{
ReadOnlyCollection> dataList = GetDataList();
SelectTriggered(dataList[SelectedGearIndex]);
}
}
// Take All is pressed
else if (InputManager.IsActionTriggered(InputManager.Action.TakeView))
{
ButtonYPressed(null); // take-all doesn't need an entry
}
}
///
/// Respond to the triggering of the Back action.
///
protected override void BackTriggered()
{
// clean up any empty entries
chestEntry.Content.Entries.RemoveAll(
delegate(ContentEntry contentEntry)
{
return (contentEntry.Count <= 0);
});
// if the chestEntry.Content is empty, remove it from the game and exit
if (chestEntry.Content.IsEmpty)
{
Session.RemoveChest(chestEntry);
}
else
{
// otherwise, store the modified chestEntry.Content
Session.StoreModifiedChest(chestEntry);
}
// exit the screen
base.BackTriggered();
}
///
/// Respond to the triggering of the Select action.
///
protected override void SelectTriggered(ContentEntry entry)
{
// if the quantity is zero, don't bother
if (selectedQuantity <= 0)
{
return;
}
// check to see if gold is selected
if (IsGoldSelected)
{
// play the "pick up gold" cue
AudioManager.PlayCue("Money");
// add the gold to the party
Session.Party.PartyGold += selectedQuantity;
chestEntry.Content.Gold -= selectedQuantity;
if (chestEntry.Content.Gold > 0)
{
selectedQuantity =
Math.Min(selectedQuantity, chestEntry.Content.Gold);
}
else
{
ResetSelectedQuantity();
}
}
else
{
// remove the selected quantity of gear from the chest
int quantity = selectedQuantity;
if ((entry.Content != null) && (quantity > 0))
{
Session.Party.AddToInventory(entry.Content, quantity);
entry.Count -= quantity;
}
if (entry.Count > 0)
{
selectedQuantity = Math.Min(entry.Count, selectedQuantity);
}
else
{
// if the entry is now empty, remove it from the chest
chestEntry.Content.Entries.RemoveAt(SelectedGearIndex);
ResetSelectedQuantity();
}
}
}
///
/// Respond to the triggering of the Y button (and related key).
///
protected override void ButtonYPressed(ContentEntry entry)
{
// add the entire amount of gold
if (chestEntry.Content.Gold > 0)
{
AudioManager.PlayCue("Money");
Session.Party.PartyGold += chestEntry.Content.Gold;
chestEntry.Content.Gold = 0;
}
// add all items at full quantity
// -- there is no limit to the party's inventory
ReadOnlyCollection> entries = GetDataList();
foreach (ContentEntry gearEntry in entries)
{
Session.Party.AddToInventory(gearEntry.Content, gearEntry.Count);
}
// clear the entries, as they're all gone now
chestEntry.Content.Entries.Clear();
selectedQuantity = 0;
}
#endregion
#region Drawing
///
/// Draws the screen.
///
public override void Draw(Microsoft.Xna.Framework.GameTime gameTime)
{
SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
// get the content list
ReadOnlyCollection> dataList = GetDataList();
// fix the indices for the current list size
int maximumCount = chestEntry.Content.Gold > 0 ? dataList.Count + 1 :
dataList.Count;
SelectedIndex = (int)MathHelper.Clamp(SelectedIndex, 0, maximumCount - 1);
StartIndex = (int)MathHelper.Clamp(StartIndex, 0,
maximumCount - MaximumListEntries);
EndIndex = Math.Min(StartIndex + MaximumListEntries, maximumCount);
spriteBatch.Begin();
DrawBackground();
if (dataList.Count > 0)
{
DrawListPosition(SelectedIndex + 1, maximumCount);
}
DrawButtons();
DrawPartyGold();
DrawColumnHeaders();
DrawTitle();
// draw each item currently shown
Vector2 position = listEntryStartPosition +
new Vector2(0f, listLineSpacing / 2);
for (int index = StartIndex; index < EndIndex; index++)
{
if ((index == 0) && (chestEntry.Content.Gold > 0))
{
if (index == SelectedIndex)
{
DrawSelection(position);
DrawGoldEntry(position, true);
}
else
{
DrawGoldEntry(position, false);
}
}
else
{
int currentIndex = chestEntry.Content.Gold > 0 ? index - 1 : index;
ContentEntry entry = dataList[currentIndex];
if (index == SelectedIndex)
{
DrawSelection(position);
DrawEntry(entry, position, true);
DrawSelectedDescription(entry);
}
else
{
DrawEntry(entry, position, false);
}
}
position.Y += listLineSpacing;
}
spriteBatch.End();
}
///
/// Draw the chest's gold at the given position in the list.
///
/// The position to draw the gold at.
/// If true, the gold is selected.
protected virtual void DrawGoldEntry(Vector2 position, bool isSelected)
{
SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
Vector2 drawPosition = position;
// draw the icon
spriteBatch.Draw(goldTexture,
drawPosition + iconOffset + new Vector2(0f, 7f), Color.White);
// draw the name
Color color = isSelected ? Fonts.HighlightColor : Fonts.DisplayColor;
drawPosition.Y += listLineSpacing / 4;
drawPosition.X += nameColumnInterval;
spriteBatch.DrawString(Fonts.GearInfoFont, "Gold", drawPosition, color);
// skip the power text
drawPosition.X += powerColumnInterval;
// draw the quantity
drawPosition.X += quantityColumnInterval;
if (isSelected)
{
// draw the left selection arrow
drawPosition.X -= leftQuantityArrow.Width;
spriteBatch.Draw(leftQuantityArrow,
new Vector2(drawPosition.X, drawPosition.Y - 4), Color.White);
drawPosition.X += leftQuantityArrow.Width;
// draw the selected quantity ratio
string quantityText = selectedQuantity.ToString() + "/" +
chestEntry.Content.Gold.ToString();
spriteBatch.DrawString(Fonts.GearInfoFont, quantityText,
drawPosition, color);
drawPosition.X += Fonts.GearInfoFont.MeasureString(quantityText).X;
// draw the right selection arrow
spriteBatch.Draw(rightQuantityArrow,
new Vector2(drawPosition.X, drawPosition.Y - 4), Color.White);
drawPosition.X += rightQuantityArrow.Width;
}
else
{
// draw the remaining quantity
spriteBatch.DrawString(Fonts.GearInfoFont,
chestEntry.Content.Gold.ToString(), drawPosition, color);
}
}
///
/// Draw the gear's content entry at the given position in the list.
///
/// The content entry to draw.
/// The position to draw the entry at.
/// If true, this item is selected.
protected override void DrawEntry(ContentEntry entry, Vector2 position,
bool isSelected)
{
// check the parameter
if (entry == null)
{
throw new ArgumentNullException("entry");
}
Gear gear = entry.Content as Gear;
if (gear == null)
{
return;
}
SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
Vector2 drawPosition = position;
// draw the icon
spriteBatch.Draw(gear.IconTexture, drawPosition + iconOffset, Color.White);
// draw the name
Color color = isSelected ? Fonts.HighlightColor : Fonts.DisplayColor;
drawPosition.Y += listLineSpacing / 4;
drawPosition.X += nameColumnInterval;
spriteBatch.DrawString(Fonts.GearInfoFont, gear.Name, drawPosition, color);
// draw the power
drawPosition.X += powerColumnInterval;
string powerText = gear.GetPowerText();
Vector2 powerTextSize = Fonts.GearInfoFont.MeasureString(powerText);
Vector2 powerPosition = drawPosition;
powerPosition.Y -= (float)Math.Ceiling((powerTextSize.Y - 30f) / 2);
spriteBatch.DrawString(Fonts.GearInfoFont, powerText,
powerPosition, color);
// draw the quantity
drawPosition.X += quantityColumnInterval;
if (isSelected)
{
// draw the left selection arrow
drawPosition.X -= leftQuantityArrow.Width;
spriteBatch.Draw(leftQuantityArrow,
new Vector2(drawPosition.X, drawPosition.Y - 4), Color.White);
drawPosition.X += leftQuantityArrow.Width;
// draw the selected quantity ratio
string quantityText = selectedQuantity.ToString() + "/" +
entry.Count.ToString();
spriteBatch.DrawString(Fonts.GearInfoFont, quantityText,
drawPosition, color);
drawPosition.X += Fonts.GearInfoFont.MeasureString(quantityText).X;
// draw the right selection arrow
spriteBatch.Draw(rightQuantityArrow,
new Vector2(drawPosition.X, drawPosition.Y - 4), Color.White);
drawPosition.X += rightQuantityArrow.Width;
}
else
{
// draw the remaining quantity
spriteBatch.DrawString(Fonts.GearInfoFont, entry.Count.ToString(),
drawPosition, color);
}
}
#endregion
}
}