P0-02 补齐数据表:组件、敌人、波次、节点、事件、商店商品
- 组件:
- 底座:Assets\GameMain\DataTables\BaseComp.txt
- 轴承:Assets\GameMain\DataTables\BearingComp.txt
- 枪口:Assets\GameMain\DataTables\MuzzleComp.txt
- 敌人:Assets\GameMain\DataTables\Enemy.txt
- 波次:
- 关卡:Assets\GameMain\DataTables\Level.txt
- 关卡阶段(波次):Assets\GameMain\DataTables\LevelPhase.txt
- 波次条目(波次出怪规则):Assets\GameMain\DataTables\LevelSpawnEntry.txt
- 事件:Assets\GameMain\DataTables\Event.txt
- 商店:Assets\GameMain\DataTables\ShopPrice.txt
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
using System.Collections.Generic;
|
||||
using GameFramework.DataTable;
|
||||
using GeometryTD.DataTable;
|
||||
using GeometryTD.Definition;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// 战斗节点组件
|
||||
/// </summary>
|
||||
public class CombatNodeComponent : GameFrameworkComponent
|
||||
{
|
||||
// Level.Id => Level
|
||||
private readonly Dictionary<int, DRLevel> _levelsById = new();
|
||||
|
||||
// LevelId => LevelPhases
|
||||
private readonly Dictionary<int, List<DRLevelPhase>> _phasesByLevelId = new();
|
||||
|
||||
// LevelPhase.Id => LevelSpawnEntries
|
||||
private readonly Dictionary<int, List<DRLevelSpawnEntry>> _spawnEntriesByPhaseId = new();
|
||||
|
||||
private readonly List<int> _levelIdBuffer = new();
|
||||
|
||||
public LevelThemeType CurrentThemeType { get; private set; }
|
||||
public DRLevel CurrentLevel { get; private set; }
|
||||
|
||||
public void OnInit(LevelThemeType themeType)
|
||||
{
|
||||
CurrentThemeType = themeType;
|
||||
CurrentLevel = null;
|
||||
_levelsById.Clear();
|
||||
_phasesByLevelId.Clear();
|
||||
_spawnEntriesByPhaseId.Clear();
|
||||
_levelIdBuffer.Clear();
|
||||
|
||||
IDataTable<DRLevel> dtLevel = GameEntry.DataTable.GetDataTable<DRLevel>();
|
||||
IDataTable<DRLevelPhase> dtLevelPhase = GameEntry.DataTable.GetDataTable<DRLevelPhase>();
|
||||
IDataTable<DRLevelSpawnEntry> dtSpawnEntry = GameEntry.DataTable.GetDataTable<DRLevelSpawnEntry>();
|
||||
if (dtLevel == null || dtLevelPhase == null || dtSpawnEntry == null)
|
||||
{
|
||||
Log.Warning("CombatNodeComponent init failed. Missing data table(s).");
|
||||
return;
|
||||
}
|
||||
|
||||
DRLevel[] levels = dtLevel.GetAllDataRows();
|
||||
foreach (var level in levels)
|
||||
{
|
||||
if (level.LevelThemeType != themeType)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_levelsById[level.Id] = level;
|
||||
_phasesByLevelId[level.Id] = new List<DRLevelPhase>();
|
||||
_levelIdBuffer.Add(level.Id);
|
||||
}
|
||||
|
||||
DRLevelPhase[] levelPhases = dtLevelPhase.GetAllDataRows();
|
||||
foreach (var phase in levelPhases)
|
||||
{
|
||||
int levelId = phase.Id / 1000;
|
||||
if (!_levelsById.ContainsKey(levelId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_phasesByLevelId.TryGetValue(levelId, out List<DRLevelPhase> phases))
|
||||
{
|
||||
phases = new List<DRLevelPhase>();
|
||||
_phasesByLevelId[levelId] = phases;
|
||||
}
|
||||
|
||||
phases.Add(phase);
|
||||
_spawnEntriesByPhaseId[phase.Id] = new List<DRLevelSpawnEntry>();
|
||||
}
|
||||
|
||||
DRLevelSpawnEntry[] spawnEntries = dtSpawnEntry.GetAllDataRows();
|
||||
for (int i = 0; i < spawnEntries.Length; i++)
|
||||
{
|
||||
DRLevelSpawnEntry spawnEntry = spawnEntries[i];
|
||||
int phaseId = spawnEntry.Id / 1000;
|
||||
int levelId = phaseId / 1000;
|
||||
if (!_levelsById.ContainsKey(levelId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_spawnEntriesByPhaseId.TryGetValue(phaseId, out List<DRLevelSpawnEntry> entries))
|
||||
{
|
||||
entries = new List<DRLevelSpawnEntry>();
|
||||
_spawnEntriesByPhaseId[phaseId] = entries;
|
||||
}
|
||||
|
||||
entries.Add(spawnEntry);
|
||||
}
|
||||
|
||||
Log.Info(
|
||||
"CombatNodeComponent initialized. Theme={0}, Levels={1}, Phases={2}, Entries={3}",
|
||||
themeType,
|
||||
_levelsById.Count,
|
||||
CountPhases(),
|
||||
CountEntries());
|
||||
}
|
||||
|
||||
public void StartCombat()
|
||||
{
|
||||
if (_levelIdBuffer.Count <= 0)
|
||||
{
|
||||
Log.Warning("CombatNodeComponent has no level cache. Call OnInit(levelThemeType) first.");
|
||||
return;
|
||||
}
|
||||
|
||||
int randomIndex = Random.Range(0, _levelIdBuffer.Count);
|
||||
int randomLevelId = _levelIdBuffer[randomIndex];
|
||||
CurrentLevel = _levelsById[randomLevelId];
|
||||
|
||||
// TODO: 在这里接入真实战斗节点玩法启动流程(场景进入、敌人生成、结算等)。
|
||||
Log.Info("StartCombat selected level '{0}' (Theme={1}).", CurrentLevel.Id, CurrentThemeType);
|
||||
}
|
||||
|
||||
private int CountPhases()
|
||||
{
|
||||
int count = 0;
|
||||
foreach (List<DRLevelPhase> phases in _phasesByLevelId.Values)
|
||||
{
|
||||
count += phases.Count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private int CountEntries()
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var list in _spawnEntriesByPhaseId.Values)
|
||||
{
|
||||
count += list.Count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e646500b9304d438746f2351c71a0f4
|
||||
timeCreated: 1772103300
|
||||
@@ -0,0 +1,172 @@
|
||||
using System.Collections.Generic;
|
||||
using GameFramework.DataTable;
|
||||
using GeometryTD.DataTable;
|
||||
using GeometryTD.Definition;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using GeometryTD.UI;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public class EventNodeComponent : GameFrameworkComponent
|
||||
{
|
||||
private readonly List<EventItem> _eventItems = new List<EventItem>();
|
||||
|
||||
private EventFormUseCase _eventFormUseCase;
|
||||
private EventFormController _eventFormController;
|
||||
private bool _initialized;
|
||||
|
||||
public void OnInit()
|
||||
{
|
||||
_eventItems.Clear();
|
||||
|
||||
IDataTable<DREvent> dtEvent = GameEntry.DataTable.GetDataTable<DREvent>();
|
||||
if (dtEvent == null)
|
||||
{
|
||||
Log.Warning("Event data table is not loaded.");
|
||||
_initialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
DREvent[] rows = dtEvent.GetAllDataRows();
|
||||
foreach (var drEvent in rows)
|
||||
{
|
||||
EventOption[] options = ParseOptions(drEvent.OptionsRaw);
|
||||
_eventItems.Add(new EventItem(drEvent.Id, drEvent.Title, drEvent.Description, options));
|
||||
}
|
||||
|
||||
if (_eventFormUseCase == null)
|
||||
{
|
||||
_eventFormUseCase = new EventFormUseCase();
|
||||
}
|
||||
|
||||
if (_eventFormController == null)
|
||||
{
|
||||
_eventFormController = new EventFormController();
|
||||
_eventFormController.BindUseCase(_eventFormUseCase);
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
Log.Info("EventNodeComponent initialized with {0} events.", _eventItems.Count);
|
||||
}
|
||||
|
||||
public void StartEvent()
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
OnInit();
|
||||
}
|
||||
|
||||
if (_eventItems.Count <= 0)
|
||||
{
|
||||
Log.Warning("EventNodeComponent has no event data.");
|
||||
return;
|
||||
}
|
||||
|
||||
int index = Random.Range(0, _eventItems.Count);
|
||||
EventItem randomEvent = _eventItems[index];
|
||||
|
||||
if (_eventFormUseCase == null || _eventFormController == null)
|
||||
{
|
||||
Log.Warning("EventNodeComponent StartEvent failed. Event form is not initialized.");
|
||||
return;
|
||||
}
|
||||
|
||||
_eventFormUseCase.SetCurrentEvent(randomEvent);
|
||||
_eventFormController.OpenUI();
|
||||
}
|
||||
|
||||
private static EventOption[] ParseOptions(string optionsRaw)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(optionsRaw))
|
||||
{
|
||||
return System.Array.Empty<EventOption>();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
JArray array = JArray.Parse(optionsRaw);
|
||||
List<EventOption> options = new List<EventOption>(array.Count);
|
||||
|
||||
for (int i = 0; i < array.Count; i++)
|
||||
{
|
||||
if (!(array[i] is JObject optionObj))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string optionText = optionObj.Value<string>("optionText") ?? string.Empty;
|
||||
float probability = optionObj.Value<float?>("probability") ?? 1f;
|
||||
|
||||
EventRequirementBase[] requirements = ParseRequirements(optionObj["requirements"] as JArray);
|
||||
EventEffectBase[] costEffects = ParseEffects(optionObj["costEffects"] as JArray, probability);
|
||||
EventEffectBase[] rewardEffects = ParseEffects(optionObj["rewardEffects"] as JArray, probability);
|
||||
|
||||
options.Add(new EventOption(optionText, requirements, costEffects, rewardEffects, probability));
|
||||
}
|
||||
|
||||
return options.ToArray();
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Log.Warning("Failed to parse event options json. {0}", e.Message);
|
||||
return System.Array.Empty<EventOption>();
|
||||
}
|
||||
}
|
||||
|
||||
private static EventRequirementBase[] ParseRequirements(JArray requirementsArray)
|
||||
{
|
||||
if (requirementsArray == null || requirementsArray.Count == 0)
|
||||
{
|
||||
return System.Array.Empty<EventRequirementBase>();
|
||||
}
|
||||
|
||||
List<EventRequirementBase> requirements = new List<EventRequirementBase>(requirementsArray.Count);
|
||||
for (int i = 0; i < requirementsArray.Count; i++)
|
||||
{
|
||||
if (!(requirementsArray[i] is JObject reqObj))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string type = reqObj.Value<string>("type");
|
||||
JObject param = reqObj["param"] as JObject;
|
||||
EventRequirementBase requirement = EventRequirementFactory.Create(type, param);
|
||||
if (requirement != null)
|
||||
{
|
||||
requirements.Add(requirement);
|
||||
}
|
||||
}
|
||||
|
||||
return requirements.ToArray();
|
||||
}
|
||||
|
||||
private static EventEffectBase[] ParseEffects(JArray effectsArray, float probability)
|
||||
{
|
||||
if (effectsArray == null || effectsArray.Count == 0)
|
||||
{
|
||||
return System.Array.Empty<EventEffectBase>();
|
||||
}
|
||||
|
||||
List<EventEffectBase> effects = new List<EventEffectBase>(effectsArray.Count);
|
||||
for (int i = 0; i < effectsArray.Count; i++)
|
||||
{
|
||||
if (!(effectsArray[i] is JObject effectObj))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string type = effectObj.Value<string>("type");
|
||||
JObject param = effectObj["param"] as JObject;
|
||||
EventEffectBase effect = EventEffectFactory.Create(type, param, probability);
|
||||
if (effect != null)
|
||||
{
|
||||
effects.Add(effect);
|
||||
}
|
||||
}
|
||||
|
||||
return effects.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a0c1c547ca24c95819f5f62f0bd3ea3
|
||||
timeCreated: 1772102402
|
||||
Reference in New Issue
Block a user