#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 PurchaseScreen.cs
* @date Created: 2007/06/25
* @author File creator: David Teviotdale
* @author Credits: none
*/
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using System.Text;
using CeGui;
using ProjectXenocide.Utils;
using ProjectXenocide.Model.Geoscape;
using ProjectXenocide.Model.Geoscape.Outposts;
using ProjectXenocide.Model.StaticData.Items;
using Xenocide.Resources;
#endregion
namespace ProjectXenocide.UI.Screens
{
///
/// This is the screen that allows user to buy items for a base
///
public class PurchaseScreen : Screen
{
///
/// Constructor (obviously)
///
/// Index to outpost purchases will be sent to
public PurchaseScreen(int selectedBaseIndex)
: base("PurchaseScreen")
{
this.selectedBaseIndex = selectedBaseIndex;
}
#region Create the CeGui widgets
///
/// add the buttons to the screen
///
protected override void CreateCeguiWidgets()
{
// add text giving the available funds
fundsText = GuiBuilder.CreateText(CeguiId + "_fundsText");
AddWidget(fundsText, 0.01f, 0.06f, 0.2275f, 0.04125f);
fundsText.Text = Util.StringFormat(Strings.SCREEN_PURCHASE_FUNDS,
Xenocide.GameState.GeoData.XCorp.Bank.CurrentBalance);
// add text giving the running total of the items selected for purchase
totalCostText = GuiBuilder.CreateText(CeguiId + "_totalCostText");
AddWidget(totalCostText, 0.35f, 0.06f, 0.2275f, 0.04125f);
UpdateTotalCost();
// The gird of items available for purchase
InitializeGrid();
PopulateGrid();
// other buttons
buyMoreButton = AddButton("BUTTON_BUY_MORE", 0.7475f, 0.80f, 0.2275f, 0.04125f, "PlanetView\\zoomin.ogg");
buyLessButton = AddButton("BUTTON_BUY_LESS", 0.7475f, 0.85f, 0.2275f, 0.04125f, "PlanetView\\zoomout.ogg");
confirmButton = AddButton("BUTTON_CONFIRM", 0.7475f, 0.90f, 0.2275f, 0.04125f);
cancelButton = AddButton("BUTTON_CANCEL", 0.7475f, 0.95f, 0.2275f, 0.04125f);
buyMoreButton.Clicked += new CeGui.GuiEventHandler(OnBuyMoreButton);
buyLessButton.Clicked += new CeGui.GuiEventHandler(OnBuyLessButton);
confirmButton.Clicked += new CeGui.GuiEventHandler(OnConfirmButton);
cancelButton.Clicked += new CeGui.GuiEventHandler(OnCancelButton);
}
private CeGui.Widgets.StaticText fundsText;
private CeGui.Widgets.StaticText totalCostText;
private CeGui.Widgets.MultiColumnList grid;
private CeGui.Widgets.PushButton buyMoreButton;
private CeGui.Widgets.PushButton buyLessButton;
private CeGui.Widgets.PushButton confirmButton;
private CeGui.Widgets.PushButton cancelButton;
///
/// Create MultiColumnListBox which holds items available for purchase
///
private void InitializeGrid()
{
grid = GuiBuilder.CreateGrid("purchaseGrid");
AddWidget(grid, 0.01f, 0.13f, 0.70f, 0.86f);
grid.AddColumn(Strings.SCREEN_PURCHASE_COLUMN_ITEM, grid.ColumnCount, 0.58f);
grid.AddColumn(Strings.SCREEN_PURCHASE_COLUMN_QUANTITY_IN_BASE, grid.ColumnCount, 0.12f);
grid.AddColumn(Strings.SCREEN_PURCHASE_COLUMN_COST_PER_UNIT, grid.ColumnCount, 0.13f);
grid.AddColumn(Strings.SCREEN_PURCHASE_COLUMN_QUANTITY, grid.ColumnCount, 0.12f);
}
///
/// Put the list of items available for purchase into the grid
///
private void PopulateGrid()
{
foreach (ItemInfo i in Xenocide.StaticTables.ItemList)
{
if (AvailableForPurchase(i))
{
AddRowToGrid(i);
}
}
}
///
/// Can items of this type be purchased?
///
/// type of item
/// true if items can be purchased
private static bool AvailableForPurchase(ItemInfo item)
{
// Note, with initial tree, all buyable items don't need researching.
// however this might not be true with later research trees
return item.CanPurchase && Xenocide.GameState.GeoData.XCorp.TechManager.IsAvailable(item.Id);
}
///
/// Add a row to the grid
///
/// item to put on grid
private void AddRowToGrid(ItemInfo item)
{
// add item to grid
CeGui.ListboxTextItem listboxItem = Util.CreateListboxItem(item.Name);
listboxItem.ID = Xenocide.StaticTables.ItemList.IndexOf(item.Id);
int rowNum = grid.AddRow(listboxItem, 0);
Util.AddNumericElementToGrid(grid, 1, rowNum, SelectedBase.Inventory.NumberInInventory(item));
Util.AddNumericElementToGrid(grid, 2, rowNum, item.BuyPrice);
Util.AddNumericElementToGrid(grid, 3, rowNum, 0);
// and record number of items of this type user is purchasing
ShoppingList[listboxItem.ID] = 0;
}
#endregion Create the CeGui widgets
#region event handlers
/// Handle user clicking on the "Buy More" button
/// Not used
/// Not used
private void OnBuyMoreButton(object sender, GuiEventArgs e)
{
CeGui.Widgets.ListboxItem selectedItem = GetSelectedItem();
if (null != selectedItem)
{
// update count of items
int itemListIndex = selectedItem.ID;
++ShoppingList[itemListIndex];
// if shopping list is no longer valid, revert
if (!CanFit() ||
!Xenocide.GameState.GeoData.XCorp.Bank.CanAfford(CalculateTotalCost())
)
{
--ShoppingList[itemListIndex];
}
// update display on screen
UpdateDetails(selectedItem, itemListIndex);
}
}
/// Handle user clicking on the "Buy Less" button
/// Not used
/// Not used
private void OnBuyLessButton(object sender, GuiEventArgs e)
{
CeGui.Widgets.ListboxItem selectedItem = GetSelectedItem();
if (null != selectedItem)
{
// update count of items
int itemListIndex = selectedItem.ID;
if (0 < ShoppingList[itemListIndex])
{
--ShoppingList[itemListIndex];
// update display on screen
UpdateDetails(selectedItem, itemListIndex);
}
}
}
/// Handle user clicking on the "Confirm" button
/// That is, buy all the items the user has selected
/// Not used
/// Not used
private void OnConfirmButton(object sender, GuiEventArgs e)
{
// Pay for the items
Xenocide.GameState.GeoData.XCorp.Bank.Debit(CalculateTotalCost());
Shipment shipment = new Shipment(SelectedBase, Shipment.CalcEta());
foreach (KeyValuePair kvp in ShoppingList)
{
ItemInfo item = Xenocide.StaticTables.ItemList[kvp.Key];
for (int i = 0; i < kvp.Value; ++i)
{
shipment.Add(item.Manufacture());
}
}
shipment.Ship();
GoToBasesScreen();
}
/// React to user pressing the Cancel button
/// Not used
/// Not used
private void OnCancelButton(object sender, CeGui.GuiEventArgs e)
{
GoToBasesScreen();
}
#endregion event handlers
// Get currently selected item from Grid. Give error message if nothing selected
private CeGui.Widgets.ListboxItem GetSelectedItem()
{
CeGui.Widgets.ListboxItem selectedItem = grid.GetFirstSelectedItem();
if (null == selectedItem)
{
Util.ShowMessageBox(Strings.MSGBOX_NO_PURCHASE_SELECTED);
}
return selectedItem;
}
///
/// Populate the Total Cost field on the dialog
///
private void UpdateTotalCost()
{
totalCostText.Text = Util.StringFormat(Strings.SCREEN_PURCHASE_TOTAL_COST, CalculateTotalCost());
}
///
/// Update the screen to reflect the latest changes
///
/// row in gird that is selected
/// Index into StaticData.ItemList for data on item
private void UpdateDetails(CeGui.Widgets.ListboxItem selectedItem, int itemListIndex)
{
UpdateTotalCost();
// update quantity column of row in grid
int row = grid.GetRowIndexOfItem(selectedItem);
CeGui.Widgets.GridReference position = new CeGui.Widgets.GridReference(row, 3);
grid.GetItemAtGridReference(position).Text = Util.StringFormat("{0}", ShoppingList[itemListIndex]);
}
///
/// Figure out what the total cost of the purchases is going to be
///
/// total cost
private int CalculateTotalCost()
{
int cost = 0;
foreach (KeyValuePair kvp in ShoppingList)
{
cost += (Xenocide.StaticTables.ItemList[kvp.Key].BuyPrice * kvp.Value);
}
return cost;
}
///
/// Check if user fit everything on the shopping list into the outpost's inventory
///
/// 1. Gives a warning dialog if user has insufficent funds
/// 2. It's not very efficient, but it runs in response to user input, so doesn't need to be
///
///
/// true if user can fit everything on the list
private bool CanFit()
{
bool canFit = true;
// first put everything into the base
foreach (KeyValuePair kvp in ShoppingList)
{
ItemInfo item = Xenocide.StaticTables.ItemList[kvp.Key];
for (int i = 0; i < kvp.Value; ++i)
{
if (!SelectedBase.Inventory.CanFit(item))
{
canFit = false;
}
SelectedBase.Inventory.AllocateSpace(item);
}
}
// now take them all out again
foreach (KeyValuePair kvp in ShoppingList)
{
ItemInfo item = Xenocide.StaticTables.ItemList[kvp.Key];
for (int i = 0; i < kvp.Value; ++i)
{
SelectedBase.Inventory.ReleaseSpace(item);
}
}
if (!canFit)
{
Util.ShowMessageBox(Strings.MSGBOX_CANT_FIT);
}
return canFit;
}
///
/// Close this screen and go back to the Bases Screen
///
private void GoToBasesScreen()
{
ScreenManager.ScheduleScreen(new BasesScreen(selectedBaseIndex));
}
#region Fields
///
/// The outpost purchases will be sent to
///
private Outpost SelectedBase { get { return Xenocide.GameState.GeoData.Outposts[selectedBaseIndex]; } }
// index specifying the outpost that purchases will be sent to
private int selectedBaseIndex;
// The list of items we're buying
// Format is ItemList index, count
private Dictionary ShoppingList = new Dictionary();
#endregion Fields
}
}