diff --git a/Assets/GameMain/Scripts/CustomComponent/EventNodeComponent.cs b/Assets/GameMain/Scripts/CustomComponent/EventNodeComponent.cs index b2b8f64..0a8d26c 100644 --- a/Assets/GameMain/Scripts/CustomComponent/EventNodeComponent.cs +++ b/Assets/GameMain/Scripts/CustomComponent/EventNodeComponent.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using GameFramework.DataTable; +using GeometryTD.Core; using GeometryTD.CustomEvent; using GeometryTD.DataTable; using GeometryTD.Definition; @@ -79,7 +80,7 @@ namespace GeometryTD.CustomComponent return; } - _eventFormUseCase.BindEvent(_activeEvent, _activeContext); + _eventFormUseCase.BindEvent(_activeEvent, CreateEventOptionExecutionContext(_activeContext)); GameEntry.UIRouter.OpenUI(UIFormType.EventForm); GameEntry.Event.Fire( this, @@ -236,5 +237,12 @@ namespace GeometryTD.CustomComponent return seed; } } + + private static EventOptionExecutionContext CreateEventOptionExecutionContext(RunNodeExecutionContext context) + { + return new EventOptionExecutionContext( + context?.RunSeed ?? 0, + context?.SequenceIndex ?? -1); + } } } diff --git a/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/ShopGoodsBuilder.cs b/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/ShopGoodsBuilder.cs index f2b15b8..a5c63d7 100644 --- a/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/ShopGoodsBuilder.cs +++ b/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/ShopGoodsBuilder.cs @@ -123,7 +123,7 @@ namespace GeometryTD.CustomComponent private int ResolveRandomPrice(RarityType rarity, Random random) { - return ShopPriceRuleService.ResolveRandomBuyPrice(_shopPriceRows, rarity, random); + return ShopPriceRuleService.ResolveRandomBuyPrice(rarity, random); } private static IconAreaContext BuildIconAreaContext(TowerCompItemData item) diff --git a/Assets/GameMain/Scripts/CustomComponent/PlayerInventory/PlayerInventoryTowerRosterService.cs b/Assets/GameMain/Scripts/CustomComponent/PlayerInventory/PlayerInventoryTowerRosterService.cs index 4488642..3b8c9ea 100644 --- a/Assets/GameMain/Scripts/CustomComponent/PlayerInventory/PlayerInventoryTowerRosterService.cs +++ b/Assets/GameMain/Scripts/CustomComponent/PlayerInventory/PlayerInventoryTowerRosterService.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System.Collections.Generic; +using GeometryTD.Core; using GeometryTD.CustomUtility; using GeometryTD.Definition; using UnityEngine; @@ -42,108 +43,4 @@ namespace GeometryTD.CustomComponent enduranceLoss); } } - - public static class InventoryTowerEnduranceUtility - { - public static int ReduceTowerEndurance( - BackpackInventoryData inventory, - IReadOnlyList towerInstanceIds, - float enduranceLoss) - { - float resolvedLoss = Mathf.Max(0f, enduranceLoss); - if (inventory?.Towers == null || - inventory.Towers.Count <= 0 || - resolvedLoss <= 0f || - towerInstanceIds == null || - towerInstanceIds.Count <= 0) - { - return 0; - } - - Dictionary muzzleMap = BuildComponentMap(inventory.MuzzleComponents); - Dictionary bearingMap = BuildComponentMap(inventory.BearingComponents); - Dictionary baseMap = BuildComponentMap(inventory.BaseComponents); - HashSet processedTowerIds = new HashSet(); - - int affectedCount = 0; - for (int i = 0; i < towerInstanceIds.Count; i++) - { - long towerInstanceId = towerInstanceIds[i]; - if (towerInstanceId <= 0 || !processedTowerIds.Add(towerInstanceId)) - { - continue; - } - - if (!InventoryParticipantUtility.TryGetTowerById(inventory, towerInstanceId, out TowerItemData tower) || - tower == null) - { - continue; - } - - bool towerAffected = false; - if (muzzleMap.TryGetValue(tower.MuzzleComponentInstanceId, out MuzzleCompItemData muzzleComp)) - { - towerAffected |= TryReduceComponentEndurance(muzzleComp, resolvedLoss); - } - - if (bearingMap.TryGetValue(tower.BearingComponentInstanceId, out BearingCompItemData bearingComp)) - { - towerAffected |= TryReduceComponentEndurance(bearingComp, resolvedLoss); - } - - if (baseMap.TryGetValue(tower.BaseComponentInstanceId, out BaseCompItemData baseComp)) - { - towerAffected |= TryReduceComponentEndurance(baseComp, resolvedLoss); - } - - if (towerAffected) - { - affectedCount++; - } - } - - return affectedCount; - } - - private static bool TryReduceComponentEndurance(TowerCompItemData component, float enduranceLoss) - { - if (component == null) - { - return false; - } - - float originalEndurance = component.Endurance; - float nextEndurance = Mathf.Clamp(originalEndurance - Mathf.Max(0f, enduranceLoss), 0f, 100f); - if (nextEndurance >= originalEndurance) - { - return false; - } - - component.Endurance = nextEndurance; - return true; - } - - private static Dictionary BuildComponentMap(List components) - where TComp : TowerCompItemData - { - Dictionary map = new Dictionary(); - if (components == null || components.Count <= 0) - { - return map; - } - - for (int i = 0; i < components.Count; i++) - { - TComp component = components[i]; - if (component == null || component.InstanceId <= 0) - { - continue; - } - - map[component.InstanceId] = component; - } - - return map; - } - } } diff --git a/Assets/GameMain/Scripts/CustomComponent/PlayerInventory/PlayerInventoryTradeService.cs b/Assets/GameMain/Scripts/CustomComponent/PlayerInventory/PlayerInventoryTradeService.cs index 65c569d..f68af49 100644 --- a/Assets/GameMain/Scripts/CustomComponent/PlayerInventory/PlayerInventoryTradeService.cs +++ b/Assets/GameMain/Scripts/CustomComponent/PlayerInventory/PlayerInventoryTradeService.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; -using GameFramework.DataTable; using GeometryTD.CustomUtility; -using GeometryTD.DataTable; using GeometryTD.Definition; using UnityEngine; @@ -41,16 +39,13 @@ namespace GeometryTD.CustomComponent { private readonly PlayerInventoryQueryModel _queryModel; private readonly PlayerInventoryCommandModel _commandModel; - private IDataTable _shopPriceTable; public PlayerInventoryTradeService( PlayerInventoryQueryModel queryModel, - PlayerInventoryCommandModel commandModel, - IDataTable shopPriceTable = null) + PlayerInventoryCommandModel commandModel) { _queryModel = queryModel; _commandModel = commandModel; - _shopPriceTable = shopPriceTable; } public bool TryPurchaseComponent(TowerCompItemData item, int price) @@ -179,7 +174,7 @@ namespace GeometryTD.CustomComponent }; } - if (!ShopPriceRuleService.TryResolveTowerSalePrice(tower, inventory, out int towerPrice, EnsureShopPriceTable())) + if (!ShopPriceRuleService.TryResolveTowerSalePrice(tower, inventory, out int towerPrice)) { return new PlayerInventorySaleCandidate { @@ -249,7 +244,7 @@ namespace GeometryTD.CustomComponent ItemId = component.InstanceId, IsSellable = true, IsTower = false, - Price = ShopPriceRuleService.ResolveComponentSalePrice(component, EnsureShopPriceTable()), + Price = ShopPriceRuleService.ResolveComponentSalePrice(component), FailureReason = PlayerInventorySaleFailureReason.None }; } @@ -390,11 +385,5 @@ namespace GeometryTD.CustomComponent return inventory; } - - private IDataTable EnsureShopPriceTable() - { - _shopPriceTable ??= GameEntry.DataTable.GetDataTable(); - return _shopPriceTable; - } } } diff --git a/Assets/GameMain/Scripts/DataTable/GeometryTD.Core.asmdef b/Assets/GameMain/Scripts/DataTable/GeometryTD.Core.asmdef index b2b7729..3f3c4c9 100644 --- a/Assets/GameMain/Scripts/DataTable/GeometryTD.Core.asmdef +++ b/Assets/GameMain/Scripts/DataTable/GeometryTD.Core.asmdef @@ -2,9 +2,7 @@ "name": "GeometryTD.Core", "rootNamespace": "GeometryTD.Core", "references": [ - "GUID:363c5eb08ff8e6a439b85e37b8c20d96", - "GUID:75469ad4d38634e559750d17036d5f7c", - "GUID:6055be8ebefd69e48b49212b09b47b2f" + "GUID:363c5eb08ff8e6a439b85e37b8c20d96" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Assets/GameMain/Scripts/Definition/Event/EventOptionExecutor.cs b/Assets/GameMain/Scripts/Definition/Event/EventOptionExecutor.cs index 1c4cc1d..53b7892 100644 --- a/Assets/GameMain/Scripts/Definition/Event/EventOptionExecutor.cs +++ b/Assets/GameMain/Scripts/Definition/Event/EventOptionExecutor.cs @@ -1,12 +1,21 @@ using System; using System.Collections.Generic; -using GeometryTD.CustomComponent; -using GeometryTD.Core; -using GeometryTD.Procedure; using UnityEngine; namespace GeometryTD.Core { + public sealed class EventOptionExecutionContext + { + public EventOptionExecutionContext(int runSeed, int sequenceIndex) + { + RunSeed = runSeed; + SequenceIndex = sequenceIndex; + } + + public int RunSeed { get; } + public int SequenceIndex { get; } + } + public sealed class EventOptionExecutor { public EventOptionAvailability EvaluateOption(EventOption option, BackpackInventoryData inventory) @@ -37,7 +46,7 @@ namespace GeometryTD.Core public EventOptionExecutionResult Execute( EventItem eventItem, int optionIndex, - RunNodeExecutionContext context, + EventOptionExecutionContext context, BackpackInventoryData workingInventory) { if (eventItem == null || workingInventory == null) @@ -72,7 +81,7 @@ namespace GeometryTD.Core EventEffectBase[] effects, EventItem eventItem, int optionIndex, - RunNodeExecutionContext context, + EventOptionExecutionContext context, BackpackInventoryData workingInventory, bool isRewardPhase) { @@ -143,7 +152,7 @@ namespace GeometryTD.Core RemoveRandomCompsParam param, int eventId, int optionIndex, - RunNodeExecutionContext context, + EventOptionExecutionContext context, BackpackInventoryData workingInventory, int effectIndex) { @@ -171,7 +180,7 @@ namespace GeometryTD.Core AddRandomCompsParam param, int eventId, int optionIndex, - RunNodeExecutionContext context, + EventOptionExecutionContext context, BackpackInventoryData workingInventory, int effectIndex) { @@ -181,12 +190,12 @@ namespace GeometryTD.Core return; } - if (GameEntry.InventoryGeneration == null) + if (CoreServiceHub.InventoryGeneration == null) { throw new InvalidOperationException("Event component generation requires InventoryGenerationComponent."); } - IReadOnlyList generatedComponents = GameEntry.InventoryGeneration.BuildEventRewardComponents( + IReadOnlyList generatedComponents = CoreServiceHub.InventoryGeneration.BuildEventRewardComponents( addCount, param.MinRarity, param.MaxRarity, @@ -205,7 +214,7 @@ namespace GeometryTD.Core DamageRandomTowerEnduranceParam param, int eventId, int optionIndex, - RunNodeExecutionContext context, + EventOptionExecutionContext context, BackpackInventoryData workingInventory, int effectIndex) { @@ -272,7 +281,7 @@ namespace GeometryTD.Core } } - private static bool RollProbability(int eventId, int optionIndex, RunNodeExecutionContext context, float probability) + private static bool RollProbability(int eventId, int optionIndex, EventOptionExecutionContext context, float probability) { float clampedProbability = Mathf.Clamp01(probability); if (clampedProbability >= 1f) @@ -290,7 +299,7 @@ namespace GeometryTD.Core } private static System.Random CreateRandom( - RunNodeExecutionContext context, + EventOptionExecutionContext context, int eventId, int optionIndex, int effectIndex, diff --git a/Assets/GameMain/Scripts/Definition/Ports.meta b/Assets/GameMain/Scripts/Definition/Ports.meta new file mode 100644 index 0000000..95f82a5 --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9aeb92ccac2068f489dcbd0200417463 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Definition/Ports/CoreServiceHub.cs b/Assets/GameMain/Scripts/Definition/Ports/CoreServiceHub.cs new file mode 100644 index 0000000..4a9d1db --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/CoreServiceHub.cs @@ -0,0 +1,31 @@ +using System; + +namespace GeometryTD.Core +{ + public static class CoreServiceHub + { + public static IPlayerInventoryManager PlayerInventory { get; private set; } + public static IInventoryGenerationManager InventoryGeneration { get; private set; } + public static IEventFlowManager EventFlow { get; private set; } + public static ISpriteCacheService SpriteCache { get; private set; } + public static IStaticDataService StaticData { get; private set; } + public static ITextService TextService { get; private set; } + + public static void Bind( + IPlayerInventoryManager playerInventory, + IInventoryGenerationManager inventoryGeneration, + IEventFlowManager eventFlow, + ISpriteCacheService spriteCache, + IStaticDataService staticData, + ITextService textService) + { + PlayerInventory = playerInventory ?? throw new ArgumentNullException(nameof(playerInventory)); + InventoryGeneration = inventoryGeneration ?? throw new + ArgumentNullException(nameof(inventoryGeneration)); + EventFlow = eventFlow ?? throw new ArgumentNullException(nameof(eventFlow)); + SpriteCache = spriteCache ?? throw new ArgumentNullException(nameof(spriteCache)); + StaticData = staticData ?? throw new ArgumentNullException(nameof(staticData)); + TextService = textService ?? throw new ArgumentNullException(nameof(textService)); + } + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Definition/Ports/CoreServiceHub.cs.meta b/Assets/GameMain/Scripts/Definition/Ports/CoreServiceHub.cs.meta new file mode 100644 index 0000000..4a030f5 --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/CoreServiceHub.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 95f8a75dcf78e4545b36f1e24b92d82e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Definition/Ports/IEventFlowManager.cs b/Assets/GameMain/Scripts/Definition/Ports/IEventFlowManager.cs new file mode 100644 index 0000000..2b5582f --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/IEventFlowManager.cs @@ -0,0 +1,7 @@ +namespace GeometryTD.Core +{ + public interface IEventFlowManager + { + void EndEvent(); + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Definition/Ports/IEventFlowManager.cs.meta b/Assets/GameMain/Scripts/Definition/Ports/IEventFlowManager.cs.meta new file mode 100644 index 0000000..00a1dbf --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/IEventFlowManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c14fccc4cf6d239489afdc5b302c03b9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Definition/Ports/IInventoryGenerationManager.cs b/Assets/GameMain/Scripts/Definition/Ports/IInventoryGenerationManager.cs new file mode 100644 index 0000000..3b2fbc5 --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/IInventoryGenerationManager.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace GeometryTD.Core +{ + public interface IInventoryGenerationManager + { + IReadOnlyList BuildEventRewardComponents( + int count, + RarityType minRarity, + RarityType maxRarity, + int runSeed, + int sequenceIndex, + int eventId, + int optionIndex, + int effectIndex); + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Definition/Ports/IInventoryGenerationManager.cs.meta b/Assets/GameMain/Scripts/Definition/Ports/IInventoryGenerationManager.cs.meta new file mode 100644 index 0000000..a04c6cf --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/IInventoryGenerationManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ba83daa081633074ab92ff9ad75c9c52 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Definition/Ports/IInventoryManager.cs b/Assets/GameMain/Scripts/Definition/Ports/IInventoryManager.cs new file mode 100644 index 0000000..ac375d3 --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/IInventoryManager.cs @@ -0,0 +1,8 @@ +namespace GeometryTD.Core +{ + public interface IPlayerInventoryManager + { + BackpackInventoryData GetInventorySnapshot(); + void ReplaceInventorySnapshot(BackpackInventoryData snapshot); + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Definition/Ports/IInventoryManager.cs.meta b/Assets/GameMain/Scripts/Definition/Ports/IInventoryManager.cs.meta new file mode 100644 index 0000000..1a02964 --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/IInventoryManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0ce0e4176795db941a0f7ed57065f73d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Definition/Ports/ISpriteCacheService.cs b/Assets/GameMain/Scripts/Definition/Ports/ISpriteCacheService.cs new file mode 100644 index 0000000..aa8dcd1 --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/ISpriteCacheService.cs @@ -0,0 +1,11 @@ + +using System; +using UnityEngine; + +namespace GeometryTD.Core +{ + public interface ISpriteCacheService + { + void Get(string key, Action callback); + } +} diff --git a/Assets/GameMain/Scripts/Definition/Ports/ISpriteCacheService.cs.meta b/Assets/GameMain/Scripts/Definition/Ports/ISpriteCacheService.cs.meta new file mode 100644 index 0000000..5654892 --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/ISpriteCacheService.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 675e9ac521922ac46b3b7afe4973a706 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Definition/Ports/IStaticDataService.cs b/Assets/GameMain/Scripts/Definition/Ports/IStaticDataService.cs new file mode 100644 index 0000000..c4cc99b --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/IStaticDataService.cs @@ -0,0 +1,12 @@ +namespace GeometryTD.Core +{ + public interface IStaticDataService + { + DRLevel GetLevel(int id); + DRTag GetTag(int id); + DRShopPrice[] GetAllShopPrices(); + DRBearingComp[] GetAllBearingComps(); + DRBaseComp[] GetAllBaseComps(); + DRMuzzleComp[] GetAllMuzzleComps(); + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Definition/Ports/IStaticDataService.cs.meta b/Assets/GameMain/Scripts/Definition/Ports/IStaticDataService.cs.meta new file mode 100644 index 0000000..d86f844 --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/IStaticDataService.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: db37b943863752b41a8a0deef641dca6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Definition/Ports/ITextService.cs b/Assets/GameMain/Scripts/Definition/Ports/ITextService.cs new file mode 100644 index 0000000..91bd664 --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/ITextService.cs @@ -0,0 +1,7 @@ +namespace GeometryTD.Core +{ + public interface ITextService + { + string Get(string key, params object[] args); + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Definition/Ports/ITextService.cs.meta b/Assets/GameMain/Scripts/Definition/Ports/ITextService.cs.meta new file mode 100644 index 0000000..dcb6bcf --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Ports/ITextService.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9440fb32740fa50409ce370f9eab4d6d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Definition/Run.meta b/Assets/GameMain/Scripts/Definition/Run.meta new file mode 100644 index 0000000..58952b5 --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Run.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f9d6ff9eff8570b4a96f296f9b107baa +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Definition/Run/RunContracts.cs b/Assets/GameMain/Scripts/Definition/Run/RunContracts.cs new file mode 100644 index 0000000..7ba3e40 --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Run/RunContracts.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; + +namespace GeometryTD.Core +{ + public enum RunNodeType + { + None = 0, + Combat = 1, + Event = 2, + Shop = 3, + BossCombat = 4 + } + + public enum RunNodeCompletionStatus + { + None = 0, + Completed = 1, + Exception = 2 + } + + [Serializable] + public sealed class RunItemState + { + public int ItemId { get; set; } + public int StackCount { get; set; } + + public RunItemState Clone() + { + return new RunItemState + { + ItemId = ItemId, + StackCount = StackCount + }; + } + } + + [Serializable] + public sealed class RunNodeExecutionContext + { + public string RunId { get; set; } + public int RunSeed { get; set; } + public int NodeId { get; set; } + public RunNodeType NodeType { get; set; } + public int SequenceIndex { get; set; } + public LevelThemeType ThemeType { get; set; } + public int ThemeStageIndex { get; set; } + public List CurrentThemePool { get; set; } = new List(); + public List ThemeHistory { get; set; } = new List(); + public int CurrentNodeContinueChallengeLayer { get; set; } + public List RunItems { get; set; } = new List(); + + public RunNodeExecutionContext Clone() + { + return new RunNodeExecutionContext + { + RunId = RunId, + RunSeed = RunSeed, + NodeId = NodeId, + NodeType = NodeType, + SequenceIndex = SequenceIndex, + ThemeType = ThemeType, + ThemeStageIndex = ThemeStageIndex, + CurrentThemePool = RunStateCloneUtility.CloneThemeList(CurrentThemePool), + ThemeHistory = RunStateCloneUtility.CloneThemeList(ThemeHistory), + CurrentNodeContinueChallengeLayer = CurrentNodeContinueChallengeLayer, + RunItems = RunStateCloneUtility.CloneRunItems(RunItems) + }; + } + + public RunNodeCompletionSnapshot CreateCompletionSnapshot(BackpackInventoryData inventorySnapshot) + { + return new RunNodeCompletionSnapshot + { + InventorySnapshot = InventoryCloneUtility.CloneInventory(inventorySnapshot), + ThemeType = ThemeType, + ThemeStageIndex = ThemeStageIndex, + CurrentThemePool = RunStateCloneUtility.CloneThemeList(CurrentThemePool), + ThemeHistory = RunStateCloneUtility.CloneThemeList(ThemeHistory), + CurrentNodeContinueChallengeLayer = CurrentNodeContinueChallengeLayer, + RunItems = RunStateCloneUtility.CloneRunItems(RunItems) + }; + } + } + + [Serializable] + public sealed class RunNodeCompletionSnapshot + { + public BackpackInventoryData InventorySnapshot { get; set; } + public LevelThemeType ThemeType { get; set; } + public int ThemeStageIndex { get; set; } + public List CurrentThemePool { get; set; } = new List(); + public List ThemeHistory { get; set; } = new List(); + public int CurrentNodeContinueChallengeLayer { get; set; } + public List RunItems { get; set; } = new List(); + + public RunNodeCompletionSnapshot Clone() + { + return new RunNodeCompletionSnapshot + { + InventorySnapshot = InventoryCloneUtility.CloneInventory(InventorySnapshot), + ThemeType = ThemeType, + ThemeStageIndex = ThemeStageIndex, + CurrentThemePool = RunStateCloneUtility.CloneThemeList(CurrentThemePool), + ThemeHistory = RunStateCloneUtility.CloneThemeList(ThemeHistory), + CurrentNodeContinueChallengeLayer = CurrentNodeContinueChallengeLayer, + RunItems = RunStateCloneUtility.CloneRunItems(RunItems) + }; + } + } + + public static class RunStateCloneUtility + { + public static List CloneThemeList(IReadOnlyList source) + { + List cloned = new List(); + if (source == null) + { + return cloned; + } + + for (int i = 0; i < source.Count; i++) + { + cloned.Add(source[i]); + } + + return cloned; + } + + public static List CloneRunItems(IReadOnlyList source) + { + List cloned = new List(); + if (source == null) + { + return cloned; + } + + for (int i = 0; i < source.Count; i++) + { + RunItemState item = source[i]; + if (item != null) + { + cloned.Add(item.Clone()); + } + } + + return cloned; + } + } +} diff --git a/Assets/GameMain/Scripts/Definition/Run/RunContracts.cs.meta b/Assets/GameMain/Scripts/Definition/Run/RunContracts.cs.meta new file mode 100644 index 0000000..ac26223 --- /dev/null +++ b/Assets/GameMain/Scripts/Definition/Run/RunContracts.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e73cd16e1283cc94f903bb3d7728f543 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/EnemyTagStatusRuntime.cs b/Assets/GameMain/Scripts/Definition/Tag/Combat/EnemyTagStatusRuntime.cs similarity index 98% rename from Assets/GameMain/Scripts/Entity/EntityLogic/EnemyTagStatusRuntime.cs rename to Assets/GameMain/Scripts/Definition/Tag/Combat/EnemyTagStatusRuntime.cs index 9618fde..5147604 100644 --- a/Assets/GameMain/Scripts/Entity/EntityLogic/EnemyTagStatusRuntime.cs +++ b/Assets/GameMain/Scripts/Definition/Tag/Combat/EnemyTagStatusRuntime.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; -using GeometryTD.Definition; +using GeometryTD.Core; using UnityEngine; -namespace GeometryTD.Entity +namespace GeometryTD.Core { public sealed class EnemyTagStatusRuntime { diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/EnemyTagStatusRuntime.cs.meta b/Assets/GameMain/Scripts/Definition/Tag/Combat/EnemyTagStatusRuntime.cs.meta similarity index 100% rename from Assets/GameMain/Scripts/Entity/EntityLogic/EnemyTagStatusRuntime.cs.meta rename to Assets/GameMain/Scripts/Definition/Tag/Combat/EnemyTagStatusRuntime.cs.meta diff --git a/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/EnemyStatusTagEffectBase.cs b/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/EnemyStatusTagEffectBase.cs index 310f5bd..9c6fc89 100644 --- a/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/EnemyStatusTagEffectBase.cs +++ b/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/EnemyStatusTagEffectBase.cs @@ -1,5 +1,4 @@ using System; -using GeometryTD.Entity; namespace GeometryTD.Core { diff --git a/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/FireTagEffect.cs b/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/FireTagEffect.cs index 1c9c158..946e0d1 100644 --- a/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/FireTagEffect.cs +++ b/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/FireTagEffect.cs @@ -1,5 +1,4 @@ using System; -using GeometryTD.Entity; using UnityEngine; namespace GeometryTD.Core diff --git a/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/IEnemyStatusTagEffect.cs b/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/IEnemyStatusTagEffect.cs index a60f626..8ba9f1c 100644 --- a/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/IEnemyStatusTagEffect.cs +++ b/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/IEnemyStatusTagEffect.cs @@ -1,5 +1,4 @@ using System; -using GeometryTD.Entity; namespace GeometryTD.Core { diff --git a/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/IceTagEffect.cs b/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/IceTagEffect.cs index f79244a..4e77c41 100644 --- a/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/IceTagEffect.cs +++ b/Assets/GameMain/Scripts/Definition/Tag/Combat/StatusEffects/IceTagEffect.cs @@ -1,5 +1,4 @@ using System; -using GeometryTD.Entity; using UnityEngine; namespace GeometryTD.Core diff --git a/Assets/GameMain/Scripts/Definition/Tag/Presentation/TagDisplayUtility.cs b/Assets/GameMain/Scripts/Definition/Tag/Presentation/TagDisplayUtility.cs index 082abd2..3994e2d 100644 --- a/Assets/GameMain/Scripts/Definition/Tag/Presentation/TagDisplayUtility.cs +++ b/Assets/GameMain/Scripts/Definition/Tag/Presentation/TagDisplayUtility.cs @@ -13,17 +13,10 @@ namespace GeometryTD.Core return string.Empty; } - if (GameEntry.DataTable != null) + DRTag tagRow = CoreServiceHub.StaticData.GetTag((int)tagType); + if (tagRow != null && !string.IsNullOrWhiteSpace(tagRow.Name)) { - var tagTable = GameEntry.DataTable.GetDataTable(); - if (tagTable != null) - { - DRTag tagRow = tagTable.GetDataRow((int)tagType); - if (tagRow != null && !string.IsNullOrWhiteSpace(tagRow.Name)) - { - return tagRow.Name; - } - } + return tagRow.Name; } return tagType.ToString(); @@ -171,4 +164,4 @@ namespace GeometryTD.Core return string.Empty; } } -} +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Event/Game/NodeEnterEventArgs.cs b/Assets/GameMain/Scripts/Event/Game/NodeEnterEventArgs.cs index dc12343..70eddf0 100644 --- a/Assets/GameMain/Scripts/Event/Game/NodeEnterEventArgs.cs +++ b/Assets/GameMain/Scripts/Event/Game/NodeEnterEventArgs.cs @@ -1,6 +1,5 @@ using GameFramework; using GameFramework.Event; -using GeometryTD.Procedure; namespace GeometryTD.Core { diff --git a/Assets/GameMain/Scripts/Event/Game/NodeMapNodeEnterRequestedEventArgs.cs b/Assets/GameMain/Scripts/Event/Game/NodeMapNodeEnterRequestedEventArgs.cs index 5767f36..3abf059 100644 --- a/Assets/GameMain/Scripts/Event/Game/NodeMapNodeEnterRequestedEventArgs.cs +++ b/Assets/GameMain/Scripts/Event/Game/NodeMapNodeEnterRequestedEventArgs.cs @@ -1,6 +1,5 @@ using GameFramework; using GameFramework.Event; -using GeometryTD.Procedure; namespace GeometryTD.Core { diff --git a/Assets/GameMain/Scripts/Procedure/Base/ProcedurePreload.cs b/Assets/GameMain/Scripts/Procedure/Base/ProcedurePreload.cs index 050ff44..25b773e 100644 --- a/Assets/GameMain/Scripts/Procedure/Base/ProcedurePreload.cs +++ b/Assets/GameMain/Scripts/Procedure/Base/ProcedurePreload.cs @@ -50,8 +50,6 @@ namespace GeometryTD.Procedure GameEntry.Event.Subscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure); GameEntry.Event.Subscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess); GameEntry.Event.Subscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure); - GameEntry.Event.Subscribe(LoadDictionarySuccessEventArgs.EventId, OnLoadDictionarySuccess); - GameEntry.Event.Subscribe(LoadDictionaryFailureEventArgs.EventId, OnLoadDictionaryFailure); _loadedFlag.Clear(); @@ -64,8 +62,6 @@ namespace GeometryTD.Procedure GameEntry.Event.Unsubscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure); GameEntry.Event.Unsubscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess); GameEntry.Event.Unsubscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure); - GameEntry.Event.Unsubscribe(LoadDictionarySuccessEventArgs.EventId, OnLoadDictionarySuccess); - GameEntry.Event.Unsubscribe(LoadDictionaryFailureEventArgs.EventId, OnLoadDictionaryFailure); base.OnLeave(procedureOwner, isShutdown); } @@ -97,9 +93,6 @@ namespace GeometryTD.Procedure LoadDataTable(dataTableName); } - // Preload dictionaries - //LoadDictionary("Default"); - // Preload fonts LoadFont("MainFont"); LoadTMPFont("MainTMPFont"); @@ -119,13 +112,6 @@ namespace GeometryTD.Procedure GameEntry.DataTable.LoadDataTable(dataTableName, dataTableAssetName, this); } - private void LoadDictionary(string dictionaryName) - { - string dictionaryAssetName = AssetUtility.GetDictionaryAsset(dictionaryName, false); - _loadedFlag.Add(dictionaryAssetName, false); - GameEntry.Localization.ReadData(dictionaryAssetName, this); - } - private void LoadFont(string fontName) { _loadedFlag.Add(Utility.Text.Format("Font.{0}", fontName), false); @@ -209,29 +195,5 @@ namespace GeometryTD.Procedure Log.Error("Can not load data table '{0}' from '{1}' with error message '{2}'.", ne.DataTableAssetName, ne.DataTableAssetName, ne.ErrorMessage); } - - private void OnLoadDictionarySuccess(object sender, GameEventArgs e) - { - LoadDictionarySuccessEventArgs ne = (LoadDictionarySuccessEventArgs)e; - if (ne.UserData != this) - { - return; - } - - _loadedFlag[ne.DictionaryAssetName] = true; - Log.Info("Load dictionary '{0}' OK.", ne.DictionaryAssetName); - } - - private void OnLoadDictionaryFailure(object sender, GameEventArgs e) - { - LoadDictionaryFailureEventArgs ne = (LoadDictionaryFailureEventArgs)e; - if (ne.UserData != this) - { - return; - } - - Log.Error("Can not load dictionary '{0}' from '{1}' with error message '{2}'.", ne.DictionaryAssetName, - ne.DictionaryAssetName, ne.ErrorMessage); - } } } diff --git a/Assets/GameMain/Scripts/Procedure/ProcedureMain/RunModel.cs b/Assets/GameMain/Scripts/Procedure/ProcedureMain/RunModel.cs index 720d46d..aa3d730 100644 --- a/Assets/GameMain/Scripts/Procedure/ProcedureMain/RunModel.cs +++ b/Assets/GameMain/Scripts/Procedure/ProcedureMain/RunModel.cs @@ -1,20 +1,10 @@ using System; using System.Collections.Generic; -using GeometryTD.CustomUtility; -using GeometryTD.Definition; +using GeometryTD.Core; using GeometryTD.Factory; namespace GeometryTD.Procedure { - public enum RunNodeType - { - None = 0, - Combat = 1, - Event = 2, - Shop = 3, - BossCombat = 4 - } - public enum RunNodeStatus { Locked = 0, @@ -24,13 +14,6 @@ namespace GeometryTD.Procedure Skipped = 4 } - public enum RunNodeCompletionStatus - { - None = 0, - Completed = 1, - Exception = 2 - } - [Serializable] public sealed class RunNodeSeed { @@ -65,96 +48,6 @@ namespace GeometryTD.Procedure } } - [Serializable] - public sealed class RunItemState - { - public int ItemId { get; set; } - public int StackCount { get; set; } - - internal RunItemState Clone() - { - return new RunItemState - { - ItemId = ItemId, - StackCount = StackCount - }; - } - } - - [Serializable] - public sealed class RunNodeExecutionContext - { - public string RunId { get; set; } - public int RunSeed { get; set; } - public int NodeId { get; set; } - public RunNodeType NodeType { get; set; } - public int SequenceIndex { get; set; } - public LevelThemeType ThemeType { get; set; } - public int ThemeStageIndex { get; set; } - public List CurrentThemePool { get; set; } = new List(); - public List ThemeHistory { get; set; } = new List(); - public int CurrentNodeContinueChallengeLayer { get; set; } - public List RunItems { get; set; } = new List(); - - internal RunNodeExecutionContext Clone() - { - return new RunNodeExecutionContext - { - RunId = RunId, - RunSeed = RunSeed, - NodeId = NodeId, - NodeType = NodeType, - SequenceIndex = SequenceIndex, - ThemeType = ThemeType, - ThemeStageIndex = ThemeStageIndex, - CurrentThemePool = RunStateCloneUtility.CloneThemeList(CurrentThemePool), - ThemeHistory = RunStateCloneUtility.CloneThemeList(ThemeHistory), - CurrentNodeContinueChallengeLayer = CurrentNodeContinueChallengeLayer, - RunItems = RunStateCloneUtility.CloneRunItems(RunItems) - }; - } - - public RunNodeCompletionSnapshot CreateCompletionSnapshot(BackpackInventoryData inventorySnapshot) - { - return new RunNodeCompletionSnapshot - { - InventorySnapshot = InventoryCloneUtility.CloneInventory(inventorySnapshot), - ThemeType = ThemeType, - ThemeStageIndex = ThemeStageIndex, - CurrentThemePool = RunStateCloneUtility.CloneThemeList(CurrentThemePool), - ThemeHistory = RunStateCloneUtility.CloneThemeList(ThemeHistory), - CurrentNodeContinueChallengeLayer = CurrentNodeContinueChallengeLayer, - RunItems = RunStateCloneUtility.CloneRunItems(RunItems) - }; - } - } - - [Serializable] - public sealed class RunNodeCompletionSnapshot - { - public BackpackInventoryData InventorySnapshot { get; set; } - public LevelThemeType ThemeType { get; set; } - public int ThemeStageIndex { get; set; } - public List CurrentThemePool { get; set; } = new List(); - public List ThemeHistory { get; set; } = new List(); - public int CurrentNodeContinueChallengeLayer { get; set; } - public List RunItems { get; set; } = new List(); - - internal RunNodeCompletionSnapshot Clone() - { - return new RunNodeCompletionSnapshot - { - InventorySnapshot = InventoryCloneUtility.CloneInventory(InventorySnapshot), - ThemeType = ThemeType, - ThemeStageIndex = ThemeStageIndex, - CurrentThemePool = RunStateCloneUtility.CloneThemeList(CurrentThemePool), - ThemeHistory = RunStateCloneUtility.CloneThemeList(ThemeHistory), - CurrentNodeContinueChallengeLayer = CurrentNodeContinueChallengeLayer, - RunItems = RunStateCloneUtility.CloneRunItems(RunItems) - }; - } - } - [Serializable] public sealed class RunState { @@ -314,42 +207,4 @@ namespace GeometryTD.Procedure } } - internal static class RunStateCloneUtility - { - internal static List CloneThemeList(IReadOnlyList source) - { - List cloned = new List(); - if (source == null) - { - return cloned; - } - - for (int i = 0; i < source.Count; i++) - { - cloned.Add(source[i]); - } - - return cloned; - } - - internal static List CloneRunItems(IReadOnlyList source) - { - List cloned = new List(); - if (source == null) - { - return cloned; - } - - for (int i = 0; i < source.Count; i++) - { - RunItemState item = source[i]; - if (item != null) - { - cloned.Add(item.Clone()); - } - } - - return cloned; - } - } } diff --git a/Assets/GameMain/Scripts/UI/Game/UseCase/EventFormUseCase.cs b/Assets/GameMain/Scripts/UI/Game/UseCase/EventFormUseCase.cs index 39ea5b7..96d9743 100644 --- a/Assets/GameMain/Scripts/UI/Game/UseCase/EventFormUseCase.cs +++ b/Assets/GameMain/Scripts/UI/Game/UseCase/EventFormUseCase.cs @@ -1,5 +1,5 @@ +using GeometryTD.Core; using GeometryTD.Definition; -using GeometryTD.Procedure; using UnityGameFramework.Runtime; namespace GeometryTD.UI @@ -7,15 +7,15 @@ namespace GeometryTD.UI public class EventFormUseCase : IUIUseCase { private EventItem _currentEvent; - private RunNodeExecutionContext _currentContext; + private EventOptionExecutionContext _currentContext; private readonly EventOptionExecutor _executor = new EventOptionExecutor(); public void BindEvent( EventItem eventItem, - RunNodeExecutionContext context) + EventOptionExecutionContext context) { _currentEvent = eventItem; - _currentContext = context != null ? context.Clone() : null; + _currentContext = context; } public void Clear() diff --git a/Assets/GameMain/Scripts/Utility/AssetUtility.cs b/Assets/GameMain/Scripts/Utility/AssetUtility.cs index bca0674..664c5bb 100644 --- a/Assets/GameMain/Scripts/Utility/AssetUtility.cs +++ b/Assets/GameMain/Scripts/Utility/AssetUtility.cs @@ -15,12 +15,6 @@ namespace GeometryTD.Core return Utility.Text.Format("Assets/GameMain/DataTables/{0}.{1}", assetName, fromBytes ? "bytes" : "txt"); } - public static string GetDictionaryAsset(string assetName, bool fromBytes) - { - return Utility.Text.Format("Assets/GameMain/Localization/{0}/Dictionaries/{1}.{2}", - GameEntry.Localization.Language, assetName, fromBytes ? "bytes" : "xml"); - } - public static string GetFontAsset(string assetName) { return Utility.Text.Format("Assets/GameMain/Fonts/{0}.ttf", assetName); diff --git a/Assets/GameMain/Scripts/Utility/IconColorGenerator.cs b/Assets/GameMain/Scripts/Utility/IconColorGenerator.cs index d5399f1..9d672c4 100644 --- a/Assets/GameMain/Scripts/Utility/IconColorGenerator.cs +++ b/Assets/GameMain/Scripts/Utility/IconColorGenerator.cs @@ -121,7 +121,7 @@ namespace GeometryTD.Core private static void TryRefreshRangesFromDataTables() { - if (GameEntry.DataTable == null) + if (CoreServiceHub.StaticData == null) { return; } @@ -154,13 +154,7 @@ namespace GeometryTD.Core attackDamageRange = _attackDamageRange; damageRandomRateRange = _damageRandomRateRange; - IDataTable dataTable = GameEntry.DataTable.GetDataTable(); - if (dataTable == null || dataTable.Count <= 0) - { - return false; - } - - DRMuzzleComp[] rows = dataTable.GetAllDataRows(); + DRMuzzleComp[] rows = CoreServiceHub.StaticData.GetAllMuzzleComps(); if (rows == null || rows.Length <= 0) { return false; @@ -201,13 +195,7 @@ namespace GeometryTD.Core rotateSpeedRange = _rotateSpeedRange; attackRangeRange = _attackRangeRange; - IDataTable dataTable = GameEntry.DataTable.GetDataTable(); - if (dataTable == null || dataTable.Count <= 0) - { - return false; - } - - DRBearingComp[] rows = dataTable.GetAllDataRows(); + DRBearingComp[] rows = CoreServiceHub.StaticData.GetAllBearingComps(); if (rows == null || rows.Length <= 0) { return false; @@ -246,13 +234,7 @@ namespace GeometryTD.Core { attackSpeedRange = _attackSpeedRange; - IDataTable dataTable = GameEntry.DataTable.GetDataTable(); - if (dataTable == null || dataTable.Count <= 0) - { - return false; - } - - DRBaseComp[] rows = dataTable.GetAllDataRows(); + DRBaseComp[] rows = CoreServiceHub.StaticData.GetAllBaseComps(); if (rows == null || rows.Length <= 0) { return false; diff --git a/Assets/GameMain/Scripts/Utility/InventoryTowerEnduranceUtility.cs b/Assets/GameMain/Scripts/Utility/InventoryTowerEnduranceUtility.cs new file mode 100644 index 0000000..5ca3117 --- /dev/null +++ b/Assets/GameMain/Scripts/Utility/InventoryTowerEnduranceUtility.cs @@ -0,0 +1,109 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace GeometryTD.Core +{ + public static class InventoryTowerEnduranceUtility + { + public static int ReduceTowerEndurance( + BackpackInventoryData inventory, + IReadOnlyList towerInstanceIds, + float enduranceLoss) + { + float resolvedLoss = Mathf.Max(0f, enduranceLoss); + if (inventory?.Towers == null || + inventory.Towers.Count <= 0 || + resolvedLoss <= 0f || + towerInstanceIds == null || + towerInstanceIds.Count <= 0) + { + return 0; + } + + Dictionary muzzleMap = BuildComponentMap(inventory.MuzzleComponents); + Dictionary bearingMap = BuildComponentMap(inventory.BearingComponents); + Dictionary baseMap = BuildComponentMap(inventory.BaseComponents); + HashSet processedTowerIds = new HashSet(); + + int affectedCount = 0; + for (int i = 0; i < towerInstanceIds.Count; i++) + { + long towerInstanceId = towerInstanceIds[i]; + if (towerInstanceId <= 0 || !processedTowerIds.Add(towerInstanceId)) + { + continue; + } + + if (!InventoryParticipantUtility.TryGetTowerById(inventory, towerInstanceId, out TowerItemData tower) || + tower == null) + { + continue; + } + + bool towerAffected = false; + if (muzzleMap.TryGetValue(tower.MuzzleComponentInstanceId, out MuzzleCompItemData muzzleComp)) + { + towerAffected |= TryReduceComponentEndurance(muzzleComp, resolvedLoss); + } + + if (bearingMap.TryGetValue(tower.BearingComponentInstanceId, out BearingCompItemData bearingComp)) + { + towerAffected |= TryReduceComponentEndurance(bearingComp, resolvedLoss); + } + + if (baseMap.TryGetValue(tower.BaseComponentInstanceId, out BaseCompItemData baseComp)) + { + towerAffected |= TryReduceComponentEndurance(baseComp, resolvedLoss); + } + + if (towerAffected) + { + affectedCount++; + } + } + + return affectedCount; + } + + private static bool TryReduceComponentEndurance(TowerCompItemData component, float enduranceLoss) + { + if (component == null) + { + return false; + } + + float originalEndurance = component.Endurance; + float nextEndurance = Mathf.Clamp(originalEndurance - Mathf.Max(0f, enduranceLoss), 0f, 100f); + if (nextEndurance >= originalEndurance) + { + return false; + } + + component.Endurance = nextEndurance; + return true; + } + + private static Dictionary BuildComponentMap(List components) + where TComp : TowerCompItemData + { + Dictionary map = new Dictionary(); + if (components == null || components.Count <= 0) + { + return map; + } + + for (int i = 0; i < components.Count; i++) + { + TComp component = components[i]; + if (component == null || component.InstanceId <= 0) + { + continue; + } + + map[component.InstanceId] = component; + } + + return map; + } + } +} diff --git a/Assets/GameMain/Scripts/Utility/InventoryTowerEnduranceUtility.cs.meta b/Assets/GameMain/Scripts/Utility/InventoryTowerEnduranceUtility.cs.meta new file mode 100644 index 0000000..f8fbd6e --- /dev/null +++ b/Assets/GameMain/Scripts/Utility/InventoryTowerEnduranceUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: abb0c22f9d11c6b4aae1d76fede68320 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Utility/ShopPriceRuleService.cs b/Assets/GameMain/Scripts/Utility/ShopPriceRuleService.cs index e67646c..c6d6d93 100644 --- a/Assets/GameMain/Scripts/Utility/ShopPriceRuleService.cs +++ b/Assets/GameMain/Scripts/Utility/ShopPriceRuleService.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using GameFramework.DataTable; -using GeometryTD.Core; using UnityEngine; using Random = System.Random; @@ -9,9 +7,11 @@ namespace GeometryTD.Core { public static class ShopPriceRuleService { - public static int ResolveRandomBuyPrice(IReadOnlyList shopPriceRows, RarityType rarity, Random random) + private static Dictionary _shopPriceByRarity; + + public static int ResolveRandomBuyPrice(RarityType rarity, Random random) { - if (!TryFindPriceRow(shopPriceRows, rarity, out DRShopPrice row) || row == null) + if (!TryFindPriceRow(rarity, out DRShopPrice row) || row == null) { return 0; } @@ -21,21 +21,20 @@ namespace GeometryTD.Core return random != null ? random.Next(min, max + 1) : min; } - public static int ResolveComponentSalePrice(TowerCompItemData component, IDataTable shopPriceTable = null) + public static int ResolveComponentSalePrice(TowerCompItemData component) { if (component == null) { return 0; } - return ResolveBasePrice(component.Rarity, shopPriceTable); + return ResolveBasePrice(component.Rarity); } public static bool TryResolveTowerSalePrice( TowerItemData tower, BackpackInventoryData inventory, - out int price, - IDataTable shopPriceTable = null) + out int price) { price = 0; if (tower == null || inventory == null) @@ -50,22 +49,15 @@ namespace GeometryTD.Core return false; } - price = ResolveComponentSalePrice(muzzleComp, shopPriceTable) + - ResolveComponentSalePrice(bearingComp, shopPriceTable) + - ResolveComponentSalePrice(baseComp, shopPriceTable); + price = ResolveComponentSalePrice(muzzleComp) + + ResolveComponentSalePrice(bearingComp) + + ResolveComponentSalePrice(baseComp); return price > 0; } - public static int ResolveBasePrice(RarityType rarity, IDataTable shopPriceTable = null) + public static int ResolveBasePrice(RarityType rarity) { - IDataTable resolvedTable = shopPriceTable ?? GameEntry.DataTable.GetDataTable(); - if (resolvedTable == null) - { - return 0; - } - - DRShopPrice[] rows = resolvedTable.GetAllDataRows(); - if (!TryFindPriceRow(rows, rarity, out DRShopPrice row) || row == null) + if (!TryFindPriceRow(rarity, out DRShopPrice row) || row == null) { return 0; } @@ -75,25 +67,49 @@ namespace GeometryTD.Core return Mathf.RoundToInt((min + max) * 0.5f); } - private static bool TryFindPriceRow(IReadOnlyList rows, RarityType rarity, out DRShopPrice result) + public static void ClearCache() { - result = null; - if (rows == null) + _shopPriceByRarity = null; + } + + private static bool TryFindPriceRow(RarityType rarity, out DRShopPrice result) + { + EnsureShopPriceCache(); + if (_shopPriceByRarity == null) { + result = null; return false; } - for (int i = 0; i < rows.Count; i++) + return _shopPriceByRarity.TryGetValue(rarity, out result); + } + + private static void EnsureShopPriceCache() + { + if (_shopPriceByRarity != null) { - DRShopPrice row = rows[i]; - if (row != null && row.Rarity == rarity) - { - result = row; - return true; - } + return; } - return false; + DRShopPrice[] rows = CoreServiceHub.StaticData?.GetAllShopPrices(); + if (rows == null) + { + return; + } + + Dictionary shopPriceByRarity = new Dictionary(); + for (int i = 0; i < rows.Length; i++) + { + DRShopPrice row = rows[i]; + if (row == null) + { + continue; + } + + shopPriceByRarity[row.Rarity] = row; + } + + _shopPriceByRarity = shopPriceByRarity; } private static bool TryGetComponentById(IReadOnlyList components, long instanceId, out TComp result) diff --git a/Assets/GameMain/Scripts/Utility/TowerComposedIconCacheUtility.cs b/Assets/GameMain/Scripts/Utility/TowerComposedIconCacheUtility.cs index 23dbc8b..8392cec 100644 --- a/Assets/GameMain/Scripts/Utility/TowerComposedIconCacheUtility.cs +++ b/Assets/GameMain/Scripts/Utility/TowerComposedIconCacheUtility.cs @@ -13,9 +13,9 @@ namespace GeometryTD.Core private static Sprite _muzzleSprite; private static Sprite _bearingSprite; private static Sprite _baseSprite; - private static bool s_RequestedMuzzle; - private static bool s_RequestedBearing; - private static bool s_RequestedBase; + private static bool _requestedMuzzle; + private static bool _requestedBearing; + private static bool _requestedBase; public static Sprite ResolveTowerIconSprite( TowerItemData tower, @@ -103,28 +103,23 @@ namespace GeometryTD.Core private static void EnsureBaseSpritesRequested() { - if (GameEntry.SpriteCache == null) + if (!_requestedMuzzle) { - return; + _requestedMuzzle = true; + CoreServiceHub.SpriteCache.Get(MuzzleAssetName, sprite => { _muzzleSprite = sprite; }); } - if (!s_RequestedMuzzle) + if (!_requestedBearing) { - s_RequestedMuzzle = true; - GameEntry.SpriteCache.GetSprite(MuzzleAssetName, sprite => { _muzzleSprite = sprite; }); + _requestedBearing = true; + CoreServiceHub.SpriteCache.Get(BearingAssetName, sprite => { _bearingSprite = sprite; }); } - if (!s_RequestedBearing) + if (!_requestedBase) { - s_RequestedBearing = true; - GameEntry.SpriteCache.GetSprite(BearingAssetName, sprite => { _bearingSprite = sprite; }); - } - - if (!s_RequestedBase) - { - s_RequestedBase = true; - GameEntry.SpriteCache.GetSprite(BaseAssetName, sprite => { _baseSprite = sprite; }); + _requestedBase = true; + CoreServiceHub.SpriteCache.Get(BaseAssetName, sprite => { _baseSprite = sprite; }); } } } -} +} \ No newline at end of file diff --git a/Assets/Tests/EditMode/EventOptionExecutorTests.cs b/Assets/Tests/EditMode/EventOptionExecutorTests.cs index 6164a0f..532bc5f 100644 --- a/Assets/Tests/EditMode/EventOptionExecutorTests.cs +++ b/Assets/Tests/EditMode/EventOptionExecutorTests.cs @@ -194,7 +194,7 @@ namespace GeometryTD.Tests.EditMode new AddRandomCompsEffect(new AddRandomCompsParam(2, RarityType.Blue)) }) }); - RunNodeExecutionContext context = CreateContext(); + EventOptionExecutionContext context = CreateContext(); BackpackInventoryData firstInventory = new BackpackInventoryData(); BackpackInventoryData secondInventory = new BackpackInventoryData(); @@ -407,7 +407,7 @@ namespace GeometryTD.Tests.EditMode BindingFlags.Instance | BindingFlags.NonPublic); Assert.That(method, Is.Not.Null); - RunNodeExecutionContext context = CreateContext(); + RunNodeExecutionContext context = CreateRunNodeContext(); EventItem first = (EventItem)method.Invoke(component, new object[] { context }); EventItem second = (EventItem)method.Invoke(component, new object[] { context }); @@ -437,7 +437,14 @@ namespace GeometryTD.Tests.EditMode SetStaticInventoryGeneration(component); } - private static RunNodeExecutionContext CreateContext() + private static EventOptionExecutionContext CreateContext() + { + return new EventOptionExecutionContext( + runSeed: 12345, + sequenceIndex: 3); + } + + private static RunNodeExecutionContext CreateRunNodeContext() { return new RunNodeExecutionContext { diff --git a/Assets/Tests/EditMode/GeometryTD.Tests.EditMode.asmdef b/Assets/Tests/EditMode/GeometryTD.Tests.EditMode.asmdef index 29e4e8c..1da2ec1 100644 --- a/Assets/Tests/EditMode/GeometryTD.Tests.EditMode.asmdef +++ b/Assets/Tests/EditMode/GeometryTD.Tests.EditMode.asmdef @@ -10,7 +10,7 @@ "GeometryTD.Gameplay" ], "includePlatforms": [ - "Editor" + "Android" ], "excludePlatforms": [], "allowUnsafeCode": false, diff --git a/Assets/Tests/EditMode/ProcedureMainFlowTests.cs b/Assets/Tests/EditMode/ProcedureMainFlowTests.cs index 7356822..1a92e0e 100644 --- a/Assets/Tests/EditMode/ProcedureMainFlowTests.cs +++ b/Assets/Tests/EditMode/ProcedureMainFlowTests.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Reflection; -using CustomComponent; -using GeometryTD.CustomComponent; using GeometryTD.Core; using GeometryTD.Factory; using GeometryTD.Procedure;