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;
|
2024-06-04 16:50:16 +08:00
|
|
|
|
using cfg.FightCfg;
|
2024-06-04 12:59:37 +08:00
|
|
|
|
using Gameplay.Utils;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
using Gameplay.Level;
|
|
|
|
|
|
using Sirenix.Utilities;
|
2024-11-04 18:19:57 +08:00
|
|
|
|
using Gameplay.Level.Data;
|
2024-06-04 12:59:37 +08:00
|
|
|
|
using Sirenix.OdinInspector;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
using Sirenix.Utilities.Editor;
|
2024-11-04 18:19:57 +08:00
|
|
|
|
using UnityEngine.Serialization;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
using System.Collections.Generic;
|
2024-06-04 12:59:37 +08:00
|
|
|
|
using Sirenix.OdinInspector.Editor;
|
2023-11-16 15:57:47 +08:00
|
|
|
|
using Constants = Framework.Constants;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
using ObjectFieldAlignment = Sirenix.OdinInspector.ObjectFieldAlignment;
|
|
|
|
|
|
|
|
|
|
|
|
public class LevelEditorWindow : OdinEditorWindow
|
|
|
|
|
|
{
|
2023-11-16 15:57:47 +08:00
|
|
|
|
private static readonly Color regionColor = MapUtils.GetRGBAColor("FF960072");
|
2023-08-22 19:08:45 +08:00
|
|
|
|
|
2023-11-16 15:57:47 +08:00
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class RegionData
|
|
|
|
|
|
{
|
2024-04-02 16:53:46 +08:00
|
|
|
|
[LabelText("出战区")] [OnValueChanged("OnRegionChanged")]
|
2023-11-16 15:57:47 +08:00
|
|
|
|
public int preparingRegionId;
|
|
|
|
|
|
|
2024-04-02 16:53:46 +08:00
|
|
|
|
[LabelText("出战区朝向")] public LevelData.CharacterToward preparingRegionToward;
|
2023-11-16 15:57:47 +08:00
|
|
|
|
|
2024-04-02 16:53:46 +08:00
|
|
|
|
[LabelText("撤退区")] public int fallbackRegionId;
|
2023-11-16 15:57:47 +08:00
|
|
|
|
|
2024-04-02 16:53:46 +08:00
|
|
|
|
[LabelText("敌方撤退区")] public int enemyFallbackRegionId;
|
2023-11-16 15:57:47 +08:00
|
|
|
|
|
2024-04-02 16:53:46 +08:00
|
|
|
|
[LabelText("PVP防守区")] public int pvpDefendRegionId;
|
2023-12-26 18:19:05 +08:00
|
|
|
|
|
2024-04-02 16:53:46 +08:00
|
|
|
|
[LabelText("PVP防守方朝向")] public LevelData.CharacterToward pvpDefendToward;
|
2023-12-26 18:19:05 +08:00
|
|
|
|
|
2024-06-04 12:59:37 +08:00
|
|
|
|
[LabelText("扛旗终点区")] [ShowIf("needSetFlagRegion")]
|
|
|
|
|
|
public int flagTargetRegionId;
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("占领进度")] [ShowIf("needSetCaptureProgress")]
|
|
|
|
|
|
public int captureProgress;
|
|
|
|
|
|
|
|
|
|
|
|
[HideInInspector] public bool needSetFlagRegion;
|
|
|
|
|
|
[HideInInspector] public bool needSetCaptureProgress;
|
|
|
|
|
|
|
2023-11-16 15:57:47 +08:00
|
|
|
|
private void OnRegionChanged()
|
|
|
|
|
|
{
|
2024-06-04 12:59:37 +08:00
|
|
|
|
var regionsList = currWindow._curMap.MapData.regions;
|
|
|
|
|
|
for (int i = 0; i < regionsList.Count; i++)
|
2023-11-16 15:57:47 +08:00
|
|
|
|
{
|
2023-12-22 15:26:48 +08:00
|
|
|
|
currWindow._curMap.SetRegionColor(i, false, regionColor);
|
2023-11-16 15:57:47 +08:00
|
|
|
|
}
|
2023-11-21 15:04:56 +08:00
|
|
|
|
|
2023-12-22 15:26:48 +08:00
|
|
|
|
currWindow._curMap.SetRegionColor(preparingRegionId, true, regionColor);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class NPCEditorInfo
|
|
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
[ReadOnly] [LabelText("序号ID")] public int id;
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("MonsterID")] [ValueDropdown("GetMonsterIDs")] [OnValueChanged("ChangeNpcID")]
|
|
|
|
|
|
public int monsterId;
|
2024-11-04 18:43:29 +08:00
|
|
|
|
|
|
|
|
|
|
private IEnumerable<int> GetMonsterIDs()
|
|
|
|
|
|
{
|
|
|
|
|
|
return currWindow.GetMonsterIDs();
|
|
|
|
|
|
}
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
2024-11-04 18:43:29 +08:00
|
|
|
|
private void ChangeNpcID()
|
|
|
|
|
|
{
|
|
|
|
|
|
currWindow.ChangeNpcID(npcInfo, monsterId);
|
|
|
|
|
|
}
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-11-04 18:43:29 +08:00
|
|
|
|
[LabelText("朝向")] [OnValueChanged("NpcTowardOnChange")]
|
|
|
|
|
|
public LevelData.CharacterToward npcToward;
|
|
|
|
|
|
|
|
|
|
|
|
private void NpcTowardOnChange()
|
|
|
|
|
|
{
|
|
|
|
|
|
npcInfo.npcToward = npcToward;
|
|
|
|
|
|
currWindow.ChangeNpcToward(npcInfo.position, npcToward);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[HideLabel] public LevelData.NPCInfo npcInfo;
|
|
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
public NPCEditorInfo(LevelData.NPCInfo npcInfo, int index)
|
2023-12-22 15:26:48 +08:00
|
|
|
|
{
|
|
|
|
|
|
this.npcInfo = npcInfo;
|
2024-11-04 18:19:57 +08:00
|
|
|
|
monsterId = npcInfo.id;
|
|
|
|
|
|
id = index;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("位置调整")] [OnValueChanged("ChangeNpcPos")]
|
|
|
|
|
|
public bool isChangePos;
|
|
|
|
|
|
|
|
|
|
|
|
private void ChangeNpcPos()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isChangePos)
|
|
|
|
|
|
{
|
|
|
|
|
|
currWindow.isEditingPatrolInfo = false;
|
|
|
|
|
|
if (currWindow._currEditingNPCInfo != null)
|
|
|
|
|
|
DebugUtil.LogWarning("检查其他怪物是否处于位置调整或编辑巡逻信息状态");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
currWindow.isEditingNpcPos = isChangePos;
|
|
|
|
|
|
currWindow._currEditingNPCInfo = isChangePos ? npcInfo : null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("显示该怪物序号")] [OnValueChanged("ShowNpcID")]
|
|
|
|
|
|
public bool isShowNpcID;
|
|
|
|
|
|
|
|
|
|
|
|
private void ShowNpcID()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isShowNpcID && !currWindow._showNpcInfos.Contains(this))
|
|
|
|
|
|
currWindow._showNpcInfos.Add(this);
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
currWindow._showNpcInfos.Remove(this);
|
|
|
|
|
|
}
|
2023-12-22 15:26:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-04 18:43:29 +08:00
|
|
|
|
private bool _isEditing;
|
|
|
|
|
|
|
2023-12-22 15:26:48 +08:00
|
|
|
|
[Button("开始编辑巡逻信息")]
|
|
|
|
|
|
[HideIf("_isEditing")]
|
2024-11-04 18:19:57 +08:00
|
|
|
|
private void StartEditNpc()
|
2023-12-22 15:26:48 +08:00
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
currWindow.StartEditPatrolInfo(npcInfo);
|
2023-12-22 15:26:48 +08:00
|
|
|
|
_isEditing = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[Button("完成编辑巡逻信息")]
|
|
|
|
|
|
[ShowIf("_isEditing")]
|
2024-11-04 18:19:57 +08:00
|
|
|
|
private void FinishEditNpc()
|
2023-12-22 15:26:48 +08:00
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
currWindow.FinishEditPatrolInfo();
|
2023-12-22 15:26:48 +08:00
|
|
|
|
_isEditing = false;
|
2023-11-16 15:57:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-08-22 19:08:45 +08:00
|
|
|
|
|
2024-06-04 16:50:16 +08:00
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class ProtectEditorInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
[HorizontalGroup("Protect")] [HideLabel]
|
|
|
|
|
|
public LevelData.ProtectUnit protectUnitInfo;
|
|
|
|
|
|
|
|
|
|
|
|
[HorizontalGroup("Protect")]
|
|
|
|
|
|
[TableColumnWidth(50, Resizable = false)]
|
|
|
|
|
|
[PreviewField(150, ObjectFieldAlignment.Center)]
|
|
|
|
|
|
[LabelText("护送对象预览图")]
|
|
|
|
|
|
[AssetList(Path = Constants.LEVEL_PROTECT_UNIT_PATH)]
|
|
|
|
|
|
[OnValueChanged("OnProtectUnitChanged")]
|
|
|
|
|
|
public GameObject protectUnitPrefab;
|
|
|
|
|
|
|
|
|
|
|
|
public ProtectEditorInfo(LevelData.ProtectUnit protectUnitInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.protectUnitInfo = protectUnitInfo;
|
|
|
|
|
|
InitData();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void InitData()
|
|
|
|
|
|
{
|
|
|
|
|
|
prefabPathDic = new Dictionary<string, int>();
|
|
|
|
|
|
var protectCfg = EditorTableManager.instance.tables.ProtectUnitConfig;
|
|
|
|
|
|
dataProtectUnits = protectCfg.DataList;
|
|
|
|
|
|
foreach (var data in dataProtectUnits)
|
|
|
|
|
|
{
|
|
|
|
|
|
prefabPathDic.Add(data.PrefabPath, data.ID);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (protectCfg.DataMap.TryGetValue(protectUnitInfo.id, out var dataConfig))
|
|
|
|
|
|
{
|
|
|
|
|
|
protectUnitPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(dataConfig.PrefabPath);
|
|
|
|
|
|
if (protectUnitPrefab == null)
|
|
|
|
|
|
DebugUtil.LogError("检查 ProtectUnitConfig 表,该ID: {0} 没有对应模型配置", protectUnitInfo.id);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnProtectUnitChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (prefabPathDic == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
InitData();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var path = AssetDatabase.GetAssetPath(protectUnitPrefab);
|
|
|
|
|
|
if (!prefabPathDic.TryGetValue(path, out var id))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("检查 ProtectUnitConfig 表,该模型没有对应配置: {0}", path);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
protectUnitInfo.id = id;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private Dictionary<string, int> prefabPathDic;
|
|
|
|
|
|
private List<DataProtectUnit> dataProtectUnits;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
private static LevelEditorWindow currWindow;
|
2023-11-21 15:04:56 +08:00
|
|
|
|
|
2023-12-18 19:42:46 +08:00
|
|
|
|
private MapManager _mapManager;
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
private Dictionary<Vector2Int, GameObject> _npcObjectDic;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
|
2023-11-16 15:57:47 +08:00
|
|
|
|
private Map _curMap;
|
2023-10-19 15:00:19 +08:00
|
|
|
|
|
2023-11-21 15:04:56 +08:00
|
|
|
|
private LevelEditor _levelEditor;
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
|
|
|
|
|
private LevelData.NPCInfo _currEditingNPCInfo;
|
|
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
private bool isEditingPatrolInfo;
|
|
|
|
|
|
|
|
|
|
|
|
private bool isEditingNpcPos;
|
|
|
|
|
|
|
|
|
|
|
|
private bool isShowNpcID => _showNpcInfos != null && _showNpcInfos.Count > 0;
|
|
|
|
|
|
|
|
|
|
|
|
private List<NPCEditorInfo> _showNpcInfos;
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
private bool ResponseClickOnCell => isEditingNPC || isEditingPatrolInfo;
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2024-04-02 16:53:46 +08:00
|
|
|
|
[LabelText("当前关卡数据"), Indent] [OnValueChanged("OnCurrentLevelDataChanged")]
|
2023-08-22 19:08:45 +08:00
|
|
|
|
public LevelData currentLevelData = null;
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2024-04-02 16:53:46 +08:00
|
|
|
|
[LabelText("当前地区数据"), Indent] [OnValueChanged("OnCurrentLevelDataChanged")]
|
2023-11-16 15:57:47 +08:00
|
|
|
|
public RegionData curRegionData = null;
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
[LabelText("编辑NPC"), Indent] [HorizontalGroup("NPC")] [LabelWidth(100)] [SerializeField]
|
2023-12-22 15:26:48 +08:00
|
|
|
|
public bool isEditingNPC;
|
|
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
[LabelText("显示索引地图"), Indent] [HorizontalGroup("NPC/1")] [LabelWidth(100)] [OnValueChanged("ShowCellCoordinates")] [SerializeField]
|
|
|
|
|
|
public bool isShowCellCoordinates;
|
|
|
|
|
|
|
|
|
|
|
|
private void ShowCellCoordinates()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_curMap == null || _curMap.TerrainGridSystem == null) return;
|
|
|
|
|
|
_curMap.TerrainGridSystem.displayCellDebugInfo = isShowCellCoordinates ? CellDebugInfo.CellCoordinates : CellDebugInfo.Nothing;
|
|
|
|
|
|
var obj = FindObjectOfType<TerrainGridSystem>().gameObject;
|
|
|
|
|
|
|
|
|
|
|
|
Selection.activeGameObject = obj;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-29 14:03:39 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 关卡ID 通过关卡数据 json文件名 获得
|
|
|
|
|
|
/// </summary>
|
2024-06-04 16:50:16 +08:00
|
|
|
|
[FormerlySerializedAs("LevelID")]
|
|
|
|
|
|
[LabelText("手动指定关卡ID"), Indent]
|
2024-05-29 14:03:39 +08:00
|
|
|
|
[LabelWidth(100)]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
[ShowIf("NeedManualInputLevelID")]
|
|
|
|
|
|
[OnValueChanged("GetLevelMonsterClass")]
|
|
|
|
|
|
[InfoBox("无法正确获得关卡ID,请手动指定")]
|
2024-06-04 16:50:16 +08:00
|
|
|
|
public string levelID;
|
2024-05-29 14:03:39 +08:00
|
|
|
|
|
2024-06-04 16:50:16 +08:00
|
|
|
|
[LabelText("怪物ID"), Indent]
|
2024-05-29 14:03:39 +08:00
|
|
|
|
[LabelWidth(100)]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
[OnValueChanged("MonsterIDChanged")]
|
|
|
|
|
|
[ValueDropdown("GetMonsterIDs")]
|
2023-12-22 15:26:48 +08:00
|
|
|
|
[ShowIf("isEditingNPC")]
|
2024-05-29 14:03:39 +08:00
|
|
|
|
public int curMonsterID;
|
|
|
|
|
|
|
2024-06-04 16:50:16 +08:00
|
|
|
|
[PreviewField(150, ObjectFieldAlignment.Center), Indent, ReadOnly] [LabelText("NPC预制体预览图"), ShowIf("isEditingNPC")]
|
2023-11-16 15:57:47 +08:00
|
|
|
|
public GameObject npcObject;
|
2023-12-21 12:48:58 +08:00
|
|
|
|
|
2024-05-29 14:03:39 +08:00
|
|
|
|
//当前怪物类ID
|
|
|
|
|
|
private int _curMonsterClassID;
|
|
|
|
|
|
|
|
|
|
|
|
private IEnumerable<int> GetMonsterIDs()
|
|
|
|
|
|
{
|
|
|
|
|
|
return monsterIDs;
|
|
|
|
|
|
}
|
2024-04-02 16:53:46 +08:00
|
|
|
|
|
2024-05-29 14:03:39 +08:00
|
|
|
|
private void MonsterIDChanged()
|
2023-12-21 12:48:58 +08:00
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
var obj = LoadNpcPrefab(curMonsterID);
|
|
|
|
|
|
if (obj != null)
|
|
|
|
|
|
npcObject = obj;
|
|
|
|
|
|
}
|
2023-12-21 12:48:58 +08:00
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
[LabelText("显示所有怪物序号ID"), Indent] [OnValueChanged("ShowAllNpcId")] [SerializeField]
|
|
|
|
|
|
public bool isShowAllNpcID;
|
|
|
|
|
|
|
|
|
|
|
|
private void ShowAllNpcId()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var npc in currentNpcInfo)
|
2024-09-05 13:26:43 +08:00
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
npc.isShowNpcID = isShowAllNpcID;
|
|
|
|
|
|
if (isShowAllNpcID)
|
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
|
|
|
|
}
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2024-08-27 14:18:39 +08:00
|
|
|
|
[LabelText("当前怪物列表"), Indent] [ListDrawerSettings(HideAddButton = true, HideRemoveButton = true)]
|
|
|
|
|
|
public List<NPCEditorInfo> currentNpcInfo = null;
|
2024-06-04 16:50:16 +08:00
|
|
|
|
|
|
|
|
|
|
[LabelText("编辑护送对象"), Indent] public bool isEditingProtectUnit;
|
2024-05-29 14:03:39 +08:00
|
|
|
|
|
2024-06-04 16:50:16 +08:00
|
|
|
|
[LabelText("护送对象列表"), ShowIf("isEditingProtectUnit"), Indent]
|
|
|
|
|
|
public List<ProtectEditorInfo> currentProtectUnits = null;
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2024-06-04 16:50:16 +08:00
|
|
|
|
[Button("保存当前关卡"), Indent]
|
2023-08-22 19:08:45 +08:00
|
|
|
|
private void SaveCurrentLevel()
|
|
|
|
|
|
{
|
|
|
|
|
|
CheckCorrectLevel();
|
2023-11-21 15:04:56 +08:00
|
|
|
|
//var configFilePath = string.Format(Constants.LEVEL_CONFIG_FORMAT_PATH, currentLevelData.id);
|
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;
|
2023-11-21 15:04:56 +08:00
|
|
|
|
|
2023-11-16 15:57:47 +08:00
|
|
|
|
//NPC列表
|
2024-06-04 16:50:16 +08:00
|
|
|
|
currentLevelData.npcInfos = currentNpcInfo.Select(editorNPCInfo => editorNPCInfo.npcInfo).ToList();
|
2023-11-16 15:57:47 +08:00
|
|
|
|
|
2024-06-04 12:59:37 +08:00
|
|
|
|
//占领进度 抗旗终点
|
|
|
|
|
|
currentLevelData.captureProgress = curRegionData.captureProgress;
|
|
|
|
|
|
currentLevelData.flagTargetRegionId = curRegionData.flagTargetRegionId;
|
|
|
|
|
|
|
2024-06-04 16:50:16 +08:00
|
|
|
|
//护送对象
|
|
|
|
|
|
currentLevelData.protectUnitInfos =
|
|
|
|
|
|
currentProtectUnits.Select(editorProtectInfo => editorProtectInfo.protectUnitInfo).ToList();
|
|
|
|
|
|
|
2023-11-21 15:04:56 +08:00
|
|
|
|
_levelEditor.SaveLevelData();
|
|
|
|
|
|
}
|
2023-08-22 19:08:45 +08:00
|
|
|
|
|
2023-11-21 15:04:56 +08:00
|
|
|
|
public static void OpenWindow(LevelEditor levelEditor)
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
|
|
|
|
|
MapEditorSettings.Init();
|
2023-12-22 15:26:48 +08:00
|
|
|
|
currWindow = GetWindow<LevelEditorWindow>();
|
|
|
|
|
|
currWindow.position = GUIHelper.GetEditorWindowRect().AlignCenter(800, 600);
|
|
|
|
|
|
currWindow.currentLevelData = null;
|
|
|
|
|
|
currWindow._levelEditor = levelEditor;
|
|
|
|
|
|
currWindow.LoadLevel(levelEditor.LevelData);
|
2024-05-29 14:03:39 +08:00
|
|
|
|
|
|
|
|
|
|
var level = Path.GetFileNameWithoutExtension(levelEditor.LevelDataJson.name);
|
2024-06-04 16:50:16 +08:00
|
|
|
|
currWindow.levelID = level.Substring(level.Length - 6);
|
2024-05-29 14:03:39 +08:00
|
|
|
|
currWindow.GetLevelMonsterClass();
|
2024-06-04 12:59:37 +08:00
|
|
|
|
currWindow.CheckFlagAndCapture();
|
2024-06-04 16:50:16 +08:00
|
|
|
|
DebugUtil.Log("关卡数据:{0}", currWindow.levelID);
|
2024-05-29 14:03:39 +08:00
|
|
|
|
}
|
2024-06-04 12:59:37 +08:00
|
|
|
|
|
2024-05-29 14:03:39 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 该关卡的怪物ID
|
|
|
|
|
|
/// </summary>
|
2024-06-04 12:59:37 +08:00
|
|
|
|
[HideInInspector] public List<int> monsterIDs;
|
2024-05-29 14:03:39 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 需要手动输入关卡ID
|
|
|
|
|
|
/// </summary>
|
2024-06-04 12:59:37 +08:00
|
|
|
|
[HideInInspector] public bool NeedManualInputLevelID;
|
2024-05-29 14:03:39 +08:00
|
|
|
|
|
|
|
|
|
|
public void GetLevelMonsterClass()
|
|
|
|
|
|
{
|
|
|
|
|
|
var levelCfg = EditorTableManager.instance.tables.Level;
|
2024-06-04 16:50:16 +08:00
|
|
|
|
if (!int.TryParse(levelID, out var levelIndex) ||
|
2024-05-29 14:03:39 +08:00
|
|
|
|
!levelCfg.DataMap.TryGetValue(levelIndex, out var level))
|
|
|
|
|
|
{
|
|
|
|
|
|
NeedManualInputLevelID = true;
|
|
|
|
|
|
DebugUtil.LogError("无对应的关卡ID请手动输入关卡ID");
|
|
|
|
|
|
curMonsterID = 0;
|
|
|
|
|
|
npcObject = null;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
monsterIDs = new List<int>();
|
|
|
|
|
|
|
|
|
|
|
|
var monsterCfg = EditorTableManager.instance.tables.Monster;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var monster in monsterCfg.DataMap)
|
|
|
|
|
|
{
|
|
|
|
|
|
var strID = monster.Key.ToString();
|
|
|
|
|
|
var tempID = strID.Substring(0, 6);
|
|
|
|
|
|
|
|
|
|
|
|
//关卡ID相同
|
2024-06-04 16:50:16 +08:00
|
|
|
|
if (tempID.Equals(levelID))
|
2024-05-29 14:03:39 +08:00
|
|
|
|
{
|
|
|
|
|
|
monsterIDs.Add(monster.Key);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (monsterIDs.Count <= 0)
|
|
|
|
|
|
{
|
2024-06-04 16:50:16 +08:00
|
|
|
|
DebugUtil.LogError("请检查Monster表,没有{0}关卡的怪物数据", levelID);
|
2024-05-29 14:03:39 +08:00
|
|
|
|
}
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-04 12:59:37 +08:00
|
|
|
|
private void CheckFlagAndCapture()
|
|
|
|
|
|
{
|
2024-06-04 17:21:01 +08:00
|
|
|
|
curRegionData.needSetFlagRegion = _curMap.MapData.flagStartPoints.Count > 0;
|
|
|
|
|
|
curRegionData.needSetCaptureProgress = _curMap.MapData.capturePoints.Count > 0;
|
2024-06-04 12:59:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private const string PreparingRegionErrorMessage = "关卡出战区设置错误,该地图没有:<{0}>号地区。\n";
|
|
|
|
|
|
private const string FallbackRegionErrorMessage = "关卡撤退区设置错误,该地图没有:<{0}>号地区。\n";
|
|
|
|
|
|
private const string EnemyFallbackRegionErrorMessage = "关卡敌方撤退区设置错误,该地图没有:<{0}>号地区。\n";
|
|
|
|
|
|
private const string FlagTargetRegionErrorMessage = "抗旗终点区设置错误,该地图没有:<{0}>号地区。\n";
|
2024-06-04 16:50:16 +08:00
|
|
|
|
private const string ProtectUnitInfoErrorMessage = "护送 {0} 的起点和终点相同或出错,请检查。\n";
|
2024-06-04 12:59:37 +08:00
|
|
|
|
private const string FixedMessage = "已将错误区域设置为默认<0>号地区。";
|
2023-08-22 19:08:45 +08:00
|
|
|
|
|
|
|
|
|
|
private void CheckCorrectLevel()
|
|
|
|
|
|
{
|
2023-11-16 15:57:47 +08:00
|
|
|
|
if (_curMap == null)
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-11-16 15:57:47 +08:00
|
|
|
|
|
2024-06-04 12:59:37 +08:00
|
|
|
|
if (curRegionData.needSetCaptureProgress && curRegionData.captureProgress == 0)
|
|
|
|
|
|
DebugUtil.LogError("该地图有占领地格,无占领进度");
|
|
|
|
|
|
if (curRegionData.needSetFlagRegion && curRegionData.flagTargetRegionId <= 0)
|
|
|
|
|
|
DebugUtil.LogError("该地图有抗旗地格,抗旗终点区似乎无修改,默认为0号区域");
|
2023-08-22 19:08:45 +08:00
|
|
|
|
|
|
|
|
|
|
var errorMessage = string.Empty;
|
|
|
|
|
|
|
2024-06-04 12:59:37 +08:00
|
|
|
|
if (!_curMap.MapData.IsRegionExist(curRegionData.preparingRegionId))
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2024-06-04 12:59:37 +08:00
|
|
|
|
errorMessage += string.Format(PreparingRegionErrorMessage,
|
|
|
|
|
|
curRegionData.preparingRegionId);
|
|
|
|
|
|
curRegionData.preparingRegionId = 0;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
2023-11-21 15:04:56 +08:00
|
|
|
|
|
2024-06-04 12:59:37 +08:00
|
|
|
|
if (!_curMap.MapData.IsRegionExist(curRegionData.fallbackRegionId))
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2024-06-04 12:59:37 +08:00
|
|
|
|
errorMessage += string.Format(FallbackRegionErrorMessage,
|
|
|
|
|
|
curRegionData.fallbackRegionId);
|
|
|
|
|
|
curRegionData.fallbackRegionId = 0;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
2023-11-21 15:04:56 +08:00
|
|
|
|
|
2024-06-04 12:59:37 +08:00
|
|
|
|
if (!_curMap.MapData.IsRegionExist(curRegionData.enemyFallbackRegionId))
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2024-06-04 12:59:37 +08:00
|
|
|
|
errorMessage += string.Format(EnemyFallbackRegionErrorMessage,
|
|
|
|
|
|
curRegionData.enemyFallbackRegionId);
|
|
|
|
|
|
curRegionData.enemyFallbackRegionId = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!_curMap.MapData.IsRegionExist(curRegionData.flagTargetRegionId))
|
|
|
|
|
|
{
|
|
|
|
|
|
errorMessage += string.Format(FlagTargetRegionErrorMessage,
|
|
|
|
|
|
curRegionData.flagTargetRegionId);
|
|
|
|
|
|
curRegionData.flagTargetRegionId = 0;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-04 16:50:16 +08:00
|
|
|
|
foreach (var protectEditor in currentProtectUnits)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (protectEditor.protectUnitInfo.protectStartPoint == protectEditor.protectUnitInfo.protectTargetPoint ||
|
|
|
|
|
|
protectEditor.protectUnitInfo.protectTargetPoint < 0 ||
|
|
|
|
|
|
protectEditor.protectUnitInfo.protectStartPoint < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
errorMessage += string.Format(ProtectUnitInfoErrorMessage,
|
|
|
|
|
|
protectEditor.protectUnitInfo.id);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-16 15:57:47 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(errorMessage))
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2024-06-04 12:59:37 +08:00
|
|
|
|
CustomPopUpWindow.PopUp(errorMessage + FixedMessage);
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-20 15:55:42 +08:00
|
|
|
|
private void Awake()
|
|
|
|
|
|
{
|
2023-12-22 15:26:48 +08:00
|
|
|
|
SceneView.duringSceneGui += OnSceneGUI;
|
2023-12-20 15:55:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-19 15:00:19 +08:00
|
|
|
|
protected override void OnEnable()
|
|
|
|
|
|
{
|
2023-11-15 17:59:47 +08:00
|
|
|
|
TerrainTypeConfig.Load();
|
2024-11-04 18:19:57 +08:00
|
|
|
|
_npcObjectDic = new Dictionary<Vector2Int, GameObject>();
|
|
|
|
|
|
_showNpcInfos = new List<NPCEditorInfo>();
|
2023-10-19 15:00:19 +08:00
|
|
|
|
base.OnEnable();
|
|
|
|
|
|
}
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2023-08-22 19:08:45 +08:00
|
|
|
|
protected override void OnDisable()
|
|
|
|
|
|
{
|
2023-12-22 15:26:48 +08:00
|
|
|
|
currWindow = null;
|
2023-12-18 19:42:46 +08:00
|
|
|
|
//MapEditorUtils.UnLoadMap(EditorMap.Instance);
|
2023-11-21 15:04:56 +08:00
|
|
|
|
//DestroyImmediate(GameObject.Find("Main Camera"));
|
2023-11-16 15:57:47 +08:00
|
|
|
|
DestroyNpcPrefab();
|
2024-11-04 18:19:57 +08:00
|
|
|
|
_npcObjectDic = null;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
base.OnDisable();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-21 15:04:56 +08:00
|
|
|
|
protected override void OnDestroy()
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2023-11-21 15:04:56 +08:00
|
|
|
|
base.OnDestroy();
|
2023-12-22 15:26:48 +08:00
|
|
|
|
if (_curMap != null)
|
2023-11-21 15:04:56 +08:00
|
|
|
|
_curMap.TerrainGridSystem.OnMouseClickOnGrid -= OnCellClick;
|
2023-12-22 15:26:48 +08:00
|
|
|
|
SaveCurrentLevel();
|
|
|
|
|
|
SceneView.duringSceneGui -= OnSceneGUI;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-21 15:04:56 +08:00
|
|
|
|
private bool banSaveLevelList = false;
|
2023-11-16 15:57:47 +08:00
|
|
|
|
|
2023-08-22 19:08:45 +08:00
|
|
|
|
private void OnCurrentLevelDataChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.Log($"{GetType()}.OnCurrentLevelDataChanged");
|
|
|
|
|
|
}
|
2023-11-16 15:57:47 +08:00
|
|
|
|
|
2023-10-19 15:00:19 +08:00
|
|
|
|
private const string descKey = "LevelDesc";
|
|
|
|
|
|
private const string nameKey = "LevelName";
|
|
|
|
|
|
|
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();
|
2024-11-04 18:19:57 +08:00
|
|
|
|
_npcObjectDic.Clear();
|
|
|
|
|
|
_showNpcInfos.Clear();
|
2023-11-21 15:04:56 +08:00
|
|
|
|
|
|
|
|
|
|
currentLevelData = levelData;
|
|
|
|
|
|
|
2023-11-16 15:57:47 +08:00
|
|
|
|
//加载地区信息
|
|
|
|
|
|
curRegionData = new RegionData();
|
|
|
|
|
|
curRegionData.preparingRegionId = currentLevelData.preparingRegionId;
|
|
|
|
|
|
curRegionData.fallbackRegionId = currentLevelData.fallbackRegionId;
|
|
|
|
|
|
curRegionData.enemyFallbackRegionId = currentLevelData.enemyFallbackRegionId;
|
|
|
|
|
|
curRegionData.preparingRegionToward = currentLevelData.preparingRegionToward;
|
2023-12-26 18:19:05 +08:00
|
|
|
|
curRegionData.pvpDefendRegionId = currentLevelData.pvpDefendRegionId;
|
|
|
|
|
|
curRegionData.pvpDefendToward = currentLevelData.pvpDefendToward;
|
2024-04-02 16:53:46 +08:00
|
|
|
|
|
2024-06-04 12:59:37 +08:00
|
|
|
|
//加载抗旗和占领
|
|
|
|
|
|
curRegionData.flagTargetRegionId = currentLevelData.flagTargetRegionId;
|
|
|
|
|
|
curRegionData.captureProgress = currentLevelData.captureProgress;
|
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-04-02 16:53:46 +08:00
|
|
|
|
var monsterConfigDic = EditorTableManager.instance.tables.Monster.DataMap;
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
2023-11-16 15:57:47 +08:00
|
|
|
|
//加载NPC到场景中
|
2024-06-04 16:50:16 +08:00
|
|
|
|
currentNpcInfo = 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-11-04 18:19:57 +08:00
|
|
|
|
var npcEditor = new NPCEditorInfo(npcInfo, index);
|
|
|
|
|
|
currentNpcInfo.Add(npcEditor);
|
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
|
|
|
|
|
2024-09-05 13:26:43 +08:00
|
|
|
|
npcInfo.level = monsterClassData.MonsterLevel;
|
2024-09-05 12:28:32 +08:00
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
var npcObj = LoadNpcPrefab(npcInfo.id);
|
|
|
|
|
|
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);
|
|
|
|
|
|
_npcObjectDic.Add(npcInfo.position, Instantiate(npcObj, setPos, Quaternion.Euler(0, yaw, 0)));
|
|
|
|
|
|
|
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-06-04 16:50:16 +08:00
|
|
|
|
|
|
|
|
|
|
//加载护送对象
|
|
|
|
|
|
currentProtectUnits = new List<ProtectEditorInfo>();
|
|
|
|
|
|
foreach (var protectUnit in currentLevelData.protectUnitInfos)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentProtectUnits.Add(new ProtectEditorInfo(protectUnit));
|
|
|
|
|
|
}
|
2023-11-16 15:57:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnCellClick(TerrainGridSystem tgs, int cellindex, int buttonindex)
|
|
|
|
|
|
{
|
2024-06-04 16:50:16 +08:00
|
|
|
|
if (isEditingProtectUnit) DebugUtil.LogWarning("当前点击索引: {0}", cellindex);
|
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-04 18:19:57 +08:00
|
|
|
|
if (isEditingPatrolInfo)
|
2023-12-22 15:26:48 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (opTrue)
|
|
|
|
|
|
AddPatrolInfo(clickPosition);
|
|
|
|
|
|
else
|
|
|
|
|
|
RemovePatrolInfo(clickPosition);
|
|
|
|
|
|
}
|
2024-11-04 18:19:57 +08:00
|
|
|
|
else if (isEditingNpcPos)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (opTrue)
|
|
|
|
|
|
ChangeNpcPos(clickPosition);
|
|
|
|
|
|
}
|
2023-12-22 15:26:48 +08:00
|
|
|
|
else if (isEditingNPC)
|
2023-11-16 15:57:47 +08:00
|
|
|
|
{
|
2023-12-22 15:26:48 +08:00
|
|
|
|
if (opTrue)
|
2023-11-16 15:57:47 +08:00
|
|
|
|
{
|
2023-12-22 15:26:48 +08:00
|
|
|
|
AddNPC(clickPosition);
|
2023-11-16 15:57:47 +08:00
|
|
|
|
}
|
2023-12-22 15:26:48 +08:00
|
|
|
|
else
|
2023-11-16 15:57:47 +08:00
|
|
|
|
{
|
2023-12-22 15:26:48 +08:00
|
|
|
|
RemoveNPC(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-04 18:19:57 +08:00
|
|
|
|
private void ChangeNpcPos(Vector2Int clickPosition)
|
|
|
|
|
|
{
|
|
|
|
|
|
var oldPos = _currEditingNPCInfo.position;
|
|
|
|
|
|
if (oldPos == clickPosition) return;
|
|
|
|
|
|
var newWorldPos = _curMap.BlockPosition2WorldPosition(clickPosition);
|
|
|
|
|
|
if (_npcObjectDic.TryGetValue(oldPos, out var npcObj))
|
|
|
|
|
|
{
|
|
|
|
|
|
npcObj.transform.position = newWorldPos;
|
|
|
|
|
|
_currEditingNPCInfo.position = clickPosition;
|
|
|
|
|
|
_npcObjectDic.Remove(oldPos);
|
|
|
|
|
|
_npcObjectDic.Add(clickPosition, npcObj);
|
|
|
|
|
|
DebugUtil.Log("怪物: [ {0} ] 移动到 [ {1} ]位置上", _currEditingNPCInfo.id, clickPosition);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-22 15:26:48 +08:00
|
|
|
|
private void AddNPC(Vector2Int clickPosition)
|
|
|
|
|
|
{
|
2024-05-29 14:03:39 +08:00
|
|
|
|
if (npcObject == null || curMonsterID == 0)
|
2023-12-22 15:26:48 +08:00
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请选择正确的NPC!!");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-11-21 15:04:56 +08:00
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
_npcObjectDic ??= new Dictionary<Vector2Int, GameObject>();
|
2024-05-29 14:03:39 +08:00
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
if (_npcObjectDic.ContainsKey(clickPosition))
|
2023-12-22 15:26:48 +08:00
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("该位置已有NPC存在,请重新选!!!");
|
|
|
|
|
|
return;
|
2023-11-16 15:57:47 +08:00
|
|
|
|
}
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
LevelData.NPCInfo npcInfo = new LevelData.NPCInfo
|
2024-09-05 13:26:43 +08:00
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
id = curMonsterID,
|
|
|
|
|
|
position = clickPosition
|
|
|
|
|
|
};
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2024-08-28 15:04:25 +08:00
|
|
|
|
var monsterConfigDic = EditorTableManager.instance.tables.Monster.DataMap;
|
|
|
|
|
|
if (monsterConfigDic.TryGetValue(curMonsterID, out var monster))
|
|
|
|
|
|
{
|
|
|
|
|
|
npcInfo.level = monster.MonsterLevel;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("获取怪物[{0}]配置数据错误", curMonsterID);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
currentNpcInfo.Add(new(npcInfo, currentNpcInfo.Count + 1));
|
|
|
|
|
|
var pos = _curMap.BlockPosition2WorldPosition(npcInfo.position);
|
|
|
|
|
|
_npcObjectDic.Add(npcInfo.position, Instantiate(npcObject, pos, npcObject.transform.rotation));
|
2024-05-29 14:03:39 +08:00
|
|
|
|
DebugUtil.Log("添加了怪物: [ {0} ] 到 [ {1} ]位置上, 其预制体为: {2}", npcInfo.id, npcInfo.position, npcObject.name);
|
2023-12-22 15:26:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void RemoveNPC(Vector2Int clickPosition)
|
|
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
if (_npcObjectDic.TryGetValue(clickPosition, out var npcObj))
|
2023-11-16 15:57:47 +08:00
|
|
|
|
{
|
2024-06-04 16:50:16 +08:00
|
|
|
|
var npc = currentNpcInfo.FirstOrDefault(npc => npc.npcInfo.position == clickPosition);
|
2023-12-22 15:26:48 +08:00
|
|
|
|
if (npc != null)
|
2023-11-16 15:57:47 +08:00
|
|
|
|
{
|
2024-06-04 16:50:16 +08:00
|
|
|
|
currentNpcInfo.Remove(npc);
|
2023-12-22 15:26:48 +08:00
|
|
|
|
DebugUtil.Log("从[ {0} ]位置上移除了[{1}]NPC", clickPosition, npcObj.name);
|
|
|
|
|
|
DestroyImmediate(npcObj);
|
2024-11-04 18:19:57 +08:00
|
|
|
|
_npcObjectDic.Remove(clickPosition);
|
2023-11-16 15:57:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
|
|
|
|
|
ReorderNpcID();
|
2023-11-16 15:57:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-22 15:26:48 +08:00
|
|
|
|
private void AddPatrolInfo(Vector2Int clickPosition)
|
|
|
|
|
|
{
|
|
|
|
|
|
_currEditingNPCInfo.patrolInfos.Add(new LevelData.PatrolInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
patrolPoint = clickPosition,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void RemovePatrolInfo(Vector2Int clickPosition)
|
|
|
|
|
|
{
|
|
|
|
|
|
var index = _currEditingNPCInfo.patrolInfos.FindLastIndex(pInfo => pInfo.patrolPoint == clickPosition);
|
|
|
|
|
|
if (index >= 0)
|
|
|
|
|
|
_currEditingNPCInfo.patrolInfos.RemoveAt(index);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
private void StartEditPatrolInfo(LevelData.NPCInfo npcInfo)
|
2023-12-22 15:26:48 +08:00
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
isEditingPatrolInfo = true;
|
2023-12-22 15:26:48 +08:00
|
|
|
|
_currEditingNPCInfo = npcInfo;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
private void FinishEditPatrolInfo()
|
2023-12-22 15:26:48 +08:00
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
isEditingPatrolInfo = false;
|
2023-12-22 15:26:48 +08:00
|
|
|
|
_currEditingNPCInfo = null;
|
|
|
|
|
|
}
|
2023-11-16 15:57:47 +08:00
|
|
|
|
|
2024-11-04 18:19:57 +08:00
|
|
|
|
private void ReorderNpcID()
|
|
|
|
|
|
{
|
|
|
|
|
|
for (var i = 0; i < currentNpcInfo.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentNpcInfo[i].id = i + 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void ChangeNpcID(LevelData.NPCInfo npcInfo, int newMonsterID)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_npcObjectDic.TryGetValue(npcInfo.position, out var npcObj))
|
|
|
|
|
|
{
|
|
|
|
|
|
var newObj = LoadNpcPrefab(newMonsterID);
|
|
|
|
|
|
if (newObj != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
npcInfo.id = newMonsterID;
|
|
|
|
|
|
_npcObjectDic[npcInfo.position] = Instantiate(newObj, npcObj.transform.position, npcObj.transform.rotation);
|
|
|
|
|
|
DestroyImmediate(npcObj);
|
|
|
|
|
|
DebugUtil.Log("位置上[ {0} ]的怪物ID改为: [ {1} ] ", npcInfo.position, npcInfo.id);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private GameObject LoadNpcPrefab(int monsterID)
|
|
|
|
|
|
{
|
|
|
|
|
|
GameObject obj = null;
|
|
|
|
|
|
var monsterCfg = EditorTableManager.instance.tables.Monster;
|
|
|
|
|
|
if (monsterCfg.DataMap.TryGetValue(monsterID, out var monster))
|
|
|
|
|
|
{
|
|
|
|
|
|
_curMonsterClassID = monster.MonsterClassID;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (monster.NpcType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case ENpcType.ENEMY_VEHICLE:
|
|
|
|
|
|
{
|
|
|
|
|
|
var vehicleConfig = EditorTableManager.instance.tables.EnemyVehicleConfig;
|
|
|
|
|
|
if (vehicleConfig.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 ENpcType.ENEMY_CHARACTER:
|
|
|
|
|
|
{
|
|
|
|
|
|
var monsterClassCfg = EditorTableManager.instance.tables.MonsterClass;
|
|
|
|
|
|
if (monsterClassCfg.DataMap.TryGetValue(_curMonsterClassID, out var monsterClass))
|
|
|
|
|
|
{
|
|
|
|
|
|
var prefabPath = PathEx.GetCharacterFightModelPath(monsterClass.NameId);
|
|
|
|
|
|
obj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
|
|
|
|
|
if (obj == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请检查怪物类: {0}的预制体路径是否存在,对应的完整路径: {1}", _curMonsterClassID, prefabPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("请检查怪物类: {0}的配置是否存在", _curMonsterClassID);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
|
}
|
|
|
|
|
|
default: return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-16 15:57:47 +08:00
|
|
|
|
private void DestroyNpcPrefab()
|
|
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
foreach (var npc in _npcObjectDic)
|
2023-11-16 15:57:47 +08:00
|
|
|
|
{
|
|
|
|
|
|
DestroyImmediate(npc.Value);
|
|
|
|
|
|
}
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
2024-11-04 18:43:29 +08:00
|
|
|
|
private void ChangeNpcToward(Vector2Int pos, LevelData.CharacterToward npcToward)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_npcObjectDic.TryGetValue(pos, out var npcObj))
|
|
|
|
|
|
{
|
|
|
|
|
|
var yaw = LevelUtils.SetCharaterToward(npcToward);
|
|
|
|
|
|
npcObj.transform.eulerAngles = new Vector3(0, yaw, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnSceneGUI(SceneView sceneView)
|
|
|
|
|
|
{
|
|
|
|
|
|
DrawPatrolPath();
|
2024-11-04 18:19:57 +08:00
|
|
|
|
DrawNpcID();
|
2023-12-22 15:26:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void DrawPatrolPath()
|
|
|
|
|
|
{
|
2024-11-04 18:19:57 +08:00
|
|
|
|
if (!isEditingPatrolInfo) return;
|
2023-12-22 15:26:48 +08:00
|
|
|
|
|
|
|
|
|
|
Vector3 lastWorldPos = Vector3.zero;
|
|
|
|
|
|
for (int i = 0; i < _currEditingNPCInfo.patrolInfos.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var gridPos = _currEditingNPCInfo.patrolInfos[i].patrolPoint;
|
|
|
|
|
|
var worldPos = _curMap.BlockPosition2WorldPosition(gridPos);
|
|
|
|
|
|
Handles.color = Color.blue;
|
|
|
|
|
|
Handles.DrawSolidDisc(worldPos, Vector3.up, 0.4f);
|
|
|
|
|
|
if (i > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
Handles.color = Color.yellow;
|
2023-12-26 18:19:05 +08:00
|
|
|
|
EditorUtil.DrawArrowInScene(lastWorldPos, worldPos, 0.5f);
|
2023-12-22 15:26:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Handles.color = Color.black;
|
2023-12-26 18:19:05 +08:00
|
|
|
|
Handles.Label(worldPos, i.ToString());
|
2023-12-22 15:26:48 +08:00
|
|
|
|
lastWorldPos = worldPos;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-11-04 18:19:57 +08:00
|
|
|
|
|
|
|
|
|
|
private GUIStyle labelStyle;
|
|
|
|
|
|
|
|
|
|
|
|
private void DrawNpcID()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!isShowNpcID) return;
|
|
|
|
|
|
|
|
|
|
|
|
if (labelStyle == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
labelStyle = new GUIStyle
|
|
|
|
|
|
{
|
|
|
|
|
|
fontSize = 38,
|
|
|
|
|
|
fontStyle = FontStyle.Bold,
|
|
|
|
|
|
normal =
|
|
|
|
|
|
{
|
|
|
|
|
|
textColor = Color.red
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var npc in _showNpcInfos)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_npcObjectDic.TryGetValue(npc.npcInfo.position, out var npcObj))
|
|
|
|
|
|
{
|
|
|
|
|
|
Handles.Label(npcObj.transform.position, npc.id.ToString(), labelStyle);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|