添加参战防御塔功能(UI)

This commit is contained in:
SepComet
2026-03-04 20:36:05 +08:00
parent 298345fa17
commit a62309e8c1
25 changed files with 1160 additions and 20 deletions
@@ -11,9 +11,11 @@ namespace GeometryTD.UI
{
public class RepoFormController : UIFormControllerCommonBase<RepoFormContext, RepoForm>
{
private const int MaxParticipantCount = 4;
private RepoFormUseCase _useCase;
private readonly Dictionary<long, RepoItemContext> _itemContextMap = new Dictionary<long, RepoItemContext>();
private readonly Dictionary<long, ItemDescSeed> _itemDescSeedMap = new Dictionary<long, ItemDescSeed>();
private readonly HashSet<long> _participantTowerIds = new HashSet<long>();
private sealed class ItemDescSeed
{
@@ -28,6 +30,7 @@ namespace GeometryTD.UI
protected override void RefreshUI(RepoForm form, RepoFormContext context)
{
form.RefreshUI(context);
ApplyParticipantSelection();
}
protected override void SubscribeCustomEvents()
@@ -36,6 +39,8 @@ namespace GeometryTD.UI
GameEntry.Event.Subscribe(RepoItemDragEndedEventArgs.EventId, OnRepoItemDragEnded);
GameEntry.Event.Subscribe(CombineSlotClickedEventArgs.EventId, OnCombineSlotClicked);
GameEntry.Event.Subscribe(RepoCombineRequestedEventArgs.EventId, OnRepoCombineRequested);
GameEntry.Event.Subscribe(RepoParticipantAssignRequestedEventArgs.EventId, OnRepoParticipantAssignRequested);
GameEntry.Event.Subscribe(RepoParticipantRemoveRequestedEventArgs.EventId, OnRepoParticipantRemoveRequested);
GameEntry.Event.Subscribe(RepoFormReturnEventArgs.EventId, OnRepoFormReturn);
}
@@ -45,6 +50,8 @@ namespace GeometryTD.UI
GameEntry.Event.Unsubscribe(RepoItemDragEndedEventArgs.EventId, OnRepoItemDragEnded);
GameEntry.Event.Unsubscribe(CombineSlotClickedEventArgs.EventId, OnCombineSlotClicked);
GameEntry.Event.Unsubscribe(RepoCombineRequestedEventArgs.EventId, OnRepoCombineRequested);
GameEntry.Event.Unsubscribe(RepoParticipantAssignRequestedEventArgs.EventId, OnRepoParticipantAssignRequested);
GameEntry.Event.Unsubscribe(RepoParticipantRemoveRequestedEventArgs.EventId, OnRepoParticipantRemoveRequested);
GameEntry.Event.Unsubscribe(RepoFormReturnEventArgs.EventId, OnRepoFormReturn);
}
@@ -99,12 +106,14 @@ namespace GeometryTD.UI
_itemDescSeedMap.Clear();
if (rawData?.Inventory == null)
{
_participantTowerIds.Clear();
return null;
}
Dictionary<long, MuzzleCompItemData> muzzleMap = BuildComponentMap(rawData.Inventory.MuzzleComponents);
Dictionary<long, BearingCompItemData> bearingMap = BuildComponentMap(rawData.Inventory.BearingComponents);
Dictionary<long, BaseCompItemData> baseMap = BuildComponentMap(rawData.Inventory.BaseComponents);
Dictionary<long, TowerItemData> towerMap = BuildTowerMap(rawData.Inventory.Towers);
List<RepoItemContext> items = new List<RepoItemContext>();
if (rawData.Inventory.Towers != null)
@@ -121,6 +130,7 @@ namespace GeometryTD.UI
InstanceId = tower.InstanceId,
CanDrag = true,
EnduranceRate01 = ItemDescUtility.ResolveTowerEnduranceRate(tower, muzzleMap, bearingMap, baseMap),
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.None,
IconAreaContext = BuildIconAreaContext(tower)
});
@@ -147,6 +157,7 @@ namespace GeometryTD.UI
InstanceId = item.InstanceId,
CanDrag = true,
EnduranceRate01 = ItemDescUtility.ResolveComponentEnduranceRate(item),
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.Muzzle,
IconAreaContext = BuildIconAreaContext(item)
});
@@ -173,6 +184,7 @@ namespace GeometryTD.UI
InstanceId = item.InstanceId,
CanDrag = true,
EnduranceRate01 = ItemDescUtility.ResolveComponentEnduranceRate(item),
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.Bearing,
IconAreaContext = BuildIconAreaContext(item)
});
@@ -199,6 +211,7 @@ namespace GeometryTD.UI
InstanceId = item.InstanceId,
CanDrag = true,
EnduranceRate01 = ItemDescUtility.ResolveComponentEnduranceRate(item),
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.Base,
IconAreaContext = BuildIconAreaContext(item)
});
@@ -211,13 +224,17 @@ namespace GeometryTD.UI
}
}
ParticipantAreaContext participantAreaContext =
BuildParticipantAreaContext(rawData.Inventory, towerMap, muzzleMap, bearingMap, baseMap);
return new RepoFormContext
{
CombineAreaContext = new CombineAreaContext(),
CompAreaContext = new CompAreaContext
{
Items = items.ToArray()
}
},
ParticipantAreaContext = participantAreaContext
};
}
@@ -288,6 +305,112 @@ namespace GeometryTD.UI
return map;
}
private static Dictionary<long, TowerItemData> BuildTowerMap(IReadOnlyList<TowerItemData> towers)
{
Dictionary<long, TowerItemData> map = new Dictionary<long, TowerItemData>();
if (towers == null)
{
return map;
}
for (int i = 0; i < towers.Count; i++)
{
TowerItemData tower = towers[i];
if (tower == null || tower.InstanceId <= 0)
{
continue;
}
map[tower.InstanceId] = tower;
}
return map;
}
private ParticipantAreaContext BuildParticipantAreaContext(
BackpackInventoryData inventory,
IReadOnlyDictionary<long, TowerItemData> towerMap,
IReadOnlyDictionary<long, MuzzleCompItemData> muzzleMap,
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap)
{
_participantTowerIds.Clear();
List<RepoItemContext> participantItems = new List<RepoItemContext>();
if (inventory?.ParticipantTowerInstanceIds != null && towerMap != null)
{
for (int i = 0; i < inventory.ParticipantTowerInstanceIds.Count; i++)
{
long towerId = inventory.ParticipantTowerInstanceIds[i];
if (towerId <= 0)
{
continue;
}
if (!towerMap.TryGetValue(towerId, out TowerItemData tower) || tower == null)
{
continue;
}
if (!_participantTowerIds.Add(towerId))
{
continue;
}
participantItems.Add(new RepoItemContext
{
InstanceId = tower.InstanceId,
CanDrag = false,
EnduranceRate01 = ItemDescUtility.ResolveTowerEnduranceRate(tower, muzzleMap, bearingMap, baseMap),
ClickActionType = RepoItemClickActionType.RemoveParticipant,
ComponentSlotType = TowerCompSlotType.None,
IconAreaContext = BuildIconAreaContext(tower)
});
}
}
return new ParticipantAreaContext
{
Items = participantItems.ToArray(),
MaxCount = MaxParticipantCount
};
}
private void ApplyParticipantSelection()
{
if (Form == null || _itemContextMap.Count <= 0)
{
return;
}
foreach (KeyValuePair<long, RepoItemContext> pair in _itemContextMap)
{
RepoItemContext itemContext = pair.Value;
if (itemContext == null || itemContext.ComponentSlotType != TowerCompSlotType.None)
{
continue;
}
Form.SetRepoItemSelected(pair.Key, _participantTowerIds.Contains(pair.Key));
}
}
private void RefreshParticipantAreaOnly()
{
if (_useCase == null || Form == null)
{
return;
}
RepoFormContext latestContext = BuildContext(_useCase.CreateInitialModel());
if (latestContext?.ParticipantAreaContext == null)
{
return;
}
Form.RefreshParticipantArea(latestContext.ParticipantAreaContext);
ApplyParticipantSelection();
}
private static IconAreaContext BuildIconAreaContext(TowerItemData tower)
{
if (tower == null)
@@ -447,9 +570,60 @@ namespace GeometryTD.UI
if (latestContext != null)
{
Form.RefreshUI(latestContext);
ApplyParticipantSelection();
}
}
private void OnRepoParticipantAssignRequested(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender))
{
return;
}
if (!(e is RepoParticipantAssignRequestedEventArgs args))
{
return;
}
if (_useCase == null || Form == null || args.TowerItemId <= 0)
{
return;
}
if (!_useCase.TryAddParticipantTower(args.TowerItemId))
{
return;
}
RefreshParticipantAreaOnly();
}
private void OnRepoParticipantRemoveRequested(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender))
{
return;
}
if (!(e is RepoParticipantRemoveRequestedEventArgs args))
{
return;
}
if (_useCase == null || Form == null || args.TowerItemId <= 0)
{
return;
}
if (!_useCase.TryRemoveParticipantTower(args.TowerItemId))
{
return;
}
RefreshParticipantAreaOnly();
}
private bool IsEventFromCurrentForm(object sender)
{
if (Form == null)