zxl
/
CTT
forked from Cal/CTT
1
0
Fork 0
CTT/Unity/Assets/XNodeDemo/Skill/SkillAndModifierSObject.cs

430 lines
20 KiB
C#

using Cal;
using ET;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.Options;
using Sirenix.OdinInspector;
using Sirenix.Utilities;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
#endif
namespace CalEditor
{
using CalEditor.Cal.DataTable;
#if UNITY_EDITOR
#region Config
using ET;
using MongoDB.Bson.Serialization.Attributes;
namespace Cal.DataTable
{
[Config]
public partial class SkillConfigCategory : ACategory<SkillConfig>
{
public static SkillConfigCategory Instance;
public SkillConfigCategory()
{
Instance = this;
}
}
public partial class SkillConfig : IConfig
{
[BsonId]
public long Id { get; set; }
public string Name;
public string Desc;
public int CD;
public int CastType;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float CastValue;
public int PreSkillId;
public int MaxLevel;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args0;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args1;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args2;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args3;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args4;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args5;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args6;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args7;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args8;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args9;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args10;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args11;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args12;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args13;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args14;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args15;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args16;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args17;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args18;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args19;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args20;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args29;
[BsonRepresentation(MongoDB.Bson.BsonType.Double, AllowTruncation = true)]
public float Args30;
public int SkillType;
public int LearnLevel;
public int EffectId;
public int DelayTime;
public int HurtEffectId;
public string Icon;
}
}
#endregion
[CreateAssetMenu]
public class SkillAndModifierSObject : Sirenix.OdinInspector.SerializedScriptableObject
{
public static SkillAndModifierSObject Instance;
private void OnEnable()
{
Instance = this;
//LoadConfig();
}
private void LoadConfig()
{
SkillConfigCategory.Instance = new SkillConfigCategory();
SkillConfigCategory.Instance.LoadAsync();
}
[FolderPath()]
[LabelText("SO保存路径"), PropertyOrder(120)]
public string soDir = "Assets/XNodeDemo/Assets/Skill";
public string soDataPath = "Assets/XNodeDemo/Assets/SOData/nodes.json";
[FolderPath(AbsolutePath = true)]
[LabelText("存档保存路径"), PropertyOrder(120)]
public string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "/CTT/Skill/Skill";
[FolderPath(AbsolutePath = true)]
[LabelText("日志保存路径"), PropertyOrder(120)]
public string logPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "/CTT/Skill/Logs";
[LabelText("文件名"), PropertyOrder(120)]
public string fileName = "SkillLogicConfig.json";
[LabelText("二进制文件名"), PropertyOrder(120)]
public string fileBytesName = "SkillLogicConfig.bytes";
[Button("重置"), PropertyOrder(-1)]
[ButtonGroup]
public void ReSet()
{
loop = 0;
RegisterMongo();
string str = File.ReadAllText(soDataPath);
NodeDataUtil.dic = MongoHelper.FromJson<Dictionary<int, SkillNodeGraph>>(str);
Deserilize();
AssetDatabase.Refresh();
Log.Info($"加载完毕:{str.Length / 1000}K " + DateTime.Now);
}
private List<int> GetSkills()
{
var arr = Utility.FileOpation.GetFiles(soDir, "*.asset", SearchOption.AllDirectories);
List<int> list = new List<int>();
foreach (var item in arr)
{
var asset = AssetDatabase.LoadAssetAtPath<SkillNodeGraph>(Utility.Path.DataPathToAssetPath(item.FullName));
list.Add(asset.Id);
}
Utility.FileOpation.DeleteDirectory(soDir,true);
return list;
}
void Deserilize()
{
try
{
foreach (var skillGraphKV in NodeDataUtil.dic)
{
var deserilizedGraph = skillGraphKV.Value;
var _skillNodeGraph = CreateInstance<SkillNodeGraph>();
_skillNodeGraph.name = skillGraphKV.Key.ToString();
AssetDatabase.CreateAsset(_skillNodeGraph,Path.Combine(soDir,_skillNodeGraph.name)+".asset");
try
{
foreach (SkillNode node in deserilizedGraph.nodes)
{
try
{
SkillNode oldNode = _skillNodeGraph.nodes.Find(t => t.As<SkillNode>().uniqeId == node.uniqeId) as SkillNode;
if (oldNode == null)
{
GeanerateNotExistNode(_skillNodeGraph, deserilizedGraph.nodes.Find(t => t.As<SkillNode>().uniqeId == node.uniqeId) as SkillNode, node.uniqeId);
}
}
catch (Exception)
{
Log.Error($"[1]skill has error in dic which id = {_skillNodeGraph.Id}");
throw;
}
}
}
catch (Exception)
{
Log.Error($"[2]skill has error in dic which id = {_skillNodeGraph.Id}");
throw;
}
foreach (SkillNode node in deserilizedGraph.nodes)
{
SkillNode oldNode = _skillNodeGraph.nodes.Find(t => t.As<SkillNode>().uniqeId == node.uniqeId) as SkillNode;
if (oldNode == null)
{
Log.Error($"oldNode == null where id = {node.uniqeId}");
continue;
}
switch (oldNode)
{
default:
break;
case RootNode rootNode:
rootNode.skillLogic = node.As<RootNode>().skillLogic;
break;
case SkillEventConditionNode rootNode:
rootNode.condition = node.As<SkillEventConditionNode>().condition;
break;
case ModifierNode rootNode:
rootNode.modifier = node.As<ModifierNode>().modifier;
break;
case ModifierEventConditionNode rootNode:
rootNode.condition = node.As<ModifierEventConditionNode>().condition;
break;
case SkillOptionBase rootNode:
int index = _skillNodeGraph.nodes.IndexOf(oldNode);
_skillNodeGraph.nodes[index] = oldNode = node.As<SkillOptionBase>().Clone(rootNode);
break;
}
oldNode.position = node.position;
if (node.nextIds != null)
foreach (var kv in node.nextIds)
{
var outPut = oldNode.GetOutputPort(kv.Key);
outPut.ClearConnections();
foreach (var uniqeId in kv.Value)
{
SkillNode targetNode = _skillNodeGraph.GetNode(uniqeId);
if (targetNode == null)
{
Log.Error($"this is wrong when id = {uniqeId}");
targetNode = GeanerateNotExistNode(_skillNodeGraph, deserilizedGraph.nodes.Find(t => t.As<SkillNode>().uniqeId == uniqeId) as SkillNode, uniqeId);
}
outPut.Connect(targetNode.GetInputPort("input"));
}
}
}
EditorUtility.SetDirty(_skillNodeGraph);
AssetDatabase.SaveAssets();
}
Log.Info($"反序列化成功 {DateTime.Now:MM_dd+HH_mm_ss}");
}
catch (Exception e)
{
Log.Info($"反序列化失败 {DateTime.Now:MM_dd+HH_mm_ss}");
Log.Error($"{e}");
}
AssetDatabase.Refresh();
}
private void SetSkillLogicInfo(SkillLogicConfig skillLogic)
{
int skillId = skillLogic.skillId;
SkillConfig skillConfig = SkillConfigCategory.Instance.Get(skillId * 100);
skillLogic.CD = skillConfig.CD;
skillLogic.maxLevel = skillConfig.MaxLevel;
skillLogic.cast = new CastParam
{
skillCastType = (SkillCastType)skillConfig.CastType,
skillCast = skillConfig.CastValue,
castBaseType =(SkillCastType)skillConfig.CastType == SkillCastType.? CastBaseType.Level: CastBaseType.Max
};
}
private SkillNode GeanerateNotExistNode(SkillNodeGraph skillGraph, SkillNode skillNode, int uniqeId)
{
SkillNode node = skillGraph.AddNodeWithId(skillNode.GetType(), uniqeId) as SkillNode;
switch (node)
{
default:
break;
case RootNode rootNode:
rootNode.skillLogic = skillNode.As<RootNode>().skillLogic;
break;
case SkillEventConditionNode rootNode:
rootNode.condition = skillNode.As<SkillEventConditionNode>().condition;
break;
case ModifierNode rootNode:
rootNode.modifier = skillNode.As<ModifierNode>().modifier;
break;
case ModifierEventConditionNode rootNode:
rootNode.condition = skillNode.As<ModifierEventConditionNode>().condition;
break;
case SkillOptionBase rootNode:
int index = skillGraph.nodes.IndexOf(node);
node.position = skillNode.position;
skillGraph.nodes[index] = node = skillNode.As<SkillOptionBase>().Clone(rootNode);
break;
}
node.name = skillNode.name;
AssetDatabase.AddObjectToAsset(node, skillGraph);
return node;
}
void LoadAllAsync(SkillLogicConfigCollection data)
{
foreach (var item in data.skillDic)
{
var logic = item.Value;
string assetPath = $"{soDir}/{item.Key}.asset";
SkillNodeGraph so = CreateInstance<SkillNodeGraph>();
AssetDatabase.CreateAsset(so, assetPath);
RootNode root = so.AddNode<RootNode>();
root.name = "Root";
root.position = so.GetEmptyNodePos();
AssetDatabase.AddObjectToAsset(root, so);
root.skillLogic = logic;
Dictionary<ModifierId, ModifierNode> modifierNodeDic = new Dictionary<ModifierId, ModifierNode>();
if (logic.modifierDic != null)
{
foreach (var modifier in logic.modifierDic)
{
ModifierNode modifierNode = so.AddNode<ModifierNode>();
modifierNode.name = "Modifier";
modifierNode.position = so.GetEmptyNodePos();
AssetDatabase.AddObjectToAsset(modifierNode, so);
modifierNode.modifier = modifier.Value;
modifierNodeDic.Add(modifier.Key, modifierNode);
}
}
foreach (var modifierKV in modifierNodeDic)
{
if (modifierKV.Value.modifier.modifierEventDic != null)
foreach (var modifierEvent in modifierKV.Value.modifier.modifierEventDic)
{
ModifierEventConditionNode skillEventConditionNode = so.AddNode<ModifierEventConditionNode>();
skillEventConditionNode.name = "ModifierEventCondition";
skillEventConditionNode.position = so.GetEmptyNodePos();
AssetDatabase.AddObjectToAsset(skillEventConditionNode, so);
modifierKV.Value.GetOutputPort("result").Connect(skillEventConditionNode.GetInputPort("input"));
skillEventConditionNode.condition = modifierEvent.Key;
CreateSkillOption(so, skillEventConditionNode.GetOutputPort("result"), modifierNodeDic, modifierEvent.Value);
}
}
if (logic.skillEventDic != null)
foreach (var skillEvent in logic.skillEventDic)
{
SkillEventConditionNode skillEventConditionNode = so.AddNode<SkillEventConditionNode>();
skillEventConditionNode.name = "SkillEventCondition";
skillEventConditionNode.position = so.GetEmptyNodePos();
AssetDatabase.AddObjectToAsset(skillEventConditionNode, so);
root.GetOutputPort("result").Connect(skillEventConditionNode.GetInputPort("input"));
skillEventConditionNode.condition = skillEvent.Key;
CreateSkillOption(so, skillEventConditionNode.GetOutputPort("result"), modifierNodeDic, skillEvent.Value);
}
EditorUtility.SetDirty(so);
AssetDatabase.SaveAssets();
}
void CreateSkillOption(SkillNodeGraph so, XNode.NodePort lastNode, Dictionary<ModifierId, ModifierNode> modifierNodeDic, SkillOptionBase[] options)
{
if (options == null) return;
AvoidLoop();
foreach (var option in options)
{
Type type = option.GetType();
SkillOptionBase skillOptionNode = so.AddNode(type) as SkillOptionBase;
skillOptionNode.name = type.Name;
skillOptionNode.position = so.GetEmptyNodePos();
AssetDatabase.AddObjectToAsset(skillOptionNode, so);
lastNode.Connect(skillOptionNode.GetInputPort("input"));
skillOptionNode = option.Clone(skillOptionNode);
foreach (var fieldInfo in type.GetFields())
{
if (fieldInfo.FieldType == typeof(SkillOptionBase[]))
{
SkillOptionBase[] arr = fieldInfo.GetValue(option) as SkillOptionBase[];
CreateSkillOption(so, skillOptionNode.GetNodePort(fieldInfo.Name), modifierNodeDic, arr);
}
else
if (fieldInfo.FieldType == typeof(ModifierId))
{
ModifierId id = (ModifierId)fieldInfo.GetValue(option);
if (modifierNodeDic == null)
{
Log.Error($"modifierNodeDic == null skillId = {so.nodes.Find(t => t.name.Equals("Root")).As<RootNode>().skillLogic.skillId}");
continue;
}
if (modifierNodeDic.TryGetValue(id, out var modifierNode))
{
skillOptionNode.GetOutputPort("result").Connect(modifierNode.GetInputPort("input"));
}
}
else
if (fieldInfo.FieldType == typeof(ModifierId[]))
{
ModifierId[] ids = (ModifierId[])fieldInfo.GetValue(option);
if (modifierNodeDic == null)
{
Log.Error($"modifierNodeDic == null skillId = {so.nodes.Find(t => t.name.Equals("Root")).As<RootNode>().skillLogic.skillId}");
continue;
}
foreach (var id in ids)
{
if (modifierNodeDic.TryGetValue(id, out var modifierNode))
{
skillOptionNode.GetOutputPort("result").Connect(modifierNode.GetInputPort("input"));
}
}
}
}
}
}
}
private int loop;
private void AvoidLoop()
{
loop++;
if (loop > 1000)
throw new Exception("stack overflow");
}
public static void RegisterMongo()
{
RootNode.RegisterMongo();
}
}
#endif
}