2024-06-04 12:59:37 +08:00
|
|
|
|
using TGS;
|
|
|
|
|
|
using System;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
using Gameplay;
|
2024-06-04 12:59:37 +08:00
|
|
|
|
using Framework;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using UnityEditor;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using Gameplay.Utils;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
using Gameplay.Level;
|
|
|
|
|
|
using Sirenix.Utilities;
|
2024-06-04 12:59:37 +08:00
|
|
|
|
using Sirenix.OdinInspector;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
using Sirenix.Utilities.Editor;
|
|
|
|
|
|
using System.Collections.Generic;
|
2024-11-07 15:40:07 +08:00
|
|
|
|
using cfg;
|
2025-06-25 17:48:43 +08:00
|
|
|
|
using cfg.AICfg;
|
2024-11-18 16:50:35 +08:00
|
|
|
|
using cfg.FightCfg;
|
2025-06-10 18:45:59 +08:00
|
|
|
|
using cfg.GuideCfg;
|
2025-06-04 15:23:36 +08:00
|
|
|
|
using cfg.LevelCfg;
|
2024-11-18 16:50:35 +08:00
|
|
|
|
using cfg.MonsterCfg;
|
|
|
|
|
|
using cfg.VehicleCfg;
|
2024-06-04 12:59:37 +08:00
|
|
|
|
using Sirenix.OdinInspector.Editor;
|
2024-11-18 16:50:35 +08:00
|
|
|
|
using Level = cfg.LevelCfg.Level;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
using ObjectFieldAlignment = Sirenix.OdinInspector.ObjectFieldAlignment;
|
2025-06-26 14:56:16 +08:00
|
|
|
|
using static Gameplay.Level.LevelData;
|
2025-06-30 14:51:47 +08:00
|
|
|
|
using static LevelEditorWindow;
|
|
|
|
|
|
using NPOI.SS.Formula.Functions;
|
2025-06-30 18:46:13 +08:00
|
|
|
|
using Gameplay.Character;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
|
|
|
|
|
|
public class LevelEditorWindow : OdinEditorWindow
|
|
|
|
|
|
{
|
2025-02-27 13:31:47 +08:00
|
|
|
|
[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("关卡编辑器");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private static LevelEditorWindow currWindow;
|
2024-11-07 15:50:33 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private MapManager _mapManager;
|
2024-11-04 18:43:29 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private Map _curMap;
|
2024-11-07 15:50:33 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private LevelEditor _levelEditor;
|
2025-02-17 17:11:38 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#region 配置表
|
2025-02-17 17:11:38 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private Level LevelCfg => EditorTableManager.instance.tables.Level;
|
|
|
|
|
|
private Monster MonsterCfg => EditorTableManager.instance.tables.Monster;
|
2025-06-10 15:46:40 +08:00
|
|
|
|
private MonsterClass MonsterClassCfg => EditorTableManager.instance.tables.MonsterClass;
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private VehicleConfig VehicleCfg => EditorTableManager.instance.tables.VehicleConfig;
|
|
|
|
|
|
private FightNPCConfig FightNpcCfg => EditorTableManager.instance.tables.FightNPCConfig;
|
2025-06-10 15:46:40 +08:00
|
|
|
|
private BuildConfig FightBuildCfg => EditorTableManager.instance.tables.BuildConfig;
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#endregion
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#region 地块颜色
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private static readonly Color RegionColor = MapUtils.GetRGBAColor("FF960072");
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#endregion
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#region 关卡数据
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[BoxGroup("当前关卡数据")] [LabelText("当前关卡数据"), Indent]
|
|
|
|
|
|
public LevelData currentLevelData = null;
|
2024-11-04 18:43:29 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#endregion
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2025-06-10 18:45:59 +08:00
|
|
|
|
#region 关卡进度
|
|
|
|
|
|
|
2025-06-11 13:31:37 +08:00
|
|
|
|
[BoxGroup("关卡引导")] [LabelText("关卡进度"), Indent]
|
2025-06-10 18:45:59 +08:00
|
|
|
|
public List<LevelData.ProgressGuideData> progressGuideDatas = new();
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 引导立标
|
|
|
|
|
|
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class SetFlagGuideEditorInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
public SetFlagGuideEditorInfo(LevelData.SetFlagGuideData flagGuideData)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.flagGuideData = flagGuideData;
|
|
|
|
|
|
guideTagID = flagGuideData.guideTagID;
|
|
|
|
|
|
if (GuideTagConfig.DataMap.TryGetValue(guideTagID, out var guideData))
|
|
|
|
|
|
{
|
|
|
|
|
|
flagGuideData.guideTagPath = guideData.ImagePath;
|
|
|
|
|
|
guideTagName = guideData.Name;
|
|
|
|
|
|
var sprite = AssetDatabase.LoadAssetAtPath<Sprite>(guideData.ImagePath);
|
|
|
|
|
|
if (sprite != null)
|
|
|
|
|
|
guideTagSprite = sprite;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private GuideTagConfig GuideTagConfig => EditorTableManager.instance.tables.GuideTagConfig;
|
|
|
|
|
|
|
|
|
|
|
|
[HorizontalGroup("1")] [LabelText("立标配置ID")] [ValueDropdown("GetGuideTagIDs")] [OnValueChanged("ChangeTagID")]
|
|
|
|
|
|
public int guideTagID;
|
|
|
|
|
|
|
|
|
|
|
|
[HorizontalGroup("1")] [LabelText("立标名字")] [ReadOnly]
|
|
|
|
|
|
public string guideTagName;
|
|
|
|
|
|
|
|
|
|
|
|
[HorizontalGroup("2")] [LabelText("预览图")] [PreviewField(150, ObjectFieldAlignment.Center), Indent]
|
|
|
|
|
|
public Sprite guideTagSprite;
|
|
|
|
|
|
|
|
|
|
|
|
[HorizontalGroup("3")] [LabelText("具体数据")]
|
|
|
|
|
|
public LevelData.SetFlagGuideData flagGuideData;
|
|
|
|
|
|
|
|
|
|
|
|
private IEnumerable<int> GetGuideTagIDs()
|
|
|
|
|
|
{
|
|
|
|
|
|
return GuideTagConfig.DataMap.Keys;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void ChangeTagID()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (GuideTagConfig.DataMap.TryGetValue(guideTagID, out var guideData))
|
|
|
|
|
|
{
|
|
|
|
|
|
flagGuideData.guideTagPath = guideData.ImagePath;
|
|
|
|
|
|
flagGuideData.guideTagID = guideTagID;
|
|
|
|
|
|
guideTagName = guideData.Name;
|
|
|
|
|
|
var sprite = AssetDatabase.LoadAssetAtPath<Sprite>(guideData.ImagePath);
|
|
|
|
|
|
if (sprite != null)
|
|
|
|
|
|
|
|
|
|
|
|
guideTagSprite = sprite;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[BoxGroup("关卡引导")] [LabelText("立标数据"), Indent]
|
|
|
|
|
|
public List<SetFlagGuideEditorInfo> setFlagEditorInfos = new();
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 关卡进度
|
|
|
|
|
|
|
2025-06-11 13:31:37 +08:00
|
|
|
|
[BoxGroup("关卡引导")] [LabelText("信息板数据"), Indent]
|
2025-06-10 18:45:59 +08:00
|
|
|
|
public List<LevelData.InfoPanelGuideData> infoPanelGuideDatas = new();
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#region 占领相关
|
2023-08-22 19:08:45 +08:00
|
|
|
|
|
2024-11-07 17:22:30 +08:00
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class CaptureEditorInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
[LabelText("占领点位")] public Vector2Int capturePoint;
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("占领时间")] public int captureProgress;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-10 15:46:40 +08:00
|
|
|
|
[BoxGroup("占领相关")] [VerticalGroup("占领相关/数据")] [LabelText("当前占领数据"), Indent]
|
2025-05-28 17:49:04 +08:00
|
|
|
|
public List<CaptureEditorInfo> captureEditorInfo = new();
|
|
|
|
|
|
|
2025-06-06 18:17:42 +08:00
|
|
|
|
[BoxGroup("占领相关")] [VerticalGroup("占领相关/编辑")] [LabelText("编辑占领数据"), Indent]
|
2025-05-28 17:49:04 +08:00
|
|
|
|
public bool isEditingCapture = false;
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 扛旗相关
|
|
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class FlagEditorInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
[LabelText("扛旗起点")] public List<Vector2Int> flagStartPoints = new();
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("扛旗终点")] public List<Vector2Int> flagEndPoints = new();
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("添加起点")] [OnValueChanged("EditingStartPoints")]
|
|
|
|
|
|
public bool isEditingStart;
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("添加终点")] [OnValueChanged("EditingEndPoints")]
|
|
|
|
|
|
public bool isEditingEnd;
|
|
|
|
|
|
|
|
|
|
|
|
private void EditingStartPoints()
|
|
|
|
|
|
{
|
|
|
|
|
|
currWindow.isEditingFlagStart = isEditingStart;
|
|
|
|
|
|
if (isEditingStart)
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingEnd = false;
|
|
|
|
|
|
currWindow.isEditingFlagEnd = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void EditingEndPoints()
|
|
|
|
|
|
{
|
|
|
|
|
|
currWindow.isEditingFlagEnd = isEditingEnd;
|
|
|
|
|
|
if (isEditingEnd)
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingStart = false;
|
|
|
|
|
|
currWindow.isEditingFlagStart = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private bool isEditingFlagStart;
|
|
|
|
|
|
|
|
|
|
|
|
private bool isEditingFlagEnd;
|
|
|
|
|
|
|
2025-06-10 15:46:40 +08:00
|
|
|
|
[BoxGroup("扛棋相关")] [LabelText("当前扛旗数据"), Indent]
|
2025-05-28 17:49:04 +08:00
|
|
|
|
public FlagEditorInfo flagEditorInfo = new();
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 撤离相关
|
|
|
|
|
|
|
2024-11-11 13:46:47 +08:00
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class FallbackEditorInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
[LabelText("单次撤离点")] public List<Vector2Int> fallbackSinglePoints = new();
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("复用撤离点")] public List<Vector2Int> fallbackReusablePoints = new();
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("添加单次撤离点")] [OnValueChanged("EditingFallbackPoints")]
|
|
|
|
|
|
public bool isEditingSinglePoints;
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("添加复用撤离点")] [OnValueChanged("EditingMultiplexPoint")]
|
|
|
|
|
|
public bool isEditingReusablePoints;
|
|
|
|
|
|
|
|
|
|
|
|
private void EditingFallbackPoints()
|
|
|
|
|
|
{
|
|
|
|
|
|
currWindow.isEditingFallbackSingle = isEditingSinglePoints;
|
|
|
|
|
|
if (isEditingSinglePoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingReusablePoints = false;
|
|
|
|
|
|
currWindow.isEditingFallbackReusable = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void EditingMultiplexPoint()
|
|
|
|
|
|
{
|
|
|
|
|
|
currWindow.isEditingFallbackReusable = isEditingReusablePoints;
|
|
|
|
|
|
if (isEditingReusablePoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingSinglePoints = false;
|
|
|
|
|
|
currWindow.isEditingFallbackSingle = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private bool isEditingFallbackSingle;
|
2025-02-21 17:03:56 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private bool isEditingFallbackReusable;
|
2025-02-21 17:03:56 +08:00
|
|
|
|
|
2025-06-10 15:46:40 +08:00
|
|
|
|
[BoxGroup("撤离相关")] [LabelText("当前撤离数据"), Indent]
|
2025-05-28 17:49:04 +08:00
|
|
|
|
public FallbackEditorInfo fallbackEditorInfo = new();
|
2025-06-10 15:46:40 +08:00
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#region 地区相关
|
2023-10-19 15:00:19 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class RegionData
|
|
|
|
|
|
{
|
|
|
|
|
|
[LabelText("出战区")] [OnValueChanged("OnRegionChanged")]
|
|
|
|
|
|
public int preparingRegionId;
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[LabelText("出战区朝向")] public LevelData.CharacterToward preparingRegionToward;
|
2024-11-07 17:22:30 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[LabelText("撤退区")] public int fallbackRegionId;
|
2024-11-07 18:30:47 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[LabelText("敌方撤退区")] public int enemyFallbackRegionId;
|
2024-11-07 17:22:30 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[LabelText("PVP防守区")] public int pvpDefendRegionId;
|
2024-11-07 17:22:30 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[LabelText("PVP防守方朝向")] public LevelData.CharacterToward pvpDefendToward;
|
2024-11-07 17:22:30 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private void OnRegionChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
var regionsList = currWindow._curMap.MapData.regions;
|
|
|
|
|
|
for (int i = 0; i < regionsList.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
currWindow._curMap.SetRegionColor(i, false, RegionColor);
|
|
|
|
|
|
}
|
2024-11-11 13:46:47 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
currWindow._curMap.SetRegionColor(preparingRegionId, true, RegionColor);
|
|
|
|
|
|
}
|
2024-11-11 13:46:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[BoxGroup("地区相关")] [LabelText("当前地区数据"), Indent]
|
2023-11-16 15:57:47 +08:00
|
|
|
|
public RegionData curRegionData = null;
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region NPC刷新点位相关
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[HideInInspector] [BoxGroup("刷新点位")] [LabelText("编辑刷新点"), Indent, OnValueChanged("OnIsEditingRefreshIDChanged")]
|
2025-02-21 17:03:56 +08:00
|
|
|
|
public bool isEditingRefreshID;
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[HideInInspector] [BoxGroup("刷新点位")] [LabelText("刷新点位"), Indent] [ShowIf("isEditingRefreshID")]
|
2025-02-21 17:03:56 +08:00
|
|
|
|
public List<int> refreshPoints = new List<int>();
|
|
|
|
|
|
|
|
|
|
|
|
private void OnIsEditingRefreshIDChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!isEditingRefreshID)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var point in refreshPoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
_curMap.TerrainGridSystem.CellHideRegionSurface(point);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var point in refreshPoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
_curMap.TerrainGridSystem.CellToggleRegionSurface(point, true, RegionColor);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#endregion
|
2025-02-21 17:03:56 +08:00
|
|
|
|
|
|
|
|
|
|
#region 指定路线
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class PrescribedRoadEditorInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
[LabelText("路线ID")] public int roadID;
|
|
|
|
|
|
|
2025-06-26 14:56:16 +08:00
|
|
|
|
[LabelText("路线点位")] public List<PatrolInfo> roadPoints = new();
|
2025-05-28 17:49:04 +08:00
|
|
|
|
|
|
|
|
|
|
private bool isEditingRoadInfo;
|
|
|
|
|
|
|
|
|
|
|
|
public PrescribedRoadEditorInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
roadID = currWindow.roadEditorInfos.Count + 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[Button("开始编辑路线"), Indent]
|
|
|
|
|
|
[HideIf("isEditingRoadInfo")]
|
|
|
|
|
|
private void StartEditRoad()
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingRoadInfo = true;
|
|
|
|
|
|
currWindow.StartEditRoadInfo(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[Button("完成路线编辑"), Indent]
|
|
|
|
|
|
[ShowIf("isEditingRoadInfo")]
|
|
|
|
|
|
private void EndEditRoad()
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingRoadInfo = false;
|
|
|
|
|
|
currWindow.FinishEditRoadInfo();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-04 12:56:03 +08:00
|
|
|
|
[BoxGroup("制定路线")] [LabelText("编辑指定路径"), Indent]
|
2025-05-28 17:49:04 +08:00
|
|
|
|
public bool isEditingRoad;
|
2025-02-21 17:03:56 +08:00
|
|
|
|
|
2025-06-04 12:56:03 +08:00
|
|
|
|
[BoxGroup("制定路线")] [LabelText("编辑指定路线"), Indent] [ShowIf("isEditingRoad")]
|
2025-06-26 14:56:16 +08:00
|
|
|
|
public List<PrescribedRoadEditorInfo> roadEditorInfos = new();
|
2025-02-21 17:03:56 +08:00
|
|
|
|
|
|
|
|
|
|
private bool isEditingRoadInfo;
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private PrescribedRoadEditorInfo _currEditingRoadInfo;
|
|
|
|
|
|
|
2025-02-21 17:03:56 +08:00
|
|
|
|
private void StartEditRoadInfo(PrescribedRoadEditorInfo roadInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingRoadInfo = true;
|
|
|
|
|
|
_currEditingRoadInfo = roadInfo;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void FinishEditRoadInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingRoadInfo = false;
|
|
|
|
|
|
_currEditingRoadInfo = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2025-06-26 15:25:35 +08:00
|
|
|
|
#region 指定区域
|
|
|
|
|
|
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class PrescribedAreaEditorInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
[LabelText("区域ID")] public int areaID;
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("区域点位")] public List<PatrolInfo> areaPoints = new();
|
|
|
|
|
|
|
|
|
|
|
|
private bool isEditingAreaInfo;
|
|
|
|
|
|
|
|
|
|
|
|
public PrescribedAreaEditorInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
areaID = currWindow.areaEditorInfos.Count + 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[Button("开始编辑区域"), Indent]
|
|
|
|
|
|
[HideIf("isEditingAreaInfo")]
|
|
|
|
|
|
private void StartEditArea()
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingAreaInfo = true;
|
|
|
|
|
|
currWindow.StartEditAreaInfo(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[Button("完成区域编辑"), Indent]
|
|
|
|
|
|
[ShowIf("isEditingAreaInfo")]
|
|
|
|
|
|
private void EndEditArea()
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingAreaInfo = false;
|
|
|
|
|
|
currWindow.FinishEditAreaInfo();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[BoxGroup("制定区域")]
|
|
|
|
|
|
[LabelText("编辑指定区域"), Indent]
|
|
|
|
|
|
public bool isEditingArea;
|
|
|
|
|
|
|
|
|
|
|
|
[BoxGroup("制定区域")]
|
|
|
|
|
|
[LabelText("编辑指定区域"), Indent]
|
|
|
|
|
|
[ShowIf("isEditingArea")]
|
|
|
|
|
|
public List<PrescribedAreaEditorInfo> areaEditorInfos = new();
|
|
|
|
|
|
|
|
|
|
|
|
private bool isEditingAreaInfo;
|
|
|
|
|
|
|
|
|
|
|
|
private PrescribedAreaEditorInfo _currEditingAreaInfo;
|
|
|
|
|
|
|
|
|
|
|
|
private void StartEditAreaInfo(PrescribedAreaEditorInfo roadInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingAreaInfo = true;
|
|
|
|
|
|
_currEditingAreaInfo = roadInfo;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void FinishEditAreaInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingAreaInfo = false;
|
|
|
|
|
|
_currEditingAreaInfo = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#region 显示地图索引
|
|
|
|
|
|
|
|
|
|
|
|
[BoxGroup("辅助功能")]
|
|
|
|
|
|
[LabelText("显示索引地图"), Indent]
|
|
|
|
|
|
[LabelWidth(100)]
|
|
|
|
|
|
[OnValueChanged("ShowCellCoordinates")]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
public bool isShowCellCoordinates;
|
|
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
private void ShowCellCoordinates()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_curMap == null || _curMap.TerrainGridSystem == null) return;
|
2024-11-13 13:21:36 +08:00
|
|
|
|
_curMap.TerrainGridSystem.displayCellDebugInfo =
|
|
|
|
|
|
isShowCellCoordinates ? CellDebugInfo.CellCoordinates : CellDebugInfo.Nothing;
|
2024-11-04 18:19:57 +08:00
|
|
|
|
var obj = FindObjectOfType<TerrainGridSystem>().gameObject;
|
|
|
|
|
|
|
|
|
|
|
|
Selection.activeGameObject = obj;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region NPC编辑器类
|
|
|
|
|
|
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class NpcEditorInfo
|
|
|
|
|
|
{
|
2025-06-25 17:48:43 +08:00
|
|
|
|
private AITypeConfig AITypeCfg => EditorTableManager.instance.tables.AITypeConfig;
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[HideInInspector] public int npcTroopId;
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[ReadOnly] [LabelText("序号ID")] public int id;
|
|
|
|
|
|
|
2025-06-04 16:59:05 +08:00
|
|
|
|
[FoldoutGroup("详细信息")] [LabelText("MonsterID")] [ValueDropdown("GetMonsterIDs")] [OnValueChanged("ChangeNpcID")]
|
2025-05-28 17:49:04 +08:00
|
|
|
|
public int monsterId;
|
|
|
|
|
|
|
2025-06-25 12:13:54 +08:00
|
|
|
|
[FoldoutGroup("详细信息")] [LabelText("等级")] [ReadOnly]
|
|
|
|
|
|
public int level;
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private IEnumerable<int> GetMonsterIDs()
|
|
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
return npcTroopId switch
|
|
|
|
|
|
{
|
2025-07-01 12:59:20 +08:00
|
|
|
|
ETroopsId.Neutral => currWindow.GetMidMonsterIDs(), // 中立
|
|
|
|
|
|
ETroopsId.Self => currWindow.GetSelfNpcIDs(), // 友方
|
|
|
|
|
|
ETroopsId.Enemy => currWindow.GetEnemyMonsterIDs(), // 敌人
|
2025-06-30 18:46:13 +08:00
|
|
|
|
_ => null
|
|
|
|
|
|
};
|
2025-05-28 17:49:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void ChangeNpcID()
|
|
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
switch (npcTroopId)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0: // 中立
|
|
|
|
|
|
currWindow.ChangeMidNpcID(this, monsterId);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 1: // 友方
|
|
|
|
|
|
currWindow.ChangeSelfNpcID(npcInfo, monsterId);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2: // 敌人
|
|
|
|
|
|
currWindow.ChangeEnemyNpcID(this, monsterId);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
DebugUtil.LogError($"未处理类型:{npcTroopId}");
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-05-28 17:49:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-04 16:59:05 +08:00
|
|
|
|
[FoldoutGroup("详细信息")] [LabelText("朝向")] [OnValueChanged("NpcTowardOnChange")]
|
2025-06-30 18:46:13 +08:00
|
|
|
|
public CharacterToward npcToward;
|
2025-05-28 17:49:04 +08:00
|
|
|
|
|
|
|
|
|
|
private void NpcTowardOnChange()
|
|
|
|
|
|
{
|
|
|
|
|
|
npcInfo.npcToward = npcToward;
|
2025-06-30 18:46:13 +08:00
|
|
|
|
|
|
|
|
|
|
switch (npcTroopId)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0: // 中立
|
|
|
|
|
|
currWindow.ChangeMidNpcToward(this, npcToward);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 1: // 友方
|
|
|
|
|
|
currWindow.ChangeSelfNpcToward(npcInfo.position, npcToward);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2: // 敌人
|
|
|
|
|
|
currWindow.ChangeEnemyNpcToward(this, npcToward);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
DebugUtil.LogError($"未处理类型:{npcTroopId}");
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-05-28 17:49:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[FoldoutGroup("详细信息")] [HideLabel] public NPCInfo npcInfo;
|
2025-05-28 17:49:04 +08:00
|
|
|
|
|
2025-06-04 16:59:05 +08:00
|
|
|
|
[FoldoutGroup("详细信息")] [LabelText("行为树")] [ValueDropdown(nameof(GetFilesFromFolder))]
|
2025-05-28 17:49:04 +08:00
|
|
|
|
public string aiConfigName;
|
|
|
|
|
|
|
2025-06-25 12:13:54 +08:00
|
|
|
|
[FoldoutGroup("详细信息")] [LabelText("AI预设")] [ReadOnly]
|
|
|
|
|
|
public string aiType;
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private IEnumerable<string> GetFilesFromFolder()
|
|
|
|
|
|
{
|
|
|
|
|
|
string rootPath = "Assets/Config/AI/";
|
|
|
|
|
|
return new string[] { "" }.Concat(Directory.GetFiles(rootPath, "*.asset", SearchOption.AllDirectories)
|
|
|
|
|
|
.Select(Path.GetFileNameWithoutExtension));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
public NpcEditorInfo(NPCInfo npcInfo, int index, int level, int aiType, int npcTroopId)
|
2025-05-28 17:49:04 +08:00
|
|
|
|
{
|
|
|
|
|
|
this.npcInfo = npcInfo;
|
2025-06-25 12:13:54 +08:00
|
|
|
|
this.level = level;
|
|
|
|
|
|
this.npcInfo.aiTypeID = aiType;
|
|
|
|
|
|
this.aiType = GetAITypeData(aiType);
|
2025-05-28 17:49:04 +08:00
|
|
|
|
monsterId = npcInfo.id;
|
|
|
|
|
|
id = index;
|
2025-06-30 18:46:13 +08:00
|
|
|
|
this.npcTroopId = npcTroopId;
|
2025-05-28 17:49:04 +08:00
|
|
|
|
npcToward = this.npcInfo.npcToward;
|
|
|
|
|
|
aiConfigName = npcInfo.configName;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-04 16:59:05 +08:00
|
|
|
|
[FoldoutGroup("详细信息")] [LabelText("位置调整")] [OnValueChanged("ChangeNpcPos")]
|
2025-05-28 17:49:04 +08:00
|
|
|
|
public bool isChangePos;
|
|
|
|
|
|
|
|
|
|
|
|
private void ChangeNpcPos()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isChangePos)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (currWindow._currEditingNpcInfo != null)
|
|
|
|
|
|
DebugUtil.LogWarning("检查其他怪物是否处于位置调整或编辑巡逻信息状态");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-06 18:02:48 +08:00
|
|
|
|
currWindow._currNpcEditorInfo = isChangePos ? this : null;
|
2025-05-28 17:49:04 +08:00
|
|
|
|
currWindow.isEditingNpcPos = isChangePos;
|
2025-06-30 18:46:13 +08:00
|
|
|
|
currWindow.npcTroopId = npcTroopId;
|
2025-05-28 17:49:04 +08:00
|
|
|
|
currWindow._currEditingNpcInfo = isChangePos ? npcInfo : null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-04 16:59:05 +08:00
|
|
|
|
[FoldoutGroup("详细信息")] [LabelText("显示该怪物序号")] [OnValueChanged("ShowNpcID")]
|
2025-05-28 17:49:04 +08:00
|
|
|
|
public bool isShowNpcID;
|
|
|
|
|
|
|
|
|
|
|
|
private void ShowNpcID()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isShowNpcID && !currWindow._showNpcInfos.Contains(this))
|
|
|
|
|
|
currWindow._showNpcInfos.Add(this);
|
|
|
|
|
|
else if (!isShowNpcID)
|
|
|
|
|
|
{
|
|
|
|
|
|
currWindow._showNpcInfos.Remove(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-25 17:48:43 +08:00
|
|
|
|
private string GetAITypeData(int aiTypeID)
|
2025-06-25 12:13:54 +08:00
|
|
|
|
{
|
2025-06-25 17:48:43 +08:00
|
|
|
|
if (AITypeCfg.DataMap.TryGetValue(aiTypeID, out var dataAIType))
|
|
|
|
|
|
{
|
|
|
|
|
|
return dataAIType.Name;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return $"无效AI类型: {aiTypeID},请检查配置表";
|
2025-06-25 12:13:54 +08:00
|
|
|
|
}
|
2025-05-28 17:49:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private NPCInfo _currEditingNpcInfo;
|
2025-06-10 15:46:40 +08:00
|
|
|
|
|
2025-06-06 18:02:48 +08:00
|
|
|
|
private NpcEditorInfo _currNpcEditorInfo;
|
2025-05-28 17:49:04 +08:00
|
|
|
|
|
|
|
|
|
|
private bool isEditingNpcPos;
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private int npcTroopId;
|
2025-05-28 17:49:04 +08:00
|
|
|
|
|
|
|
|
|
|
#endregion
|
2024-05-29 14:03:39 +08:00
|
|
|
|
|
2024-11-13 17:14:27 +08:00
|
|
|
|
#region 敌方Npc
|
2025-06-06 18:02:48 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 波次/怪物ID对应的NPC预制体
|
|
|
|
|
|
/// </summary>
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private Dictionary<int, Dictionary<NpcEditorInfo, GameObject>> _enemyNpcObjectWaveDic;
|
2025-05-28 17:49:04 +08:00
|
|
|
|
|
|
|
|
|
|
[BoxGroup("敌方Npc")]
|
|
|
|
|
|
[LabelText("编辑NPC"), Indent]
|
|
|
|
|
|
[LabelWidth(100)]
|
|
|
|
|
|
[SerializeField]
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[OnValueChanged("OnIsEditingEnemyNpcChanged")]
|
|
|
|
|
|
public bool isEditingEnemyNpc;
|
2024-11-18 16:50:35 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[BoxGroup("敌方Npc")]
|
|
|
|
|
|
[LabelText("显示所有怪物序号ID"), Indent]
|
|
|
|
|
|
[OnValueChanged("ShowAllEnemyNpcId")]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
public bool isShowAllEnemyNpcID;
|
2024-11-18 16:50:35 +08:00
|
|
|
|
|
2025-07-01 13:19:07 +08:00
|
|
|
|
[BoxGroup("敌方Npc")]
|
|
|
|
|
|
[LabelText("添加怪物ID"), Indent, LabelWidth(100)]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
[ShowIf("isEditingEnemyNpc")]
|
|
|
|
|
|
public int addEnemyMonsterId;
|
|
|
|
|
|
|
|
|
|
|
|
[BoxGroup("敌方Npc")]
|
|
|
|
|
|
[Button("添加怪物id"), Indent, ShowIf("isEditingEnemyNpc")]
|
|
|
|
|
|
private void AddEnemyMonsterId()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!MonsterCfg.DataMap.ContainsKey(addEnemyMonsterId))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError($"没有该怪物id:{addEnemyMonsterId}");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
enemyMonsterIDs.Add(addEnemyMonsterId);
|
|
|
|
|
|
DebugUtil.LogError($"添加怪物id:{addEnemyMonsterId}成功");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[BoxGroup("敌方Npc")]
|
2024-11-12 20:31:06 +08:00
|
|
|
|
[LabelText("怪物ID"), Indent, LabelWidth(100)]
|
2024-05-29 14:03:39 +08:00
|
|
|
|
[SerializeField]
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[OnValueChanged("EnemyMonsterIDChanged")]
|
|
|
|
|
|
[ValueDropdown("GetEnemyMonsterIDs")]
|
|
|
|
|
|
[ShowIf("isEditingEnemyNpc")]
|
|
|
|
|
|
public int curEnemyMonsterID;
|
2024-05-29 14:03:39 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[BoxGroup("敌方Npc")]
|
|
|
|
|
|
[PreviewField(150, ObjectFieldAlignment.Center), Indent, ReadOnly]
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[LabelText("NPC预制体预览图"), ShowIf("isEditingEnemyNpc")]
|
|
|
|
|
|
public GameObject enemyNpcObject;
|
2023-12-21 12:48:58 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[BoxGroup("敌方Npc")]
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[LabelText("当前怪物列表"), Indent, ShowIf("isEditingEnemyNpc")]
|
2025-06-04 16:59:05 +08:00
|
|
|
|
[ListDrawerSettings(HideAddButton = true, HideRemoveButton = true, ShowFoldout = true)]
|
2025-06-30 18:46:13 +08:00
|
|
|
|
public List<NpcEditorInfo> currentEenemyNpcInfo = null;
|
2024-11-12 20:31:06 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 该关卡的敌方NPCID
|
|
|
|
|
|
/// </summary>
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[HideInInspector] public List<int> enemyMonsterIDs;
|
2025-05-28 17:49:04 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private IEnumerable<int> GetEnemyMonsterIDs()
|
2024-05-29 14:03:39 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
return enemyMonsterIDs;
|
2024-05-29 14:03:39 +08:00
|
|
|
|
}
|
2024-04-02 16:53:46 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void EnemyMonsterIDChanged()
|
2023-12-21 12:48:58 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
var obj = LoadEnemyNpcPrefab(curEnemyMonsterID);
|
2024-11-04 18:19:57 +08:00
|
|
|
|
if (obj != null)
|
2025-06-30 18:46:13 +08:00
|
|
|
|
enemyNpcObject = obj;
|
2024-11-04 18:19:57 +08:00
|
|
|
|
}
|
2023-12-21 12:48:58 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void OnIsEditingEnemyNpcChanged()
|
2024-11-18 16:50:35 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (isEditingEnemyNpc && isEditingSelfNpc && isEditingMidNpc)
|
|
|
|
|
|
{
|
2024-11-18 16:50:35 +08:00
|
|
|
|
isEditingSelfNpc = false;
|
2025-06-30 18:46:13 +08:00
|
|
|
|
isEditingMidNpc = false;
|
|
|
|
|
|
}
|
2024-11-18 16:50:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void ShowAllEnemyNpcId()
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
foreach (var npc in currentEenemyNpcInfo)
|
2024-09-05 13:26:43 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
npc.isShowNpcID = isShowAllEnemyNpcID;
|
|
|
|
|
|
if (isShowAllEnemyNpcID)
|
2024-09-05 12:28:32 +08:00
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
if (!_showNpcInfos.Contains(npc))
|
2024-09-05 12:28:32 +08:00
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
_showNpcInfos.Add(npc);
|
2024-09-05 12:28:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-11-04 18:19:57 +08:00
|
|
|
|
else
|
2024-05-29 14:03:39 +08:00
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
_showNpcInfos.Remove(npc);
|
2024-05-29 14:03:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-12-21 12:48:58 +08:00
|
|
|
|
}
|
2024-11-12 20:31:06 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-11-13 17:14:27 +08:00
|
|
|
|
#region 己方Npc
|
2024-11-12 20:31:06 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private const int SelfID = 200;
|
|
|
|
|
|
|
|
|
|
|
|
private Dictionary<Vector2Int, GameObject> _selfNpcObjectDic;
|
|
|
|
|
|
|
|
|
|
|
|
[BoxGroup("己方Npc")]
|
|
|
|
|
|
[LabelText("编辑己方NPC"), Indent]
|
|
|
|
|
|
[LabelWidth(100)]
|
|
|
|
|
|
[OnValueChanged("OnIsEditingSelfNpcChanged")]
|
|
|
|
|
|
[SerializeField]
|
2024-11-13 17:14:27 +08:00
|
|
|
|
public bool isEditingSelfNpc;
|
2024-11-12 20:31:06 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[BoxGroup("己方Npc")] [LabelText("显示所有己方序号ID"), Indent] [OnValueChanged("ShowAllSelfNpcId")] [SerializeField]
|
2024-11-18 16:50:35 +08:00
|
|
|
|
public bool isShowAllSelfNpcID;
|
|
|
|
|
|
|
2025-07-01 13:19:07 +08:00
|
|
|
|
[BoxGroup("己方Npc")]
|
|
|
|
|
|
[LabelText("添加怪物ID"), Indent, LabelWidth(100)]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
[ShowIf("isEditingSelfNpc")]
|
|
|
|
|
|
public int addSelfMonsterId;
|
|
|
|
|
|
|
|
|
|
|
|
[BoxGroup("己方Npc")]
|
|
|
|
|
|
[Button("添加怪物id"), Indent, ShowIf("isEditingSelfNpc")]
|
|
|
|
|
|
private void AddSelfMonsterId()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!MonsterCfg.DataMap.ContainsKey(addSelfMonsterId))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError($"没有该怪物id:{addSelfMonsterId}");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
selfMonsterIDs.Add(addSelfMonsterId);
|
|
|
|
|
|
DebugUtil.LogError($"添加怪物id:{addSelfMonsterId}成功");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[BoxGroup("己方Npc")]
|
2024-11-13 17:14:27 +08:00
|
|
|
|
[LabelText("己方NpcID"), Indent, LabelWidth(100)]
|
2024-11-12 20:31:06 +08:00
|
|
|
|
[SerializeField]
|
2024-11-13 17:14:27 +08:00
|
|
|
|
[OnValueChanged("SelfNpcIDChanged")]
|
|
|
|
|
|
[ValueDropdown("GetSelfNpcIDs")]
|
|
|
|
|
|
[ShowIf("isEditingSelfNpc")]
|
|
|
|
|
|
public int curSelfNpcID;
|
2024-11-12 20:31:06 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[BoxGroup("己方Npc")]
|
2024-11-13 13:21:36 +08:00
|
|
|
|
[PreviewField(150, ObjectFieldAlignment.Center), Indent, ReadOnly]
|
2024-11-13 17:14:27 +08:00
|
|
|
|
[LabelText("己方NPC预制体预览图"), ShowIf("isEditingSelfNpc")]
|
|
|
|
|
|
public GameObject selfNpcObject;
|
2024-11-12 20:31:06 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[BoxGroup("己方Npc")]
|
2024-11-13 17:14:27 +08:00
|
|
|
|
[LabelText("当前己方NPC列表"), Indent, ShowIf("isEditingSelfNpc")]
|
2024-11-13 13:21:36 +08:00
|
|
|
|
[ListDrawerSettings(HideAddButton = true, HideRemoveButton = true)]
|
2024-11-18 16:50:35 +08:00
|
|
|
|
public List<NpcEditorInfo> currentSelfNpcInfo = null;
|
2024-11-12 20:31:06 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 该关卡的己方NPCID
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[HideInInspector] public List<int> selfMonsterIDs;
|
|
|
|
|
|
|
2024-11-13 17:14:27 +08:00
|
|
|
|
private IEnumerable<int> GetSelfNpcIDs()
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
2024-11-18 14:34:15 +08:00
|
|
|
|
return selfMonsterIDs;
|
2024-11-12 20:31:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-13 17:14:27 +08:00
|
|
|
|
private void SelfNpcIDChanged()
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
2024-11-13 17:14:27 +08:00
|
|
|
|
var obj = LoadSelfNpcPrefab(curSelfNpcID);
|
2024-11-12 20:31:06 +08:00
|
|
|
|
if (obj != null)
|
2024-11-13 17:14:27 +08:00
|
|
|
|
selfNpcObject = obj;
|
2024-11-12 20:31:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-18 16:50:35 +08:00
|
|
|
|
private void OnIsEditingSelfNpcChanged()
|
|
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (isEditingEnemyNpc && isEditingSelfNpc && isEditingMidNpc)
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingEnemyNpc = false;
|
|
|
|
|
|
isEditingMidNpc = false;
|
|
|
|
|
|
}
|
2024-11-18 16:50:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void ShowAllSelfNpcId()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var npc in currentSelfNpcInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
npc.isShowNpcID = isShowAllSelfNpcID;
|
|
|
|
|
|
if (isShowAllSelfNpcID)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_showNpcInfos.Contains(npc))
|
|
|
|
|
|
{
|
|
|
|
|
|
_showNpcInfos.Add(npc);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
_showNpcInfos.Remove(npc);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-12 20:31:06 +08:00
|
|
|
|
#endregion
|
2024-06-04 16:50:16 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
#region 中立Npc
|
2025-06-30 14:51:47 +08:00
|
|
|
|
/// <summary>
|
2025-06-30 18:46:13 +08:00
|
|
|
|
/// 中立 波次/怪物ID对应的NPC预制体
|
2025-06-30 14:51:47 +08:00
|
|
|
|
/// </summary>
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private Dictionary<int, Dictionary<NpcEditorInfo, GameObject>> _midNpcObjectWaveDic;
|
2025-06-30 14:51:47 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[BoxGroup("中立Npc")]
|
|
|
|
|
|
[LabelText("编辑NPC"), Indent]
|
2025-06-30 14:51:47 +08:00
|
|
|
|
[LabelWidth(100)]
|
|
|
|
|
|
[SerializeField]
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[OnValueChanged("OnIsEditingMidNpcChanged")]
|
|
|
|
|
|
public bool isEditingMidNpc;
|
2025-06-30 14:51:47 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[BoxGroup("中立Npc")]
|
|
|
|
|
|
[LabelText("显示所有怪物序号ID"), Indent]
|
|
|
|
|
|
[OnValueChanged("ShowAllMidNpcId")]
|
2025-06-30 14:51:47 +08:00
|
|
|
|
[SerializeField]
|
2025-06-30 18:46:13 +08:00
|
|
|
|
public bool isShowAllMidNpcID;
|
2025-06-30 14:51:47 +08:00
|
|
|
|
|
2025-07-01 13:19:07 +08:00
|
|
|
|
[BoxGroup("中立Npc")]
|
|
|
|
|
|
[LabelText("添加怪物ID"), Indent, LabelWidth(100)]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
[ShowIf("isEditingMidNpc")]
|
|
|
|
|
|
public int addMidMonsterId;
|
|
|
|
|
|
|
|
|
|
|
|
[BoxGroup("中立Npc")]
|
|
|
|
|
|
[Button("添加怪物id"), Indent, ShowIf("isEditingMidNpc")]
|
|
|
|
|
|
private void AddMidMonsterId()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!MonsterCfg.DataMap.ContainsKey(addMidMonsterId))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError($"没有该怪物id:{addMidMonsterId}");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
midMonsterIDs.Add(addMidMonsterId);
|
|
|
|
|
|
DebugUtil.LogError($"添加怪物id:{addMidMonsterId}成功");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[BoxGroup("中立Npc")]
|
|
|
|
|
|
[LabelText("怪物ID"), Indent, LabelWidth(100)]
|
2025-06-30 14:51:47 +08:00
|
|
|
|
[SerializeField]
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[OnValueChanged("MidMonsterIDChanged")]
|
|
|
|
|
|
[ValueDropdown("GetMidMonsterIDs")]
|
|
|
|
|
|
[ShowIf("isEditingMidNpc")]
|
|
|
|
|
|
public int curMidMonsterID;
|
2025-06-30 14:51:47 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[BoxGroup("中立Npc")]
|
2025-06-30 14:51:47 +08:00
|
|
|
|
[PreviewField(150, ObjectFieldAlignment.Center), Indent, ReadOnly]
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[LabelText("NPC预制体预览图"), ShowIf("isEditingMidNpc")]
|
|
|
|
|
|
public GameObject midNpcObject;
|
2025-06-30 14:51:47 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[BoxGroup("中立Npc")]
|
|
|
|
|
|
[LabelText("当前怪物列表"), Indent, ShowIf("isEditingMidNpc")]
|
2025-06-30 14:51:47 +08:00
|
|
|
|
[ListDrawerSettings(HideAddButton = true, HideRemoveButton = true, ShowFoldout = true)]
|
2025-06-30 18:46:13 +08:00
|
|
|
|
public List<NpcEditorInfo> currentMidNpcInfo = null;
|
2025-06-30 14:51:47 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-06-30 18:46:13 +08:00
|
|
|
|
/// 该关卡的中立NPCID
|
2025-06-30 14:51:47 +08:00
|
|
|
|
/// </summary>
|
2025-06-30 18:46:13 +08:00
|
|
|
|
[HideInInspector] public List<int> midMonsterIDs;
|
2025-06-30 14:51:47 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private IEnumerable<int> GetMidMonsterIDs()
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
return midMonsterIDs;
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void MidMonsterIDChanged()
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
var obj = LoadMidNpcPrefab(curMidMonsterID);
|
|
|
|
|
|
if (obj != null)
|
|
|
|
|
|
midNpcObject = obj;
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void OnIsEditingMidNpcChanged()
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (isEditingEnemyNpc && isEditingSelfNpc && isEditingMidNpc)
|
|
|
|
|
|
{
|
|
|
|
|
|
isEditingEnemyNpc = false;
|
2025-06-30 14:51:47 +08:00
|
|
|
|
isEditingSelfNpc = false;
|
2025-06-30 18:46:13 +08:00
|
|
|
|
}
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void ShowAllMidNpcId()
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
foreach (var npc in currentMidNpcInfo)
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
npc.isShowNpcID = isShowAllMidNpcID;
|
|
|
|
|
|
if (isShowAllMidNpcID)
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (!_showNpcInfos.Contains(npc))
|
|
|
|
|
|
{
|
|
|
|
|
|
_showNpcInfos.Add(npc);
|
|
|
|
|
|
}
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
2025-06-30 18:46:13 +08:00
|
|
|
|
{
|
|
|
|
|
|
_showNpcInfos.Remove(npc);
|
|
|
|
|
|
}
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
#region 保存
|
|
|
|
|
|
|
2024-06-04 16:50:16 +08:00
|
|
|
|
[Button("保存当前关卡"), Indent]
|
2023-08-22 19:08:45 +08:00
|
|
|
|
private void SaveCurrentLevel()
|
|
|
|
|
|
{
|
|
|
|
|
|
CheckCorrectLevel();
|
2024-11-07 18:15:12 +08:00
|
|
|
|
|
|
|
|
|
|
// 地区
|
2023-11-16 15:57:47 +08:00
|
|
|
|
currentLevelData.preparingRegionId = curRegionData.preparingRegionId;
|
|
|
|
|
|
currentLevelData.fallbackRegionId = curRegionData.fallbackRegionId;
|
|
|
|
|
|
currentLevelData.enemyFallbackRegionId = curRegionData.enemyFallbackRegionId;
|
|
|
|
|
|
currentLevelData.preparingRegionToward = curRegionData.preparingRegionToward;
|
2023-12-26 18:19:05 +08:00
|
|
|
|
currentLevelData.pvpDefendRegionId = curRegionData.pvpDefendRegionId;
|
|
|
|
|
|
currentLevelData.pvpDefendToward = curRegionData.pvpDefendToward;
|
2024-11-07 15:50:33 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
#region 敌方NPC
|
|
|
|
|
|
foreach (var npcEditor in currentEenemyNpcInfo)
|
2024-11-07 13:09:27 +08:00
|
|
|
|
{
|
|
|
|
|
|
npcEditor.npcInfo.index = npcEditor.id;
|
2025-02-17 17:11:38 +08:00
|
|
|
|
npcEditor.npcInfo.configName = npcEditor.aiConfigName;
|
2024-11-07 13:09:27 +08:00
|
|
|
|
}
|
2024-11-13 17:14:27 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
currentLevelData.npcInfos = currentEenemyNpcInfo.Select(editorNpcInfo => editorNpcInfo.npcInfo).ToList();
|
|
|
|
|
|
#endregion
|
2024-11-18 16:50:35 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
#region 己方NPC
|
2024-11-13 17:14:27 +08:00
|
|
|
|
foreach (var npcFightEditorInfo in currentSelfNpcInfo)
|
2024-11-13 13:21:36 +08:00
|
|
|
|
{
|
|
|
|
|
|
npcFightEditorInfo.npcInfo.index = npcFightEditorInfo.id;
|
2025-02-17 17:11:38 +08:00
|
|
|
|
npcFightEditorInfo.npcInfo.configName = npcFightEditorInfo.aiConfigName;
|
2024-11-13 13:21:36 +08:00
|
|
|
|
}
|
2024-11-13 17:14:27 +08:00
|
|
|
|
|
|
|
|
|
|
currentLevelData.selfNpcInfos =
|
|
|
|
|
|
currentSelfNpcInfo.Select(editorFightNpcInfo => editorFightNpcInfo.npcInfo).ToList();
|
2025-06-30 18:46:13 +08:00
|
|
|
|
#endregion
|
2024-11-12 20:31:06 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
#region 中立NPC
|
|
|
|
|
|
foreach (var npcEditor in currentMidNpcInfo)
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
npcEditor.npcInfo.index = npcEditor.id;
|
|
|
|
|
|
npcEditor.npcInfo.configName = npcEditor.aiConfigName;
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
currentLevelData.midNpcInfos = currentMidNpcInfo.Select(editorNpcInfo => editorNpcInfo.npcInfo).ToList();
|
|
|
|
|
|
#endregion
|
2025-06-30 14:51:47 +08:00
|
|
|
|
|
2024-11-07 17:22:30 +08:00
|
|
|
|
// 占领数据
|
|
|
|
|
|
currentLevelData.CapturePoints.Clear();
|
|
|
|
|
|
foreach (var captureInfo in captureEditorInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
var capture = new LevelData.CaptureInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
CapturePoint = _curMap.BlockPosition2TGSCellIndex(captureInfo.capturePoint),
|
|
|
|
|
|
CaptureProgress = captureInfo.captureProgress,
|
|
|
|
|
|
};
|
|
|
|
|
|
currentLevelData.CapturePoints.Add(capture);
|
|
|
|
|
|
}
|
2024-06-04 12:59:37 +08:00
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
// 扛旗数据
|
|
|
|
|
|
currentLevelData.flagStartPoints.Clear();
|
|
|
|
|
|
currentLevelData.flagEndPoints.Clear();
|
|
|
|
|
|
foreach (var flag in flagEditorInfo.flagStartPoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
var cellIndex = _curMap.BlockPosition2TGSCellIndex(flag);
|
|
|
|
|
|
currentLevelData.flagStartPoints.Add(cellIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var flag in flagEditorInfo.flagEndPoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
var cellIndex = _curMap.BlockPosition2TGSCellIndex(flag);
|
|
|
|
|
|
currentLevelData.flagEndPoints.Add(cellIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-11 13:46:47 +08:00
|
|
|
|
// 撤离数据
|
|
|
|
|
|
currentLevelData.fallbackSinglePoints.Clear();
|
|
|
|
|
|
currentLevelData.fallbackReusablePoints.Clear();
|
|
|
|
|
|
foreach (var fallback in fallbackEditorInfo.fallbackSinglePoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
var cellIndex = _curMap.BlockPosition2TGSCellIndex(fallback);
|
|
|
|
|
|
currentLevelData.fallbackSinglePoints.Add(cellIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var fallback in fallbackEditorInfo.fallbackReusablePoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
var cellIndex = _curMap.BlockPosition2TGSCellIndex(fallback);
|
|
|
|
|
|
currentLevelData.fallbackReusablePoints.Add(cellIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-21 17:03:56 +08:00
|
|
|
|
// 刷新点位
|
|
|
|
|
|
currentLevelData.refreshPoints.Clear();
|
|
|
|
|
|
currentLevelData.refreshPoints.AddRange(refreshPoints);
|
|
|
|
|
|
|
|
|
|
|
|
// 指定路径
|
2025-06-26 14:56:16 +08:00
|
|
|
|
currentLevelData.patrolRoadData = roadEditorInfos.Select(editorInfo => new PatrolData
|
2025-02-21 17:03:56 +08:00
|
|
|
|
{
|
2025-06-26 14:56:16 +08:00
|
|
|
|
id = editorInfo.roadID,
|
|
|
|
|
|
patrolInfos = editorInfo.roadPoints,
|
2025-06-11 17:37:11 +08:00
|
|
|
|
}).ToList();
|
2025-02-21 17:03:56 +08:00
|
|
|
|
|
2025-06-26 15:25:35 +08:00
|
|
|
|
// 指定区域
|
|
|
|
|
|
currentLevelData.patrolRegionData = areaEditorInfos.Select(editorInfo => new PatrolData
|
|
|
|
|
|
{
|
|
|
|
|
|
id = editorInfo.areaID,
|
|
|
|
|
|
patrolInfos = editorInfo.areaPoints,
|
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
2025-06-10 18:45:59 +08:00
|
|
|
|
// 关卡进度
|
2025-06-11 17:28:44 +08:00
|
|
|
|
currentLevelData.progressGuideDatas = progressGuideDatas;
|
2025-06-10 18:45:59 +08:00
|
|
|
|
|
|
|
|
|
|
// 立标数据
|
2025-06-11 17:28:44 +08:00
|
|
|
|
currentLevelData.setFlagGuideDatas = setFlagEditorInfos.Select(x => x.flagGuideData).ToList();
|
2025-06-10 18:45:59 +08:00
|
|
|
|
|
|
|
|
|
|
// 信息板数据
|
2025-06-11 17:28:44 +08:00
|
|
|
|
currentLevelData.infoPanelGuideDatas = infoPanelGuideDatas;
|
|
|
|
|
|
|
|
|
|
|
|
// 处理条件(击杀对象列表)
|
|
|
|
|
|
ProcessCondition();
|
2025-06-10 18:45:59 +08:00
|
|
|
|
|
2023-11-21 15:04:56 +08:00
|
|
|
|
_levelEditor.SaveLevelData();
|
|
|
|
|
|
}
|
2023-08-22 19:08:45 +08:00
|
|
|
|
|
2025-06-11 17:28:44 +08:00
|
|
|
|
private void ProcessCondition()
|
2024-11-07 15:50:33 +08:00
|
|
|
|
{
|
2025-06-11 17:28:44 +08:00
|
|
|
|
foreach (var condition in currentLevelData.setFlagGuideDatas)
|
|
|
|
|
|
{
|
|
|
|
|
|
ProcessCondition(condition.triggerCondition);
|
|
|
|
|
|
ProcessCondition(condition.finishCondition);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var condition in currentLevelData.progressGuideDatas)
|
|
|
|
|
|
{
|
|
|
|
|
|
ProcessCondition(condition.triggerCondition);
|
|
|
|
|
|
ProcessCondition(condition.finishCondition);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var condition in currentLevelData.infoPanelGuideDatas)
|
|
|
|
|
|
{
|
|
|
|
|
|
ProcessCondition(condition.triggerCondition);
|
|
|
|
|
|
ProcessCondition(condition.finishCondition);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-07 15:50:33 +08:00
|
|
|
|
ProcessConditionForList(currentLevelData.starTarget);
|
|
|
|
|
|
ProcessConditionForList(currentLevelData.scoreTarget);
|
2025-06-11 17:28:44 +08:00
|
|
|
|
}
|
2024-11-07 15:50:33 +08:00
|
|
|
|
|
|
|
|
|
|
private void ProcessConditionForList(IEnumerable<ConditionModifier> conditionModifiers)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var conditionModifier in conditionModifiers)
|
|
|
|
|
|
{
|
2025-06-11 17:28:44 +08:00
|
|
|
|
ProcessCondition(conditionModifier);
|
2024-11-07 15:50:33 +08:00
|
|
|
|
}
|
2025-06-11 17:28:44 +08:00
|
|
|
|
}
|
2024-11-26 16:58:42 +08:00
|
|
|
|
|
2025-06-11 17:28:44 +08:00
|
|
|
|
private void ProcessCondition(ConditionModifier conditionModifier)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 击杀条件特殊处理
|
|
|
|
|
|
if (conditionModifier.conditionType == ConditionType.CombatKillEnemy)
|
2024-11-26 16:58:42 +08:00
|
|
|
|
{
|
2025-06-11 17:28:44 +08:00
|
|
|
|
conditionModifier.conditionArgs.Clear();
|
|
|
|
|
|
foreach (var enemy in conditionModifier.killEnemyIDList)
|
2024-11-26 16:58:42 +08:00
|
|
|
|
{
|
2025-06-11 17:28:44 +08:00
|
|
|
|
conditionModifier.conditionArgs.Add(new Param("", enemy, ""));
|
2024-11-26 16:58:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-11 19:04:52 +08:00
|
|
|
|
else if (conditionModifier.conditionType == ConditionType.CombatInTargetGridByJob)
|
|
|
|
|
|
{
|
|
|
|
|
|
conditionModifier.conditionArgs.Clear();
|
|
|
|
|
|
conditionModifier.conditionArgs.Add(new Param("职业", conditionModifier.job,
|
|
|
|
|
|
typeof(cfg.CharacterCfg.Ejob).FullName));
|
|
|
|
|
|
conditionModifier.conditionArgs.Add(new Param("是否路过", conditionModifier.isPass, ""));
|
|
|
|
|
|
foreach (var unitID in conditionModifier.unitIDList)
|
|
|
|
|
|
{
|
|
|
|
|
|
conditionModifier.conditionArgs.Add(new Param("地格位置", unitID, ""));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (conditionModifier.conditionType == ConditionType.CombatInTargetGridByCharacterId)
|
|
|
|
|
|
{
|
|
|
|
|
|
conditionModifier.conditionArgs.Clear();
|
|
|
|
|
|
conditionModifier.conditionArgs.Add(new Param("角色ID", conditionModifier.roleID, ""));
|
|
|
|
|
|
conditionModifier.conditionArgs.Add(new Param("是否路过", conditionModifier.isPass, ""));
|
|
|
|
|
|
foreach (var unitID in conditionModifier.unitIDList)
|
|
|
|
|
|
{
|
|
|
|
|
|
conditionModifier.conditionArgs.Add(new Param("地格位置", unitID, ""));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-11 18:14:49 +08:00
|
|
|
|
// 任意角色在目标位置特殊处理
|
|
|
|
|
|
else if (conditionModifier.conditionType == ConditionType.CombatInTargetGrid)
|
|
|
|
|
|
{
|
|
|
|
|
|
conditionModifier.conditionArgs.Clear();
|
2025-06-11 19:04:52 +08:00
|
|
|
|
conditionModifier.conditionArgs.Add(new Param("是否路过", conditionModifier.isPass, ""));
|
2025-06-11 18:14:49 +08:00
|
|
|
|
foreach (var unitID in conditionModifier.unitIDList)
|
|
|
|
|
|
{
|
2025-06-11 19:14:38 +08:00
|
|
|
|
conditionModifier.conditionArgs.Add(new Param("地格位置", unitID, ""));
|
2025-06-11 18:14:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-11 17:28:44 +08:00
|
|
|
|
// 撤退数量特殊处理
|
|
|
|
|
|
else if (conditionModifier.conditionType == ConditionType.CombatFallBack &&
|
|
|
|
|
|
conditionModifier.conditionArgs.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentLevelData.fallBackCount = (int)conditionModifier.conditionArgs[0].Arg;
|
|
|
|
|
|
}
|
2024-11-07 15:50:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
#endregion
|
2024-06-04 12:59:37 +08:00
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#region 关卡ID相关
|
2024-11-18 14:34:15 +08:00
|
|
|
|
|
2024-11-12 20:31:06 +08:00
|
|
|
|
/// <summary>
|
2025-05-28 17:49:04 +08:00
|
|
|
|
/// 关卡ID 通过关卡数据 json文件名 获得
|
2024-11-12 20:31:06 +08:00
|
|
|
|
/// </summary>
|
2025-05-28 17:49:04 +08:00
|
|
|
|
[LabelText("手动指定关卡ID"), Indent, LabelWidth(100), ShowIf("needManualInputLevelID")]
|
|
|
|
|
|
[OnValueChanged("GetLevelMonsterClass")]
|
|
|
|
|
|
[InfoBox("无法正确获得关卡ID,请手动指定")]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
public string levelID;
|
2024-11-12 20:31:06 +08:00
|
|
|
|
|
2024-05-29 14:03:39 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 需要手动输入关卡ID
|
|
|
|
|
|
/// </summary>
|
2024-11-18 16:50:35 +08:00
|
|
|
|
[HideInInspector] public bool needManualInputLevelID;
|
2024-05-29 14:03:39 +08:00
|
|
|
|
|
2025-06-10 15:46:40 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取关卡怪物列表
|
|
|
|
|
|
/// </summary>
|
2024-05-29 14:03:39 +08:00
|
|
|
|
public void GetLevelMonsterClass()
|
|
|
|
|
|
{
|
2025-07-01 12:59:20 +08:00
|
|
|
|
if (!int.TryParse(levelID, out int levelIndex) ||
|
|
|
|
|
|
!LevelCfg.DataMap.TryGetValue(levelIndex, out _))
|
2024-05-29 14:03:39 +08:00
|
|
|
|
{
|
2024-11-18 16:50:35 +08:00
|
|
|
|
needManualInputLevelID = true;
|
2024-05-29 14:03:39 +08:00
|
|
|
|
DebugUtil.LogError("无对应的关卡ID请手动输入关卡ID");
|
2025-06-30 18:46:13 +08:00
|
|
|
|
curEnemyMonsterID = 0;
|
|
|
|
|
|
enemyNpcObject = null;
|
2024-05-29 14:03:39 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
enemyMonsterIDs = new List<int>();
|
2024-11-18 14:34:15 +08:00
|
|
|
|
selfMonsterIDs = new List<int>();
|
2025-07-01 12:59:20 +08:00
|
|
|
|
midMonsterIDs = new List<int>();
|
2024-05-29 14:03:39 +08:00
|
|
|
|
|
2024-11-18 16:50:35 +08:00
|
|
|
|
foreach (var monster in MonsterCfg.DataMap)
|
2024-05-29 14:03:39 +08:00
|
|
|
|
{
|
2025-07-01 12:59:20 +08:00
|
|
|
|
string strID = monster.Key.ToString();
|
|
|
|
|
|
string tempID = strID[..6];
|
2024-05-29 14:03:39 +08:00
|
|
|
|
|
2025-07-01 12:59:20 +08:00
|
|
|
|
// 关卡ID相同
|
|
|
|
|
|
if (!tempID.Equals(levelID))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
switch (monster.Value.NpcType)
|
2024-05-29 14:03:39 +08:00
|
|
|
|
{
|
2025-07-01 12:59:20 +08:00
|
|
|
|
case EMonsterType.EnemyCharacter:
|
|
|
|
|
|
{
|
|
|
|
|
|
enemyMonsterIDs.Add(monster.Key);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case EMonsterType.SelfCharacter:
|
|
|
|
|
|
{
|
2024-11-18 15:02:49 +08:00
|
|
|
|
selfMonsterIDs.Add(monster.Key);
|
2025-07-01 12:59:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case EMonsterType.Vehicle:
|
|
|
|
|
|
case EMonsterType.FightBuild:
|
|
|
|
|
|
{
|
|
|
|
|
|
midMonsterIDs.Add(monster.Key);
|
2025-06-30 18:46:13 +08:00
|
|
|
|
enemyMonsterIDs.Add(monster.Key);
|
2025-07-01 12:59:20 +08:00
|
|
|
|
selfMonsterIDs.Add(monster.Key);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
DebugUtil.LogError($"未处理类型:{monster.Value.NpcType}");
|
|
|
|
|
|
break;
|
2024-05-29 14:03:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-01 12:59:20 +08:00
|
|
|
|
if (enemyMonsterIDs.Count <= 0 && midMonsterIDs.Count <= 0)
|
|
|
|
|
|
DebugUtil.LogError($"请检查Monster表,没有{levelID}关卡的怪物数据");
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
#region 加载
|
2023-11-16 15:57:47 +08:00
|
|
|
|
|
2023-11-21 15:04:56 +08:00
|
|
|
|
private void LoadLevel(LevelData levelData)
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2023-11-16 15:57:47 +08:00
|
|
|
|
DestroyNpcPrefab();
|
2025-06-30 18:46:13 +08:00
|
|
|
|
_enemyNpcObjectWaveDic.Clear();
|
|
|
|
|
|
_midNpcObjectWaveDic.Clear();
|
2024-11-04 18:19:57 +08:00
|
|
|
|
_showNpcInfos.Clear();
|
2024-11-13 17:14:27 +08:00
|
|
|
|
_selfNpcObjectDic.Clear();
|
2023-11-21 15:04:56 +08:00
|
|
|
|
|
|
|
|
|
|
currentLevelData = levelData;
|
|
|
|
|
|
|
2023-11-16 15:57:47 +08:00
|
|
|
|
//加载地区信息
|
2024-11-07 17:22:30 +08:00
|
|
|
|
curRegionData = new RegionData
|
|
|
|
|
|
{
|
|
|
|
|
|
preparingRegionId = currentLevelData.preparingRegionId,
|
|
|
|
|
|
fallbackRegionId = currentLevelData.fallbackRegionId,
|
|
|
|
|
|
enemyFallbackRegionId = currentLevelData.enemyFallbackRegionId,
|
|
|
|
|
|
preparingRegionToward = currentLevelData.preparingRegionToward,
|
|
|
|
|
|
pvpDefendRegionId = currentLevelData.pvpDefendRegionId,
|
|
|
|
|
|
pvpDefendToward = currentLevelData.pvpDefendToward
|
|
|
|
|
|
};
|
2024-04-02 16:53:46 +08:00
|
|
|
|
|
2023-12-18 19:42:46 +08:00
|
|
|
|
_mapManager = FindObjectOfType<MapManager>();
|
|
|
|
|
|
_curMap = _mapManager.Map;
|
2023-11-16 15:57:47 +08:00
|
|
|
|
|
2023-11-21 15:04:56 +08:00
|
|
|
|
_curMap.TerrainGridSystem.OnMouseClickOnGrid += OnCellClick;
|
2023-11-16 15:57:47 +08:00
|
|
|
|
|
2024-11-07 17:22:30 +08:00
|
|
|
|
// 加载占领数据
|
2024-11-07 18:15:12 +08:00
|
|
|
|
captureEditorInfo = new List<CaptureEditorInfo>();
|
2024-11-07 17:22:30 +08:00
|
|
|
|
foreach (var captureInfo in currentLevelData.CapturePoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
var captureEditor = new CaptureEditorInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
capturePoint = _curMap.TGSCellIndex2BlockPosition(captureInfo.CapturePoint),
|
|
|
|
|
|
captureProgress = captureInfo.CaptureProgress,
|
|
|
|
|
|
};
|
|
|
|
|
|
captureEditorInfo.Add(captureEditor);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
// 加载扛旗数据
|
|
|
|
|
|
flagEditorInfo = new FlagEditorInfo();
|
|
|
|
|
|
foreach (var flagStartPoint in currentLevelData.flagStartPoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
var pos = _curMap.TGSCellIndex2BlockPosition(flagStartPoint);
|
|
|
|
|
|
flagEditorInfo.flagStartPoints.Add(pos);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var flagEndPoint in currentLevelData.flagEndPoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
var pos = _curMap.TGSCellIndex2BlockPosition(flagEndPoint);
|
|
|
|
|
|
flagEditorInfo.flagEndPoints.Add(pos);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-11 13:46:47 +08:00
|
|
|
|
// 加载撤离数据
|
|
|
|
|
|
fallbackEditorInfo = new FallbackEditorInfo();
|
|
|
|
|
|
foreach (var fallback in currentLevelData.fallbackSinglePoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
var pos = _curMap.TGSCellIndex2BlockPosition(fallback);
|
|
|
|
|
|
fallbackEditorInfo.fallbackSinglePoints.Add(pos);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var fallback in currentLevelData.fallbackReusablePoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
var pos = _curMap.TGSCellIndex2BlockPosition(fallback);
|
|
|
|
|
|
fallbackEditorInfo.fallbackReusablePoints.Add(pos);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-21 17:03:56 +08:00
|
|
|
|
// 加载刷新点位
|
|
|
|
|
|
refreshPoints = new List<int>();
|
|
|
|
|
|
refreshPoints.AddRange(currentLevelData.refreshPoints);
|
|
|
|
|
|
|
|
|
|
|
|
// 加载指定路线
|
2025-06-26 14:56:16 +08:00
|
|
|
|
roadEditorInfos = currentLevelData.patrolRoadData.Select(roadInfo => new PrescribedRoadEditorInfo
|
2025-02-21 17:03:56 +08:00
|
|
|
|
{
|
2025-06-26 14:56:16 +08:00
|
|
|
|
roadID = roadInfo.id,
|
|
|
|
|
|
roadPoints = roadInfo.patrolInfos,
|
2025-06-11 17:37:11 +08:00
|
|
|
|
}).ToList();
|
2025-02-21 17:03:56 +08:00
|
|
|
|
|
2025-06-26 15:25:35 +08:00
|
|
|
|
// 加载指定区域
|
|
|
|
|
|
areaEditorInfos = currentLevelData.patrolRegionData.Select(areaInfo => new PrescribedAreaEditorInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
areaID = areaInfo.id,
|
|
|
|
|
|
areaPoints = areaInfo.patrolInfos,
|
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
2025-06-10 18:45:59 +08:00
|
|
|
|
// 加载关卡进度数据
|
2025-06-11 17:28:44 +08:00
|
|
|
|
progressGuideDatas = currentLevelData.progressGuideDatas;
|
2025-06-10 18:45:59 +08:00
|
|
|
|
|
|
|
|
|
|
// 加载关卡引导立标数据
|
2025-06-11 17:28:44 +08:00
|
|
|
|
setFlagEditorInfos = currentLevelData.setFlagGuideDatas.Select(x => new SetFlagGuideEditorInfo(x)).ToList();
|
2025-06-10 18:45:59 +08:00
|
|
|
|
|
|
|
|
|
|
// 加载信息板数据
|
2025-06-11 17:28:44 +08:00
|
|
|
|
infoPanelGuideDatas = currentLevelData.infoPanelGuideDatas;
|
2025-06-10 18:45:59 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
// 加载敌方NPC到场景中
|
|
|
|
|
|
LoadEnemyNpcInfo();
|
2024-11-07 17:22:30 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
// 加载中立NPC到场景中
|
|
|
|
|
|
LoadMidNpcInfo();
|
|
|
|
|
|
|
|
|
|
|
|
// 加载己方NPC到场景中
|
2024-11-18 16:50:35 +08:00
|
|
|
|
LoadSelfNpcInfo();
|
2024-11-07 17:22:30 +08:00
|
|
|
|
}
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void LoadEnemyNpcInfo()
|
2024-11-07 17:22:30 +08:00
|
|
|
|
{
|
2024-11-18 16:50:35 +08:00
|
|
|
|
var monsterConfigDic = MonsterCfg.DataMap;
|
2025-06-30 18:46:13 +08:00
|
|
|
|
currentEenemyNpcInfo = new();
|
2024-11-04 18:19:57 +08:00
|
|
|
|
var index = 1;
|
2023-11-16 15:57:47 +08:00
|
|
|
|
foreach (var npcInfo in currentLevelData.npcInfos)
|
|
|
|
|
|
{
|
2024-09-05 13:26:43 +08:00
|
|
|
|
if (!monsterConfigDic.TryGetValue(npcInfo.id, out var monsterClassData))
|
2024-06-04 16:50:16 +08:00
|
|
|
|
{
|
2024-09-05 13:26:43 +08:00
|
|
|
|
DebugUtil.LogError("请检查配置,没有 {0} 的怪物类ID", npcInfo.id);
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
2024-09-05 12:28:32 +08:00
|
|
|
|
|
2025-06-30 19:57:08 +08:00
|
|
|
|
var npcEditor = new NpcEditorInfo(npcInfo, index, monsterClassData.MonsterLevel, monsterClassData.AIType, ETroopsId.Enemy);
|
2025-06-30 18:46:13 +08:00
|
|
|
|
currentEenemyNpcInfo.Add(npcEditor);
|
|
|
|
|
|
|
|
|
|
|
|
var npcObj = LoadEnemyNpcPrefab(npcInfo.id);
|
|
|
|
|
|
if (npcObj != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var setPos = _curMap.BlockPosition2WorldPosition(npcInfo.position);
|
|
|
|
|
|
var yaw = LevelUtils.SetCharaterToward(npcInfo.npcToward);
|
|
|
|
|
|
if (_enemyNpcObjectWaveDic.TryGetValue(npcInfo.waveIndex, out var npcObjectDic))
|
|
|
|
|
|
{
|
|
|
|
|
|
npcObjectDic.Add(npcEditor, Instantiate(npcObj, setPos, Quaternion.Euler(0, yaw, 0)));
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
npcObjectDic = new Dictionary<NpcEditorInfo, GameObject>
|
|
|
|
|
|
{ { npcEditor, Instantiate(npcObj, setPos, Quaternion.Euler(0, yaw, 0)) } };
|
|
|
|
|
|
_enemyNpcObjectWaveDic.Add(npcInfo.waveIndex, npcObjectDic);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
index++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void LoadMidNpcInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
var monsterConfigDic = MonsterCfg.DataMap;
|
|
|
|
|
|
currentMidNpcInfo = new();
|
|
|
|
|
|
var index = 1;
|
|
|
|
|
|
foreach (var npcInfo in currentLevelData.midNpcInfos)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!monsterConfigDic.TryGetValue(npcInfo.id, out var monsterClassData))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请检查配置,没有 {0} 的怪物类ID", npcInfo.id);
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 19:57:08 +08:00
|
|
|
|
var npcEditor = new NpcEditorInfo(npcInfo, index, monsterClassData.MonsterLevel, monsterClassData.AIType, ETroopsId.Neutral);
|
2025-06-30 18:46:13 +08:00
|
|
|
|
currentMidNpcInfo.Add(npcEditor);
|
2024-11-18 16:50:35 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
var npcObj = LoadMidNpcPrefab(npcInfo.id);
|
2024-11-04 18:19:57 +08:00
|
|
|
|
if (npcObj != null)
|
2024-09-05 13:26:43 +08:00
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
var setPos = _curMap.BlockPosition2WorldPosition(npcInfo.position);
|
2024-11-04 18:43:29 +08:00
|
|
|
|
var yaw = LevelUtils.SetCharaterToward(npcInfo.npcToward);
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (_midNpcObjectWaveDic.TryGetValue(npcInfo.waveIndex, out var npcObjectDic))
|
2025-06-06 18:02:48 +08:00
|
|
|
|
{
|
|
|
|
|
|
npcObjectDic.Add(npcEditor, Instantiate(npcObj, setPos, Quaternion.Euler(0, yaw, 0)));
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
npcObjectDic = new Dictionary<NpcEditorInfo, GameObject>
|
|
|
|
|
|
{ { npcEditor, Instantiate(npcObj, setPos, Quaternion.Euler(0, yaw, 0)) } };
|
2025-06-30 18:46:13 +08:00
|
|
|
|
_midNpcObjectWaveDic.Add(npcInfo.waveIndex, npcObjectDic);
|
2025-06-06 18:02:48 +08:00
|
|
|
|
}
|
2024-04-02 16:53:46 +08:00
|
|
|
|
}
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
|
|
|
|
|
index++;
|
2023-11-16 15:57:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-18 16:50:35 +08:00
|
|
|
|
private void LoadSelfNpcInfo()
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
2024-11-18 16:50:35 +08:00
|
|
|
|
var monsterConfigDic = MonsterCfg.DataMap;
|
2024-11-13 17:14:27 +08:00
|
|
|
|
currentSelfNpcInfo = new();
|
2024-11-13 19:11:46 +08:00
|
|
|
|
var index = SelfID + 1;
|
2024-11-18 15:27:53 +08:00
|
|
|
|
foreach (var selfNpcInfo in currentLevelData.selfNpcInfos)
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
2024-11-18 16:50:35 +08:00
|
|
|
|
if (!monsterConfigDic.TryGetValue(selfNpcInfo.id, out var monsterClassData))
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
2024-11-18 15:27:53 +08:00
|
|
|
|
DebugUtil.LogError("请检查配置,没有 {0} 的怪物类ID, 已经删除对应", selfNpcInfo.id);
|
2024-11-12 20:31:06 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 19:57:08 +08:00
|
|
|
|
var npcEditor = new NpcEditorInfo(selfNpcInfo, index, monsterClassData.MonsterLevel, monsterClassData.AIType, ETroopsId.Self);
|
2024-11-18 16:50:35 +08:00
|
|
|
|
currentSelfNpcInfo.Add(npcEditor);
|
2024-11-18 15:27:53 +08:00
|
|
|
|
var npcObj = LoadSelfNpcPrefab(selfNpcInfo.id);
|
2024-11-12 20:31:06 +08:00
|
|
|
|
if (npcObj != null)
|
|
|
|
|
|
{
|
2024-11-18 15:27:53 +08:00
|
|
|
|
var setPos = _curMap.BlockPosition2WorldPosition(selfNpcInfo.position);
|
|
|
|
|
|
var yaw = LevelUtils.SetCharaterToward(selfNpcInfo.npcToward);
|
|
|
|
|
|
_selfNpcObjectDic.Add(selfNpcInfo.position, Instantiate(npcObj, setPos, Quaternion.Euler(0, yaw, 0)));
|
2024-11-12 20:31:06 +08:00
|
|
|
|
}
|
2024-11-13 13:21:36 +08:00
|
|
|
|
|
|
|
|
|
|
index++;
|
2024-11-12 20:31:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-11-07 18:15:12 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 点击添加事件
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private bool ResponseClickOnCell =>
|
2025-06-30 18:46:13 +08:00
|
|
|
|
isEditingEnemyNpc || isEditingSelfNpc || isEditingMidNpc || isEditingNpcPos || isEditingFlagStart ||
|
2025-05-28 17:49:04 +08:00
|
|
|
|
isEditingFlagEnd || isEditingCapture ||
|
2025-06-26 15:25:35 +08:00
|
|
|
|
isEditingFallbackReusable || isEditingFallbackSingle || isEditingRefreshID || isEditingRoadInfo || isEditingAreaInfo;
|
2025-05-28 17:49:04 +08:00
|
|
|
|
|
2023-11-16 15:57:47 +08:00
|
|
|
|
private void OnCellClick(TerrainGridSystem tgs, int cellindex, int buttonindex)
|
|
|
|
|
|
{
|
2023-12-22 15:26:48 +08:00
|
|
|
|
if (!ResponseClickOnCell) return;
|
2023-11-16 15:57:47 +08:00
|
|
|
|
|
|
|
|
|
|
var clickPosition = _curMap.TGSCellIndex2BlockPosition(cellindex);
|
2023-11-21 15:04:56 +08:00
|
|
|
|
|
2023-11-16 15:57:47 +08:00
|
|
|
|
int leftButton = 0;
|
|
|
|
|
|
int rightButton = 1;
|
|
|
|
|
|
|
2023-12-22 15:26:48 +08:00
|
|
|
|
if (buttonindex != leftButton && buttonindex != rightButton)
|
|
|
|
|
|
return;
|
|
|
|
|
|
bool opTrue = buttonindex == leftButton;
|
|
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
if (isEditingFlagStart)
|
|
|
|
|
|
{
|
|
|
|
|
|
EditingFlagStart(clickPosition, true, opTrue);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (isEditingFlagEnd)
|
|
|
|
|
|
{
|
|
|
|
|
|
EditingFlagStart(clickPosition, false, opTrue);
|
|
|
|
|
|
}
|
2024-11-11 13:46:47 +08:00
|
|
|
|
else if (isEditingFallbackSingle)
|
|
|
|
|
|
{
|
|
|
|
|
|
EditingFallBack(clickPosition, true, opTrue);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (isEditingFallbackReusable)
|
|
|
|
|
|
{
|
|
|
|
|
|
EditingFallBack(clickPosition, false, opTrue);
|
|
|
|
|
|
}
|
2024-11-07 18:30:47 +08:00
|
|
|
|
else if (isEditingCapture)
|
|
|
|
|
|
{
|
|
|
|
|
|
EditingCapture(clickPosition, opTrue);
|
|
|
|
|
|
}
|
2024-11-04 18:19:57 +08:00
|
|
|
|
else if (isEditingNpcPos)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (opTrue)
|
2025-06-30 18:46:13 +08:00
|
|
|
|
ChangeNpcPos(clickPosition, npcTroopId);
|
2024-11-04 18:19:57 +08:00
|
|
|
|
}
|
2025-06-30 18:46:13 +08:00
|
|
|
|
else if (isEditingEnemyNpc)
|
2023-11-16 15:57:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
EditEnemyNpc(clickPosition, opTrue);
|
2024-11-12 20:31:06 +08:00
|
|
|
|
}
|
2024-11-13 17:14:27 +08:00
|
|
|
|
else if (isEditingSelfNpc)
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
2024-11-13 17:14:27 +08:00
|
|
|
|
EditSelfNpc(clickPosition, opTrue);
|
2024-11-07 18:15:12 +08:00
|
|
|
|
}
|
2025-06-30 18:46:13 +08:00
|
|
|
|
else if (isEditingMidNpc)
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
EditMidNpc(clickPosition, opTrue);
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
2025-02-21 17:03:56 +08:00
|
|
|
|
else if (isEditingRefreshID)
|
|
|
|
|
|
{
|
|
|
|
|
|
EditRefreshID(cellindex, opTrue);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (isEditingRoadInfo && isEditingRoad)
|
|
|
|
|
|
{
|
|
|
|
|
|
EditRoad(cellindex, opTrue);
|
|
|
|
|
|
}
|
2025-06-26 15:25:35 +08:00
|
|
|
|
else if (isEditingAreaInfo && isEditingArea)
|
|
|
|
|
|
{
|
|
|
|
|
|
EditArea(cellindex, opTrue);
|
|
|
|
|
|
}
|
2024-11-07 18:15:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-11 13:46:47 +08:00
|
|
|
|
private void EditingFallBack(Vector2Int clickPosition, bool isEditingSingle, bool isAdd)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isEditingSingle)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isAdd && !fallbackEditorInfo.fallbackSinglePoints.Contains(clickPosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.Log("单次撤离点添加: {0}", clickPosition);
|
|
|
|
|
|
fallbackEditorInfo.fallbackSinglePoints.Add(clickPosition);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (!isAdd && fallbackEditorInfo.fallbackSinglePoints.Contains(clickPosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.Log("单次撤离点移除: {0}", clickPosition);
|
|
|
|
|
|
fallbackEditorInfo.fallbackSinglePoints.Remove(clickPosition);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isAdd && !fallbackEditorInfo.fallbackReusablePoints.Contains(clickPosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.Log("复用撤离点添加: {0}", clickPosition);
|
|
|
|
|
|
fallbackEditorInfo.fallbackReusablePoints.Add(clickPosition);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (!isAdd && fallbackEditorInfo.fallbackReusablePoints.Contains(clickPosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.Log("复用撤离点移除: {0}", clickPosition);
|
|
|
|
|
|
fallbackEditorInfo.fallbackReusablePoints.Remove(clickPosition);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-11-07 18:30:47 +08:00
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
private void EditingFlagStart(Vector2Int clickPosition, bool isEditingStart, bool isAdd)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isEditingStart)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isAdd && !flagEditorInfo.flagStartPoints.Contains(clickPosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.Log("扛旗起点添加: {0}", clickPosition);
|
|
|
|
|
|
flagEditorInfo.flagStartPoints.Add(clickPosition);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (!isAdd && flagEditorInfo.flagStartPoints.Contains(clickPosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.Log("扛旗起点移除: {0}", clickPosition);
|
|
|
|
|
|
flagEditorInfo.flagStartPoints.Remove(clickPosition);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isAdd && !flagEditorInfo.flagEndPoints.Contains(clickPosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.Log("扛旗终点添加: {0}", clickPosition);
|
|
|
|
|
|
flagEditorInfo.flagEndPoints.Add(clickPosition);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (!isAdd && flagEditorInfo.flagEndPoints.Contains(clickPosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.Log("扛旗终点移除: {0}", clickPosition);
|
|
|
|
|
|
flagEditorInfo.flagEndPoints.Remove(clickPosition);
|
2023-11-16 15:57:47 +08:00
|
|
|
|
}
|
2023-12-22 15:26:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-11-21 15:04:56 +08:00
|
|
|
|
|
2024-11-07 18:30:47 +08:00
|
|
|
|
private void EditingCapture(Vector2Int clickPosition, bool isAdd)
|
|
|
|
|
|
{
|
|
|
|
|
|
var isExist = false;
|
|
|
|
|
|
CaptureEditorInfo existCapture = null;
|
|
|
|
|
|
foreach (var capture in captureEditorInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (capture.capturePoint == clickPosition)
|
|
|
|
|
|
{
|
|
|
|
|
|
isExist = true;
|
|
|
|
|
|
existCapture = capture;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (isAdd)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!isExist)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.Log("占领点添加: {0}", clickPosition);
|
|
|
|
|
|
captureEditorInfo.Add(new CaptureEditorInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
capturePoint = clickPosition
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (existCapture != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.Log("占领点移除: {0}", clickPosition);
|
|
|
|
|
|
captureEditorInfo.Remove(existCapture);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void ChangeNpcPos(Vector2Int clickPosition, int npcTroopId)
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (null == _currNpcEditorInfo)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2024-11-07 17:22:30 +08:00
|
|
|
|
var oldPos = _currEditingNpcInfo.position;
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (oldPos == clickPosition)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
var newWorldPos = _curMap.BlockPosition2WorldPosition(clickPosition);
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (2 == npcTroopId && _enemyNpcObjectWaveDic.TryGetValue(_currEditingNpcInfo.waveIndex, out var enemyNpcObjectDic))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (enemyNpcObjectDic.TryGetValue(_currNpcEditorInfo, out var npcObj))
|
|
|
|
|
|
{
|
|
|
|
|
|
npcObj.transform.position = newWorldPos;
|
|
|
|
|
|
_currEditingNpcInfo.position = clickPosition;
|
|
|
|
|
|
DebugUtil.Log("怪物: [ {0} ] 移动到 [ {1} ]位置上", _currEditingNpcInfo.id, clickPosition);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (0 == npcTroopId && _enemyNpcObjectWaveDic.TryGetValue(_currEditingNpcInfo.waveIndex, out var midNpcObjectDic))
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (midNpcObjectDic.TryGetValue(_currNpcEditorInfo, out var npcObj))
|
2025-06-06 18:02:48 +08:00
|
|
|
|
{
|
|
|
|
|
|
npcObj.transform.position = newWorldPos;
|
|
|
|
|
|
_currEditingNpcInfo.position = clickPosition;
|
|
|
|
|
|
DebugUtil.Log("怪物: [ {0} ] 移动到 [ {1} ]位置上", _currEditingNpcInfo.id, clickPosition);
|
|
|
|
|
|
}
|
2024-11-04 18:19:57 +08:00
|
|
|
|
}
|
2025-06-30 18:46:13 +08:00
|
|
|
|
else if (1 == npcTroopId && _selfNpcObjectDic.TryGetValue(oldPos, out var selfNpcObj))
|
2024-11-18 16:50:35 +08:00
|
|
|
|
{
|
|
|
|
|
|
selfNpcObj.transform.position = newWorldPos;
|
|
|
|
|
|
_currEditingNpcInfo.position = clickPosition;
|
|
|
|
|
|
_selfNpcObjectDic.Remove(oldPos);
|
|
|
|
|
|
_selfNpcObjectDic.Add(clickPosition, selfNpcObj);
|
|
|
|
|
|
DebugUtil.Log("怪物: [ {0} ] 移动到 [ {1} ]位置上", _currEditingNpcInfo.id, clickPosition);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("需要更改的旧位置上没有怪物:{0}", oldPos);
|
|
|
|
|
|
}
|
2024-11-04 18:19:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
#region 敌方NPC编辑方法
|
|
|
|
|
|
private void EditEnemyNpc(Vector2Int clickPosition, bool isAdd)
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (isAdd)
|
|
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
AddEnemyNpc(clickPosition);
|
2024-11-12 20:31:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
RemoveEnemyNpc(clickPosition);
|
2024-11-12 20:31:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void AddEnemyNpc(Vector2Int clickPosition)
|
2023-12-22 15:26:48 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (enemyNpcObject == null || curEnemyMonsterID == 0)
|
2023-12-22 15:26:48 +08:00
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请选择正确的NPC!!");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-11-21 15:04:56 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
_enemyNpcObjectWaveDic ??= new Dictionary<int, Dictionary<NpcEditorInfo, GameObject>>();
|
2024-05-29 14:03:39 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
NPCInfo npcInfo = new()
|
2023-12-22 15:26:48 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
id = curEnemyMonsterID,
|
2025-06-06 18:02:48 +08:00
|
|
|
|
position = clickPosition,
|
2025-06-30 18:46:13 +08:00
|
|
|
|
index = currentEenemyNpcInfo.Count + 1,
|
|
|
|
|
|
troopId = ETroopsId.Enemy,
|
2024-11-04 18:19:57 +08:00
|
|
|
|
};
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2025-06-25 12:13:54 +08:00
|
|
|
|
var level = 0;
|
|
|
|
|
|
var aiType = 0;
|
2024-11-18 16:50:35 +08:00
|
|
|
|
var monsterConfigDic = MonsterCfg.DataMap;
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (monsterConfigDic.TryGetValue(curEnemyMonsterID, out var monster))
|
2024-08-28 15:04:25 +08:00
|
|
|
|
{
|
2025-06-25 12:13:54 +08:00
|
|
|
|
level = monster.MonsterLevel;
|
|
|
|
|
|
aiType = monster.AIType;
|
2024-08-28 15:04:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
DebugUtil.LogError("获取怪物[{0}]配置数据错误", curEnemyMonsterID);
|
2024-08-28 15:04:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 19:57:08 +08:00
|
|
|
|
var npcEditor = new NpcEditorInfo(npcInfo, currentEenemyNpcInfo.Count + 1, level, aiType, ETroopsId.Enemy);
|
2025-06-30 18:46:13 +08:00
|
|
|
|
currentEenemyNpcInfo.Add(npcEditor);
|
2024-11-04 18:19:57 +08:00
|
|
|
|
var pos = _curMap.BlockPosition2WorldPosition(npcInfo.position);
|
2025-06-06 18:02:48 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (_enemyNpcObjectWaveDic.TryGetValue(npcInfo.waveIndex, out var npcObjectDic))
|
2025-06-06 18:02:48 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
var obj = Instantiate(enemyNpcObject, pos, enemyNpcObject.transform.rotation);
|
2025-06-06 18:02:48 +08:00
|
|
|
|
npcObjectDic.Add(npcEditor, obj);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
var obj = Instantiate(enemyNpcObject, pos, enemyNpcObject.transform.rotation);
|
2025-06-06 18:02:48 +08:00
|
|
|
|
npcObjectDic = new Dictionary<NpcEditorInfo, GameObject>
|
|
|
|
|
|
{ { npcEditor, obj } };
|
2025-06-30 18:46:13 +08:00
|
|
|
|
_enemyNpcObjectWaveDic.Add(npcInfo.waveIndex, npcObjectDic);
|
2025-06-06 18:02:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DebugUtil.Log(
|
2025-06-30 18:46:13 +08:00
|
|
|
|
$"添加了第[ {npcInfo.waveIndex} ]波的[ {npcInfo.index} ]怪物到 [ {npcInfo.position} ]位置上, 其预制体为: {enemyNpcObject.name}");
|
2023-12-22 15:26:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void RemoveEnemyNpc(Vector2Int clickPosition)
|
2023-12-22 15:26:48 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
var npc = currentEenemyNpcInfo.LastOrDefault(npc => npc.npcInfo.position == clickPosition);
|
2025-06-06 18:02:48 +08:00
|
|
|
|
if (npc != null)
|
2023-11-16 15:57:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (_enemyNpcObjectWaveDic.TryGetValue(npc.npcInfo.waveIndex, out var npcObjectDic))
|
2023-11-16 15:57:47 +08:00
|
|
|
|
{
|
2025-06-06 18:02:48 +08:00
|
|
|
|
if (npcObjectDic.TryGetValue(npc, out var obj))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.Log(
|
|
|
|
|
|
$"从[ {clickPosition} ]位置上移除了[ {npc.npcInfo.waveIndex} ]波的[{npc.id}]NPC, 其预制体名字为:{obj.name}");
|
|
|
|
|
|
DestroyImmediate(obj);
|
|
|
|
|
|
npcObjectDic.Remove(npc);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError($"波次{npc.npcInfo.waveIndex}中没有怪物{npc.id}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("没有波次{0}的怪物信息", npc.npcInfo.waveIndex);
|
2023-11-16 15:57:47 +08:00
|
|
|
|
}
|
2025-06-06 18:02:48 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
currentEenemyNpcInfo.Remove(npc);
|
2023-11-16 15:57:47 +08:00
|
|
|
|
}
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
ReorderEnemyNpcID();
|
2023-11-16 15:57:47 +08:00
|
|
|
|
}
|
2025-06-30 18:46:13 +08:00
|
|
|
|
#endregion
|
2023-11-16 15:57:47 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
#region 已放NPC编辑方法
|
2024-11-13 17:14:27 +08:00
|
|
|
|
private void EditSelfNpc(Vector2Int clickPosition, bool isAdd)
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (isAdd)
|
|
|
|
|
|
{
|
2024-11-13 17:14:27 +08:00
|
|
|
|
AddSelfNpc(clickPosition);
|
2024-11-12 20:31:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2024-11-13 17:14:27 +08:00
|
|
|
|
RemoveSelfNpc(clickPosition);
|
2024-11-12 20:31:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void AddSelfNpc(Vector2Int clickPosition)
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (selfNpcObject == null || curSelfNpcID == 0)
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
DebugUtil.LogError("请选择正确的己方NPC!!");
|
2025-06-30 14:51:47 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
_selfNpcObjectDic ??= new Dictionary<Vector2Int, GameObject>();
|
2025-06-30 14:51:47 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (_selfNpcObjectDic.ContainsKey(clickPosition))
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
DebugUtil.LogError("该位置已有NPC存在,请重新选!!!");
|
2025-06-30 14:51:47 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
NPCInfo npcInfo = new()
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
id = curSelfNpcID,
|
2025-06-30 14:51:47 +08:00
|
|
|
|
position = clickPosition,
|
2025-06-30 18:46:13 +08:00
|
|
|
|
troopId = ETroopsId.Self,
|
2025-06-30 14:51:47 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
var level = 0;
|
|
|
|
|
|
var aiType = 0;
|
|
|
|
|
|
var monsterConfigDic = MonsterCfg.DataMap;
|
|
|
|
|
|
if (monsterConfigDic.TryGetValue(curSelfNpcID, out var monster))
|
|
|
|
|
|
{
|
|
|
|
|
|
level = monster.MonsterLevel;
|
|
|
|
|
|
aiType = monster.AIType;
|
|
|
|
|
|
}
|
2025-06-30 14:51:47 +08:00
|
|
|
|
else
|
2025-06-30 18:46:13 +08:00
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("获取己方Npc[{0}]配置数据错误", curSelfNpcID);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 19:57:08 +08:00
|
|
|
|
currentSelfNpcInfo.Add(new NpcEditorInfo(npcInfo, SelfID + currentSelfNpcInfo.Count + 1, level, aiType, ETroopsId.Self));
|
2025-06-30 18:46:13 +08:00
|
|
|
|
var pos = _curMap.BlockPosition2WorldPosition(npcInfo.position);
|
|
|
|
|
|
_selfNpcObjectDic.Add(npcInfo.position, Instantiate(selfNpcObject, pos, selfNpcObject.transform.rotation));
|
|
|
|
|
|
DebugUtil.Log("添加了己方Npc: [ {0} ] 到 [ {1} ]位置上, 其预制体为: {2}", npcInfo.id, npcInfo.position, selfNpcObject.name);
|
|
|
|
|
|
}
|
2025-06-30 14:51:47 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void RemoveSelfNpc(Vector2Int clickPosition)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_selfNpcObjectDic.TryGetValue(clickPosition, out var npcObj))
|
|
|
|
|
|
{
|
|
|
|
|
|
var npc = currentSelfNpcInfo.FirstOrDefault(npcFight => npcFight.npcInfo.position == clickPosition);
|
|
|
|
|
|
if (npc != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentSelfNpcInfo.Remove(npc);
|
|
|
|
|
|
DebugUtil.Log("从[ {0} ]位置上移除了[{1}] 己方NPC", clickPosition, npcObj.name);
|
|
|
|
|
|
DestroyImmediate(npcObj);
|
|
|
|
|
|
_selfNpcObjectDic.Remove(clickPosition);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-30 14:51:47 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
ReorderSelfNpcID();
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
2025-06-30 14:51:47 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
#region 中立NPC编辑方法
|
|
|
|
|
|
private void EditMidNpc(Vector2Int clickPosition, bool isAdd)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isAdd)
|
|
|
|
|
|
AddMidNpc(clickPosition);
|
|
|
|
|
|
else
|
|
|
|
|
|
RemoveMidNpc(clickPosition);
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void AddMidNpc(Vector2Int clickPosition)
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (midNpcObject == null || curMidMonsterID == 0)
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
DebugUtil.LogError("请选择正确的NPC!!");
|
2025-06-30 14:51:47 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
_midNpcObjectWaveDic ??= new Dictionary<int, Dictionary<NpcEditorInfo, GameObject>>();
|
|
|
|
|
|
|
|
|
|
|
|
NPCInfo npcInfo = new()
|
|
|
|
|
|
{
|
|
|
|
|
|
id = curMidMonsterID,
|
|
|
|
|
|
position = clickPosition,
|
|
|
|
|
|
index = currentMidNpcInfo.Count + 1,
|
|
|
|
|
|
troopId = ETroopsId.Neutral,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var level = 0;
|
|
|
|
|
|
var aiType = 0;
|
|
|
|
|
|
var monsterConfigDic = MonsterCfg.DataMap;
|
|
|
|
|
|
if (monsterConfigDic.TryGetValue(curMidMonsterID, out var monster))
|
|
|
|
|
|
{
|
|
|
|
|
|
level = monster.MonsterLevel;
|
|
|
|
|
|
aiType = monster.AIType;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("获取怪物[{0}]配置数据错误", curMidMonsterID);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 19:57:08 +08:00
|
|
|
|
var npcEditor = new NpcEditorInfo(npcInfo, currentMidNpcInfo.Count + 1, level, aiType, ETroopsId.Neutral);
|
2025-06-30 18:46:13 +08:00
|
|
|
|
currentMidNpcInfo.Add(npcEditor);
|
|
|
|
|
|
var pos = _curMap.BlockPosition2WorldPosition(npcInfo.position);
|
|
|
|
|
|
|
|
|
|
|
|
if (_midNpcObjectWaveDic.TryGetValue(npcInfo.waveIndex, out var npcObjectDic))
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
var obj = Instantiate(midNpcObject, pos, midNpcObject.transform.rotation);
|
|
|
|
|
|
npcObjectDic.Add(npcEditor, obj);
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
var obj = Instantiate(midNpcObject, pos, midNpcObject.transform.rotation);
|
|
|
|
|
|
npcObjectDic = new Dictionary<NpcEditorInfo, GameObject>
|
|
|
|
|
|
{ { npcEditor, obj } };
|
|
|
|
|
|
_midNpcObjectWaveDic.Add(npcInfo.waveIndex, npcObjectDic);
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
DebugUtil.Log(
|
|
|
|
|
|
$"添加了第[ {npcInfo.waveIndex} ]波的[ {npcInfo.index} ]怪物到 [ {npcInfo.position} ]位置上, 其预制体为: {midNpcObject.name}");
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void RemoveMidNpc(Vector2Int clickPosition)
|
|
|
|
|
|
{
|
|
|
|
|
|
var npc = currentMidNpcInfo.LastOrDefault(npc => npc.npcInfo.position == clickPosition);
|
|
|
|
|
|
if (npc != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_midNpcObjectWaveDic.TryGetValue(npc.npcInfo.waveIndex, out var npcObjectDic))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (npcObjectDic.TryGetValue(npc, out var obj))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.Log(
|
|
|
|
|
|
$"从[ {clickPosition} ]位置上移除了[ {npc.npcInfo.waveIndex} ]波的[{npc.id}]NPC, 其预制体名字为:{obj.name}");
|
|
|
|
|
|
DestroyImmediate(obj);
|
|
|
|
|
|
npcObjectDic.Remove(npc);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError($"波次{npc.npcInfo.waveIndex}中没有怪物{npc.id}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("没有波次{0}的怪物信息", npc.npcInfo.waveIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
currentMidNpcInfo.Remove(npc);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ReorderMidNpcID();
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2025-02-21 17:03:56 +08:00
|
|
|
|
private void EditRefreshID(int clickPosition, bool isAdd)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isAdd && !refreshPoints.Contains(clickPosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
refreshPoints.Add(clickPosition);
|
|
|
|
|
|
_curMap.TerrainGridSystem.CellToggleRegionSurface(clickPosition, true, RegionColor);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (!isAdd && refreshPoints.Contains(clickPosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
refreshPoints.Remove(clickPosition);
|
|
|
|
|
|
_curMap.TerrainGridSystem.CellHideRegionSurface(clickPosition);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-26 15:25:35 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 编辑路线
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="clickPosition"></param>
|
|
|
|
|
|
/// <param name="isAdd"></param>
|
2025-02-21 17:03:56 +08:00
|
|
|
|
private void EditRoad(int clickPosition, bool isAdd)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_currEditingRoadInfo == null) return;
|
|
|
|
|
|
|
2025-06-26 14:56:16 +08:00
|
|
|
|
if (isAdd && !_currEditingRoadInfo.roadPoints.Any(x => x.cellIndex == clickPosition))
|
2025-02-21 17:03:56 +08:00
|
|
|
|
{
|
2025-06-26 14:56:16 +08:00
|
|
|
|
_currEditingRoadInfo.roadPoints.Add(new PatrolInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
cellIndex = clickPosition,
|
|
|
|
|
|
waitTime = 0f,
|
|
|
|
|
|
});
|
2025-02-21 17:03:56 +08:00
|
|
|
|
}
|
2025-06-26 14:56:16 +08:00
|
|
|
|
else if (!isAdd && _currEditingRoadInfo.roadPoints.Any(x => x.cellIndex == clickPosition))
|
2025-02-21 17:03:56 +08:00
|
|
|
|
{
|
2025-06-26 14:56:16 +08:00
|
|
|
|
_currEditingRoadInfo.roadPoints = _currEditingRoadInfo.roadPoints.Where(x => x.cellIndex != clickPosition).ToList();
|
2025-02-21 17:03:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-26 15:25:35 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 编辑区域
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="clickPosition"></param>
|
|
|
|
|
|
/// <param name="isAdd"></param>
|
|
|
|
|
|
private void EditArea(int clickPosition, bool isAdd)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (null == _currEditingAreaInfo)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (isAdd && !_currEditingAreaInfo.areaPoints.Any(x => x.cellIndex == clickPosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
_currEditingAreaInfo.areaPoints.Add(new PatrolInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
cellIndex = clickPosition,
|
|
|
|
|
|
waitTime = 0f,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (!isAdd && _currEditingAreaInfo.areaPoints.Any(x => x.cellIndex == clickPosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
_currEditingAreaInfo.areaPoints = _currEditingAreaInfo.areaPoints.Where(x => x.cellIndex != clickPosition).ToList();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-30 18:46:13 +08:00
|
|
|
|
#endregion
|
2025-06-26 15:25:35 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
#region 敌方Npc某些值改变时响应事件
|
2024-11-12 20:31:06 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void ReorderEnemyNpcID()
|
|
|
|
|
|
{
|
|
|
|
|
|
for (var i = 0; i < currentEenemyNpcInfo.Count; i++)
|
2025-06-25 12:13:54 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
currentEenemyNpcInfo[i].id = i + 1;
|
|
|
|
|
|
currentEenemyNpcInfo[i].npcInfo.index = currentEenemyNpcInfo[i].id;
|
2025-06-25 12:13:54 +08:00
|
|
|
|
}
|
2024-11-12 20:31:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void ReorderMidNpcID()
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
for (var i = 0; i < currentMidNpcInfo.Count; i++)
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
currentMidNpcInfo[i].id = i + 1;
|
|
|
|
|
|
currentMidNpcInfo[i].npcInfo.index = currentMidNpcInfo[i].id;
|
2024-11-12 20:31:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-11-07 18:15:12 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void ReorderSelfNpcID()
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
for (var i = 0; i < currentSelfNpcInfo.Count; i++)
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
currentSelfNpcInfo[i].id = SelfID + i + 1;
|
2024-11-04 18:19:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void ChangeEnemyNpcID(NpcEditorInfo npcEditorInfo, int newMonsterID)
|
2024-11-13 13:21:36 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (_enemyNpcObjectWaveDic.TryGetValue(npcEditorInfo.npcInfo.waveIndex, out var npcObjectDic))
|
2024-11-13 13:21:36 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (npcObjectDic.TryGetValue(npcEditorInfo, out var npcObj))
|
|
|
|
|
|
{
|
|
|
|
|
|
var newObj = LoadEnemyNpcPrefab(newMonsterID);
|
|
|
|
|
|
if (newObj != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
npcEditorInfo.npcInfo.id = newMonsterID;
|
|
|
|
|
|
npcEditorInfo.npcInfo.aiTypeID = MonsterCfg.DataMap[newMonsterID].AIType;
|
|
|
|
|
|
npcEditorInfo.level = MonsterCfg.DataMap[newMonsterID].MonsterLevel;
|
|
|
|
|
|
npcObjectDic[npcEditorInfo] =
|
|
|
|
|
|
Instantiate(newObj, npcObj.transform.position, npcObj.transform.rotation);
|
|
|
|
|
|
DestroyImmediate(npcObj);
|
|
|
|
|
|
DebugUtil.Log(
|
|
|
|
|
|
$"从[ {npcEditorInfo.npcInfo.position} ]的怪物ID改为:[ {npcEditorInfo.npcInfo.id} ]");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-11-13 13:21:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void ChangeMidNpcID(NpcEditorInfo npcEditorInfo, int newMonsterID)
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (_midNpcObjectWaveDic.TryGetValue(npcEditorInfo.npcInfo.waveIndex, out var npcObjectDic))
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2025-06-06 18:02:48 +08:00
|
|
|
|
if (npcObjectDic.TryGetValue(npcEditorInfo, out var npcObj))
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
var newObj = LoadMidNpcPrefab(newMonsterID);
|
2025-06-06 18:02:48 +08:00
|
|
|
|
if (newObj != null)
|
|
|
|
|
|
{
|
2025-06-13 12:49:47 +08:00
|
|
|
|
npcEditorInfo.npcInfo.id = newMonsterID;
|
2025-06-25 12:13:54 +08:00
|
|
|
|
npcEditorInfo.npcInfo.aiTypeID = MonsterCfg.DataMap[newMonsterID].AIType;
|
|
|
|
|
|
npcEditorInfo.level = MonsterCfg.DataMap[newMonsterID].MonsterLevel;
|
2025-06-06 18:02:48 +08:00
|
|
|
|
npcObjectDic[npcEditorInfo] =
|
|
|
|
|
|
Instantiate(newObj, npcObj.transform.position, npcObj.transform.rotation);
|
|
|
|
|
|
DestroyImmediate(npcObj);
|
|
|
|
|
|
DebugUtil.Log(
|
2025-06-13 12:49:47 +08:00
|
|
|
|
$"从[ {npcEditorInfo.npcInfo.position} ]的怪物ID改为:[ {npcEditorInfo.npcInfo.id} ]");
|
2025-06-06 18:02:48 +08:00
|
|
|
|
}
|
2024-11-04 18:19:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void ChangeSelfNpcID(NPCInfo npcInfoInfo, int newMonsterID)
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
2024-11-13 17:14:27 +08:00
|
|
|
|
if (_selfNpcObjectDic.TryGetValue(npcInfoInfo.position, out var npcObj))
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
2024-11-13 17:14:27 +08:00
|
|
|
|
var newObj = LoadSelfNpcPrefab(newMonsterID);
|
2024-11-12 20:31:06 +08:00
|
|
|
|
if (newObj != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
npcInfoInfo.id = newMonsterID;
|
2025-06-25 12:13:54 +08:00
|
|
|
|
npcInfoInfo.aiTypeID = MonsterCfg.DataMap[newMonsterID].AIType;
|
2024-11-13 17:14:27 +08:00
|
|
|
|
_selfNpcObjectDic[npcInfoInfo.position] =
|
2024-11-13 13:21:36 +08:00
|
|
|
|
Instantiate(newObj, npcObj.transform.position, npcObj.transform.rotation);
|
2024-11-12 20:31:06 +08:00
|
|
|
|
DestroyImmediate(npcObj);
|
|
|
|
|
|
DebugUtil.Log("位置上[ {0} ]的fight怪物ID改为: [ {1} ] ", npcInfoInfo.position, npcInfoInfo.id);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-30 14:51:47 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
#region 检查关卡
|
|
|
|
|
|
|
|
|
|
|
|
private const string PreparingRegionErrorMessage = "关卡出战区设置错误,该地图没有:<{0}>号地区。\n";
|
|
|
|
|
|
private const string FallbackRegionErrorMessage = "关卡撤退区设置错误,该地图没有:<{0}>号地区。\n";
|
|
|
|
|
|
private const string EnemyFallbackRegionErrorMessage = "关卡敌方撤退区设置错误,该地图没有:<{0}>号地区。\n";
|
|
|
|
|
|
private const string FixedMessage = "已将错误区域设置为默认<0>号地区。";
|
|
|
|
|
|
private const string CaptureErrorMessage = "占领条件参数大于配置的占领区域。";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void CheckCorrectLevel()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_curMap == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var errorMessage = string.Empty;
|
|
|
|
|
|
|
|
|
|
|
|
if (!_curMap.MapData.IsRegionExist(curRegionData.preparingRegionId))
|
|
|
|
|
|
{
|
|
|
|
|
|
errorMessage += string.Format(PreparingRegionErrorMessage,
|
|
|
|
|
|
curRegionData.preparingRegionId);
|
|
|
|
|
|
curRegionData.preparingRegionId = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!_curMap.MapData.IsRegionExist(curRegionData.fallbackRegionId))
|
|
|
|
|
|
{
|
|
|
|
|
|
errorMessage += string.Format(FallbackRegionErrorMessage,
|
|
|
|
|
|
curRegionData.fallbackRegionId);
|
|
|
|
|
|
curRegionData.fallbackRegionId = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!_curMap.MapData.IsRegionExist(curRegionData.enemyFallbackRegionId))
|
|
|
|
|
|
{
|
|
|
|
|
|
errorMessage += string.Format(EnemyFallbackRegionErrorMessage,
|
|
|
|
|
|
curRegionData.enemyFallbackRegionId);
|
|
|
|
|
|
curRegionData.enemyFallbackRegionId = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查占领条件相关
|
2025-06-06 18:17:42 +08:00
|
|
|
|
/*
|
2024-11-07 18:15:12 +08:00
|
|
|
|
if (!CheckLevelCondition())
|
|
|
|
|
|
{
|
|
|
|
|
|
CustomPopUpWindow.PopUp(CaptureErrorMessage);
|
|
|
|
|
|
}
|
2025-06-06 18:17:42 +08:00
|
|
|
|
*/
|
2024-11-07 18:15:12 +08:00
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(errorMessage))
|
|
|
|
|
|
{
|
|
|
|
|
|
CustomPopUpWindow.PopUp(errorMessage + FixedMessage);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-06 18:17:42 +08:00
|
|
|
|
/*private bool CheckLevelCondition()
|
2024-11-07 18:15:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (currentLevelData.stages.Any(stage => stage.successCondition.conditionType == ConditionType.CombatLeastOccupy
|
2024-11-13 13:21:36 +08:00
|
|
|
|
&& stage.successCondition.conditionArgs[0].Arg >
|
|
|
|
|
|
captureEditorInfo.Count))
|
2024-11-07 18:15:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (currentLevelData.starTarget.Any(modifier => modifier.conditionType == ConditionType.CombatLeastOccupy
|
|
|
|
|
|
&& modifier.conditionArgs[0].Arg > captureEditorInfo.Count))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (currentLevelData.scoreTarget.Any(modifier => modifier.conditionType == ConditionType.CombatLeastOccupy
|
|
|
|
|
|
&& modifier.conditionArgs[0].Arg > captureEditorInfo.Count))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
2025-06-06 18:17:42 +08:00
|
|
|
|
}*/
|
2024-11-07 18:15:12 +08:00
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 内部方法
|
|
|
|
|
|
|
2025-06-10 15:46:40 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 关卡加载时 加载敌方预制体
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="monsterID">Monster表ID</param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private GameObject LoadEnemyNpcPrefab(int monsterID)
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
|
|
|
|
|
GameObject obj = null;
|
2024-11-18 15:02:49 +08:00
|
|
|
|
var curMonsterClassID = 0;
|
2024-11-18 16:50:35 +08:00
|
|
|
|
if (MonsterCfg.DataMap.TryGetValue(monsterID, out var monster))
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2024-11-18 15:02:49 +08:00
|
|
|
|
curMonsterClassID = monster.MonsterClassID;
|
2024-11-04 18:19:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (monster.NpcType)
|
|
|
|
|
|
{
|
2025-06-30 14:58:00 +08:00
|
|
|
|
case EMonsterType.Vehicle:
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2024-11-18 16:50:35 +08:00
|
|
|
|
if (VehicleCfg.DataMap.TryGetValue(curMonsterClassID, out var vehicle))
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
|
|
|
|
|
var prefabPath = PathEx.GetVehicleGameModelPath(vehicle.ID);
|
|
|
|
|
|
obj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
|
|
|
|
|
if (obj == null)
|
|
|
|
|
|
{
|
2025-06-10 15:46:40 +08:00
|
|
|
|
DebugUtil.LogError("请检查敌方载具类: {0}的预制体路径是否存在,对应的完整路径: {1}", curMonsterClassID, prefabPath);
|
2024-11-04 18:19:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-06-10 15:46:40 +08:00
|
|
|
|
DebugUtil.LogError("请检查敌方载具类: {0}的配置是否存在", curMonsterClassID);
|
2024-11-04 18:19:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
|
}
|
2025-06-04 15:23:36 +08:00
|
|
|
|
case EMonsterType.EnemyCharacter:
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2025-06-10 15:46:40 +08:00
|
|
|
|
if (MonsterClassCfg.DataMap.TryGetValue(curMonsterClassID, out var monsterClass))
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2024-11-11 16:54:20 +08:00
|
|
|
|
var prefabPath = PathEx.GetCharacterFightModelPath(monsterClass.NameId, monsterClass.WeaponId);
|
2024-11-04 18:19:57 +08:00
|
|
|
|
obj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
|
|
|
|
|
if (obj == null)
|
|
|
|
|
|
{
|
2025-06-10 15:46:40 +08:00
|
|
|
|
DebugUtil.LogError("请检查敌方怪物类: {0}的预制体路径是否存在,对应的完整路径: {1}", curMonsterClassID, prefabPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请检查敌方怪物类: {0}的配置是否存在", curMonsterClassID);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
|
}
|
2025-06-30 14:58:00 +08:00
|
|
|
|
case EMonsterType.FightBuild:
|
2025-06-10 15:46:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (FightBuildCfg.DataMap.TryGetValue(curMonsterClassID, out var buildData))
|
|
|
|
|
|
{
|
|
|
|
|
|
var prefabPath = PathEx.GetFightBuildingPath(buildData.ModelPath);
|
|
|
|
|
|
obj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
|
|
|
|
|
if (obj == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请检查敌方建筑类: {0}的预制体路径是否存在,对应的完整路径: {1}", curMonsterClassID, prefabPath);
|
2024-11-04 18:19:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-06-10 15:46:40 +08:00
|
|
|
|
DebugUtil.LogError("请检查敌方建筑类: {0}的配置是否存在", curMonsterClassID);
|
2024-11-04 18:19:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
|
}
|
|
|
|
|
|
default: return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 关卡加载时 加载中立预制体
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="monsterID">Monster表ID</param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private GameObject LoadMidNpcPrefab(int monsterID)
|
|
|
|
|
|
{
|
|
|
|
|
|
GameObject obj = null;
|
|
|
|
|
|
var curMonsterClassID = 0;
|
|
|
|
|
|
if (MonsterCfg.DataMap.TryGetValue(monsterID, out var monster))
|
|
|
|
|
|
{
|
|
|
|
|
|
curMonsterClassID = monster.MonsterClassID;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (monster.NpcType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case EMonsterType.Vehicle:
|
|
|
|
|
|
{
|
|
|
|
|
|
if (VehicleCfg.DataMap.TryGetValue(curMonsterClassID, out var vehicle))
|
|
|
|
|
|
{
|
|
|
|
|
|
var prefabPath = PathEx.GetVehicleGameModelPath(vehicle.ID);
|
|
|
|
|
|
obj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
|
|
|
|
|
if (obj == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请检查敌方载具类: {0}的预制体路径是否存在,对应的完整路径: {1}", curMonsterClassID, prefabPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请检查敌方载具类: {0}的配置是否存在", curMonsterClassID);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
|
}
|
|
|
|
|
|
case EMonsterType.EnemyCharacter:
|
|
|
|
|
|
{
|
|
|
|
|
|
if (MonsterClassCfg.DataMap.TryGetValue(curMonsterClassID, out var monsterClass))
|
|
|
|
|
|
{
|
|
|
|
|
|
var prefabPath = PathEx.GetCharacterFightModelPath(monsterClass.NameId, monsterClass.WeaponId);
|
|
|
|
|
|
obj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
|
|
|
|
|
if (obj == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请检查敌方怪物类: {0}的预制体路径是否存在,对应的完整路径: {1}", curMonsterClassID, prefabPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请检查敌方怪物类: {0}的配置是否存在", curMonsterClassID);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
|
}
|
|
|
|
|
|
case EMonsterType.FightBuild:
|
|
|
|
|
|
{
|
|
|
|
|
|
if (FightBuildCfg.DataMap.TryGetValue(curMonsterClassID, out var buildData))
|
|
|
|
|
|
{
|
|
|
|
|
|
var prefabPath = PathEx.GetFightBuildingPath(buildData.ModelPath);
|
|
|
|
|
|
obj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
|
|
|
|
|
if (obj == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请检查敌方建筑类: {0}的预制体路径是否存在,对应的完整路径: {1}", curMonsterClassID, prefabPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请检查敌方建筑类: {0}的配置是否存在", curMonsterClassID);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
|
}
|
|
|
|
|
|
default: return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-10 15:46:40 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 关卡加载时 加载己方预制体
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="monsterID">Monster表ID</param>
|
|
|
|
|
|
/// <returns></returns>
|
2024-11-13 17:14:27 +08:00
|
|
|
|
private GameObject LoadSelfNpcPrefab(int monsterID)
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
2024-11-18 15:02:49 +08:00
|
|
|
|
GameObject obj = null;
|
|
|
|
|
|
var curFightNpcID = 0;
|
2024-11-18 16:50:35 +08:00
|
|
|
|
if (MonsterCfg.DataMap.TryGetValue(monsterID, out var monster))
|
2024-11-18 15:02:49 +08:00
|
|
|
|
{
|
|
|
|
|
|
curFightNpcID = monster.MonsterClassID;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2024-11-12 20:31:06 +08:00
|
|
|
|
return null;
|
2024-11-18 15:02:49 +08:00
|
|
|
|
}
|
2024-11-12 20:31:06 +08:00
|
|
|
|
|
2024-11-18 15:02:49 +08:00
|
|
|
|
switch (monster.NpcType)
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
2025-06-30 14:58:00 +08:00
|
|
|
|
case EMonsterType.Vehicle:
|
2024-11-18 15:02:49 +08:00
|
|
|
|
{
|
2024-11-18 16:50:35 +08:00
|
|
|
|
if (VehicleCfg.DataMap.TryGetValue(curFightNpcID, out var vehicle))
|
2024-11-18 15:02:49 +08:00
|
|
|
|
{
|
|
|
|
|
|
var prefabPath = PathEx.GetVehicleGameModelPath(vehicle.ID);
|
|
|
|
|
|
obj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
|
|
|
|
|
if (obj == null)
|
|
|
|
|
|
{
|
2025-06-10 15:46:40 +08:00
|
|
|
|
DebugUtil.LogError("请检查己方载具类: {0}的预制体路径是否存在,对应的完整路径: {1}", curFightNpcID, prefabPath);
|
2024-11-18 15:02:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-06-10 15:46:40 +08:00
|
|
|
|
DebugUtil.LogError("请检查己方载具类: {0}的配置是否存在", curFightNpcID);
|
2024-11-18 15:02:49 +08:00
|
|
|
|
}
|
2024-11-12 20:31:06 +08:00
|
|
|
|
|
2024-11-18 15:02:49 +08:00
|
|
|
|
return obj;
|
|
|
|
|
|
}
|
2025-06-04 15:23:36 +08:00
|
|
|
|
case EMonsterType.SelfCharacter:
|
2024-11-18 15:02:49 +08:00
|
|
|
|
{
|
2024-11-18 16:50:35 +08:00
|
|
|
|
if (FightNpcCfg.DataMap.TryGetValue(curFightNpcID, out var fightNpc))
|
2024-11-18 15:02:49 +08:00
|
|
|
|
{
|
|
|
|
|
|
var prefabPath = PathEx.GetCharacterFightModelPath(fightNpc.NameId, fightNpc.WeaponId);
|
|
|
|
|
|
obj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
|
|
|
|
|
if (obj == null)
|
|
|
|
|
|
{
|
2025-06-10 15:46:40 +08:00
|
|
|
|
DebugUtil.LogError("请检查己方NPC类: {0}的预制体路径是否存在,对应的完整路径: {1}", curFightNpcID, prefabPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请检查己方NPC类: {0}的配置是否存在", curFightNpcID);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
|
}
|
2025-06-30 14:58:00 +08:00
|
|
|
|
case EMonsterType.FightBuild:
|
2025-06-10 15:46:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (FightBuildCfg.DataMap.TryGetValue(curFightNpcID, out var buildData))
|
|
|
|
|
|
{
|
|
|
|
|
|
var prefabPath = PathEx.GetFightBuildingPath(buildData.ModelPath);
|
|
|
|
|
|
obj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
|
|
|
|
|
if (obj == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请检查己方建筑类: {0}的预制体路径是否存在,对应的完整路径: {1}", curFightNpcID, prefabPath);
|
2024-11-18 15:02:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-06-10 15:46:40 +08:00
|
|
|
|
DebugUtil.LogError("请检查己方建筑类: {0}的配置是否存在", curFightNpcID);
|
2024-11-18 15:02:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
|
}
|
|
|
|
|
|
default: return null;
|
|
|
|
|
|
}
|
2024-11-12 20:31:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void DestroyNpcPrefab()
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
foreach (var npcData in _enemyNpcObjectWaveDic.Values)
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
foreach (var npc in npcData.Values)
|
|
|
|
|
|
{
|
|
|
|
|
|
DestroyImmediate(npc);
|
|
|
|
|
|
}
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
foreach (var npcData in _midNpcObjectWaveDic.Values)
|
2023-11-16 15:57:47 +08:00
|
|
|
|
{
|
2025-06-06 18:02:48 +08:00
|
|
|
|
foreach (var npc in npcData.Values)
|
|
|
|
|
|
{
|
|
|
|
|
|
DestroyImmediate(npc);
|
|
|
|
|
|
}
|
2023-11-16 15:57:47 +08:00
|
|
|
|
}
|
2024-11-12 20:31:06 +08:00
|
|
|
|
|
2024-11-13 17:14:27 +08:00
|
|
|
|
foreach (var npc in _selfNpcObjectDic)
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
|
|
|
|
|
DestroyImmediate(npc.Value);
|
|
|
|
|
|
}
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void ChangeEnemyNpcToward(NpcEditorInfo npcEditorInfo, CharacterToward npcToward)
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (_enemyNpcObjectWaveDic.TryGetValue(npcEditorInfo.npcInfo.waveIndex, out var npcObjectDic))
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (npcObjectDic.TryGetValue(npcEditorInfo, out var npcObj))
|
|
|
|
|
|
{
|
|
|
|
|
|
var yaw = LevelUtils.SetCharaterToward(npcToward);
|
|
|
|
|
|
npcObj.transform.eulerAngles = new Vector3(0, yaw, 0);
|
|
|
|
|
|
}
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void ChangeMidNpcToward(NpcEditorInfo npcEditorInfo, CharacterToward npcToward)
|
2024-11-04 18:43:29 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (_midNpcObjectWaveDic.TryGetValue(npcEditorInfo.npcInfo.waveIndex, out var npcObjectDic))
|
2024-11-04 18:43:29 +08:00
|
|
|
|
{
|
2025-06-06 18:02:48 +08:00
|
|
|
|
if (npcObjectDic.TryGetValue(npcEditorInfo, out var npcObj))
|
|
|
|
|
|
{
|
|
|
|
|
|
var yaw = LevelUtils.SetCharaterToward(npcToward);
|
|
|
|
|
|
npcObj.transform.eulerAngles = new Vector3(0, yaw, 0);
|
|
|
|
|
|
}
|
2024-11-04 18:43:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-30 18:46:13 +08:00
|
|
|
|
private void ChangeSelfNpcToward(Vector2Int pos, CharacterToward npcToward)
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
2024-11-13 17:14:27 +08:00
|
|
|
|
if (_selfNpcObjectDic.TryGetValue(pos, out var npcObj))
|
2024-11-12 20:31:06 +08:00
|
|
|
|
{
|
|
|
|
|
|
var yaw = LevelUtils.SetCharaterToward(npcToward);
|
|
|
|
|
|
npcObj.transform.eulerAngles = new Vector3(0, yaw, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
private bool CheckConditionSame(ConditionType conditionType)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (currentLevelData.starTarget.Any(modifier => modifier.conditionType == conditionType))
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (currentLevelData.scoreTarget.Any(modifier => modifier.conditionType == conditionType))
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region MainLife
|
|
|
|
|
|
|
|
|
|
|
|
private void Awake()
|
|
|
|
|
|
{
|
|
|
|
|
|
SceneView.duringSceneGui += OnSceneGUI;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnEnable()
|
|
|
|
|
|
{
|
|
|
|
|
|
TerrainTypeConfig.Load();
|
2025-06-30 18:46:13 +08:00
|
|
|
|
_enemyNpcObjectWaveDic = new Dictionary<int, Dictionary<NpcEditorInfo, GameObject>>();
|
|
|
|
|
|
_midNpcObjectWaveDic = new Dictionary<int, Dictionary<NpcEditorInfo, GameObject>>();
|
2024-11-13 17:14:27 +08:00
|
|
|
|
_selfNpcObjectDic = new Dictionary<Vector2Int, GameObject>();
|
2025-06-30 18:46:13 +08:00
|
|
|
|
_showNpcInfos = new List<NpcEditorInfo>();
|
|
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
base.OnEnable();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnDisable()
|
|
|
|
|
|
{
|
|
|
|
|
|
currWindow = null;
|
|
|
|
|
|
DestroyNpcPrefab();
|
2025-06-30 15:16:22 +08:00
|
|
|
|
//DestoryBuildPrefab();
|
2025-06-30 18:46:13 +08:00
|
|
|
|
_enemyNpcObjectWaveDic = null;
|
|
|
|
|
|
_midNpcObjectWaveDic = null;
|
2024-11-13 17:14:27 +08:00
|
|
|
|
_selfNpcObjectDic = null;
|
2025-06-30 14:51:47 +08:00
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
base.OnDisable();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnDestroy()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnDestroy();
|
|
|
|
|
|
if (_curMap != null)
|
|
|
|
|
|
_curMap.TerrainGridSystem.OnMouseClickOnGrid -= OnCellClick;
|
|
|
|
|
|
SaveCurrentLevel();
|
|
|
|
|
|
SceneView.duringSceneGui -= OnSceneGUI;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-22 15:26:48 +08:00
|
|
|
|
protected override void OnGUI()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnGUI();
|
|
|
|
|
|
if (_levelEditor == null || _mapManager == null || _mapManager.Map != _curMap ||
|
|
|
|
|
|
_levelEditor.LevelData != currentLevelData)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError("数据已变更,请重新打开关卡编辑器");
|
|
|
|
|
|
Close();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-07 18:15:12 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Draw
|
|
|
|
|
|
|
2025-05-28 17:49:04 +08:00
|
|
|
|
private bool IsShowNpcID => _showNpcInfos != null && _showNpcInfos.Count > 0;
|
|
|
|
|
|
|
|
|
|
|
|
private List<NpcEditorInfo> _showNpcInfos;
|
|
|
|
|
|
|
2023-12-22 15:26:48 +08:00
|
|
|
|
private void OnSceneGUI(SceneView sceneView)
|
|
|
|
|
|
{
|
2025-02-21 17:03:56 +08:00
|
|
|
|
DrawRoadPath();
|
2025-06-26 15:25:35 +08:00
|
|
|
|
DrawAreaPath();
|
2024-11-04 18:19:57 +08:00
|
|
|
|
DrawNpcID();
|
2023-12-22 15:26:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-21 17:03:56 +08:00
|
|
|
|
private void DrawRoadPath()
|
|
|
|
|
|
{
|
2025-06-26 15:25:35 +08:00
|
|
|
|
if (null == _currEditingRoadInfo)
|
|
|
|
|
|
return;
|
2025-02-21 17:03:56 +08:00
|
|
|
|
|
|
|
|
|
|
Vector3 lastWorldPos = Vector3.zero;
|
|
|
|
|
|
for (int i = 0; i < _currEditingRoadInfo.roadPoints.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var gridPos = _currEditingRoadInfo.roadPoints[i];
|
2025-06-26 14:56:16 +08:00
|
|
|
|
var worldPos = _curMap.TGSCellIndex2WorldPosition(gridPos.cellIndex);
|
2025-02-21 17:03:56 +08:00
|
|
|
|
Handles.color = Color.blue;
|
|
|
|
|
|
Handles.DrawSolidDisc(worldPos, Vector3.up, 0.4f);
|
|
|
|
|
|
if (i > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
Handles.color = Color.yellow;
|
|
|
|
|
|
EditorUtil.DrawArrowInScene(lastWorldPos, worldPos, 0.5f);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Handles.color = Color.black;
|
|
|
|
|
|
Handles.Label(worldPos, i.ToString());
|
|
|
|
|
|
lastWorldPos = worldPos;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-26 15:25:35 +08:00
|
|
|
|
private void DrawAreaPath()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (null == _currEditingAreaInfo)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < _currEditingAreaInfo.areaPoints.Count; ++i)
|
|
|
|
|
|
{
|
|
|
|
|
|
var gridPos = _currEditingAreaInfo.areaPoints[i];
|
|
|
|
|
|
var worldPos = _curMap.TGSCellIndex2WorldPosition(gridPos.cellIndex);
|
|
|
|
|
|
Handles.color = Color.blue;
|
|
|
|
|
|
Handles.DrawSolidDisc(worldPos, Vector3.up, 1.4f);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
private GUIStyle labelStyle;
|
|
|
|
|
|
|
2024-11-18 16:50:35 +08:00
|
|
|
|
private GUIStyle labelStyleSelf;
|
|
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
private void DrawNpcID()
|
|
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (!IsShowNpcID)
|
|
|
|
|
|
return;
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
2024-11-18 16:50:35 +08:00
|
|
|
|
labelStyle ??= new GUIStyle
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2024-11-18 16:50:35 +08:00
|
|
|
|
fontSize = 38,
|
|
|
|
|
|
fontStyle = FontStyle.Bold,
|
|
|
|
|
|
normal =
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2024-11-18 16:50:35 +08:00
|
|
|
|
textColor = Color.red
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
labelStyleSelf ??= new GUIStyle
|
|
|
|
|
|
{
|
|
|
|
|
|
fontSize = 38,
|
|
|
|
|
|
fontStyle = FontStyle.Bold,
|
|
|
|
|
|
normal =
|
|
|
|
|
|
{
|
|
|
|
|
|
textColor = Color.green
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
|
|
|
|
|
foreach (var npc in _showNpcInfos)
|
|
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (_enemyNpcObjectWaveDic.TryGetValue(npc.npcInfo.waveIndex, out var enemyNpcObjectDic))
|
2024-11-04 18:19:57 +08:00
|
|
|
|
{
|
2025-06-06 18:02:48 +08:00
|
|
|
|
var waveID = npc.npcInfo.waveIndex;
|
2025-06-30 18:46:13 +08:00
|
|
|
|
if (enemyNpcObjectDic.TryGetValue(npc, out var npcObj))
|
2025-06-06 18:02:48 +08:00
|
|
|
|
{
|
|
|
|
|
|
var content = $"{waveID},{npc.id}";
|
|
|
|
|
|
Handles.Label(npcObj.transform.position, content, labelStyle);
|
|
|
|
|
|
}
|
2024-11-04 18:19:57 +08:00
|
|
|
|
}
|
2025-06-30 18:46:13 +08:00
|
|
|
|
else if (_midNpcObjectWaveDic.TryGetValue(npc.npcInfo.waveIndex, out var midNpcObjectDic))
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
var waveID = npc.npcInfo.waveIndex;
|
|
|
|
|
|
if (midNpcObjectDic.TryGetValue(npc, out var npcObj))
|
|
|
|
|
|
{
|
|
|
|
|
|
var content = $"{waveID},{npc.id}";
|
|
|
|
|
|
Handles.Label(npcObj.transform.position, content, labelStyle);
|
|
|
|
|
|
}
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
2025-06-30 18:46:13 +08:00
|
|
|
|
else if (_selfNpcObjectDic.TryGetValue(npc.npcInfo.position, out var selfNpcObj))
|
2025-06-30 14:51:47 +08:00
|
|
|
|
{
|
2025-06-30 18:46:13 +08:00
|
|
|
|
Handles.Label(selfNpcObj.transform.position, npc.id.ToString(), labelStyleSelf);
|
2025-06-30 14:51:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-11-07 18:15:12 +08:00
|
|
|
|
#endregion
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|