For the vendors, we will use UI binding to their inventory, the same way we do with the Player class. But vendors will not have hit points, experience, etc. So, the Vendor class will be similar to the Player class, but with less properties and functions.
Step 1: In the Engine project, create a new class – Vendor.cs.
We’re only going to have the vendor’s name and inventory as properties in this class. We will add, and remove items, for the vendor’s inventory with functions that will raise the property changed notification.
Vendor.cs
using System.Collections.Generic; using System.ComponentModel; using System.Linq; namespace Engine { public class Vendor : INotifyPropertyChanged { public string Name { get; set; } public BindingList<InventoryItem> Inventory { get; private set; } public Vendor(string name) { Name = name; Inventory = new BindingList<InventoryItem>(); } public void AddItemToInventory(Item itemToAdd, int quantity = 1) { InventoryItem item = Inventory.SingleOrDefault(ii => ii.Details.ID == itemToAdd.ID); if(item == null) { // They didn't have the item, so add it to their inventory Inventory.Add(new InventoryItem(itemToAdd, quantity)); } else { // They have the item in their inventory, so increase the quantity item.Quantity += quantity; } OnPropertyChanged("Inventory"); } public void RemoveItemFromInventory(Item itemToRemove, int quantity = 1) { InventoryItem item = Inventory.SingleOrDefault(ii => ii.Details.ID == itemToRemove.ID); if(item == null) { // The item is not in the player's inventory, so ignore it. // We might want to raise an error for this situation } else { // They have the item in their inventory, so decrease the quantity item.Quantity -= quantity; // Don't allow negative quantities. // We might want to raise an error for this situation if(item.Quantity < 0) { item.Quantity = 0; } // If the quantity is zero, remove the item from the list if(item.Quantity == 0) { Inventory.Remove(item); } // Notify the UI that the inventory has changed OnPropertyChanged("Inventory"); } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string name) { if(PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(name)); } } } }
Step 2: Modify Location.cs.
Add a new property to hold the Vendor.
public Vendor VendorWorkingHere { get; set; }
Step 3: Modify World.cs.
In the PopulateLocations() function, create a new vendor object, and give it some inventory, for any locations where you want a vendor. I decided to add a vendor to the town square. Now, that part of PopulateLocations looks like this:
Location townSquare = new Location(LOCATION_ID_TOWN_SQUARE, "Town square", "You see a fountain."); Vendor bobTheRatCatcher = new Vendor("Bob the Rat-Catcher"); bobTheRatCatcher.AddItemToInventory(ItemByID(ITEM_ID_PIECE_OF_FUR), 5); bobTheRatCatcher.AddItemToInventory(ItemByID(ITEM_ID_RAT_TAIL), 3); townSquare.VendorWorkingHere = bobTheRatCatcher;
Step 4: Run your program, and make sure it still works. We still won’t see anything new in the UI with these changes. That will happen in the next lesson.
Source code for this lesson
Next lesson: Lesson 21.3 – Add a button and create its eventhandler in code, without the UI design screen
Previous lesson: Lesson 21.1 – Adding a price to game items
All lessons: Learn C# by Building a Simple RPG Index