297 lines
12 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|
|
} |