using System.Collections.Generic; using GameFramework.DataTable; using GeometryTD.CustomEvent; using GeometryTD.DataTable; using GeometryTD.Definition; using GeometryTD.Factory; using GeometryTD.Procedure; using Newtonsoft.Json.Linq; using GeometryTD.UI; using UnityEngine; using UnityGameFramework.Runtime; namespace GeometryTD.CustomComponent { public class EventNodeComponent : GameFrameworkComponent { private RunNodeExecutionContext _activeContext; private readonly List _eventItems = new List(); private EventFormUseCase _eventFormUseCase; private bool _initialized; public void OnInit() { _eventItems.Clear(); IDataTable dtEvent = GameEntry.DataTable.GetDataTable(); 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(); } GameEntry.UIRouter.BindUIUseCase(UIFormType.EventForm, _eventFormUseCase); _initialized = true; Log.Info("EventNodeComponent initialized with {0} events.", _eventItems.Count); } public void StartEvent(RunNodeExecutionContext context = null) { 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) { Log.Warning("EventNodeComponent StartEvent failed. Event form is not initialized."); return; } _activeContext = context != null ? context.Clone() : null; _eventFormUseCase.SetCurrentEvent(randomEvent); GameEntry.UIRouter.OpenUI(UIFormType.EventForm); GameEntry.Event.Fire( this, NodeEnterEventArgs.Create( _activeContext?.RunId, _activeContext?.NodeId ?? 0, _activeContext?.NodeType ?? RunNodeType.None, _activeContext?.SequenceIndex ?? -1)); } public void EndEvent() { GameEntry.UIRouter.CloseUI(UIFormType.EventForm); GameEntry.Event.Fire( this, NodeCompleteEventArgs.Create( _activeContext?.RunId, _activeContext?.NodeId ?? 0, _activeContext?.NodeType ?? RunNodeType.None, _activeContext?.SequenceIndex ?? -1, RunNodeCompletionStatus.Completed, true, _activeContext != null ? _activeContext.CreateCompletionSnapshot( GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : null) : null)); ClearActiveNodeContext(); } private void ClearActiveNodeContext() { _activeContext = null; } private static EventOption[] ParseOptions(string optionsRaw) { if (string.IsNullOrWhiteSpace(optionsRaw)) { return System.Array.Empty(); } try { JArray array = JArray.Parse(optionsRaw); List options = new List(array.Count); for (int i = 0; i < array.Count; i++) { if (!(array[i] is JObject optionObj)) { continue; } string optionText = optionObj.Value("optionText") ?? string.Empty; float probability = optionObj.Value("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(); } } private static EventRequirementBase[] ParseRequirements(JArray requirementsArray) { if (requirementsArray == null || requirementsArray.Count == 0) { return System.Array.Empty(); } List requirements = new List(requirementsArray.Count); for (int i = 0; i < requirementsArray.Count; i++) { if (!(requirementsArray[i] is JObject reqObj)) { continue; } string type = reqObj.Value("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(); } List effects = new List(effectsArray.Count); for (int i = 0; i < effectsArray.Count; i++) { if (!(effectsArray[i] is JObject effectObj)) { continue; } string type = effectObj.Value("type"); JObject param = effectObj["param"] as JObject; EventEffectBase effect = EventEffectFactory.Create(type, param, probability); if (effect != null) { effects.Add(effect); } } return effects.ToArray(); } } }