feat: Introduce new services and refactor existing code for better structure
- Added ISpriteCacheService, IStaticDataService, and ITextService interfaces for improved service management. - Implemented RunContracts for managing run states and node execution contexts. - Created EnemyTagStatusRuntime to handle enemy status effects and their application. - Refactored ShopPriceRuleService to utilize static data service for shop prices. - Enhanced InventoryTowerEnduranceUtility to manage tower endurance reduction. - Updated EventFormUseCase to work with new EventOptionExecutionContext. - Removed unused dictionary loading code from ProcedurePreload. - Cleaned up various utility classes and ensured consistent naming conventions. - Updated tests to reflect changes in context and service usage.
This commit is contained in:
parent
9fc0ef2216
commit
7106e0adbe
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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<long> 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<long, MuzzleCompItemData> muzzleMap = BuildComponentMap(inventory.MuzzleComponents);
|
||||
Dictionary<long, BearingCompItemData> bearingMap = BuildComponentMap(inventory.BearingComponents);
|
||||
Dictionary<long, BaseCompItemData> baseMap = BuildComponentMap(inventory.BaseComponents);
|
||||
HashSet<long> processedTowerIds = new HashSet<long>();
|
||||
|
||||
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<long, TComp> BuildComponentMap<TComp>(List<TComp> components)
|
||||
where TComp : TowerCompItemData
|
||||
{
|
||||
Dictionary<long, TComp> map = new Dictionary<long, TComp>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<DRShopPrice> _shopPriceTable;
|
||||
|
||||
public PlayerInventoryTradeService(
|
||||
PlayerInventoryQueryModel queryModel,
|
||||
PlayerInventoryCommandModel commandModel,
|
||||
IDataTable<DRShopPrice> 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<DRShopPrice> EnsureShopPriceTable()
|
||||
{
|
||||
_shopPriceTable ??= GameEntry.DataTable.GetDataTable<DRShopPrice>();
|
||||
return _shopPriceTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@
|
|||
"name": "GeometryTD.Core",
|
||||
"rootNamespace": "GeometryTD.Core",
|
||||
"references": [
|
||||
"GUID:363c5eb08ff8e6a439b85e37b8c20d96",
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c",
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f"
|
||||
"GUID:363c5eb08ff8e6a439b85e37b8c20d96"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
|
|
|||
|
|
@ -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<TowerCompItemData> generatedComponents = GameEntry.InventoryGeneration.BuildEventRewardComponents(
|
||||
IReadOnlyList<TowerCompItemData> 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,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9aeb92ccac2068f489dcbd0200417463
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 95f8a75dcf78e4545b36f1e24b92d82e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
namespace GeometryTD.Core
|
||||
{
|
||||
public interface IEventFlowManager
|
||||
{
|
||||
void EndEvent();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c14fccc4cf6d239489afdc5b302c03b9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace GeometryTD.Core
|
||||
{
|
||||
public interface IInventoryGenerationManager
|
||||
{
|
||||
IReadOnlyList<TowerCompItemData> BuildEventRewardComponents(
|
||||
int count,
|
||||
RarityType minRarity,
|
||||
RarityType maxRarity,
|
||||
int runSeed,
|
||||
int sequenceIndex,
|
||||
int eventId,
|
||||
int optionIndex,
|
||||
int effectIndex);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ba83daa081633074ab92ff9ad75c9c52
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
namespace GeometryTD.Core
|
||||
{
|
||||
public interface IPlayerInventoryManager
|
||||
{
|
||||
BackpackInventoryData GetInventorySnapshot();
|
||||
void ReplaceInventorySnapshot(BackpackInventoryData snapshot);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0ce0e4176795db941a0f7ed57065f73d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.Core
|
||||
{
|
||||
public interface ISpriteCacheService
|
||||
{
|
||||
void Get(string key, Action<Sprite> callback);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 675e9ac521922ac46b3b7afe4973a706
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: db37b943863752b41a8a0deef641dca6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
namespace GeometryTD.Core
|
||||
{
|
||||
public interface ITextService
|
||||
{
|
||||
string Get(string key, params object[] args);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9440fb32740fa50409ce370f9eab4d6d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f9d6ff9eff8570b4a96f296f9b107baa
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -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<LevelThemeType> CurrentThemePool { get; set; } = new List<LevelThemeType>();
|
||||
public List<LevelThemeType> ThemeHistory { get; set; } = new List<LevelThemeType>();
|
||||
public int CurrentNodeContinueChallengeLayer { get; set; }
|
||||
public List<RunItemState> RunItems { get; set; } = new List<RunItemState>();
|
||||
|
||||
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<LevelThemeType> CurrentThemePool { get; set; } = new List<LevelThemeType>();
|
||||
public List<LevelThemeType> ThemeHistory { get; set; } = new List<LevelThemeType>();
|
||||
public int CurrentNodeContinueChallengeLayer { get; set; }
|
||||
public List<RunItemState> RunItems { get; set; } = new List<RunItemState>();
|
||||
|
||||
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<LevelThemeType> CloneThemeList(IReadOnlyList<LevelThemeType> source)
|
||||
{
|
||||
List<LevelThemeType> cloned = new List<LevelThemeType>();
|
||||
if (source == null)
|
||||
{
|
||||
return cloned;
|
||||
}
|
||||
|
||||
for (int i = 0; i < source.Count; i++)
|
||||
{
|
||||
cloned.Add(source[i]);
|
||||
}
|
||||
|
||||
return cloned;
|
||||
}
|
||||
|
||||
public static List<RunItemState> CloneRunItems(IReadOnlyList<RunItemState> source)
|
||||
{
|
||||
List<RunItemState> cloned = new List<RunItemState>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e73cd16e1283cc94f903bb3d7728f543
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using GeometryTD.Entity;
|
||||
|
||||
namespace GeometryTD.Core
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using GeometryTD.Entity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.Core
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using GeometryTD.Entity;
|
||||
|
||||
namespace GeometryTD.Core
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using GeometryTD.Entity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.Core
|
||||
|
|
|
|||
|
|
@ -13,18 +13,11 @@ namespace GeometryTD.Core
|
|||
return string.Empty;
|
||||
}
|
||||
|
||||
if (GameEntry.DataTable != null)
|
||||
{
|
||||
var tagTable = GameEntry.DataTable.GetDataTable<DRTag>();
|
||||
if (tagTable != null)
|
||||
{
|
||||
DRTag tagRow = tagTable.GetDataRow((int)tagType);
|
||||
DRTag tagRow = CoreServiceHub.StaticData.GetTag((int)tagType);
|
||||
if (tagRow != null && !string.IsNullOrWhiteSpace(tagRow.Name))
|
||||
{
|
||||
return tagRow.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tagType.ToString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using GameFramework;
|
||||
using GameFramework.Event;
|
||||
using GeometryTD.Procedure;
|
||||
|
||||
namespace GeometryTD.Core
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using GameFramework;
|
||||
using GameFramework.Event;
|
||||
using GeometryTD.Procedure;
|
||||
|
||||
namespace GeometryTD.Core
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<LevelThemeType> CurrentThemePool { get; set; } = new List<LevelThemeType>();
|
||||
public List<LevelThemeType> ThemeHistory { get; set; } = new List<LevelThemeType>();
|
||||
public int CurrentNodeContinueChallengeLayer { get; set; }
|
||||
public List<RunItemState> RunItems { get; set; } = new List<RunItemState>();
|
||||
|
||||
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<LevelThemeType> CurrentThemePool { get; set; } = new List<LevelThemeType>();
|
||||
public List<LevelThemeType> ThemeHistory { get; set; } = new List<LevelThemeType>();
|
||||
public int CurrentNodeContinueChallengeLayer { get; set; }
|
||||
public List<RunItemState> RunItems { get; set; } = new List<RunItemState>();
|
||||
|
||||
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<LevelThemeType> CloneThemeList(IReadOnlyList<LevelThemeType> source)
|
||||
{
|
||||
List<LevelThemeType> cloned = new List<LevelThemeType>();
|
||||
if (source == null)
|
||||
{
|
||||
return cloned;
|
||||
}
|
||||
|
||||
for (int i = 0; i < source.Count; i++)
|
||||
{
|
||||
cloned.Add(source[i]);
|
||||
}
|
||||
|
||||
return cloned;
|
||||
}
|
||||
|
||||
internal static List<RunItemState> CloneRunItems(IReadOnlyList<RunItemState> source)
|
||||
{
|
||||
List<RunItemState> cloned = new List<RunItemState>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<DRMuzzleComp> dataTable = GameEntry.DataTable.GetDataTable<DRMuzzleComp>();
|
||||
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<DRBearingComp> dataTable = GameEntry.DataTable.GetDataTable<DRBearingComp>();
|
||||
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<DRBaseComp> dataTable = GameEntry.DataTable.GetDataTable<DRBaseComp>();
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.Core
|
||||
{
|
||||
public static class InventoryTowerEnduranceUtility
|
||||
{
|
||||
public static int ReduceTowerEndurance(
|
||||
BackpackInventoryData inventory,
|
||||
IReadOnlyList<long> 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<long, MuzzleCompItemData> muzzleMap = BuildComponentMap(inventory.MuzzleComponents);
|
||||
Dictionary<long, BearingCompItemData> bearingMap = BuildComponentMap(inventory.BearingComponents);
|
||||
Dictionary<long, BaseCompItemData> baseMap = BuildComponentMap(inventory.BaseComponents);
|
||||
HashSet<long> processedTowerIds = new HashSet<long>();
|
||||
|
||||
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<long, TComp> BuildComponentMap<TComp>(List<TComp> components)
|
||||
where TComp : TowerCompItemData
|
||||
{
|
||||
Dictionary<long, TComp> map = new Dictionary<long, TComp>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: abb0c22f9d11c6b4aae1d76fede68320
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -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<DRShopPrice> shopPriceRows, RarityType rarity, Random random)
|
||||
private static Dictionary<RarityType, DRShopPrice> _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<DRShopPrice> 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<DRShopPrice> 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<DRShopPrice> shopPriceTable = null)
|
||||
public static int ResolveBasePrice(RarityType rarity)
|
||||
{
|
||||
IDataTable<DRShopPrice> resolvedTable = shopPriceTable ?? GameEntry.DataTable.GetDataTable<DRShopPrice>();
|
||||
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<DRShopPrice> rows, RarityType rarity, out DRShopPrice result)
|
||||
public static void ClearCache()
|
||||
{
|
||||
_shopPriceByRarity = null;
|
||||
}
|
||||
|
||||
private static bool TryFindPriceRow(RarityType rarity, out DRShopPrice result)
|
||||
{
|
||||
EnsureShopPriceCache();
|
||||
if (_shopPriceByRarity == null)
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return _shopPriceByRarity.TryGetValue(rarity, out result);
|
||||
}
|
||||
|
||||
private static void EnsureShopPriceCache()
|
||||
{
|
||||
if (_shopPriceByRarity != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DRShopPrice[] rows = CoreServiceHub.StaticData?.GetAllShopPrices();
|
||||
if (rows == null)
|
||||
{
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rows.Count; i++)
|
||||
Dictionary<RarityType, DRShopPrice> shopPriceByRarity = new Dictionary<RarityType, DRShopPrice>();
|
||||
for (int i = 0; i < rows.Length; i++)
|
||||
{
|
||||
DRShopPrice row = rows[i];
|
||||
if (row != null && row.Rarity == rarity)
|
||||
if (row == null)
|
||||
{
|
||||
result = row;
|
||||
return true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
shopPriceByRarity[row.Rarity] = row;
|
||||
}
|
||||
|
||||
_shopPriceByRarity = shopPriceByRarity;
|
||||
}
|
||||
|
||||
private static bool TryGetComponentById<TComp>(IReadOnlyList<TComp> components, long instanceId, out TComp result)
|
||||
|
|
|
|||
|
|
@ -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,27 +103,22 @@ 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; });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
"GeometryTD.Gameplay"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
"Android"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue