diff --git a/Classes/Base/Dealer.cs b/Classes/BaseTypes/Dealer.cs similarity index 100% rename from Classes/Base/Dealer.cs rename to Classes/BaseTypes/Dealer.cs diff --git a/Classes/BaseTypes/NotifyBase.cs b/Classes/BaseTypes/NotifyBase.cs new file mode 100644 index 00000000..4c2aaa70 --- /dev/null +++ b/Classes/BaseTypes/NotifyBase.cs @@ -0,0 +1,66 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace Los.Santos.Dope.Wars.Classes.BaseTypes; + +/// +/// The class. +/// +/// The class implements the following interfaces: +/// +/// The members of the interface. +/// The members of the interface. +/// +/// +/// +public abstract class NotifyBase : INotifyPropertyChanged, INotifyPropertyChanging +{ + /// + /// Sets a new value for a property and notifies about the change. + /// + /// + /// Will throw an exception of type if is . + /// + /// + /// The referenced field. + /// The new value for the property. + /// The property name. + /// + protected void SetProperty(ref T field, T newValue, [CallerMemberName] string? propertyName = null) + { + if (propertyName is null) + throw new ArgumentNullException(nameof(propertyName)); + + if (!Equals(field, newValue)) + { + RaisePropertyChanging(propertyName); + field = newValue; + RaisePropertyChanged(propertyName); + } + } + + /// + public event PropertyChangedEventHandler? PropertyChanged; + /// + public event PropertyChangingEventHandler? PropertyChanging; + + /// + /// The method is used to raise the 'property changed' event. + /// + /// + /// The calling member's name will be used as the parameter. + /// + /// The name of the property, can be . + protected virtual void RaisePropertyChanged([CallerMemberName] string? propertyName = null) => + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + /// + /// The method is used to raise the 'property changing' event. + /// + /// + /// The calling member's name will be used as the parameter. + /// + /// The name of the property, can be . + protected virtual void RaisePropertyChanging([CallerMemberName] string? propertyName = null) => + PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName)); +} diff --git a/Classes/Base/Pedestrian.cs b/Classes/BaseTypes/Pedestrian.cs similarity index 100% rename from Classes/Base/Pedestrian.cs rename to Classes/BaseTypes/Pedestrian.cs diff --git a/Classes/Base/PlayerProperty.cs b/Classes/BaseTypes/PlayerProperty.cs similarity index 100% rename from Classes/Base/PlayerProperty.cs rename to Classes/BaseTypes/PlayerProperty.cs diff --git a/Classes/Base/Stash.cs b/Classes/BaseTypes/Stash.cs similarity index 100% rename from Classes/Base/Stash.cs rename to Classes/BaseTypes/Stash.cs diff --git a/Classes/Drug.cs b/Classes/Drug.cs index e2db08f1..b786d068 100644 --- a/Classes/Drug.cs +++ b/Classes/Drug.cs @@ -1,4 +1,6 @@ -using System.Xml.Serialization; +using Los.Santos.Dope.Wars.Classes.BaseTypes; +using System.ComponentModel; +using System.Xml.Serialization; namespace Los.Santos.Dope.Wars.Classes; @@ -6,44 +8,15 @@ namespace Los.Santos.Dope.Wars.Classes; /// The class is the root element for the drug class. /// [XmlRoot(ElementName = nameof(Drug), IsNullable = false)] -public class Drug +public class Drug : NotifyBase { #region fields - private int _quantity; + private int quantity; #endregion #region ctor /// - /// Empty constructor for - /// - public Drug() - { - Name = string.Empty; - Description = string.Empty; - CurrentPrice = default; - AveragePrice = default; - PurchasePrice = default; - Quantity = default; - } - - /// - /// The constructor for - /// - /// - /// - /// - public Drug(Enums.DrugType drugType, string description, int marketValue) - { - Name = drugType.GetName(); - Description = description; - CurrentPrice = default; - AveragePrice = marketValue; - PurchasePrice = default; - Quantity = default; - } - - /// - /// The constructor for + /// Initializes a new instance of the class. /// /// /// @@ -56,54 +29,65 @@ public Drug(string drugName, string description, int marketValue) AveragePrice = marketValue; PurchasePrice = default; Quantity = default; + PropertyChanged += OnDrugPropertyChanged; } #endregion #region properties /// - /// The property + /// The property is the name of the drug. /// [XmlText] public string Name { get; set; } /// - /// The property + /// The property is the description of the drug. /// [XmlIgnore] public string Description { get; set; } /// - /// The property + /// The property is the current price of the drug. /// [XmlIgnore] public int CurrentPrice { get; set; } /// - /// The property + /// The property is the normal market price of the drug. /// [XmlIgnore] public int AveragePrice { get; set; } /// - /// The property + /// The property is the price the drug has been purchased. /// [XmlAttribute(AttributeName = nameof(PurchasePrice))] public int PurchasePrice { get; set; } /// - /// The property, if the quantity gets set to 0 the property goes 0 too + /// The property is the amount of the drug. /// [XmlAttribute(AttributeName = nameof(Quantity))] - public int Quantity + public int Quantity { get => quantity; set => SetProperty(ref quantity, value); } + #endregion + + #region private methods + /// + /// The event trigger method if a property that notifies has changed. + /// + /// + /// + private void OnDrugPropertyChanged(object sender, PropertyChangedEventArgs e) { - get => _quantity; - set + if (sender is not Drug drug) + return; + if (e is null) + return; + + if (Equals(e.PropertyName, nameof(drug.Quantity))) { - _quantity = value; - if (value.Equals(0)) - { - PurchasePrice = value; - } + if (Equals(drug.Quantity, 0)) + drug.PurchasePrice = Quantity; } } #endregion diff --git a/Classes/PlayerStash.cs b/Classes/PlayerStash.cs index 21f92954..1ac4e692 100644 --- a/Classes/PlayerStash.cs +++ b/Classes/PlayerStash.cs @@ -5,58 +5,55 @@ namespace Los.Santos.Dope.Wars.Classes; /// -/// The class for player types, inherits from +/// The class. /// +/// +/// Inherits from the base class. +/// Implements the members of the interface. +/// public class PlayerStash : Stash, IPlayerStash { - #region ctor /// - /// The standard constructor for the class + /// Initializes a new instance of the class. /// - public PlayerStash() - { - Drugs = new(); - } - #endregion + public PlayerStash() => Drugs = new(); #region IPlayerStash members - /// + /// public void BuyDrug(string drugName, int drugQuantity, int drugPrice) { - Drug drug = Drugs.Where(x => x.Name.Equals(drugName, StringComparison.Ordinal)).SingleOrDefault(); - - if (drug.Quantity.Equals(0)) - drug.PurchasePrice = drugPrice; - else - drug.PurchasePrice = ((drug.Quantity * drug.PurchasePrice) + (drugQuantity * drugPrice)) / (drug.Quantity + drugQuantity); - + CalculateNewPurchasePrice(drugName, drugQuantity, drugPrice); AddToStash(drugName, drugQuantity); - Game.Player.Money -= drugPrice * drugQuantity; } - /// + + /// public void MoveIntoInventory(string drugName, int drugQuantity, int drugPrice) { - Drug drug = Drugs.Where(x => x.Name.Equals(drugName, StringComparison.Ordinal)).SingleOrDefault(); - - if (drug.Quantity.Equals(0)) - drug.PurchasePrice = drugPrice; - else - drug.PurchasePrice = ((drug.Quantity * drug.PurchasePrice) + (drugQuantity * drugPrice)) / (drug.Quantity + drugQuantity); - + CalculateNewPurchasePrice(drugName, drugQuantity, drugPrice); AddToStash(drugName, drugQuantity); } - /// + /// public void SellDrug(string drugName, int drugQuantity, int drugPrice) { RemoveFromStash(drugName, drugQuantity); - Game.Player.Money += drugPrice * drugQuantity; } - /// - public void TakeFromInventory(string drugName, int drugQuantity) - { + /// + public void TakeFromInventory(string drugName, int drugQuantity) => RemoveFromStash(drugName, drugQuantity); - } #endregion + + /// + /// The method calculaties the new purchase price, when adding drug into the player stash. + /// + /// The name of the drug. + /// The quantity / amount of the drug. + /// The current price of the drug. + private void CalculateNewPurchasePrice(string drugName, int drugQuantity, int drugPrice) + { + Drug drug = Drugs.Where(x => x.Name.Equals(drugName, StringComparison.Ordinal)).Single(); + drug.PurchasePrice = drug.Quantity.Equals(0) ? drugPrice + : ((drug.Quantity * drug.PurchasePrice) + (drugQuantity * drugPrice)) / (drug.Quantity + drugQuantity); + } } diff --git a/Interfaces/IPlayerStash.cs b/Interfaces/IPlayerStash.cs index 1feeef36..bb537b54 100644 --- a/Interfaces/IPlayerStash.cs +++ b/Interfaces/IPlayerStash.cs @@ -1,38 +1,38 @@ namespace Los.Santos.Dope.Wars.Interfaces; /// -/// The interface, provides methods specifically for the player +/// The interface, provides th epublic methods for the player stash. /// public interface IPlayerStash { /// - /// The method is used to manipulate the player stash + /// The method is used to manipulate the player stash by adding drugs through a buy transaction. /// - /// - /// - /// + /// The name of the drug. + /// The quantity / amount of the drug. + /// The current price of the drug. void BuyDrug(string drugName, int drugQuantity, int drugPrice); /// - /// The method is used to manipulate the player stash + /// The method is used to manipulate the player stash by adding drugs through a sell transaction. /// - /// - /// - /// + /// The name of the drug. + /// The quantity / amount of the drug. + /// The current price of the drug. void SellDrug(string drugName, int drugQuantity, int drugPrice); /// - /// The method is used to make transfers into player inventories + /// The method is used to make transfers into player inventories by adding drug into a inventory. /// - /// - /// - /// + /// The name of the drug. + /// The quantity / amount of the drug. + /// The current price of the drug. void MoveIntoInventory(string drugName, int drugQuantity, int drugPrice); /// - /// The method is used to make transfers from player inventories + /// The method is used to make transfers into player inventories by removing drug from a inventory. /// - /// - /// + /// The name of the drug. + /// The quantity / amount of the drug. void TakeFromInventory(string drugName, int drugQuantity); } diff --git a/Persistence/State/PlayerStats.cs b/Persistence/State/PlayerStats.cs index e395b5b4..cc1a2203 100644 --- a/Persistence/State/PlayerStats.cs +++ b/Persistence/State/PlayerStats.cs @@ -1,6 +1,6 @@ using Los.Santos.Dope.Wars.Classes; +using Los.Santos.Dope.Wars.Classes.BaseTypes; using System.ComponentModel; -using System.Runtime.CompilerServices; using System.Xml.Serialization; namespace Los.Santos.Dope.Wars.Persistence.State; @@ -9,11 +9,11 @@ namespace Los.Santos.Dope.Wars.Persistence.State; /// The class is the root element for each character. /// [XmlRoot(ElementName = nameof(PlayerStats), IsNullable = false)] -public class PlayerStats : INotifyPropertyChanged +public class PlayerStats : NotifyBase { #region fields private int currentLevel; - + private int currentExperience; #endregion #region ctor @@ -30,77 +30,68 @@ public PlayerStats() Stash.Init(); Reward = new(); Warehouse = new(); + PropertyChanged += OnPlayerStatsPropertyChanged; } #endregion #region properties /// - /// The property, money spend for buying drugs + /// The property, money spend for buying drugs. /// [XmlAttribute(AttributeName = nameof(SpentMoney))] public int SpentMoney { get; set; } /// - /// The property, money earned from selling drugs + /// The property, money earned from selling drugs. /// [XmlAttribute(AttributeName = nameof(EarnedMoney))] public int EarnedMoney { get; set; } /// - /// The property, increases depending on experience gain + /// The property, increases depending on experience gain. /// [XmlAttribute(AttributeName = nameof(CurrentLevel))] - public int CurrentLevel - { - get => currentLevel; - set - { - if (value != currentLevel) - { - currentLevel = value; - OnPropertyChanged(); - } - } - } + public int CurrentLevel { get => currentLevel; set => SetProperty(ref currentLevel, value); } /// /// The property /// [XmlAttribute(AttributeName = nameof(CurrentExperience))] - public int CurrentExperience { get; set; } + public int CurrentExperience { get => currentExperience; set => SetProperty(ref currentExperience, value); } /// - /// The property, calculated not serialized + /// The property, calculated depending on the current level, not serialized. /// [XmlIgnore] - public int NextLevelExperience { get => GetNextLevelExpPoints(); } + public int NextLevelExperience => GetNextLevelExpPoints(); /// - /// The property, increases/decreasing depending on the amount of drugs the player has + /// The property, increases/decreasing depending on the amount of drugs the player has. /// [XmlAttribute(AttributeName = nameof(CurrentBagSize))] - public int CurrentBagSize { get => GetCurrentBagSize(); } + public int CurrentBagSize => GetCurrentBagSize(); /// - /// The property, increases depending on level gain + /// The property, increases depending on level gain. /// + // TODO: The maximum player bag size is still hard coded here ... [XmlAttribute(AttributeName = nameof(MaxBagSize))] - public int MaxBagSize { get => CurrentLevel * 50; } + public int MaxBagSize => CurrentLevel * 50; /// - /// The property, holds the bought player drugs and drug money for trading + /// The property, holds the bought and otherwise acquired drugs for trading. /// [XmlElement(ElementName = nameof(Stash), IsNullable = false)] public PlayerStash Stash { get; set; } /// - /// The property, holds the information about achieved rewards + /// The property, holds the information about achieved rewards. /// [XmlElement(ElementName = nameof(Reward), IsNullable = false)] public Reward Reward { get; set; } /// - /// The property, holds the warehouse information + /// The property, holds the warehouse information. /// [XmlElement(ElementName = nameof(Warehouse), IsNullable = false)] public Warehouse Warehouse { get; set; } @@ -108,22 +99,17 @@ public int CurrentLevel #region public members /// - /// bad implementation for now ... + /// The Method adds the desired experience points to the current experience. /// - /// - public void AddExperiencePoints(int points) - { - CurrentExperience += points; - while (GetNextLevelExpPoints() < CurrentExperience) - CurrentLevel++; - } + /// The experience points to add to the current experience. + public void AddExperiencePoints(int points) => CurrentExperience += points; #endregion #region private members /// - /// Returns the need experience points fo the next level + /// The method calculates the experience points needed for the next level up. /// - /// + /// The needed experience points. private int GetNextLevelExpPoints() => (int)Math.Pow(CurrentLevel + 1, 2.5) * 1000; /// @@ -135,6 +121,7 @@ public void AddExperiencePoints(int points) /// The current bag size. private int GetCurrentBagSize() { + // TODO: this needs to be redone / refac ... think this is a bad implementation. int bagSize = default; if (Stash.Drugs.Count.Equals(0)) return bagSize; @@ -142,20 +129,22 @@ private int GetCurrentBagSize() bagSize += drug.Quantity; return bagSize; } - #endregion - - #region INotifyPropertyChanged interface members - /// - public event PropertyChangedEventHandler? PropertyChanged; /// - /// The method for the event trigger. + /// The event trigger method if a property that notifies has changed. /// - /// - /// It should not be necessary to set the 'propertyName' parameter. - /// - /// The name of the propery which has changed. - private protected void OnPropertyChanged([CallerMemberName] string propertyName = "") => - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + /// + /// + private void OnPlayerStatsPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e is null) + return; + + if (Equals(e.PropertyName, nameof(CurrentExperience))) + { + if (GetNextLevelExpPoints() < CurrentExperience) + CurrentLevel++; + } + } #endregion }