TH1/Unity/Assets/Scripts/TH1_Logic/Editor/AIConfigEditorWindow.cs
2026-06-10 11:58:18 +08:00

297 lines
12 KiB
C#

/*
* @Author: 白哉
* @Description: AI 编辑器
* @Date: 2025年04月22日 星期二 15:04:14
* @Modify:
*/
using System.Collections.Generic;
using System.Linq;
using CanvasCoreExpand;
using Logic.AI;
using NodeCanvas.BehaviourTrees;
using NodeCanvas.Framework;
using NodeCanvas.Tasks.Actions;
using RuntimeData;
using TH1_Logic.Core;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;
namespace Logic.Editor
{
public enum EditorType
{
Asset,
Tech,
ScoreShow,
}
public class AIConfigEditorWindow : EditorWindow
{
// 滑条
private Vector2 _barPosition;
// 背景
private GUIStyle _redBoxStyle;
private GUIStyle _whiteBoxStyle;
private PlayerData _player;
private CityData _city;
private Main _main;
private AIConfigAsset _asset;
[MenuItem("Tools/AI 编辑器")]
private static void ShowWindow()
{
var window = CreateWindow<AIConfigEditorWindow>();
window.titleContent = new GUIContent("AI 编辑器");
window.Show();
window.minSize = new Vector2(500, 600);
}
protected virtual void OnEnable()
{
ExpandGraphEditor.Exporter = new GraphExporter();
}
private void OnDisable()
{
}
private void OnGUI()
{
if (_redBoxStyle == null)
{
_redBoxStyle = InspectorUtils.GetHelpBoxStyle();
InspectorUtils.AddBorder(_redBoxStyle, new Color(0.5f, 0.4f, 0.4f, 0.6f));
}
if (_whiteBoxStyle == null)
{
_whiteBoxStyle = InspectorUtils.GetHelpBoxStyle();
InspectorUtils.AddBorder(_whiteBoxStyle, new Color(1f, 1f, 1f, 0.2f));
}
GUI.skin.button.wordWrap = true;
_barPosition = EditorGUILayout.BeginScrollView(_barPosition);
if (!Application.isPlaying) OnInspectorAIConfig();
OnGUIRunTime();
OnShowPlayerInfo();
OnShowCityInfo();
OnInspectorAIRecord();
EditorGUILayout.EndScrollView();
}
private void OnInspectorAIRecord()
{
if (_player == null) return;
var records = AILogic.GetAIRecords(_player.Id);
if (records == null) return;
foreach (var record in records) OnInspectorAIRecordItem(record);
}
private void OnInspectorAIRecordItem(AIRecord record)
{
EditorGUILayout.BeginVertical(_redBoxStyle);
record.IsFoldout = EditorGUILayout.Foldout(record.IsFoldout, $"{record.GetDesc()}");
if (record.IsFoldout)
{
if (record.Action != null)
{
InspectorUtils.InspectorTextWidthRich($"<b> {record.Action.ActionLogic.ActionId.GetStringLog()} </b>");
InspectorUtils.InspectorTextWidthRich($"<b> {record.Action.Param.GetStringLog()} </b>");
}
for (int i = record.StateRecords.Count - 1; i >= 0; i--)
{
var state = record.StateRecords[i];
InspectorUtils.InspectorTextWidthRich($" {state.ID} : {state.Result} : {state.Desc} ");
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
EditorGUILayout.Space();
}
private void OnInspectorAIConfig()
{
if (!_asset)
{
var path = $"Assets/BundleResources/DataAssets/AIConfig.asset";
_asset = AssetDatabase.LoadAssetAtPath<AIConfigAsset>(path);
if (!_asset)
{
_asset = CreateInstance<AIConfigAsset>();
AssetDatabase.CreateAsset(_asset, path);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
if (InspectorUtils.InspectorButtonWithTextWidth("保存"))
{
EditorUtility.SetDirty(_asset);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
for (int i = (int)AIDifficult.EASY; i <= (int)AIDifficult.LUNATIC; i++)
{
if (_asset.GetAIDiffInfo((AIDifficult)i) == null)
{
_asset.AidiffInfos.Add(new AIDiffInfo((AIDifficult)i));
}
}
_asset.AidiffInfos = _asset.AidiffInfos.OrderBy(i => i.Level).ToList();
foreach (var diffInfo in _asset.AidiffInfos)
{
EditorGUILayout.BeginVertical(_whiteBoxStyle);
InspectorUtils.InspectorTextWidthRich($"<b>难度:{diffInfo.Level}</b>");
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"<b>自由人撤退攻击收益</b>");
diffInfo.FreeUnitRetreat = EditorGUILayout.FloatField(diffInfo.FreeUnitRetreat);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"<b>自由人其他攻击收益</b>");
diffInfo.FreeUnitRetreat = EditorGUILayout.FloatField(diffInfo.FreeUnitOther);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"<b>军团成员协防攻击收益</b>");
diffInfo.FreeUnitRetreat = EditorGUILayout.FloatField(diffInfo.LegionUnitDefend);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"<b>军团成员进攻攻击收益</b>");
diffInfo.FreeUnitRetreat = EditorGUILayout.FloatField(diffInfo.LegionUnitAttack);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"<b>军团成员驻扎攻击收益</b>");
diffInfo.FreeUnitRetreat = EditorGUILayout.FloatField(diffInfo.LegionUnitDevelopment);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"<b>城中小兵攻击收益</b>");
diffInfo.FreeUnitRetreat = EditorGUILayout.FloatField(diffInfo.UnitInCity);
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
}
}
private void OnGUIRunTime()
{
if (!Application.isPlaying) return;
if (!_main)
{
var obj = GameObject.Find("Main");
if (!obj) return;
_main = obj.GetComponent<Main>();
if (!_main) return;
}
if (Main.MapData == null) return;
EditorGUILayout.BeginHorizontal();
foreach (var player in Main.MapData.PlayerMap.PlayerDataList)
{
if (player.Id == Main.MapData.PlayerMap.SelfPlayerId) continue;
if (InspectorUtils.InspectorButtonWithTextWidth($"玩家{player.Id}")) _player = player;
}
EditorGUILayout.EndHorizontal();
var selfCity = new HashSet<CityData>();
Main.MapData.GetCityDataListByPlayerId(Main.MapData.PlayerMap.SelfPlayerId, selfCity);
EditorGUILayout.BeginHorizontal();
foreach (var city in Main.MapData.CityMap.CityList)
{
if (selfCity.Contains(city)) continue;
if (InspectorUtils.InspectorButtonWithTextWidth($"城市{city.Id}")) _city = city;
}
EditorGUILayout.EndHorizontal();
}
private void OnShowPlayerInfo()
{
if (Main.MapData == null || _player == null) return;
MainEditor.Instance.GetPlayerStrategy(_player.Id, out var playerStrategy, out var targetIdSet);
EditorGUILayout.BeginHorizontal();
if (playerStrategy != Strategy.Attack)
InspectorUtils.InspectorTextWidthRich($"<b>玩家ID: {_player.Id}, 国家战略为: {playerStrategy}</b>");
else
{
var idStr = "";
foreach (var id in targetIdSet) idStr += $"{id}";
InspectorUtils.InspectorTextWidthRich(
$"<b>玩家ID: {_player.Id}, 国家战略为: {playerStrategy}, 目标:{idStr}</b>");
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginVertical(_redBoxStyle);
InspectorUtils.InspectorTextWidthRich($"<b>城市信息</b>");
var selfCity = new HashSet<CityData>();
Main.MapData.GetCityDataListByPlayerId(_player.Id, selfCity);
foreach (var city in selfCity)
{
MainEditor.Instance.GetCityStrategy(city.Id, out var strategy);
InspectorUtils.InspectorTextWidthRich($"<b>ID: {city.Id}, 策略: {strategy}</b>");
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.BeginVertical(_redBoxStyle);
InspectorUtils.InspectorTextWidthRich($"<b>小兵信息</b>");
var selfUnits = new HashSet<UnitData>();
Main.MapData.GetUnitDataListByPlayerId(_player.Id, selfUnits);
foreach (var unit in selfUnits)
{
MainEditor.Instance.GetUnitStrategy(unit.Id, unit.LegionId, _player.Id, out var strategy, out var target, out var type);
InspectorUtils.InspectorTextWidthRich(unit.LegionId == 0
? $"<b>ID: {unit.Id}, 自由人, 策略: {strategy}, 目标城市: {target}</b>"
: $"<b>ID: {unit.Id}, 军团ID:{unit.LegionId}, 策略: {strategy}, 类型:{type}, 目标城市: {target}</b>");
}
EditorGUILayout.EndVertical();
}
private void OnShowCityInfo()
{
if (Main.MapData == null || _city == null) return;
var actions = MainEditor.Instance.GetCityActions(_city.Id);
if (actions == null || actions.Count == 0) return;
foreach (var aiAction in actions)
{
EditorGUILayout.BeginVertical(_whiteBoxStyle);
if (aiAction.Param.GridData != null)
InspectorUtils.InspectorTextWidthRich($"<b>位置:</b> {aiAction.Param.GridData.Pos.X}, {aiAction.Param.GridData.Pos.Y}");
InspectorUtils.InspectorTextWidthRich($"<b>ActionType:</b> {aiAction.ActionLogic.ActionId.ActionType}");
InspectorUtils.InspectorTextWidthRich($"<b>WonderType:</b> {aiAction.ActionLogic.ActionId.WonderType}");
InspectorUtils.InspectorTextWidthRich($"<b>ResourceType:</b> {aiAction.ActionLogic.ActionId.ResourceType}");
InspectorUtils.InspectorTextWidthRich($"<b>FeatureType:</b> {aiAction.ActionLogic.ActionId.FeatureType}");
InspectorUtils.InspectorTextWidthRich($"<b>TerrainType:</b> {aiAction.ActionLogic.ActionId.TerrainType}");
InspectorUtils.InspectorTextWidthRich($"<b>UnitType:</b> {aiAction.ActionLogic.ActionId.UnitType}");
InspectorUtils.InspectorTextWidthRich($"<b>GiantType:</b> {aiAction.ActionLogic.ActionId.GiantType}");
InspectorUtils.InspectorTextWidthRich($"<b>Vegetation:</b> {aiAction.ActionLogic.ActionId.Vegetation}");
InspectorUtils.InspectorTextWidthRich($"<b>UnitActionType:</b> {aiAction.ActionLogic.ActionId.UnitActionType}");
InspectorUtils.InspectorTextWidthRich($"<b>CityLevelUpActionType:</b> {aiAction.ActionLogic.ActionId.CityLevelUpActionType}");
InspectorUtils.InspectorTextWidthRich($"<b>GridMiscActionType:</b> {aiAction.ActionLogic.ActionId.GridMiscActionType}");
InspectorUtils.InspectorTextWidthRich($"<b>SkillType:</b> {aiAction.ActionLogic.ActionId.SkillType}");
InspectorUtils.InspectorTextWidthRich($"<b>TechType:</b> {aiAction.ActionLogic.ActionId.TechType}");
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
}
}
}
}