仓库组件 + 防御塔升级

- `PlayerInventoryComponent`:玩家库存组件,收集金币/组件/防御塔等道具
- 补全防御塔的升级逻辑,最高 5 级
This commit is contained in:
SepComet
2026-03-02 19:50:12 +08:00
parent 5ba94828a8
commit daba9cbdf9
20 changed files with 753 additions and 138 deletions
@@ -8,9 +8,15 @@ namespace GeometryTD.Entity
{
public sealed class CombatSelectInputService
{
public bool TryBuildUserData(Tilemap tilemap, Transform mapTransform,
IReadOnlyDictionary<Vector3Int, int> towerEntityIdByFoundationCell, Func<Vector3Int, bool> isFoundationCell,
int upgradeCost, int destroyGain, out CombatSelectFormUserData userData)
public bool TryBuildUserData(
Tilemap tilemap,
Transform mapTransform,
IReadOnlyDictionary<Vector3Int, int> towerEntityIdByFoundationCell,
Func<Vector3Int, bool> isFoundationCell,
Func<int, bool> isTowerAtMaxLevel,
int upgradeCost,
int destroyGain,
out CombatSelectFormUserData userData)
{
userData = null;
if (tilemap == null || !TryGetPointerWorldPosition(tilemap, mapTransform, out Vector3 worldPosition,
@@ -44,13 +50,15 @@ namespace GeometryTD.Entity
WorldPosition = worldPosition,
CellPosition = clickedCell,
TowerEntityId = towerEntityId,
IsTowerAtMaxLevel = towerEntityId != 0 && isTowerAtMaxLevel != null && isTowerAtMaxLevel(towerEntityId),
UpgradeCost = Mathf.Max(0, upgradeCost),
DestroyGain = Mathf.Max(0, destroyGain)
};
return true;
}
private static bool TryGetPointerWorldPosition(Tilemap tilemap, Transform mapTransform, out Vector3 worldPosition,
private static bool TryGetPointerWorldPosition(Tilemap tilemap, Transform mapTransform,
out Vector3 worldPosition,
out Vector2 contentPosition)
{
worldPosition = Vector3.zero;
@@ -63,7 +71,9 @@ namespace GeometryTD.Entity
}
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
float mapPlaneZ = tilemap != null ? tilemap.transform.position.z : (mapTransform != null ? mapTransform.position.z : 0f);
float mapPlaneZ = tilemap != null
? tilemap.transform.position.z
: (mapTransform != null ? mapTransform.position.z : 0f);
Vector3 planeNormal = mainCamera.transform.forward.sqrMagnitude > Mathf.Epsilon
? -mainCamera.transform.forward
: Vector3.forward;
@@ -1,4 +1,5 @@
using Components;
using GeometryTD.Definition;
using GeometryTD.Entity.EntityData;
using UnityGameFramework.Runtime;
@@ -13,6 +14,17 @@ namespace GeometryTD.Entity
_towerController?.SetAttackRangeVisible(visible);
}
public bool TryApplyStats(DefenseTowerStatsData stats, int towerLevel)
{
if (_towerController == null || stats == null)
{
return false;
}
_towerController.OnInit(stats, towerLevel);
return true;
}
protected override void OnInit(object userData)
{
base.OnInit(userData);
@@ -41,8 +53,7 @@ namespace GeometryTD.Entity
return;
}
_towerController.SetAutoUpdate(false);
_towerController.OnInit(towerData.Stats);
_towerController.OnInit(towerData.Stats, towerData.TowerLevel);
}
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
@@ -242,7 +242,8 @@ namespace GeometryTD.Entity
if (_combatSelectInputService == null ||
!_combatSelectInputService.TryBuildUserData(Tilemap, CachedTransform,
_towerPlacementService != null ? _towerPlacementService.TowerEntityIdByFoundationCell : null,
IsFoundationCell, _upgradeCost, _destroyGain, out CombatSelectFormUserData userData))
IsFoundationCell, IsTowerAtMaxLevel, _upgradeCost, _destroyGain,
out CombatSelectFormUserData userData))
{
userData = new CombatSelectFormUserData
{
@@ -254,6 +255,11 @@ namespace GeometryTD.Entity
GameEntry.UIRouter.OpenUI(UIFormType.CombatSelectForm, userData);
}
private bool IsTowerAtMaxLevel(int towerEntityId)
{
return _towerPlacementService != null && _towerPlacementService.IsTowerAtMaxLevel(towerEntityId);
}
private void ApplySelectedObject(CombatSelectFormUserData userData)
{
_towerSelectionPresenter?.ApplySelectedObject(userData);