#region File Description
//-----------------------------------------------------------------------------
// SpellbookScreen.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
{
///
/// Lists the spells available to the character.
///
class SpellbookScreen : ListScreen
{
#region Graphics Data
private readonly Vector2 spellDescriptionPosition = new Vector2(200, 550);
private readonly Vector2 warningMessagePosition = new Vector2(200, 580);
#endregion
#region Columns
private string nameColumnText = "Name";
private const int nameColumnInterval = 80;
private string levelColumnText = "Level";
private const int levelColumnInterval = 240;
private string powerColumnText = "Power (min, max)";
private const int powerColumnInterval = 110;
private string magicCostColumnText = "MP";
private const int magicCostColumnInterval = 380;
#endregion
#region Data Access
///
/// The FightingCharacter object whose spells are displayed.
///
private FightingCharacter fightingCharacter;
///
/// The statistics of the character, for calculating the eligibility of spells.
///
///
/// Needed because combat statistics override character statistics.
///
private StatisticsValue statistics;
///
/// Get the list that this screen displays.
///
public override ReadOnlyCollection GetDataList()
{
return fightingCharacter.Spells.AsReadOnly();
}
#endregion
#region Initialization
///
/// Creates a new SpellbookScreen object for the given player and statistics.
///
public SpellbookScreen(FightingCharacter fightingCharacter,
StatisticsValue statistics)
: base()
{
// check the parameter
if (fightingCharacter == null)
{
throw new ArgumentNullException("fightingCharacter");
}
this.fightingCharacter = fightingCharacter;
this.statistics = statistics;
// sort the player's spell
this.fightingCharacter.Spells.Sort(
delegate(Spell spell1, Spell spell2)
{
// handle null values
if (spell1 == null)
{
return (spell2 == null ? 0 : 1);
}
else if (spell2 == null)
{
return -1;
}
// sort by name
return spell1.Name.CompareTo(spell2.Name);
});
// configure the menu text
titleText = "Spell Book";
selectButtonText = "Cast";
backButtonText = "Back";
xButtonText = String.Empty;
yButtonText = String.Empty;
leftTriggerText = String.Empty;
rightTriggerText = String.Empty;
}
#endregion
#region Input Handling
///
/// Delegate for spell-selection events.
///
public delegate void SpellSelectedHandler(Spell spell);
///
/// Responds when an spell is selected by this menu.
///
///
/// Typically used by the calling menu, like the combat HUD menu,
/// to respond to selection.
///
public event SpellSelectedHandler SpellSelected;
///
/// Respond to the triggering of the Select action (and related key).
///
protected override void SelectTriggered(Spell entry)
{
// check the parameter
if (entry == null)
{
return;
}
// make sure the spell can be selected
if (!CanSelectEntry(entry))
{
return;
}
// if the event is valid, fire it and exit this screen
if (SpellSelected != null)
{
SpellSelected(entry);
ExitScreen();
return;
}
}
///
/// Returns true if the specified spell can be selected.
///
private bool CanSelectEntry(Spell entry)
{
if (entry == null)
{
return false;
}
return (statistics.MagicPoints >= entry.MagicPointCost) &&
(!entry.IsOffensive || CombatEngine.IsActive);
}
#endregion
#region Drawing
///
/// Draw the spell at the given position in the list.
///
/// The spell to draw.
/// The position to draw the entry at.
/// If true, this item is selected.
protected override void DrawEntry(Spell entry, Vector2 position,
bool isSelected)
{
// check the parameter
if (entry == null)
{
throw new ArgumentNullException("entry");
}
SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
Vector2 drawPosition = position;
Color color = isSelected ? Fonts.HighlightColor : Fonts.DisplayColor;
// draw the icon
spriteBatch.Draw(entry.IconTexture, drawPosition + iconOffset, Color.White);
// draw the name
drawPosition.Y += listLineSpacing / 4;
drawPosition.X += nameColumnInterval;
spriteBatch.DrawString(Fonts.GearInfoFont, entry.Name, drawPosition, color);
// draw the level
drawPosition.X += levelColumnInterval;
spriteBatch.DrawString(Fonts.GearInfoFont, entry.Level.ToString(),
drawPosition, color);
// draw the power
drawPosition.X += powerColumnInterval;
string powerText = entry.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 += magicCostColumnInterval;
spriteBatch.DrawString(Fonts.GearInfoFont, entry.MagicPointCost.ToString(),
drawPosition, color);
// draw the cast button if needed
if (isSelected)
{
selectButtonText = (CanSelectEntry(entry) && (SpellSelected != null)) ?
"Cast" : String.Empty;
}
}
///
/// Draw the description of the selected item.
///
protected override void DrawSelectedDescription(Spell entry)
{
// check the parameter
if (entry == null)
{
throw new ArgumentNullException("entry");
}
SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
Vector2 position = descriptionTextPosition;
// draw the insufficient-mp warning
if (CombatEngine.IsActive && (entry.MagicPointCost > statistics.MagicPoints))
{
// draw the insufficient-mp warning
spriteBatch.DrawString(Fonts.DescriptionFont,
"Not enough MP to Cast Spell", warningMessagePosition,
Color.Red);
}
// draw the description
spriteBatch.DrawString(Fonts.DescriptionFont,
Fonts.BreakTextIntoLines(entry.Description, 90, 3),
spellDescriptionPosition, Fonts.DescriptionColor);
}
///
/// Draw the column headers above the list.
///
protected override void DrawColumnHeaders()
{
SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
Vector2 position = listEntryStartPosition;
position.X += nameColumnInterval;
if (!String.IsNullOrEmpty(nameColumnText))
{
spriteBatch.DrawString(Fonts.CaptionFont, nameColumnText, position,
Fonts.CaptionColor);
}
position.X += levelColumnInterval;
if (!String.IsNullOrEmpty(levelColumnText))
{
spriteBatch.DrawString(Fonts.CaptionFont, levelColumnText, position,
Fonts.CaptionColor);
}
position.X += powerColumnInterval;
if (!String.IsNullOrEmpty(powerColumnText))
{
spriteBatch.DrawString(Fonts.CaptionFont, powerColumnText, position,
Fonts.CaptionColor);
}
position.X += magicCostColumnInterval;
if (!String.IsNullOrEmpty(magicCostColumnText))
{
spriteBatch.DrawString(Fonts.CaptionFont, magicCostColumnText, position,
Fonts.CaptionColor);
}
}
#endregion
}
}