A student found a bug with the CurrentWeapon being reset when the player has multiple weapons.
Bug Description
There are times when the player’s CurrentWeapon is reset in their weapon dropdown combobox.
Bug Fix
To fix this bug, you need to modify the PlayerOnPropertyChanged() function (lines 113 through 132 below), in SuperAdventure.cs.
If the player’s “Weapons” property changed, we save their CurrentWeapon value to a variable, before resetting the DataSource on the combobox.
Then, if the player had a previously-selected weapon (the variable is not null), we set the SelectedItem in the combobox to the weapon.
FIXED CODE
SuperAdventure.cs
using System; using System.ComponentModel; using System.Linq; using System.Windows.Forms; using System.IO; using Engine; namespace SuperAdventure { public partial class SuperAdventure : Form { private const string PLAYER_DATA_FILE_NAME = "PlayerData.xml"; private Player _player; public SuperAdventure() { InitializeComponent(); _player = PlayerDataMapper.CreateFromDatabase(); if(_player == null) { if(File.Exists(PLAYER_DATA_FILE_NAME)) { _player = Player.CreatePlayerFromXmlString(File.ReadAllText(PLAYER_DATA_FILE_NAME)); } else { _player = Player.CreateDefaultPlayer(); } } _player.AddItemToInventory(World.ItemByID(World.ITEM_ID_CLUB)); lblHitPoints.DataBindings.Add("Text", _player, "CurrentHitPoints"); lblGold.DataBindings.Add("Text", _player, "Gold"); lblExperience.DataBindings.Add("Text", _player, "ExperiencePoints"); lblLevel.DataBindings.Add("Text", _player, "Level"); dgvInventory.RowHeadersVisible = false; dgvInventory.AutoGenerateColumns = false; dgvInventory.DataSource = _player.Inventory; dgvInventory.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Name", Width = 197, DataPropertyName = "Description" }); dgvInventory.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Quantity", DataPropertyName = "Quantity" }); dgvInventory.ScrollBars = ScrollBars.Vertical; dgvQuests.RowHeadersVisible = false; dgvQuests.AutoGenerateColumns = false; dgvQuests.DataSource = _player.Quests; dgvQuests.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Name", Width = 197, DataPropertyName = "Name" }); dgvQuests.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Done?", DataPropertyName = "IsCompleted" }); cboWeapons.DataSource = _player.Weapons; cboWeapons.DisplayMember = "Name"; cboWeapons.ValueMember = "Id"; if(_player.CurrentWeapon != null) { cboWeapons.SelectedItem = _player.CurrentWeapon; } cboWeapons.SelectedIndexChanged += cboWeapons_SelectedIndexChanged; cboPotions.DataSource = _player.Potions; cboPotions.DisplayMember = "Name"; cboPotions.ValueMember = "Id"; _player.PropertyChanged += PlayerOnPropertyChanged; _player.OnMessage += DisplayMessage; _player.MoveTo(_player.CurrentLocation); } private void DisplayMessage(object sender, MessageEventArgs messageEventArgs) { rtbMessages.Text += messageEventArgs.Message + Environment.NewLine; if(messageEventArgs.AddExtraNewLine) { rtbMessages.Text += Environment.NewLine; } rtbMessages.SelectionStart = rtbMessages.Text.Length; rtbMessages.ScrollToCaret(); } private void PlayerOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs) { if (propertyChangedEventArgs.PropertyName == "Weapons") { Weapon previouslySelectedWeapon = _player.CurrentWeapon; cboWeapons.DataSource = _player.Weapons; if (previouslySelectedWeapon != null && _player.Weapons.Exists(w => w.ID == previouslySelectedWeapon.ID)) { cboWeapons.SelectedItem = previouslySelectedWeapon; } if (!_player.Weapons.Any()) { cboWeapons.Visible = false; btnUseWeapon.Visible = false; } } if(propertyChangedEventArgs.PropertyName == "Potions") { cboPotions.DataSource = _player.Potions; if(!_player.Potions.Any()) { cboPotions.Visible = false; btnUsePotion.Visible = false; } } if(propertyChangedEventArgs.PropertyName == "CurrentLocation") { // Show/hide available movement buttons btnNorth.Visible = (_player.CurrentLocation.LocationToNorth != null); btnEast.Visible = (_player.CurrentLocation.LocationToEast != null); btnSouth.Visible = (_player.CurrentLocation.LocationToSouth != null); btnWest.Visible = (_player.CurrentLocation.LocationToWest != null); btnTrade.Visible = (_player.CurrentLocation.VendorWorkingHere != null); // Display current location name and description rtbLocation.Text = _player.CurrentLocation.Name + Environment.NewLine; rtbLocation.Text += _player.CurrentLocation.Description + Environment.NewLine; if(!_player.CurrentLocation.HasAMonster) { cboWeapons.Visible = false; cboPotions.Visible = false; btnUseWeapon.Visible = false; btnUsePotion.Visible = false; } else { cboWeapons.Visible = _player.Weapons.Any(); cboPotions.Visible = _player.Potions.Any(); btnUseWeapon.Visible = _player.Weapons.Any(); btnUsePotion.Visible = _player.Potions.Any(); } } } private void btnNorth_Click(object sender, EventArgs e) { _player.MoveNorth(); } private void btnEast_Click(object sender, EventArgs e) { _player.MoveEast(); } private void btnSouth_Click(object sender, EventArgs e) { _player.MoveSouth(); } private void btnWest_Click(object sender, EventArgs e) { _player.MoveWest(); } private void btnUseWeapon_Click(object sender, EventArgs e) { // Get the currently selected weapon from the cboWeapons ComboBox Weapon currentWeapon = (Weapon)cboWeapons.SelectedItem; _player.UseWeapon(currentWeapon); } private void btnUsePotion_Click(object sender, EventArgs e) { // Get the currently selected potion from the combobox HealingPotion potion = (HealingPotion)cboPotions.SelectedItem; _player.UsePotion(potion); } private void SuperAdventure_FormClosing(object sender, FormClosingEventArgs e) { File.WriteAllText(PLAYER_DATA_FILE_NAME, _player.ToXmlString()); PlayerDataMapper.SaveToDatabase(_player); } private void cboWeapons_SelectedIndexChanged(object sender, EventArgs e) { _player.CurrentWeapon = (Weapon)cboWeapons.SelectedItem; } private void btnTrade_Click(object sender, EventArgs e) { TradingScreen tradingScreen = new TradingScreen(_player); tradingScreen.StartPosition = FormStartPosition.CenterParent; tradingScreen.ShowDialog(this); } private void btnMap_Click(object sender, EventArgs e) { WorldMap mapScreen = new WorldMap(_player); mapScreen.StartPosition = FormStartPosition.CenterParent; mapScreen.ShowDialog(this); } } }
If you have any problems applying this change, or notice any other bugs, please leave a comment below.
The code that you listed has some issues… It list && and it should just be &&
haha the txt block fixed it “&&”
Thanks for letting me know. It should be fixed now.
When my web server upgraded, it broke the code that formatted source code on the pages. I’ve been trying to manually clean it up and must have missed that one.