Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Port] Discounts In Uplink / Скидки В Аплинке #11

Merged
merged 3 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Content.Client/Store/Ui/StoreMenu.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ private void AddListingGui(ListingData listing)
}

var newListing = new StoreListingControl(listing, GetListingPriceString(listing), hasBalance, texture);

if (listing.DiscountValue > 0) // WD EDIT
newListing.StoreItemBuyButton.AddStyleClass("ButtonColorRed");

newListing.StoreItemBuyButton.OnButtonDown += args
=> OnListingButtonPressed?.Invoke(args, listing);

Expand Down
8 changes: 8 additions & 0 deletions Content.Server/Store/Systems/StoreSystem.Ui.cs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,14 @@ private void OnBuyRequest(EntityUid uid, StoreComponent component, StoreBuyListi
listing.PurchaseAmount++; //track how many times something has been purchased
_audio.PlayEntity(component.BuySuccessSound, msg.Session, uid); //cha-ching!

//WD EDIT START
if (listing.SaleLimit != 0 && listing.DiscountValue > 0 && listing.PurchaseAmount >= listing.SaleLimit)
{
listing.DiscountValue = 0;
listing.Cost = listing.OldCost;
}
//WD EDIT END

UpdateUserInterface(buyer, uid, component);
}

Expand Down
6 changes: 5 additions & 1 deletion Content.Server/Store/Systems/StoreSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
using System.Linq;
using Content.Server._White.StoreDiscount;
using Robust.Shared.Utility;

namespace Content.Server.Store.Systems;
Expand All @@ -22,6 +23,7 @@ public sealed partial class StoreSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly StoreDiscountSystem _storeDiscount = default!; // WD EDIT

