NLDClient-yudde/ProjectNLD/Assets/Editor/LevelEditor/LevelEditorWindow.cs

1775 lines
55 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using TGS;
using Framework;
using System.IO;
using UnityEditor;
using UnityEngine;
using System.Linq;
using Gameplay.Level;
using Sirenix.Utilities;
using Sirenix.OdinInspector;
using Sirenix.Utilities.Editor;
using System.Collections.Generic;
using cfg.FightCfg;
using cfg.LevelCfg;
using cfg.MonsterCfg;
using cfg.VehicleCfg;
using Sirenix.OdinInspector.Editor;
using Level = cfg.LevelCfg.Level;
using ObjectFieldAlignment = Sirenix.OdinInspector.ObjectFieldAlignment;
using static Gameplay.Level.LevelData;
public partial class LevelEditorWindow : OdinEditorWindow
{
[MenuItem("Tools/*地图场景/关卡编辑器", false, (int)NLDMenuID.LevelEditor)]
private static void OpenLevelEditorWindow()
{
var window = GetWindow<LevelEditorWindow>();
window.position = GUIHelper.GetEditorWindowRect().AlignCenter(800, 600);
window.titleContent = new GUIContent("关卡编辑器");
}
public static void OpenWindow(LevelEditor levelEditor)
{
MapEditorSettings.Init();
currWindow = GetWindow<LevelEditorWindow>();
currWindow.position = GUIHelper.GetEditorWindowRect().AlignCenter(800, 600);
currWindow.currentLevelData = null;
currWindow._levelEditor = levelEditor;
currWindow.LoadLevel(levelEditor.LevelData);
var level = Path.GetFileNameWithoutExtension(levelEditor.LevelDataJson.name);
currWindow.levelID = level.Substring(level.Length - 6);
//currWindow.GetLevelMonsterClass();
DebugUtil.Log("关卡数据:{0}", currWindow.levelID);
}
private static LevelEditorWindow currWindow;
private MapManager _mapManager;
private Map _curMap;
private LevelEditor _levelEditor;
#region 配置表
private Level LevelCfg => EditorTableManager.instance.tables.Level;
private Monster MonsterCfg => EditorTableManager.instance.tables.Monster;
private MonsterClass MonsterClassCfg => EditorTableManager.instance.tables.MonsterClass;
private VehicleConfig VehicleCfg => EditorTableManager.instance.tables.VehicleConfig;
private FightNPCConfig FightNpcCfg => EditorTableManager.instance.tables.FightNPCConfig;
private BuildConfig FightBuildCfg => EditorTableManager.instance.tables.BuildConfig;
#endregion
#region 地块颜色
private static readonly Color RegionColor = MapUtils.GetRGBAColor("FF960072");
private static readonly Color ShowRegionColor = Color.red;
private static readonly Color CaptureRegionColor = Color.yellow;
private static readonly Color RetreatRegionColor = Color.cyan;
private static readonly Color GroupHighlightColor = new Color(1f, 0.5f, 0f, 0.8f);
#endregion
#region 任务相关
[BoxGroup("任务列表")] [LabelText("任务列表"), Indent]
public List<TaskInfoEditor> taskInfos = new List<TaskInfoEditor>();
#endregion
#region 关卡数据
[FoldoutGroup("当前关卡数据")] [HideLabel]
public LevelData currentLevelData = null;
#endregion
#region 触发器
[FoldoutGroup("当前关卡数据")] [BoxGroup("当前关卡数据/触发器列表")] [Indent, LabelText("触发器")]
public List<LevelTriggerDataEditor> levelTriggerData = new List<LevelTriggerDataEditor>();
#endregion
#region 波次管理
[FoldoutGroup("当前关卡数据")]
[BoxGroup("当前关卡数据/波次管理")]
[LabelText("编辑波次"), Indent]
[OnValueChanged(nameof(OnIsEditingWaveChanged))]
[SerializeField]
public bool isEditingWave;
private void OnIsEditingWaveChanged()
{
if (isEditingWave)
{
// 刷新波次信息显示
RefreshWaveInfoEditors();
}
}
[FoldoutGroup("当前关卡数据")]
[BoxGroup("当前关卡数据/波次管理")]
[LabelText("波次列表(管理怪物组)"), Indent]
[ShowIf(nameof(isEditingWave))]
[InfoBox("说明波次管理基于怪物组ID不是NPC索引。一个怪物组只能属于一个波次。直接添加项来创建新波次波次ID可修改。", InfoMessageType.Info)]
[ListDrawerSettings(
CustomRemoveIndexFunction = nameof(CustomRemoveWave),
DraggableItems = false,
ShowFoldout = true
)]
public List<WaveInfoEditor> waveInfoEditors = new();
private void CustomRemoveWave(int index)
{
if (index >= 0 && index < waveInfoEditors.Count)
{
var wave = waveInfoEditors[index];
// 清除该波次中所有怪物组的怪物的波次信息
if (currentEnemyNpcInfo != null)
{
foreach (var groupId in wave.enemies)
{
foreach (var npc in currentEnemyNpcInfo)
{
if (npc.npcInfo.groups != null && npc.npcInfo.groups.Contains(groupId))
{
npc.npcInfo.waveIndex = 0;
npc.npcInfo.isHideOnLoad = false;
}
}
}
}
waveInfoEditors.RemoveAt(index);
}
}
/// <summary>
/// 刷新波次信息编辑器
/// </summary>
[FoldoutGroup("当前关卡数据")]
[BoxGroup("当前关卡数据/波次管理")]
[Button("刷新至怪物属性"), Indent]
[ShowIf(nameof(isEditingWave))]
private void RefreshWaveInfoEditors()
{
if (waveInfoEditors == null)
waveInfoEditors = new List<WaveInfoEditor>();
if (currentEnemyNpcInfo == null)
return;
// 第一步:重建 _enemyNpcObjectWaveDic 字典
// 创建新的字典结构
var newWaveDic = new Dictionary<int, Dictionary<NpcEditorInfo, GameObject>>();
// 遍历所有NPC根据当前的waveIndex重新组织字典
foreach (var npc in currentEnemyNpcInfo)
{
int oldWaveIndex = npc.npcInfo.waveIndex;
// 从旧字典中找到这个NPC的GameObject
GameObject npcObj = null;
if (_enemyNpcObjectWaveDic != null && _enemyNpcObjectWaveDic.TryGetValue(oldWaveIndex, out var oldNpcDic))
{
if (oldNpcDic.TryGetValue(npc, out npcObj))
{
// 找到了GameObject
}
}
// 如果找不到,尝试在所有波次中查找
if (npcObj == null && _enemyNpcObjectWaveDic != null)
{
foreach (var waveDic in _enemyNpcObjectWaveDic.Values)
{
if (waveDic.TryGetValue(npc, out npcObj))
{
break;
}
}
}
// 将GameObject添加到新字典中按照即将更新的waveIndex
if (npcObj != null)
{
// 先暂存到旧的waveIndex后面会更新
if (!newWaveDic.ContainsKey(oldWaveIndex))
{
newWaveDic[oldWaveIndex] = new Dictionary<NpcEditorInfo, GameObject>();
}
newWaveDic[oldWaveIndex][npc] = npcObj;
}
}
// 第二步清空所有NPC的波次信息
foreach (var npc in currentEnemyNpcInfo)
{
npc.npcInfo.waveIndex = 0;
npc.npcInfo.isHideOnLoad = false;
}
// 第三步根据波次编辑器更新NPC属性
var finalWaveDic = new Dictionary<int, Dictionary<NpcEditorInfo, GameObject>>();
foreach (var wave in waveInfoEditors)
{
foreach (var groupId in wave.enemies)
{
foreach (var npc in currentEnemyNpcInfo)
{
if (npc.npcInfo.groups != null && npc.npcInfo.groups.Contains(groupId))
{
npc.npcInfo.waveIndex = wave.waveID;
npc.npcInfo.isHideOnLoad = true;
// 更新到最终字典使用新的waveIndex
// 从临时字典中找到GameObject
GameObject npcObj = null;
foreach (var waveDic in newWaveDic.Values)
{
if (waveDic.TryGetValue(npc, out npcObj))
{
break;
}
}
if (npcObj != null)
{
if (!finalWaveDic.ContainsKey(wave.waveID))
{
finalWaveDic[wave.waveID] = new Dictionary<NpcEditorInfo, GameObject>();
}
finalWaveDic[wave.waveID][npc] = npcObj;
}
}
}
}
}
// 第四步处理不在任何波次中的NPCwaveIndex = 0
foreach (var npc in currentEnemyNpcInfo)
{
if (npc.npcInfo.waveIndex == 0)
{
// 从临时字典中找到GameObject
GameObject npcObj = null;
foreach (var waveDic in newWaveDic.Values)
{
if (waveDic.TryGetValue(npc, out npcObj))
{
break;
}
}
if (npcObj != null)
{
if (!finalWaveDic.ContainsKey(0))
{
finalWaveDic[0] = new Dictionary<NpcEditorInfo, GameObject>();
}
finalWaveDic[0][npc] = npcObj;
}
}
}
// 第五步:替换原字典
_enemyNpcObjectWaveDic = finalWaveDic;
DebugUtil.Log("已刷新波次信息至怪物属性,并更新了预制体字典");
}
#endregion
#region 战役关卡
[FoldoutGroup("当前关卡数据")]
[BoxGroup("当前关卡数据/支线(战役)")]
[LabelText("设置该关卡为评分关卡"), Indent]
[OnValueChanged(nameof(OnScoreLevelChanged))]
public bool scoreLevel;
private void OnScoreLevelChanged()
{
currentLevelData.scoreLevel = scoreLevel;
}
[FoldoutGroup("当前关卡数据")]
[BoxGroup("当前关卡数据/支线(战役)")]
[Indent, ShowIf("@currentLevelData.scoreLevel")]
[LabelText("评分条件")]
public List<ScoreTaskEditor> scoreTasks = new List<ScoreTaskEditor>();
#endregion
#region 关卡引导
[FoldoutGroup("关卡引导")] [BoxGroup("关卡引导/关卡进度")] [LabelText("关卡进度"), Indent]
public List<ProgressGuideDataEditor> progressGuideDatas = new();
[FoldoutGroup("关卡引导")] [BoxGroup("关卡引导/立标数据")] [LabelText("立标数据"), Indent]
public List<SetFlagGuideDataEditor> setFlagEditorInfos = new();
[FoldoutGroup("关卡引导")] [BoxGroup("关卡引导/信息板数据")] [LabelText("信息板数据"), Indent]
public List<InfoPanelGuideDataEditor> infoPanelGuideDatas = new();
#endregion
#region 关卡AI广播
[FoldoutGroup("关卡AI广播")] [BoxGroup("关卡AI广播/数据")] [LabelText("AI广播数据"), Indent]
public List<AIBroadcastDataEditor> listAIBroadcastData = new();
#endregion
#region 地区相关
/// <summary>
/// 每种地区对应的显示颜色
/// </summary>
private static readonly Dictionary<ShowRegionType, Color> ShowRegionTypeColors =
new Dictionary<ShowRegionType, Color>
{
{ ShowRegionType.CaptureRegion, CaptureRegionColor },
{ ShowRegionType.RetreatRegion, RetreatRegionColor },
{ ShowRegionType.EnemyRetreatRegion, Color.green },
{ ShowRegionType.MinesRegion, Color.black },
{ ShowRegionType.DefenseRegion, Color.magenta },
{ ShowRegionType.BlockRegion, Color.blue },
};
[FoldoutGroup("地区相关")] [LabelText("显示地区颜色")] [EnumToggleButtons] [OnValueChanged(nameof(OnShowRegionTypeChanged))]
public ShowRegionType showRegionType;
/// <summary>
/// 根据当前选择的地区类型集合,高亮对应的地区格子,每种地区使用独立颜色。
/// </summary>
private void OnShowRegionTypeChanged()
{
if (_curMap == null || currentLevelData == null)
return;
ClearShowRegionColor();
if (showRegionType == ShowRegionType.None)
{
SceneView.RepaintAll();
return;
}
var mask = showRegionType;
if (mask.HasFlag(ShowRegionType.All))
{
mask |= ShowRegionType.All;
}
foreach (var kv in ShowRegionTypeColors)
{
var type = kv.Key;
var color = kv.Value;
if (!mask.HasFlag(type))
continue;
var points = GetRegionPoints(type);
if (points == null || points.Count == 0)
continue;
_curMap.SetBlocksColor(points, true, color);
}
SceneView.RepaintAll();
}
/// <summary>
/// 按地区类型获取需要高亮的格子索引列表
/// </summary>
private List<int> GetRegionPoints(ShowRegionType type)
{
var points = new HashSet<int>();
switch (type)
{
case ShowRegionType.CaptureRegion:
if (captureEditorInfos != null)
{
foreach (var capture in captureEditorInfos)
{
if (capture?.capturePointEditorInfos == null) continue;
foreach (var p in capture.capturePointEditorInfos)
{
points.Add(p.capturePoint);
}
}
}
break;
case ShowRegionType.RetreatRegion:
if (retreatEditorInfo != null)
{
foreach (var info in retreatEditorInfo)
{
points.Add(info.retreatPoint);
}
}
break;
case ShowRegionType.EnemyRetreatRegion:
if (enemyRetreatEditorInfo?.fallbackReusablePoints != null)
{
foreach (var pos in enemyRetreatEditorInfo.fallbackReusablePoints)
{
points.Add(_curMap.BlockPosition2TGSCellIndex(pos));
}
}
break;
case ShowRegionType.MinesRegion:
if (minesRegionList != null)
{
foreach (var area in minesRegionList)
{
if (area?.Positions == null) continue;
foreach (var cell in area.Positions)
{
points.Add(cell);
}
}
}
break;
case ShowRegionType.DefenseRegion:
if (defenseRegionList != null)
{
foreach (var area in defenseRegionList)
{
if (area?.Positions == null) continue;
foreach (var cell in area.Positions)
{
points.Add(cell);
}
}
}
break;
case ShowRegionType.BlockRegion:
if (blockRegionList != null)
{
foreach (var area in blockRegionList)
{
if (area?.Positions == null) continue;
foreach (var cell in area.Positions)
{
points.Add(cell);
}
}
}
break;
}
return points.ToList();
}
#region 撤离相关
[FoldoutGroup("地区相关")]
[BoxGroup("地区相关/撤离相关")]
[VerticalGroup("地区相关/撤离相关/编辑")]
[LabelText("编辑撤离数据"), Indent]
[OnValueChanged("OnIsEditingRetreatChanged")]
public bool isEditingRetreat;
[FoldoutGroup("地区相关")]
[BoxGroup("地区相关/撤离相关")]
[LabelText("当前撤离数据"), Indent]
[ShowIf("isEditingRetreat")]
[ListDrawerSettings(CustomRemoveIndexFunction = "CustomRemoveRetreatPoint",
DraggableItems = false)]
public List<RetreatEditorInfo> retreatEditorInfo = new();
private void CustomRemoveRetreatPoint(int index)
{
if (index >= retreatEditorInfo.Count) return;
var point = retreatEditorInfo[index].retreatPoint;
_curMap.TerrainGridSystem.CellHideRegionSurface(point);
retreatEditorInfo.RemoveAt(index);
}
#endregion
#region 敌人撤离相关
[FoldoutGroup("地区相关")]
[BoxGroup("地区相关/敌人撤离相关")]
[LabelText("编辑敌人撤离数据"), Indent]
[OnValueChanged("OnIsEditingEnemyRetreatChanged")]
public bool isEditingEnemyRetreat;
private void OnIsEditingEnemyRetreatChanged()
{
if (isEditingEnemyRetreat)
return;
isEditingFallbackReusable = false;
}
private bool isEditingFallbackReusable;
[FoldoutGroup("地区相关")] [BoxGroup("地区相关/敌人撤离相关")] [LabelText("当前撤离数据"), Indent] [ShowIf("isEditingEnemyRetreat")]
public EnemyRetreatEditorInfo enemyRetreatEditorInfo = new();
#endregion
#region 出战防守区
[FoldoutGroup("地区相关")] [BoxGroup("地区相关/出战防守")] [LabelText("当前地区数据"), Indent]
public RegionData curRegionData = null;
#endregion
#region 占领相关
[FoldoutGroup("地区相关")] [BoxGroup("地区相关/占领相关")] [VerticalGroup("地区相关/占领相关/编辑")] [LabelText("编辑占领区"), Indent]
public bool isEditingCapture = false;
[FoldoutGroup("地区相关")]
[BoxGroup("地区相关/占领相关")]
[VerticalGroup("地区相关/占领相关/编辑")]
[LabelText("编辑占领区"), Indent]
[ShowIf("isEditingCapture")]
public List<CaptureEditorInfo> captureEditorInfos = new();
#endregion
#region 雷达
[FoldoutGroup("地区相关")]
[BoxGroup("地区相关/编辑雷达信息")]
[HorizontalGroup("地区相关/编辑雷达信息/radar")]
[LabelText("编辑雷达信息"), Indent]
[LabelWidth(100)]
[SerializeField]
private bool canEditorRadarInfo;
[FoldoutGroup("地区相关")]
[VerticalGroup("地区相关/编辑雷达信息/radarInfo"), Indent]
[LabelText("雷达列表")]
[ShowIf("canEditorRadarInfo")]
public List<RadarEditorInfo> radarInfoList = new();
#endregion
#region 雷区 点击
[FoldoutGroup("地区相关")]
[BoxGroup("地区相关/雷区信息")]
[HorizontalGroup("地区相关/雷区信息/Region")]
[LabelText("编辑雷区"), Indent]
[OnValueChanged("OnCanEditorMinesAreaTypeChanged")]
[LabelWidth(100)]
[SerializeField]
private bool canEditorMinesArea;
private void OnCanEditorMinesAreaTypeChanged()
{
if (canEditorMinesArea)
{
CloseBlockRegion();
CloseMonsterTrigger();
CloseHoldFlag();
CloseSearchLight();
}
else
{
CloseMinesRegion();
}
SceneView.RepaintAll();
}
[FoldoutGroup("地区相关")]
[VerticalGroup("地区相关/雷区信息/RegionInfo"), Indent]
[LabelText("雷区列表")]
[ShowIf("canEditorMinesArea")]
[ListDrawerSettings(CustomAddFunction = "CustomAddMinesRegion",
CustomRemoveIndexFunction = "CustomRemoveMinesRegion",
DraggableItems = false)]
public List<MinesRegionArea> minesRegionList = new();
private void CustomAddMinesRegion()
{
var region = new LevelData.Region();
currentLevelData.minesRegions.Add(region);
UpdateMinesRegion();
}
private void CustomRemoveMinesRegion(int index)
{
ClearMinesRegionColor();
currentLevelData.minesRegions.RemoveAt(index);
UpdateMinesRegion();
}
#endregion
#region 阻挡区信息 点击
[FoldoutGroup("地区相关")]
[BoxGroup("地区相关/阻挡区信息")]
[HorizontalGroup("地区相关/阻挡区信息/Region")]
[LabelText("编辑阻挡区"), Indent]
[OnValueChanged("OnCanEditorBlockAreaChanged")]
[LabelWidth(100)]
[SerializeField]
private bool canEditorBlockArea;
private void OnCanEditorBlockAreaChanged()
{
if (canEditorBlockArea)
{
CloseMinesRegion();
CloseMinesRegion();
CloseMonsterTrigger();
CloseHoldFlag();
}
else
{
CloseBlockRegion();
}
SceneView.RepaintAll();
}
[FoldoutGroup("地区相关")]
[LabelText("阻挡区列表")]
[ShowIf("canEditorBlockArea")]
[VerticalGroup("地区相关/阻挡区信息/RegionInfo"), Indent]
[ListDrawerSettings(CustomAddFunction = "CustomAddBlockRegion",
CustomRemoveIndexFunction = "CustomRemoveBlockRegionIndex",
DraggableItems = false)]
public List<BlockRegionArea> blockRegionList = new();
private void CustomAddBlockRegion()
{
var region = new BlockRegion();
currentLevelData.blockRegions.Add(region);
UpdateBlockRegion();
}
private void CustomRemoveBlockRegionIndex(int index)
{
if (index < blockRegionList.Count)
{
if (blockRegionList[index].obj != null)
{
DebugUtil.LogError($"删除{blockRegionList[index].id}的指示");
DestroyImmediate(blockRegionList[index].obj);
}
}
ClearBlockRegionColor();
currentLevelData.blockRegions.RemoveAt(index);
UpdateBlockRegion();
}
#endregion
#region 刷怪触发区 点击
[FoldoutGroup("地区相关")]
[BoxGroup("地区相关/刷怪触发区")]
[HorizontalGroup("地区相关/刷怪触发区/Region")]
[LabelText("编辑触发区"), Indent]
[OnValueChanged("OnCanEditorMonsterTriggerChanged")]
[LabelWidth(100)]
[SerializeField]
private bool canEditorMonsterTrigger;
private void OnCanEditorMonsterTriggerChanged()
{
if (canEditorMonsterTrigger)
{
CloseBlockRegion();
CloseMinesRegion();
CloseSearchLight();
CloseHoldFlag();
}
else
{
CloseMonsterTrigger();
}
SceneView.RepaintAll();
}
[FoldoutGroup("地区相关")]
[LabelText("刷怪触发区列表")]
[ShowIf("canEditorMonsterTrigger")]
[VerticalGroup("地区相关/刷怪触发区/RegionInfo"), Indent]
[ListDrawerSettings(CustomAddFunction = "CustomAddDefenseRegion",
CustomRemoveIndexFunction = "CustomRemoveDefenseRegion",
DraggableItems = false)]
public List<MonsterTriggerEditorInfo> defenseRegionList = new();
private void CustomAddDefenseRegion()
{
var region = new LevelData.Region();
currentLevelData.defenseRegions.Add(region);
UpdateMonsterTrigger();
}
private void CustomRemoveDefenseRegion(int index)
{
ClearMonsterTriggerColor();
currentLevelData.defenseRegions.RemoveAt(index);
UpdateMonsterTrigger();
}
#endregion
#region 战旗 点击
[FoldoutGroup("地区相关")]
[BoxGroup("地区相关/战旗")]
[HorizontalGroup("地区相关/战旗/Region")]
[LabelText("编辑战旗信息"), Indent]
[OnValueChanged("OnCanEditorHoldFlagAreaChanged")]
[LabelWidth(100)]
[SerializeField]
private bool canEditorHoldFlagArea;
private void OnCanEditorHoldFlagAreaChanged()
{
if (canEditorHoldFlagArea)
{
CloseBlockRegion();
CloseMonsterTrigger();
CloseMinesRegion();
CloseSearchLight();
}
else
{
CloseHoldFlag();
}
SceneView.RepaintAll();
}
[FoldoutGroup("地区相关")]
[LabelText("战旗争夺区列表")]
[ShowIf("canEditorHoldFlagArea")]
[VerticalGroup("地区相关/战旗/RegionInfo"), Indent]
[ListDrawerSettings(CustomAddFunction = "CustomAddHoldFlag",
CustomRemoveIndexFunction = "CustomRemoveHoldFlag",
DraggableItems = false)]
public List<HoldFlagEditorInfo> holdFlagEditorList = new();
private void CustomAddHoldFlag()
{
var holdFlag = new HoldFlagData();
currentLevelData.holdGFlagInfos.Add(holdFlag);
UpdateHoldFlag();
}
private void CustomRemoveHoldFlag(int index)
{
ClearHoldFlagColor();
currentLevelData.holdGFlagInfos.RemoveAt(index);
UpdateHoldFlag();
}
#endregion
#region 探照灯 点击
[FoldoutGroup("地区相关")]
[BoxGroup("地区相关/探照灯")]
[HorizontalGroup("地区相关/探照灯/Region")]
[LabelText("编辑探照灯"), Indent]
[OnValueChanged("OnCanEditorSearchLightChanged")]
[LabelWidth(100)]
[SerializeField]
private bool canEditorSearchLight;
private void OnCanEditorSearchLightChanged()
{
if (canEditorSearchLight)
{
CloseBlockRegion();
CloseMonsterTrigger();
CloseMinesRegion();
CloseHoldFlag();
}
else
{
CloseSearchLight();
}
SceneView.RepaintAll();
}
[FoldoutGroup("地区相关")]
[VerticalGroup("地区相关/探照灯/RegionInfo"), Indent]
[LabelText("探照灯列表")]
[ShowIf("canEditorSearchLight")]
[ListDrawerSettings(CustomAddFunction = "CustomAddSearchLight",
CustomRemoveIndexFunction = "CustomRemoveSearchLight",
DraggableItems = false)]
public List<SearchLightEditorInfo> searchLightList = new();
private void CustomAddSearchLight()
{
var searchLight = new LevelData.SearchLightInfo();
currentLevelData.searchLightInfos.Add(searchLight);
UpdateSearchLightInfo();
}
private void CustomRemoveSearchLight(int index)
{
ClearSearchLightColor();
currentLevelData.searchLightInfos.RemoveAt(index);
UpdateSearchLightInfo();
}
#endregion
#region 轰炸区
[FoldoutGroup("地区相关")]
[BoxGroup("地区相关/编辑轰炸区")]
[HorizontalGroup("地区相关/编辑轰炸区/bomb")]
[LabelText("编辑编辑轰炸区"), Indent]
[LabelWidth(100)]
[SerializeField]
private bool canEditorBombAreaInfo;
[FoldoutGroup("地区相关")]
[VerticalGroup("地区相关/编辑轰炸区/bombInfo"), Indent]
[LabelText("轰炸区列表")]
[ShowIf("canEditorBombAreaInfo")]
public List<BombAreaInfoEditor> bombAreaInfoList = new();
#endregion
#endregion
#region 指定路线
[BoxGroup("制定路线")] [LabelText("编辑指定路径"), Indent]
public bool isEditingRoad;
[BoxGroup("制定路线")] [LabelText("编辑指定路线"), Indent] [ShowIf("isEditingRoad")]
public List<PrescribedRoadEditorInfo> roadEditorInfos = new();
#endregion
#region 指定区域
[BoxGroup("巡逻区域")] [LabelText("编辑巡逻区域"), Indent]
public bool isEditingArea;
[BoxGroup("巡逻区域")] [LabelText("编辑巡逻区域"), Indent] [ShowIf("isEditingArea")]
public List<PrescribedAreaEditorInfo> areaEditorInfos = new();
#endregion
#region 显示地图索引
[BoxGroup("显示地格索引")]
[LabelText("显示类型"), Indent]
[OnValueChanged("ShowCellIndex")]
[LabelWidth(100)]
[SerializeField]
private CellDebugInfo cellDebugInfo = CellDebugInfo.Nothing;
private void ShowCellIndex()
{
if (_curMap == null || _curMap.TerrainGridSystem == null) return;
_curMap.TerrainGridSystem.displayCellDebugInfo = cellDebugInfo;
var obj = FindObjectOfType<TerrainGridSystem>().gameObject;
Selection.activeGameObject = obj;
}
#endregion
#region 敌方Npc
private GameObject enemyObjRoot;
/// <summary>
/// 波次/怪物ID对应的NPC预制体
/// </summary>
private Dictionary<int, Dictionary<NpcEditorInfo, GameObject>> _enemyNpcObjectWaveDic;
[BoxGroup("敌方Npc")]
[LabelText("编辑NPC"), Indent]
[LabelWidth(100)]
[SerializeField]
[OnValueChanged("OnIsEditingEnemyNpcChanged")]
public bool isEditingEnemyNpc;
[BoxGroup("敌方Npc")] [LabelText("显示所有怪物序号ID"), Indent] [OnValueChanged("ShowAllEnemyNpcId")] [SerializeField]
public bool isShowAllEnemyNpcID;
[BoxGroup("敌方Npc")] [LabelText("筛选怪物ID"), Indent, LabelWidth(100)] [SerializeField] [ShowIf("isEditingEnemyNpc")]
public string selectEnemyMonsterId;
[BoxGroup("敌方Npc")]
[LabelText("怪物ID"), Indent, LabelWidth(100)]
[SerializeField]
[OnValueChanged("EnemyMonsterIDChanged")]
[ValueDropdown("GetEnemyMonsterIDs")]
[ShowIf("isEditingEnemyNpc")]
public string curEnemyMonsterIDStr;
private int curEnemyMonsterID;
[BoxGroup("敌方Npc")]
[PreviewField(150, ObjectFieldAlignment.Center), Indent, ReadOnly]
[LabelText("NPC预制体预览图"), ShowIf("isEditingEnemyNpc")]
public GameObject enemyNpcObject;
/// <summary>
/// 真实敌人列表
/// </summary>
[HideInInspector] public List<NpcEditorInfo> currentEnemyNpcInfo = null;
private IEnumerable<string> GetEnemyMonsterIDs()
{
if (string.IsNullOrEmpty(selectEnemyMonsterId))
return _allMonsterIDs.Keys;
_selectMonsterIDs.Clear();
foreach (var enemyMonster in _allMonsterIDs.Keys)
{
if (enemyMonster.Contains(selectEnemyMonsterId))
_selectMonsterIDs.Add(enemyMonster);
}
return _selectMonsterIDs;
}
private void EnemyMonsterIDChanged()
{
if (!_allMonsterIDs.TryGetValue(curEnemyMonsterIDStr, out var id))
return;
curEnemyMonsterID = id;
var obj = LoadEnemyNpcPrefab(curEnemyMonsterID);
if (obj != null)
enemyNpcObject = obj;
}
private void OnIsEditingEnemyNpcChanged()
{
if (isEditingEnemyNpc)
{
isEditingSelfNpc = false;
isEditingMidNpc = false;
return;
}
foreach (var npcEditorInfo in currentEnemyNpcInfo)
{
npcEditorInfo.isChangePos = false;
}
isEditingNpcPos = false;
currWindow._currNpcEditorInfo = null;
currWindow._currEditingNpcInfo = null;
// 清除所有组的高亮显示
ClearAllGroupHighlights();
}
private void ShowAllEnemyNpcId()
{
foreach (var npc in currentEnemyNpcInfo)
{
npc.isShowNpcID = isShowAllEnemyNpcID;
if (isShowAllEnemyNpcID)
{
if (!_showNpcInfos.Contains(npc))
{
_showNpcInfos.Add(npc);
}
}
else
{
_showNpcInfos.Remove(npc);
}
}
}
[BoxGroup("敌方Npc")]
[Button("保存"), ShowIf("isEditingEnemyNpc")]
private void SaveNewGroup()
{
if (enemyNpcGroups == null || enemyNpcGroups.Count == 0)
{
DebugUtil.LogWarning("没有分组需要保存");
return;
}
int changedCount = 0;
foreach (var group in enemyNpcGroups)
{
if (group != null)
{
group.ApplyGroupIdChange(false);
changedCount++;
}
}
// 所有修改完成后,统一刷新一次视图
RefreshEnemyNpcGroups();
}
/// <summary>
/// 敌方 NPC 的分组展示数据
/// </summary>
[BoxGroup("敌方Npc")]
[LabelText("按组查看怪物"), Indent, ShowIf("isEditingEnemyNpc")]
[ShowInInspector]
[ListDrawerSettings(HideAddButton = true, HideRemoveButton = true, DraggableItems = false, ShowFoldout = true)]
public List<EnemyNpcGroupView> enemyNpcGroups = new();
/// <summary>
/// 清除所有组的高亮显示
/// </summary>
private void ClearAllGroupHighlights()
{
if (enemyNpcGroups == null)
return;
foreach (var group in enemyNpcGroups)
{
if (group != null)
{
// 强制清除高亮
group.ForceClearHighlight();
}
}
}
#endregion
#region 己方Npc
private const int SelfID = 800;
private GameObject selfObjRoot;
private Dictionary<Vector2Int, GameObject> _selfNpcObjectDic;
[BoxGroup("己方Npc")]
[LabelText("编辑己方NPC"), Indent]
[LabelWidth(100)]
[OnValueChanged("OnIsEditingSelfNpcChanged")]
[SerializeField]
public bool isEditingSelfNpc;
[BoxGroup("己方Npc")] [LabelText("显示所有己方序号ID"), Indent] [OnValueChanged("ShowAllSelfNpcId")] [SerializeField]
public bool isShowAllSelfNpcID;
[BoxGroup("己方Npc")] [LabelText("筛选怪物ID"), Indent, LabelWidth(100)] [SerializeField] [ShowIf("isEditingSelfNpc")]
public string selectSelfMonsterId;
[BoxGroup("己方Npc")]
[LabelText("己方NpcID"), Indent, LabelWidth(100)]
[SerializeField]
[OnValueChanged("SelfNpcIDChanged")]
[ValueDropdown("GetSelfNpcIDs")]
[ShowIf("isEditingSelfNpc")]
public string curSelfNpcIDStr;
private int curSelfNpcID;
[BoxGroup("己方Npc")]
[PreviewField(150, ObjectFieldAlignment.Center), Indent, ReadOnly]
[LabelText("己方NPC预制体预览图"), ShowIf("isEditingSelfNpc")]
public GameObject selfNpcObject;
[BoxGroup("己方Npc")]
[LabelText("当前己方NPC列表"), Indent, ShowIf("isEditingSelfNpc")]
[ListDrawerSettings(HideAddButton = true, HideRemoveButton = true)]
public List<NpcEditorInfo> currentSelfNpcInfo = null;
private IEnumerable<string> GetSelfNpcIDs()
{
if (string.IsNullOrEmpty(selectSelfMonsterId))
return _allMonsterIDs.Keys;
_selectMonsterIDs.Clear();
foreach (var enemyMonster in _allMonsterIDs.Keys)
{
if (enemyMonster.Contains(selectSelfMonsterId))
_selectMonsterIDs.Add(enemyMonster);
}
return _selectMonsterIDs;
}
private void SelfNpcIDChanged()
{
if (!_allMonsterIDs.TryGetValue(curSelfNpcIDStr, out var id))
return;
curSelfNpcID = id;
var obj = LoadSelfNpcPrefab(curSelfNpcID);
if (obj != null)
selfNpcObject = obj;
}
private void OnIsEditingSelfNpcChanged()
{
if (isEditingSelfNpc)
{
isEditingEnemyNpc = false;
isEditingMidNpc = false;
return;
}
foreach (var npcEditorInfo in currentSelfNpcInfo)
{
npcEditorInfo.isChangePos = false;
}
isEditingNpcPos = false;
currWindow._currNpcEditorInfo = null;
currWindow._currEditingNpcInfo = null;
}
private void ShowAllSelfNpcId()
{
foreach (var npc in currentSelfNpcInfo)
{
npc.isShowNpcID = isShowAllSelfNpcID;
if (isShowAllSelfNpcID)
{
if (!_showNpcInfos.Contains(npc))
{
_showNpcInfos.Add(npc);
}
}
else
{
_showNpcInfos.Remove(npc);
}
}
}
#endregion
#region 中立Npc
private const int MidID = 500;
private GameObject midObjRoot;
/// <summary>
/// 中立 波次/怪物ID对应的NPC预制体
/// </summary>
private Dictionary<int, Dictionary<NpcEditorInfo, GameObject>> _midNpcObjectWaveDic;
[BoxGroup("中立Npc")]
[LabelText("编辑中立NPC"), Indent]
[LabelWidth(100)]
[SerializeField]
[OnValueChanged("OnIsEditingMidNpcChanged")]
public bool isEditingMidNpc;
[BoxGroup("中立Npc")] [LabelText("显示所有怪物序号ID"), Indent] [OnValueChanged("ShowAllMidNpcId")] [SerializeField]
public bool isShowAllMidNpcID;
[BoxGroup("中立Npc")] [LabelText("筛选怪物ID"), Indent, LabelWidth(100)] [SerializeField] [ShowIf("isEditingMidNpc")]
public string selectMidMonsterId;
[BoxGroup("中立Npc")]
[LabelText("怪物ID"), Indent, LabelWidth(100)]
[SerializeField]
[OnValueChanged("MidMonsterIDChanged")]
[ValueDropdown("GetMidMonsterIDs")]
[ShowIf("isEditingMidNpc")]
public string curMidMonsterIDStr;
private int curMidMonsterID;
[BoxGroup("中立Npc")]
[PreviewField(150, ObjectFieldAlignment.Center), Indent, ReadOnly]
[LabelText("NPC预制体预览图"), ShowIf("isEditingMidNpc")]
public GameObject midNpcObject;
[BoxGroup("中立Npc")]
[LabelText("当前怪物列表"), Indent, ShowIf("isEditingMidNpc")]
[ListDrawerSettings(HideAddButton = true, HideRemoveButton = true, ShowFoldout = true)]
public List<NpcEditorInfo> currentMidNpcInfo = null;
private IEnumerable<string> GetMidMonsterIDs()
{
if (string.IsNullOrEmpty(selectMidMonsterId))
return _allMonsterIDs.Keys;
_selectMonsterIDs.Clear();
foreach (var enemyMonster in _allMonsterIDs.Keys)
{
if (enemyMonster.Contains(selectMidMonsterId))
_selectMonsterIDs.Add(enemyMonster);
}
return _selectMonsterIDs;
}
private void MidMonsterIDChanged()
{
if (!_allMonsterIDs.TryGetValue(curMidMonsterIDStr, out var id))
return;
curMidMonsterID = id;
var obj = LoadMidNpcPrefab(curMidMonsterID);
if (obj != null)
midNpcObject = obj;
}
private void OnIsEditingMidNpcChanged()
{
if (isEditingMidNpc)
{
isEditingEnemyNpc = false;
isEditingSelfNpc = false;
return;
}
foreach (var npcEditorInfo in currentMidNpcInfo)
{
npcEditorInfo.isChangePos = false;
}
isEditingNpcPos = false;
currWindow._currNpcEditorInfo = null;
currWindow._currEditingNpcInfo = null;
}
private void ShowAllMidNpcId()
{
foreach (var npc in currentMidNpcInfo)
{
npc.isShowNpcID = isShowAllMidNpcID;
if (isShowAllMidNpcID)
{
if (!_showNpcInfos.Contains(npc))
{
_showNpcInfos.Add(npc);
}
}
else
{
_showNpcInfos.Remove(npc);
}
}
}
#endregion
#region 阻挡球编辑
[BoxGroup("攻击阻挡球")]
[HorizontalGroup("攻击阻挡球/Block")]
[LabelText("编辑攻击阻挡球"), Indent]
[OnValueChanged("OnCanEditorBlockSphereChanged")]
[LabelWidth(100)]
[SerializeField]
private bool canEditorBlockSphere;
private void OnCanEditorBlockSphereChanged()
{
if (canEditorBlockSphere)
{
showBuildings = false;
HideObjectsExcept();
blockSphereEditorList.Clear();
UpdateBlockSphereInfo();
foreach (var cellIndex in banAttackCells)
{
if (blockSphereInfo.TryGetValue(cellIndex, out var sphereInfo))
{
var sphere = CreateSphere(cellIndex, sphereInfo.offestPos, Vector3.one * sphereInfo.scale);
var blockEditorInfo = new BlockSpereEditorInfo(sphereInfo, sphere);
blockSphereEditorList.Add(blockEditorInfo);
}
else
{
var pos = _curMap.TGSCellIndex2WorldPosition(cellIndex);
var sphere = CreateSphere(cellIndex, pos, Vector3.one * Calibre);
var blockEditorInfo = new BlockSpereEditorInfo(cellIndex, sphere);
blockSphereEditorList.Add(blockEditorInfo);
}
}
editingBlockSphereList.Clear();
foreach (var editorInfo in blockSphereEditorList)
{
if (editorInfo.isChanged)
{
editingBlockSphereList.Add(editorInfo);
}
}
}
else
{
// 清理所有临时材质
foreach (var editorInfo in blockSphereEditorList)
{
if (editorInfo.editingMaterial != null)
{
if (editorInfo.sphere != null)
{
var renderer = editorInfo.sphere.GetComponent<Renderer>();
if (renderer != null)
{
renderer.sharedMaterial = editorInfo.originalSharedMaterial;
}
}
DestroyImmediate(editorInfo.editingMaterial);
}
}
showBuildings = true;
ShowHiddenObjects();
DestroyBlockSphere();
}
}
[LabelText("展示建筑")]
[HorizontalGroup("攻击阻挡球/BlockBuildings"), Indent]
[ShowIf("canEditorBlockSphere")]
[OnValueChanged("OnShowBuildingsChanged")]
public bool showBuildings;
private void OnShowBuildingsChanged()
{
if (showBuildings)
{
ShowHiddenObjects();
}
else
{
HideObjectsExcept();
}
}
[LabelText("添加地格")] [HorizontalGroup("攻击阻挡球/新数据"), Indent] [ShowIf("canEditorBlockSphere")]
public int addCellIndex;
[Button("添加编辑")]
[HorizontalGroup("攻击阻挡球/新数据/Add"), Indent]
[ShowIf("canEditorBlockSphere")]
public void AddBlockSphere()
{
if (!banAttackCells.Contains(addCellIndex))
{
EditorUtility.DisplayDialog("错误", $"地格 {addCellIndex} 不是攻击阻挡地格!", "确定");
return;
}
foreach (var blockSpereEditor in editingBlockSphereList)
{
if (blockSpereEditor.cellIndex == addCellIndex)
{
return;
}
}
foreach (var blockSpereEditor in blockSphereEditorList)
{
if (blockSpereEditor.cellIndex == addCellIndex)
{
editingBlockSphereList.Add(blockSpereEditor);
break;
}
}
}
[LabelText("阻挡球列表")]
[HorizontalGroup("攻击阻挡球/EditList"), Indent]
[ShowIf("canEditorBlockSphere")]
[ListDrawerSettings(HideAddButton = true, CustomRemoveIndexFunction = "CustomRemoveBlockSphereIndex")]
public List<BlockSpereEditorInfo> editingBlockSphereList = new();
[HideInInspector] public List<BlockSpereEditorInfo> blockSphereEditorList = new();
private void CustomRemoveBlockSphereIndex(int index)
{
if (index < editingBlockSphereList.Count)
{
editingBlockSphereList[index].Revert();
DebugUtil.Log($"删除并还原{editingBlockSphereList[index].cellIndex}的阻挡球编辑数据");
editingBlockSphereList.RemoveAt(index);
}
}
#endregion
#region 保存
[Button("保存当前关卡"), Indent]
private void SaveCurrentLevel()
{
CheckCorrectLevel();
if (!CheckTask())
return;
currentLevelData.taskInfos = taskInfos.Select(t => t.taskInfo).ToList();
ProcessCondition();
// 地区
currentLevelData.preparingRegionId = curRegionData.preparingRegionId;
currentLevelData.preparingRegionToward = curRegionData.preparingRegionToward;
currentLevelData.pvpDefendRegionId = curRegionData.pvpDefendRegionId;
currentLevelData.pvpDefendToward = curRegionData.pvpDefendToward;
// 评分关卡
currentLevelData.scoreTaskID = scoreTasks.Select(s => s.scoreTaskID).ToList();
//触发器
currentLevelData.levelTriggerDatas = levelTriggerData.Select(e => e.levelTriggerData).ToList();
#region 敌方NPC
foreach (var npcEditor in currentEnemyNpcInfo)
{
npcEditor.npcInfo.index = npcEditor.id;
}
currentLevelData.npcInfos = currentEnemyNpcInfo.Select(editorNpcInfo => editorNpcInfo.npcInfo).ToList();
#endregion
#region 波次信息
// 验证波次ID是否有重复且大于0
if (waveInfoEditors != null && waveInfoEditors.Count > 0)
{
var waveIdSet = new HashSet<int>();
foreach (var waveEditor in waveInfoEditors)
{
if (waveEditor.waveID <= 0)
{
EditorUtility.DisplayDialog("错误", $"波次ID必须大于0当前有波次ID为 {waveEditor.waveID}", "确定");
return;
}
if (!waveIdSet.Add(waveEditor.waveID))
{
EditorUtility.DisplayDialog("错误", $"波次ID {waveEditor.waveID} 重复,请修改后再保存!", "确定");
return;
}
}
}
// 更新所有敌方NPC的波次信息基于怪物组
foreach (var npc in currentEnemyNpcInfo)
{
bool inWave = false;
if (npc.npcInfo.groups != null && npc.npcInfo.groups.Count > 0)
{
// 检查该NPC的任何一个组是否在某个波次中
foreach (var wave in waveInfoEditors)
{
foreach (var groupId in npc.npcInfo.groups)
{
if (wave.enemies.Contains(groupId))
{
npc.npcInfo.waveIndex = wave.waveID;
npc.npcInfo.isHideOnLoad = true;
inWave = true;
break;
}
}
if (inWave) break;
}
}
// 如果不在任何波次中,清除波次信息
if (!inWave)
{
npc.npcInfo.waveIndex = 0;
npc.npcInfo.isHideOnLoad = false;
}
}
#endregion
#region 怪物组信息
// 保存敌方NPC的分组信息
currentLevelData.groupInfos.Clear();
if (enemyNpcGroups != null)
{
foreach (var groupView in enemyNpcGroups)
{
// 跳过"无编组怪物"组groupId为-1
if (groupView.groupId < 0)
continue;
var groupInfo = new GroupInfo
{
groupID = groupView.groupId,
groupName = groupView.groupName
};
currentLevelData.groupInfos.Add(groupInfo);
}
}
#endregion
#region 己方NPC
foreach (var npcFightEditorInfo in currentSelfNpcInfo)
{
npcFightEditorInfo.npcInfo.index = npcFightEditorInfo.id;
}
currentLevelData.selfNpcInfos =
currentSelfNpcInfo.Select(editorFightNpcInfo => editorFightNpcInfo.npcInfo).ToList();
#endregion
#region 中立NPC
foreach (var npcEditor in currentMidNpcInfo)
{
npcEditor.npcInfo.index = npcEditor.id;
}
currentLevelData.midNpcInfos = currentMidNpcInfo.Select(editorNpcInfo => editorNpcInfo.npcInfo).ToList();
#endregion
// 占领数据
currentLevelData.CapturePoints.Clear();
foreach (var captureInfo in captureEditorInfos)
{
var points = captureInfo.capturePointEditorInfos.Select(x => x.capturePoint).ToList();
var flagPoint = 0;
foreach (var pointData in captureInfo.capturePointEditorInfos)
{
if (pointData.captureFlag)
flagPoint = pointData.capturePoint;
}
var capture = new CaptureInfo
{
captureRegionID = captureInfo.captureRegionID,
capturePoints = points,
captureFlag = flagPoint,
CaptureProgress = captureInfo.captureProgress,
captureEffectID = captureInfo.captureEffectID,
captureEffectPoint = captureInfo.captureEffectPoint,
};
currentLevelData.CapturePoints.Add(capture);
}
// 撤离数据
currentLevelData.retreatPoints.retreatPoints.Clear();
currentLevelData.retreatPoints.retreatFlag = -1;
foreach (var retreatPoint in retreatEditorInfo)
{
if (retreatPoint.retreatFlag)
currentLevelData.retreatPoints.retreatFlag = retreatPoint.retreatPoint;
currentLevelData.retreatPoints.retreatPoints.Add(retreatPoint.retreatPoint);
}
// 撤离数据
currentLevelData.enemyRetreatReusablePoints.Clear();
foreach (var fallback in enemyRetreatEditorInfo.fallbackReusablePoints)
{
var cellIndex = _curMap.BlockPosition2TGSCellIndex(fallback);
currentLevelData.enemyRetreatReusablePoints.Add(cellIndex);
}
// 指定路径
currentLevelData.patrolRoadData = roadEditorInfos.Select(editorInfo => new PatrolData
{
id = editorInfo.roadID,
patrolInfos = editorInfo.roadPoints,
}).ToList();
// 指定区域
currentLevelData.patrolRegionData = areaEditorInfos.Select(editorInfo => new PatrolData
{
id = editorInfo.areaID,
patrolInfos = editorInfo.areaPoints,
}).ToList();
// 关卡进度
currentLevelData.progressGuideDatas = progressGuideDatas.Select(p => p.progressGuideData).ToList();
// 立标数据
currentLevelData.setFlagGuideDatas = setFlagEditorInfos.Select(f => f.flagGuideData).ToList();
// 信息板数据
currentLevelData.infoPanelGuideDatas = infoPanelGuideDatas.Select(i => i.infoPanelGuideData).ToList();
// 关卡广播
currentLevelData.listAIBroadcastData = listAIBroadcastData.Select(a => a.aiBroadcastData).ToList();
// 雷达信息
currentLevelData.radarInfos = radarInfoList.Select(r => r.radarInfo).ToList();
// 探照灯
currentLevelData.searchLightInfos = searchLightList.Select(s => s.info).ToList();
// 轰炸区
currentLevelData.bombAreaInfos = bombAreaInfoList.Select(b => b.info).ToList();
// 战旗
currentLevelData.holdGFlagInfos = holdFlagEditorList.Select(h => h.info).ToList();
// 阻挡球
SaveBlockSphereInfo();
_levelEditor.SaveLevelData();
_mapManager.SaveMapData();
}
#endregion
#region 关卡ID相关
/// <summary>
/// 关卡ID 通过关卡数据 json文件名 获得
/// </summary>
[LabelText("手动指定关卡ID"), Indent, LabelWidth(100), ShowIf("needManualInputLevelID")]
[InfoBox("无法正确获得关卡ID请手动指定")]
[SerializeField]
public string levelID;
/// <summary>
/// 需要手动输入关卡ID
/// </summary>
[HideInInspector] public bool needManualInputLevelID;
#endregion
#region Npc某些值改变时响应事件
private void ReorderEnemyNpcID()
{
for (var i = 0; i < currentEnemyNpcInfo.Count; i++)
{
currentEnemyNpcInfo[i].id = i + 1;
currentEnemyNpcInfo[i].npcInfo.index = currentEnemyNpcInfo[i].id;
}
// 注意波次存储的是怪物组ID不是NPC ID所以不需要更新波次信息
}
private void ReorderMidNpcID()
{
for (var i = 0; i < currentMidNpcInfo.Count; i++)
{
currentMidNpcInfo[i].id = MidID + i + 1;
currentMidNpcInfo[i].npcInfo.index = currentMidNpcInfo[i].id;
}
}
private void ReorderSelfNpcID()
{
for (var i = 0; i < currentSelfNpcInfo.Count; i++)
{
currentSelfNpcInfo[i].id = SelfID + i + 1;
}
}
private void ChangeEnemyNpcID(NpcEditorInfo npcEditorInfo, int newMonsterID)
{
if (_enemyNpcObjectWaveDic.TryGetValue(npcEditorInfo.npcInfo.waveIndex, out var npcObjectDic))
{
if (npcObjectDic.TryGetValue(npcEditorInfo, out var npcObj))
{
var newObj = LoadEnemyNpcPrefab(newMonsterID);
if (newObj != null)
{
var obj = Instantiate(newObj, npcObj.transform.position, npcObj.transform.rotation);
if (enemyObjRoot == null)
enemyObjRoot = new GameObject("enemyObjRoot");
if (obj != null)
obj.transform.SetParent(enemyObjRoot.transform);
npcEditorInfo.npcInfo.id = newMonsterID;
npcEditorInfo.level = MonsterCfg.DataMap[newMonsterID].MonsterLevel;
npcObjectDic[npcEditorInfo] = obj;
DestroyImmediate(npcObj);
DebugUtil.Log(
$"从[ {npcEditorInfo.npcInfo.position} ]的怪物ID改为:[ {npcEditorInfo.npcInfo.id} ]");
}
}
}
}
private void ChangeMidNpcID(NpcEditorInfo npcEditorInfo, int newMonsterID)
{
if (_midNpcObjectWaveDic.TryGetValue(npcEditorInfo.npcInfo.waveIndex, out var npcObjectDic))
{
if (npcObjectDic.TryGetValue(npcEditorInfo, out var npcObj))
{
var newObj = LoadMidNpcPrefab(newMonsterID);
if (newObj != null)
{
var obj = Instantiate(newObj, npcObj.transform.position, npcObj.transform.rotation);
if (midObjRoot == null)
midObjRoot = new GameObject("midObjRoot");
if (obj != null)
obj.transform.SetParent(midObjRoot.transform);
npcEditorInfo.npcInfo.id = newMonsterID;
npcEditorInfo.level = MonsterCfg.DataMap[newMonsterID].MonsterLevel;
npcObjectDic[npcEditorInfo] = obj;
DestroyImmediate(npcObj);
DebugUtil.Log(
$"从[ {npcEditorInfo.npcInfo.position} ]的怪物ID改为:[ {npcEditorInfo.npcInfo.id} ]");
}
}
}
}
private void ChangeSelfNpcID(NPCInfo npcInfoInfo, int newMonsterID)
{
if (_selfNpcObjectDic.TryGetValue(npcInfoInfo.position, out var npcObj))
{
var newObj = LoadSelfNpcPrefab(newMonsterID);
if (newObj != null)
{
var obj = Instantiate(newObj, npcObj.transform.position, npcObj.transform.rotation);
if (selfObjRoot == null)
selfObjRoot = new GameObject("selfObjRoot");
if (obj != null)
obj.transform.SetParent(selfObjRoot.transform);
npcInfoInfo.id = newMonsterID;
_selfNpcObjectDic[npcInfoInfo.position] = obj;
DestroyImmediate(npcObj);
DebugUtil.Log("位置上[ {0} ]的fight怪物ID改为: [ {1} ] ", npcInfoInfo.position, npcInfoInfo.id);
}
}
}
#endregion
}