using System;
using System.IO;
using System.Linq;
using HotUpdate.Gameplay;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
using Object=UnityEngine.Object;
/// Persistent, independent skill review. Never edits the production arena or account.
public static class BuildSkillSlice
{
public const string Folder="Assets/Bundles/Combat/SkillSlice";
public const string Prefab=Folder+"/SkillSlice.prefab";
public const string Scene="Assets/Bundles/Scenes/Review/SkillSlice_Review.unity";
static readonly string[] Names={"FireCharge","Fireball","FireHit","RockHit","Shield"};
static readonly string[] SoundNames={"FireCharge","FireLaunch","FireHit","RockHit","Shield"};
static void Folders(string path){if(AssetDatabase.IsValidFolder(path))return;string parent=Path.GetDirectoryName(path).Replace('\\','/');Folders(parent);AssetDatabase.CreateFolder(parent,Path.GetFileName(path));}
static ParticleSystem Part(Transform parent,string name,Color color,int count,float life,float size,bool loop=false,Mesh mesh=null)
{
var go=new GameObject(name);go.transform.SetParent(parent,false);go.layer=30;var ps=go.AddComponent();
var main=ps.main;main.playOnAwake=false;main.loop=loop;main.duration=.5f;main.startLifetime=life;main.startSpeed=mesh!=null?0:.25f;main.startSize=size;main.startColor=color;main.maxParticles=32;main.simulationSpace=ParticleSystemSimulationSpace.Local;
var emission=ps.emission;emission.rateOverTime=loop?count:0;if(!loop)emission.SetBursts(new[]{new ParticleSystem.Burst(0,(short)count)});
var shape=ps.shape;shape.shapeType=ParticleSystemShapeType.Sphere;shape.radius=loop?.035f:.08f;
var colorLife=ps.colorOverLifetime;colorLife.enabled=true;var gradient=new Gradient();gradient.SetKeys(new[]{new GradientColorKey(Color.white,0),new GradientColorKey(color,1)},new[]{new GradientAlphaKey(.85f,0),new GradientAlphaKey(0,1)});colorLife.color=gradient;
var sizeLife=ps.sizeOverLifetime;sizeLife.enabled=true;sizeLife.size=new ParticleSystem.MinMaxCurve(1,AnimationCurve.Linear(0,1,1,.1f));
var renderer=ps.GetComponent();renderer.sharedMaterial=AssetDatabase.LoadAssetAtPath("Assets/Bundles/Effects/EnemyCombat/CombatGlow.mat");renderer.renderMode=mesh==null?ParticleSystemRenderMode.Billboard:ParticleSystemRenderMode.Mesh;if(mesh!=null)renderer.mesh=mesh;
return ps;
}
static float Height(Transform root)
{
float top=0;var mesh=new Mesh();foreach(var skin in root.GetComponentsInChildren(true)){skin.BakeMesh(mesh,true);foreach(var v in mesh.vertices)top=Mathf.Max(top,root.InverseTransformPoint(skin.transform.TransformPoint(v)).y);}Object.DestroyImmediate(mesh);return top;
}
public static string Build()
{
if(EditorApplication.isPlaying)throw new Exception("Author in Edit Mode");Folders(Folder);
AssetDatabase.ImportAsset(Folder+"/trace.json",ImportAssetOptions.ForceUpdate);var trace=AssetDatabase.LoadAssetAtPath(Folder+"/trace.json");var data=JObject.Parse(trace.text);
var previous=SceneManager.GetActiveScene();var scene=EditorSceneManager.NewScene(NewSceneSetup.EmptyScene,NewSceneMode.Additive);
try
{
SceneManager.SetActiveScene(scene);var root=new GameObject("SkillSlice");var player=root.AddComponent();
var camera=new GameObject("SkillSliceCamera").AddComponent();camera.transform.SetParent(root.transform,false);camera.transform.localPosition=new Vector3(8,9,-11);camera.transform.LookAt(new Vector3(0,.5f,1.1f));camera.orthographic=true;camera.orthographicSize=4.4f;camera.cullingMask=1<<30;camera.clearFlags=CameraClearFlags.SolidColor;camera.backgroundColor=new Color(.09f,.13f,.17f);camera.depth=100;
var light=new GameObject("SkillSliceLight").AddComponent();light.transform.SetParent(root.transform,false);light.type=LightType.Directional;light.intensity=1.3f;light.transform.rotation=Quaternion.Euler(40,-35,0);light.cullingMask=1<<30;
var floor=GameObject.CreatePrimitive(PrimitiveType.Plane);floor.name="Ground_Y0";floor.transform.SetParent(root.transform,false);floor.transform.localScale=new Vector3(.6f,1,1);floor.transform.localPosition=new Vector3(0,-.005f,1);floor.GetComponent().sharedMaterial=AssetDatabase.LoadAssetAtPath("Assets/Bundles/Scenes/Review/EnemyReviewFloor.mat");Object.DestroyImmediate(floor.GetComponent());
var so=new SerializedObject(player);so.FindProperty("_trace").objectReferenceValue=trace;
var views=so.FindProperty("_views");views.arraySize=((JArray)data["initial"]).Count;
int index=0;
foreach(var u in (JArray)data["initial"])
{
int id=(int)u["id"];string actor=id==0?"RockBall":id==1?"FireCat":"Hornlet",kind=id<100?"Animal":"Enemy";
var slot=new GameObject("Entity"+id).transform;slot.SetParent(root.transform,false);slot.localPosition=new Vector3(0,0,(int)u["z"]/1000f);slot.localRotation=Quaternion.Euler(0,id<100?180:0,0);
string suffix=id<100?"Companion":"Enemy";var model=(GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath("Assets/Bundles/Characters/"+kind+"/"+actor+"Studio/"+actor+"Studio_"+suffix+".prefab"),slot);
model.transform.localScale=Vector3.one*((id<100?1.5f:1.2f)/Height(model.transform));
var muzzle=new GameObject("Muzzle").transform;muzzle.SetParent(slot,false);muzzle.localPosition=new Vector3(0,.8f,-.48f);
var label=new GameObject("State").AddComponent();label.transform.SetParent(slot,false);label.transform.localPosition=new Vector3(0,1.85f,0);label.transform.rotation=camera.transform.rotation;label.fontSize=60;label.characterSize=.032f;label.anchor=TextAnchor.MiddleCenter;label.color=Color.white;
string recipe="../Config/Art/"+(id==1?"Companions":"EnemyCharacters")+"/"+actor+".json";float impact=(float)JObject.Parse(File.ReadAllText(recipe))["attackImpact"];
var v=views.GetArrayElementAtIndex(index++);v.FindPropertyRelative("id").intValue=id;v.FindPropertyRelative("root").objectReferenceValue=slot;v.FindPropertyRelative("muzzle").objectReferenceValue=muzzle;v.FindPropertyRelative("label").objectReferenceValue=label;v.FindPropertyRelative("animator").objectReferenceValue=model.GetComponentInChildren();v.FindPropertyRelative("impact").floatValue=impact;
}
var ring=AssetDatabase.LoadAssetAtPath("Assets/Bundles/Effects/EnemyCombat/CombatRing.asset");
const string corePath=Folder+"/FireballCore.asset";var core=AssetDatabase.LoadAssetAtPath(corePath);
if(core==null){var sphere=GameObject.CreatePrimitive(PrimitiveType.Sphere);core=Object.Instantiate(sphere.GetComponent().sharedMesh);core.name="FireballCore";Object.DestroyImmediate(sphere);AssetDatabase.CreateAsset(core,corePath);}
var effects=so.FindProperty("_effects");effects.arraySize=5;
for(int i=0;i<5;i++)
{
bool loop=i==0||i==1||i==4;Color color=i==4?new Color(.35f,.85f,1):i==3?new Color(1,.78f,.35f):new Color(1,.28f,.025f);
var authored=Part(root.transform,"Vfx_Skill_"+Names[i],color,loop?12:14,i==4?.35f:i<2?.2f:.35f,i==4?2.3f:i==1?.45f:i==0?.25f:.15f,loop,i==4?ring:null);
if(i<4){var renderer=authored.GetComponent();renderer.renderMode=ParticleSystemRenderMode.Mesh;renderer.mesh=core;}
if(i==4){var main=authored.main;main.startColor=new Color(.35f,.85f,1,.22f);main.startSize=1.8f;main.startLifetime=.6f;var emission=authored.emission;emission.rateOverTime=4;}
if(i==2||i==3){var flash=Part(authored.transform,"ImpactRing",color,1,.25f,1.35f,false,ring);var size=flash.sizeOverLifetime;size.size=new ParticleSystem.MinMaxCurve(1,AnimationCurve.Linear(0,.3f,1,1.2f));}
if(i==1)Part(authored.transform,"BrightCore",new Color(1,.85f,.25f),20,.12f,.2f,true);
var asset=PrefabUtility.SaveAsPrefabAsset(authored.gameObject,Folder+"/Vfx_Skill_"+Names[i]+".prefab");Object.DestroyImmediate(authored.gameObject);
var instances=effects.GetArrayElementAtIndex(i).FindPropertyRelative("instances");instances.arraySize=i==1?8:4;
for(int n=0;n();}
}
var clips=so.FindProperty("_clips");clips.arraySize=5;
for(int i=0;i<5;i++)
{
string path="Assets/Bundles/Sound/SFX/BattleSkills/Sfx_"+SoundNames[i]+".wav";AssetDatabase.ImportAsset(path,ImportAssetOptions.ForceUpdate);var importer=(AudioImporter)AssetImporter.GetAtPath(path);if(importer==null)throw new Exception("Missing "+path);
var sample=importer.defaultSampleSettings;sample.loadType=AudioClipLoadType.DecompressOnLoad;sample.compressionFormat=AudioCompressionFormat.PCM;sample.sampleRateSetting=AudioSampleRateSetting.PreserveSampleRate;importer.defaultSampleSettings=sample;importer.forceToMono=false;importer.SaveAndReimport();clips.GetArrayElementAtIndex(i).objectReferenceValue=AssetDatabase.LoadAssetAtPath(path);
}
var voices=so.FindProperty("_voices");voices.arraySize=8;
for(int i=0;i<8;i++){var go=new GameObject("Voice"+i);go.transform.SetParent(root.transform,false);var voice=go.AddComponent();voice.playOnAwake=false;voice.spatialBlend=0;voice.volume=.7f/8;voices.GetArrayElementAtIndex(i).objectReferenceValue=voice;}
var feedback=(GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath("Assets/Bundles/Effects/EnemyCombat/EnemyCombatPresentation.prefab"),root.transform);so.FindProperty("_enemyFeedback").objectReferenceValue=feedback.GetComponent();
var status=new GameObject("TraceStatus").AddComponent();status.transform.SetParent(root.transform,false);status.transform.localPosition=new Vector3(0,.3f,-3.5f);status.transform.rotation=camera.transform.rotation;status.fontSize=60;status.characterSize=.04f;status.anchor=TextAnchor.MiddleCenter;status.color=new Color(.8f,.95f,1);so.FindProperty("_status").objectReferenceValue=status;
so.ApplyModifiedPropertiesWithoutUndo();foreach(var t in root.GetComponentsInChildren(true))t.gameObject.layer=30;
PrefabUtility.SaveAsPrefabAsset(root,Prefab);Object.DestroyImmediate(root);
PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath(Prefab),scene);EditorSceneManager.SaveScene(scene,Scene);AssetDatabase.SaveAssets();return "Saved independent "+Prefab+" and "+Scene;
}
finally{SceneManager.SetActiveScene(previous);EditorSceneManager.CloseScene(scene,true);}
}
}