public override void Initialize()
{
Expand Down Expand Up @@ -199,6 +201,8 @@ public void InitializeFromPreset(StorePresetPrototype preset, EntityUid uid, Sto
if (component.Balance == new Dictionary<string, FixedPoint2>() && preset.InitialBalance != null) //if we don't have a value stored, use the preset
TryAddCurrency(preset.InitialBalance, uid, component);

_storeDiscount.ApplyDiscounts(component.Listings, preset); // WD EDIT

var ui = _ui.GetUiOrNull(uid, StoreUiKey.Key);
if (ui != null)
{
Expand All @@ -225,7 +229,7 @@ public CurrencyInsertAttemptEvent(EntityUid user, EntityUid target, EntityUid us


/// <summary>
/// Nyano/DeltaV Code. For penguin bombs and what not.
/// Nyano/DeltaV Code. For penguin bombs and what not.
/// Raised on an item when it is purchased.
/// An item may need to set it upself up for its purchaser.
/// For example, to make sure it isn't hostile to them or
Expand Down
53 changes: 53 additions & 0 deletions Content.Server/_White/StoreDiscount/StoreDiscountSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Linq;
using Content.Shared.FixedPoint;
using Content.Shared.Store;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;

namespace Content.Server._White.StoreDiscount;

public sealed class StoreDiscountSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;

public void ApplyDiscounts(IEnumerable<ListingData> listings, StorePresetPrototype store)
{
if (!store.Sales.Enabled)
return;

var count = _random.Next(store.Sales.MinItems, store.Sales.MaxItems + 1);

listings = listings
.Where(l => !l.SaleBlacklist && l.Cost.Any(x => x.Value > 1)
&& store.Categories.Overlaps(ChangedFormatCategories(l.Categories)))
.OrderBy(_ => _random.Next()).Take(count).ToList();

foreach (var listing in listings)
{
var sale = GetDiscount(store.Sales.MinMultiplier, store.Sales.MaxMultiplier);
var newCost = listing.Cost.ToDictionary(x => x.Key,
x => FixedPoint2.New(Math.Max(1, (int) MathF.Round(x.Value.Float() * sale))));

if (listing.Cost.All(x => x.Value.Int() == newCost[x.Key].Int()))
continue;

var key = listing.Cost.First(x => x.Value > 0).Key;
listing.OldCost = listing.Cost;
listing.DiscountValue = 100 - (newCost[key] / listing.Cost[key] * 100).Int();
listing.Cost = newCost;
listing.Categories = new() {store.Sales.SalesCategory};
}
}

private IEnumerable<string> ChangedFormatCategories(List<ProtoId<StoreCategoryPrototype>> categories)
{
var modified = from p in categories select p.Id;

return modified;
}

private float GetDiscount(float minMultiplier, float maxMultiplier)
{
return _random.NextFloat() * (maxMultiplier - minMultiplier) + minMultiplier;
}
}
7 changes: 7 additions & 0 deletions Content.Shared/Store/ListingLocalisationHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ public static string GetLocalisedNameOrEntityName(ListingData listingData, IProt
else if (listingData.ProductEntity != null)
name = prototypeManager.Index(listingData.ProductEntity.Value).Name;

// WD START
if (listingData.DiscountValue > 0)
name += " " + Loc.GetString("store-sales-amount", ("amount", listingData.DiscountValue));
else if (listingData.OldCost.Count > 0)
name += " " + Loc.GetString("store-sales-over");
// WD END

return name;
}

Expand Down
22 changes: 22 additions & 0 deletions Content.Shared/Store/ListingPrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,21 @@ public partial class ListingData : IEquatable<ListingData>, ICloneable
[DataField]
public TimeSpan RestockTime = TimeSpan.Zero;

// WD START
[DataField]
public int SaleLimit = 3;

[DataField]
public bool SaleBlacklist;

public int DiscountValue;

public Dictionary<ProtoId<CurrencyPrototype>, FixedPoint2> OldCost = new();

[DataField]
public List<string> Components = new();
// WD END

public bool Equals(ListingData? listing)
{
if (listing == null)
Expand Down Expand Up @@ -166,6 +181,13 @@ public object Clone()
ProductEvent = ProductEvent,
PurchaseAmount = PurchaseAmount,
RestockTime = RestockTime,
// WD START
SaleLimit = SaleLimit,
SaleBlacklist = SaleBlacklist,
DiscountValue = DiscountValue,
OldCost = OldCost,
Components = Components,
// WD END
};
}
}
Expand Down
6 changes: 6 additions & 0 deletions Content.Shared/Store/StorePresetPrototype.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Content.Shared._White.StoreDiscount;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
Expand Down Expand Up @@ -38,4 +39,9 @@ public sealed partial class StorePresetPrototype : IPrototype
/// </summary>
[DataField("currencyWhitelist", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<CurrencyPrototype>))]
public HashSet<string> CurrencyWhitelist { get; private set; } = new();

// WD EDIT START
[DataField]
public SalesSpecifier Sales { get; private set; } = new();
// WD EDIT END
}
38 changes: 38 additions & 0 deletions Content.Shared/_White/StoreDiscount/SalesSpecifier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Content.Shared._White.StoreDiscount;

[DataDefinition]
public sealed partial class SalesSpecifier
{
[DataField]
public bool Enabled { get; private set; }

[DataField]
public float MinMultiplier { get; private set; }

[DataField]
public float MaxMultiplier { get; private set; }

[DataField]
public int MinItems { get; private set; }

[DataField]
public int MaxItems { get; private set; }

[DataField]
public string SalesCategory { get; private set; } = string.Empty;

public SalesSpecifier()
{
}

public SalesSpecifier(bool enabled, float minMultiplier, float maxMultiplier, int minItems, int maxItems,
string salesCategory)
{
Enabled = enabled;
MinMultiplier = minMultiplier;
MaxMultiplier = maxMultiplier;
MinItems = minItems;
MaxItems = maxItems;
SalesCategory = salesCategory;
}
}
2 changes: 2 additions & 0 deletions Resources/Locale/en-US/_white/store/sales.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
store-sales-amount = [DISCOUNT] { $amount }%!
store-sales-over = [The sale is over]
2 changes: 2 additions & 0 deletions Resources/Locale/ru-RU/_white/store/sales.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
store-sales-amount = [СКИДКА] { $amount }%!
store-sales-over = [Скидка закончилась]
Loading
Loading