#region Copyright
/*
--------------------------------------------------------------------------------
This source file is part of Xenocide
by Project Xenocide Team
For the latest info on Xenocide, see http://www.projectxenocide.com/
This work is licensed under the Creative Commons
Attribution-NonCommercial-ShareAlike 2.5 License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-nc-sa/2.5/
or send a letter to Creative Commons, 543 Howard Street, 5th Floor,
San Francisco, California, 94105, USA.
--------------------------------------------------------------------------------
*/
/*
* @file EquipSoldierScreenItemSource.cs
* @date Created: 2007/12/23
* @author File creator: David Teviotdale
* @author Credits: none
*/
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using CeGui;
using ProjectXenocide.Utils;
using ProjectXenocide.Model.Geoscape;
using ProjectXenocide.Model.Geoscape.Outposts;
using ProjectXenocide.Model.StaticData.Items;
using ProjectXenocide.Model.Battlescape.Combatants;
using ProjectXenocide.UI.Dialogs;
using ProjectXenocide.UI.Scenes;
#endregion
// alias Vector2
using Vector2 = Microsoft.Xna.Framework.Vector2;
namespace ProjectXenocide.UI.Screens
{
///
/// This is the screen that lets player set the items a soldier carries
///
public partial class EquipSoldierScreen
{
///
/// Represents where we're getting items to add to a soldier (or where we're dumping the items
/// removed from the soldier)
///
private abstract class ItemSource
{
///
/// Fetch the item on the "ground" area of the screen at the position given by the X and Y co-ordinates
///
/// cell co-ordinate (NOT pixel)
/// cell co-ordinate (NOT pixel)
/// Item, if there was an item at that position, else null
public Item FetchItem(int x, int y)
{
// find item in list that is at this position
int offset = 0;
int i = GetLeftmostItemIndex();
while ((i < itemList.Count) && (offset < InventoryLocation.GroundWidthInCells))
{
ItemEntry entry = itemList[i];
if ((offset <= x) && (x < offset + entry.CarryInfo.X) && (y < entry.CarryInfo.Y))
{
// item found, return it, and update list of items on ground
Item item = Remove(entry.Item);
if (0 == --entry.Count)
{
// no more items of this type at this position, so remove entry from list
itemList.RemoveAt(i);
}
else
{
itemList[i] = entry;
}
return item;
}
// try next
offset += itemList[i].CarryInfo.X;
++i;
}
// if get here, no item found
return null;
}
///
/// Remove an item from Source
///
/// type of item to remove
/// removed item
protected abstract Item Remove(Item item);
///
/// Put an item back into the store
///
/// Item being dropped
public abstract void ReplaceItem(Item item);
///
/// Draw the items on the "ground" area of the screen
///
/// where to draw the scene on the Window
/// scene that will draw the items
public void Draw(Rectangle sceneWindow, EquipSoldierScene scene)
{
int offset = 0;
int i = GetLeftmostItemIndex();
while ((i < itemList.Count) && (offset < InventoryLocation.GroundWidthInCells))
{
scene.DrawItemOnGround(sceneWindow, itemList[i].CarryInfo, offset, itemList[i].Count);
offset += itemList[i].CarryInfo.X;
++i;
}
}
///
/// Scroll the list of items to show on the "ground" area of the screen to the left
///
public void ScrollLeft()
{
// if we're not hard against the left margin, scroll items one position to the left
int index = GetLeftmostItemIndex();
if (0 < index)
{
scrollOffset -= itemList[index - 1].CarryInfo.X;
}
Debug.Assert(0 <= scrollOffset, "Invariant violated");
}
///
/// Scroll the list of items to show on the "ground" area of the screen to the right
///
public void ScrollRight()
{
// calc maximum offset value we can have
int maxOffset = -(int)(InventoryLocation.GroundWidthInCells);
foreach (ItemEntry entry in itemList)
{
maxOffset += entry.CarryInfo.X;
}
// if we can, scroll items one item to right
if (scrollOffset < maxOffset)
{
scrollOffset += itemList[GetLeftmostItemIndex()].CarryInfo.X;
}
}
///
/// Check if X-Corp soldiers can carry this type of item
///
/// type of item
/// true if soldier can carry this type of item
public static bool SoldierCanCarry(ItemInfo item)
{
// item must be carryable and of researched technology
return (null != item.CarryInfo) &&
Xenocide.GameState.GeoData.XCorp.TechManager.IsAvailable(item.Id);
}
///
/// Return index to item that is currently being drawn at leftmost position on "ground"
///
///
private int GetLeftmostItemIndex()
{
int itemOffset = 0;
for (int i = 0; i < itemList.Count; ++i)
{
if (itemOffset == scrollOffset)
{
// we've found the leftmost item.
return i;
}
// move onto next item
itemOffset += itemList[i].CarryInfo.X;
}
// if we get here, something's wrong, or there are no items.
Debug.Assert(0 == itemList.Count);
return 0;
}
///
/// Details of an item on the "ground" area of the screen
///
protected struct ItemEntry
{
///
/// Ctor
///
/// a representative instance of the item
/// number of items of this type available (when in outpost)
public ItemEntry(Item item, int count)
{
this.item = item;
this.count = count;
}
/// a representative instance of the item
public Item Item { get { return item; } }
/// number of items of this type available (when in outpost)
public int Count { get { return count; } set { count = value; } }
///
/// The CarryInfo of the specified item
///
public CarryInfo CarryInfo { get { return item.ItemInfo.BattlescapeInfo.CarryInfo; } }
/// a representative instance of the item
private Item item;
/// number of items of this type available (when in outpost)
private int count;
}
#region Fields
///
/// The items on the "ground" area of the screen
///
protected List ItemList { get { return itemList; } }
///
/// The items on the "ground" area of the screen
///
private List itemList = new List();
///
/// Number of cells to the right we have scrolled the items on the ground
///
private int scrollOffset;
#endregion Fields
}
///
/// Represents the outpost where we're getting items to add to a soldier (or where we're dumping the items
/// removed from the soldier)
///
private class OutpostItemSource : ItemSource
{
///
/// Constructor
///
/// Outpost being used as item source/sink
public OutpostItemSource(OutpostInventory outpostInventory)
{
this.outpostInventory = outpostInventory;
BuildItemList();
}
///
/// Build list of items to show on "Ground" area of screen
///
private void BuildItemList()
{
ItemList.Clear();
foreach (Item item in outpostInventory.ListContents())
{
// skip Items player's soldiers can't carry
if (SoldierCanCarry(item.ItemInfo))
{
ItemList.Add(new ItemEntry(item, outpostInventory.NumberInInventory(item.ItemInfo)));
}
}
}
///
/// Remove an item from Source
///
/// item to remove
/// removed item
protected override Item Remove(Item item)
{
// if not unique, get an item of this type from outpost
// Because if we're dealing with multiple items, we need to instanciate them
// as we equip the soldier with them.
if (!item.ItemInfo.IsUnique)
{
item = Xenocide.StaticTables.ItemList[item.ItemInfo.Id].FromOutpost(outpostInventory);
}
outpostInventory.Remove(item);
return item;
}
///
/// Put an item back into the store
///
/// Item being dropped
public override void ReplaceItem(Item item)
{
// put item into Outpost's inventory
Debug.Assert(null != item);
outpostInventory.Add(item, false);
BuildItemList();
}
#region Fields
/// Outpost being used as item source/sink
private OutpostInventory outpostInventory;
#endregion Fields
}
}
}