diff --git a/OpenRA.Mods.Cnc/Traits/ResourcePurifier.cs b/OpenRA.Mods.Cnc/Traits/ResourcePurifier.cs index 09ce8f4b03..d69f8f1be0 100644 --- a/OpenRA.Mods.Cnc/Traits/ResourcePurifier.cs +++ b/OpenRA.Mods.Cnc/Traits/ResourcePurifier.cs @@ -56,12 +56,12 @@ namespace OpenRA.Mods.Cnc.Traits base.Created(self); } - void INotifyResourceAccepted.OnResourceAccepted(Actor self, Actor refinery, int amount) + void INotifyResourceAccepted.OnResourceAccepted(Actor self, Actor refinery, ResourceTypeInfo resourceType, int count, int value) { if (IsTraitDisabled) return; - var cash = OpenRA.Mods.Common.Util.ApplyPercentageModifiers(amount, modifier); + var cash = Common.Util.ApplyPercentageModifiers(value, modifier); playerResources.GiveCash(cash); if (Info.ShowTicks && self.Info.HasTraitInfo()) diff --git a/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs b/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs index 4e119a474b..8a63d4eea2 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs @@ -58,7 +58,7 @@ namespace OpenRA.Mods.Common.Traits readonly Actor self; readonly RefineryInfo info; PlayerResources playerResources; - RefineryResourceMultiplier[] resourceMultipliers; + IEnumerable resourceValueModifiers; int currentDisplayTick = 0; int currentDisplayValue = 0; @@ -86,7 +86,7 @@ namespace OpenRA.Mods.Common.Traits void INotifyCreated.Created(Actor self) { - resourceMultipliers = self.TraitsImplementing().ToArray(); + resourceValueModifiers = self.TraitsImplementing().ToArray().Select(m => m.GetResourceValueModifier()); } public virtual Activity DockSequence(Actor harv, Actor self) @@ -100,32 +100,39 @@ namespace OpenRA.Mods.Common.Traits .Where(a => a.Trait.LinkedProc == self); } - public bool CanGiveResource(int amount) { return !info.UseStorage || info.DiscardExcessResources || playerResources.CanGiveResources(amount); } - - public void GiveResource(int amount) + int IAcceptResources.AcceptResources(ResourceTypeInfo resourceType, int count) { - amount = Util.ApplyPercentageModifiers(amount, resourceMultipliers.Select(m => m.GetModifier())); + var value = Util.ApplyPercentageModifiers(count * resourceType.ValuePerUnit, resourceValueModifiers); if (info.UseStorage) { - if (info.DiscardExcessResources) - amount = Math.Min(amount, playerResources.ResourceCapacity - playerResources.Resources); + var storageLimit = Math.Max(playerResources.ResourceCapacity - playerResources.Resources, 0); + if (!info.DiscardExcessResources) + { + // Reduce amount if needed until it will fit the available storage + while (value > storageLimit) + value = Util.ApplyPercentageModifiers(--count * resourceType.ValuePerUnit, resourceValueModifiers); + } + else + value = Math.Min(value, playerResources.ResourceCapacity - playerResources.Resources); - playerResources.GiveResources(amount); + playerResources.GiveResources(value); } else - amount = playerResources.ChangeCash(amount); + value = playerResources.ChangeCash(value); foreach (var notify in self.World.ActorsWithTrait()) { if (notify.Actor.Owner != self.Owner) continue; - notify.Trait.OnResourceAccepted(notify.Actor, self, amount); + notify.Trait.OnResourceAccepted(notify.Actor, self, resourceType, count, value); } if (info.ShowTicks) - currentDisplayValue += amount; + currentDisplayValue += value; + + return count; } void CancelDock(Actor self) diff --git a/OpenRA.Mods.Common/Traits/Harvester.cs b/OpenRA.Mods.Common/Traits/Harvester.cs index 72623d90e3..17fa0e971d 100644 --- a/OpenRA.Mods.Common/Traits/Harvester.cs +++ b/OpenRA.Mods.Common/Traits/Harvester.cs @@ -110,7 +110,6 @@ namespace OpenRA.Mods.Common.Traits readonly ResourceClaimLayer claimLayer; readonly Dictionary contents = new Dictionary(); int conditionToken = Actor.InvalidConditionToken; - HarvesterResourceMultiplier[] resourceMultipliers; [Sync] public Actor LastLinkedProc = null; @@ -145,7 +144,6 @@ namespace OpenRA.Mods.Common.Traits void INotifyCreated.Created(Actor self) { - resourceMultipliers = self.TraitsImplementing().ToArray(); UpdateCondition(self); // Note: This is queued in a FrameEndTask because otherwise the activity is dropped/overridden while moving out of a factory. @@ -242,7 +240,7 @@ namespace OpenRA.Mods.Common.Traits } // Returns true when unloading is complete - public bool TickUnload(Actor self, Actor proc) + public virtual bool TickUnload(Actor self, Actor proc) { // Wait until the next bale is ready if (--currentUnloadTicks > 0) @@ -250,21 +248,23 @@ namespace OpenRA.Mods.Common.Traits if (contents.Keys.Count > 0) { - var type = contents.First().Key; - var iao = proc.Trait(); - var count = Math.Min(contents[type], Info.BaleUnloadAmount); - var value = Util.ApplyPercentageModifiers(type.ValuePerUnit * count, resourceMultipliers.Select(m => m.GetModifier())); + var acceptResources = proc.Trait(); + foreach (var c in contents) + { + var resourceType = c.Key; + var count = Math.Min(c.Value, Info.BaleUnloadAmount); + var accepted = acceptResources.AcceptResources(resourceType, count); + if (accepted == 0) + continue; - if (!iao.CanGiveResource(value)) + contents[resourceType] -= accepted; + if (contents[resourceType] <= 0) + contents.Remove(resourceType); + + currentUnloadTicks = Info.BaleUnloadDelay; + UpdateCondition(self); return false; - - iao.GiveResource(value); - contents[type] -= count; - if (contents[type] == 0) - contents.Remove(type); - - currentUnloadTicks = Info.BaleUnloadDelay; - UpdateCondition(self); + } } return contents.Count == 0; diff --git a/OpenRA.Mods.Common/Traits/Multipliers/RefineryResourceMultiplier.cs b/OpenRA.Mods.Common/Traits/Multipliers/RefineryResourceMultiplier.cs deleted file mode 100644 index c81ae94738..0000000000 --- a/OpenRA.Mods.Common/Traits/Multipliers/RefineryResourceMultiplier.cs +++ /dev/null @@ -1,33 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. For more - * information, see COPYING. - */ -#endregion - -using OpenRA.Traits; - -namespace OpenRA.Mods.Common.Traits -{ - [Desc("Modifies the bale values delivered to this refinery.")] - public class RefineryResourceMultiplierInfo : ConditionalTraitInfo - { - [FieldLoader.Require] - [Desc("Percentage modifier to apply.")] - public readonly int Modifier = 100; - - public override object Create(ActorInitializer init) { return new RefineryResourceMultiplier(this); } - } - - public class RefineryResourceMultiplier : ConditionalTrait, Requires - { - public RefineryResourceMultiplier(RefineryResourceMultiplierInfo info) - : base(info) { } - - public int GetModifier() { return IsTraitDisabled ? 100 : Info.Modifier; } - } -} diff --git a/OpenRA.Mods.Common/Traits/Multipliers/HarvesterResourceMultiplier.cs b/OpenRA.Mods.Common/Traits/Multipliers/ResourceValueMultiplier.cs similarity index 60% rename from OpenRA.Mods.Common/Traits/Multipliers/HarvesterResourceMultiplier.cs rename to OpenRA.Mods.Common/Traits/Multipliers/ResourceValueMultiplier.cs index 00d1259923..fd52b8fbff 100644 --- a/OpenRA.Mods.Common/Traits/Multipliers/HarvesterResourceMultiplier.cs +++ b/OpenRA.Mods.Common/Traits/Multipliers/ResourceValueMultiplier.cs @@ -13,21 +13,21 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { - [Desc("Modifies the bale values of this harvester.")] - public class HarvesterResourceMultiplierInfo : ConditionalTraitInfo + [Desc("Modifies the value of resources delivered to this actor.")] + public class ResourceValueMultiplierInfo : ConditionalTraitInfo { [FieldLoader.Require] [Desc("Percentage modifier to apply.")] public readonly int Modifier = 100; - public override object Create(ActorInitializer init) { return new HarvesterResourceMultiplier(this); } + public override object Create(ActorInitializer init) { return new ResourceValueMultiplier(this); } } - public class HarvesterResourceMultiplier : ConditionalTrait, Requires + public class ResourceValueMultiplier : ConditionalTrait, IResourceValueModifier { - public HarvesterResourceMultiplier(HarvesterResourceMultiplierInfo info) + public ResourceValueMultiplier(ResourceValueMultiplierInfo info) : base(info) { } - public int GetModifier() { return IsTraitDisabled ? 100 : Info.Modifier; } + int IResourceValueModifier.GetResourceValueModifier() { return IsTraitDisabled ? 100 : Info.Modifier; } } } diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index bab2cdb664..0c4be4a6b7 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -152,7 +152,7 @@ namespace OpenRA.Mods.Common.Traits public interface INotifyDocking { void Docked(Actor self, Actor harvester); void Undocked(Actor self, Actor harvester); } [RequireExplicitImplementation] - public interface INotifyResourceAccepted { void OnResourceAccepted(Actor self, Actor refinery, int amount); } + public interface INotifyResourceAccepted { void OnResourceAccepted(Actor self, Actor refinery, ResourceTypeInfo resourceType, int count, int value); } public interface INotifyParachute { void OnParachute(Actor self); void OnLanded(Actor self); } [RequireExplicitImplementation] @@ -260,8 +260,7 @@ namespace OpenRA.Mods.Common.Traits public interface IAcceptResources { void OnDock(Actor harv, DeliverResources dockOrder); - void GiveResource(int amount); - bool CanGiveResource(int amount); + int AcceptResources(ResourceTypeInfo resourceType, int count = 1); CVec DeliveryOffset { get; } bool AllowDocking { get; } } @@ -380,6 +379,9 @@ namespace OpenRA.Mods.Common.Traits [RequireExplicitImplementation] public interface IDetectCloakedModifier { int GetDetectCloakedModifier(); } + [RequireExplicitImplementation] + public interface IResourceValueModifier { int GetResourceValueModifier(); } + [RequireExplicitImplementation] public interface ICustomMovementLayer { diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20201213/ReplaceResourceValueModifiers.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20201213/ReplaceResourceValueModifiers.cs new file mode 100644 index 0000000000..fd89274a6c --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20201213/ReplaceResourceValueModifiers.cs @@ -0,0 +1,35 @@ +#region Copyright & License Information +/* + * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Linq; + +namespace OpenRA.Mods.Common.UpdateRules.Rules +{ + public class ReplaceResourceValueModifiers : UpdateRule + { + public override string Name => "HarvesterResourceMultiplier and RefineryResourceMultiplier replaced with ResourceValueMultiplier."; + + public override string Description => "The HarvesterResourceMultiplier trait has been removed, and the RefineryResourceMultiplier trait renamed to ResourceValueMultiplier."; + + bool notified; + public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode) + { + if (actorNode.RemoveNodes("HarvesterResourceModifier") > 0 && !notified) + { + notified = true; + yield return "The HarvesterResourceMultiplier trait is no longer supported and has been removed."; + } + + actorNode.RenameChildrenMatching("RefineryResourceMultiplier", "ResourceValueMultiplier"); + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs index 9bff9b597a..31794d8990 100644 --- a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs +++ b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs @@ -90,6 +90,7 @@ namespace OpenRA.Mods.Common.UpdateRules new RemoveRenderSpritesScale(), new RemovePlaceBuildingPalette(), new ReplaceShadowPalette(), + new ReplaceResourceValueModifiers(), }) };