Ability - Effect Editor window
This commit is contained in:
parent
f92d5d5866
commit
6ba55cb483
8
Assets/Scriptables/Data/Resources/Awakenings.meta
Normal file
8
Assets/Scriptables/Data/Resources/Awakenings.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e0c2df9140a6fce45a9576a1db3e0d43
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,44 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 03064a0d3f6200145b50c40e4cd12615, type: 3}
|
||||
m_Name: TestingAwakenings
|
||||
m_EditorClassIdentifier:
|
||||
data:
|
||||
Name:
|
||||
Description:
|
||||
CurrentPoints: 0
|
||||
MaxPoints: 1
|
||||
requiredAwakenings: []
|
||||
StrengthBonus: 0
|
||||
AgilityBonus: 0
|
||||
IntelligenceBonus: 0
|
||||
SpiritBonus: 0
|
||||
VitalityBonus: 0
|
||||
StrengthPercentBonus: 0
|
||||
AgilityPercentBonus: 0
|
||||
IntelligencePercentBonus: 0
|
||||
SpiritPercentBonus: 0
|
||||
VitalityPercentBonus: 0
|
||||
AttackDamageBonus: 0
|
||||
SpellDamageBonus: 0
|
||||
CritChanceBonus: 0
|
||||
CritDamageBonus: 0
|
||||
MaxHealthBonus: 0
|
||||
ArmorBonus: 0
|
||||
MagicResistanceBonus: 0
|
||||
AttackDamagePercentBonus: 0
|
||||
SpellDamagePercentBonus: 0
|
||||
CritChancePercentBonus: 0
|
||||
CritDamagePercentBonus: 0
|
||||
MaxHealthPercentBonus: 0
|
||||
ArmorPercentBonus: 0
|
||||
MagicResistancePercentBonus: 0
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bfc36a68112b4534c8eb33a78518ab6c
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/Scripts/AbilitySystem/AbilityData.meta
Normal file
8
Assets/Scripts/AbilitySystem/AbilityData.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 307841cd77271a8468c442f4a604e862
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
20
Assets/Scripts/AbilitySystem/AbilityData/BaseAbilityData.cs
Normal file
20
Assets/Scripts/AbilitySystem/AbilityData/BaseAbilityData.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
[System.Serializable]
|
||||
public class BaseAbilityData
|
||||
{
|
||||
public Sprite Icon;
|
||||
public List<TargetTag> targettingTags = new List<TargetTag>();
|
||||
public List<GameTag> tags = new List<GameTag>();
|
||||
public List<BaseEffect> abilityEffects = new List<BaseEffect>();
|
||||
[Space]
|
||||
public float castTime;
|
||||
public float manaCost;
|
||||
public float healthCost = 0;
|
||||
public float classResourceCost = 0;
|
||||
public float cooldown;
|
||||
public bool castableWhileMoving;
|
||||
public AbilityAnimationType animationType;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85e3596f5bd1bf44d8343b3f2b4cd7ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/Scripts/AbilitySystem/AbilityInstance.meta
Normal file
8
Assets/Scripts/AbilitySystem/AbilityInstance.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b2dc875bac316e49b4963b666aafd44
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
[System.Serializable]
|
||||
public class BaseAbilityInstance
|
||||
{
|
||||
public BaseAbilityData abilityData;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ecbc603708f7b784ab0a4bc2cce24156
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -93,8 +93,6 @@ public class InstantValueEffect : BaseEffect
|
||||
else if(stats.secondaryStatsDictionary.TryGetValue(statInfluence.statTag.name.ToLower(), out CharacterStat secondaryStat))
|
||||
{
|
||||
finalValue += secondaryStat.Value * statInfluence.percentInfluence;
|
||||
|
||||
|
||||
}
|
||||
if (statInfluence.statTag.name.ToLower().Contains("Attack")) damageType = DamageType.Attack;
|
||||
else if (statInfluence.statTag.name.ToLower().Contains("Spell")) damageType = DamageType.Spell;
|
||||
|
8
Assets/Scripts/AbilityTalentSystem.meta
Normal file
8
Assets/Scripts/AbilityTalentSystem.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3e9fe72bbbe46648920a316a683101f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
134
Assets/Scripts/AbilityTalentSystem/Awakening.cs
Normal file
134
Assets/Scripts/AbilityTalentSystem/Awakening.cs
Normal file
@ -0,0 +1,134 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
[CreateAssetMenu(fileName = "Awakening", menuName = "RiftMayhem/AwakeningSystem/Awakenings/new BaseAwakening", order = 0)]
|
||||
public class Awakening : ScriptableObject
|
||||
{
|
||||
public AwakeningData data;
|
||||
|
||||
public bool AllRequirementsMet(List<Awakening> unlockedAwakenings)
|
||||
{
|
||||
for (int i = 0; i < data.requiredAwakenings.Count; i++)
|
||||
{
|
||||
if (!unlockedAwakenings.Contains(data.requiredAwakenings[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class AwakeningInstance
|
||||
{
|
||||
public AwakeningData data;
|
||||
|
||||
public bool AllRequirementsMet(List<Awakening> unlockedAwakenings)
|
||||
{
|
||||
for (int i = 0; i < data.requiredAwakenings.Count; i++)
|
||||
{
|
||||
if (!unlockedAwakenings.Contains(data.requiredAwakenings[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class AwakeningData
|
||||
{
|
||||
public string Name;
|
||||
public string Description;
|
||||
public int CurrentPoints;
|
||||
public int MaxPoints;
|
||||
public List<Awakening> requiredAwakenings = new List<Awakening>();
|
||||
|
||||
[Space]
|
||||
public int StrengthBonus;
|
||||
public int AgilityBonus;
|
||||
public int IntelligenceBonus;
|
||||
public int SpiritBonus;
|
||||
public int VitalityBonus;
|
||||
[Space]
|
||||
public float StrengthPercentBonus;
|
||||
public float AgilityPercentBonus;
|
||||
public float IntelligencePercentBonus;
|
||||
public float SpiritPercentBonus;
|
||||
public float VitalityPercentBonus;
|
||||
[Space]
|
||||
public int AttackDamageBonus;
|
||||
public int SpellDamageBonus;
|
||||
public int CritChanceBonus;
|
||||
public int CritDamageBonus;
|
||||
public int MaxHealthBonus;
|
||||
public int ArmorBonus;
|
||||
public int MagicResistanceBonus;
|
||||
[Space]
|
||||
public float AttackDamagePercentBonus;
|
||||
public float SpellDamagePercentBonus;
|
||||
public float CritChancePercentBonus;
|
||||
public float CritDamagePercentBonus;
|
||||
public float MaxHealthPercentBonus;
|
||||
public float ArmorPercentBonus;
|
||||
public float MagicResistancePercentBonus;
|
||||
|
||||
public AwakeningData()
|
||||
{
|
||||
Name = "";
|
||||
Description = "";
|
||||
CurrentPoints = 0;
|
||||
MaxPoints = 1;
|
||||
requiredAwakenings = new List<Awakening>();
|
||||
}
|
||||
public AwakeningData(string name, string description)
|
||||
{
|
||||
Name = name;
|
||||
Description = description;
|
||||
CurrentPoints = 0;
|
||||
MaxPoints = 1;
|
||||
requiredAwakenings = new List<Awakening>();
|
||||
}
|
||||
public AwakeningData(string name, string description, int currentPoints, int totalPoints, List<Awakening> requirements)
|
||||
{
|
||||
Name = name;
|
||||
Description = description;
|
||||
CurrentPoints = currentPoints;
|
||||
MaxPoints = totalPoints;
|
||||
requiredAwakenings = requirements;
|
||||
}
|
||||
|
||||
public AwakeningData(AwakeningData data)
|
||||
{
|
||||
this.Name = data.Name;
|
||||
this.Description = data.Description;
|
||||
this.CurrentPoints = data.CurrentPoints;
|
||||
this.MaxPoints = data.MaxPoints;
|
||||
this.requiredAwakenings = data.requiredAwakenings;
|
||||
|
||||
this.StrengthBonus = data.StrengthBonus;
|
||||
this.AgilityBonus = data.AgilityBonus;
|
||||
this.IntelligenceBonus = data.IntelligenceBonus;
|
||||
this.SpiritBonus = data.SpiritBonus;
|
||||
this.VitalityBonus = data.VitalityBonus;
|
||||
|
||||
this.StrengthPercentBonus = data.StrengthPercentBonus;
|
||||
this.AgilityPercentBonus = data.AgilityPercentBonus;
|
||||
this.IntelligencePercentBonus = data.IntelligencePercentBonus;
|
||||
this.SpiritPercentBonus = data.SpiritPercentBonus;
|
||||
this.VitalityPercentBonus = data.VitalityPercentBonus;
|
||||
|
||||
this.AttackDamageBonus = data.AttackDamageBonus;
|
||||
this.SpellDamageBonus = data.SpellDamageBonus;
|
||||
this.CritChanceBonus = data.CritChanceBonus;
|
||||
this.CritDamageBonus = data.CritDamageBonus;
|
||||
this.MaxHealthBonus = data.MaxHealthBonus;
|
||||
this.ArmorBonus = data.ArmorBonus;
|
||||
this.MagicResistanceBonus = data.MagicResistanceBonus;
|
||||
|
||||
this.AttackDamagePercentBonus = data.AttackDamagePercentBonus;
|
||||
this.SpellDamagePercentBonus = data.SpellDamagePercentBonus;
|
||||
this.CritChancePercentBonus = data.CritChancePercentBonus;
|
||||
this.CritDamagePercentBonus = data.CritDamagePercentBonus;
|
||||
this.MaxHealthPercentBonus = data.MaxHealthPercentBonus;
|
||||
this.ArmorPercentBonus = data.ArmorPercentBonus;
|
||||
this.MagicResistancePercentBonus = data.MagicResistancePercentBonus;
|
||||
}
|
||||
}
|
11
Assets/Scripts/AbilityTalentSystem/Awakening.cs.meta
Normal file
11
Assets/Scripts/AbilityTalentSystem/Awakening.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03064a0d3f6200145b50c40e4cd12615
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/Scripts/AbilityTalentSystem/Awakenings.meta
Normal file
8
Assets/Scripts/AbilityTalentSystem/Awakenings.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bac7dcb65e711114fa3203ffde968f74
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,18 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class SpecificDamageIncreaseAwakening : MonoBehaviour
|
||||
{
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12323d49914f700448c37231a033bb2c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
9
Assets/Scripts/AbilityTalentSystem/ClassAwakenings.cs
Normal file
9
Assets/Scripts/AbilityTalentSystem/ClassAwakenings.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class ClassAwakenings
|
||||
{
|
||||
public List<Awakening> AllAvailableAwakenings = new List<Awakening>();
|
||||
|
||||
}
|
11
Assets/Scripts/AbilityTalentSystem/ClassAwakenings.cs.meta
Normal file
11
Assets/Scripts/AbilityTalentSystem/ClassAwakenings.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9485a30ee3b5f804d959e444e9d5130c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
34
Assets/Scripts/AbilityTalentSystem/PlayerAwakenings.cs
Normal file
34
Assets/Scripts/AbilityTalentSystem/PlayerAwakenings.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class PlayerAwakenings : MonoBehaviour
|
||||
{
|
||||
private List<BaseAbility> unlockedAbilities = new List<BaseAbility>();
|
||||
private List<Awakening> unlockedAwakenings = new List<Awakening>();
|
||||
|
||||
public void UnlockAbility(BaseAbility ability)
|
||||
{
|
||||
if (unlockedAbilities.Contains(ability)) return;
|
||||
|
||||
unlockedAbilities.Add(ability);
|
||||
}
|
||||
|
||||
public void UnlockAwakening(Awakening awakening)
|
||||
{
|
||||
if (unlockedAwakenings.Contains(awakening)) return;
|
||||
|
||||
if (!awakening.AllRequirementsMet(unlockedAwakenings)) return;
|
||||
|
||||
unlockedAwakenings.Add(awakening);
|
||||
}
|
||||
|
||||
public bool IsAbilityUnlocked(BaseAbility ability)
|
||||
{
|
||||
return unlockedAbilities.Contains(ability);
|
||||
}
|
||||
public bool IsAwakeningUnlocked(Awakening awakening)
|
||||
{
|
||||
return unlockedAwakenings.Contains(awakening);
|
||||
}
|
||||
}
|
11
Assets/Scripts/AbilityTalentSystem/PlayerAwakenings.cs.meta
Normal file
11
Assets/Scripts/AbilityTalentSystem/PlayerAwakenings.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a860d52346f7abb4fbc40f3477364ae9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
70
Assets/Scripts/Editor/ability-editor-core.cs
Normal file
70
Assets/Scripts/Editor/ability-editor-core.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
public partial class AbilityEditorWindow : EditorWindow
|
||||
{
|
||||
private Vector2 scrollPosition;
|
||||
private string searchQuery = "";
|
||||
private AbilityCreationData abilityData;
|
||||
private Type selectedAbilityType;
|
||||
private Dictionary<string, Type> abilityTypes;
|
||||
|
||||
[MenuItem("Tools/Ability Editor")]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
GetWindow<AbilityEditorWindow>("Ability Editor");
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
InitializeData();
|
||||
CacheAbilityTypes();
|
||||
}
|
||||
|
||||
private void InitializeData()
|
||||
{
|
||||
abilityData = new AbilityCreationData();
|
||||
}
|
||||
|
||||
private void CacheAbilityTypes()
|
||||
{
|
||||
// Cache all ability types that inherit from BaseAbility
|
||||
abilityTypes = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(assembly => assembly.GetTypes())
|
||||
.Where(type => type.IsClass && !type.IsAbstract && typeof(BaseAbility).IsAssignableFrom(type))
|
||||
.ToDictionary(type => type.Name, type => type);
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
DrawHeader();
|
||||
DrawSearchBar();
|
||||
|
||||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||||
|
||||
DrawAbilityCreation();
|
||||
EditorGUILayout.Space(20);
|
||||
DrawExistingAbilities();
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
private void DrawHeader()
|
||||
{
|
||||
EditorGUILayout.Space(10);
|
||||
GUILayout.Label("Ability Editor", EditorStyles.boldLabel);
|
||||
EditorGUILayout.Space(5);
|
||||
}
|
||||
|
||||
private void DrawSearchBar()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
searchQuery = EditorGUILayout.TextField("Search", searchQuery);
|
||||
if (GUILayout.Button("Clear", GUILayout.Width(50)))
|
||||
searchQuery = "";
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
11
Assets/Scripts/Editor/ability-editor-core.cs.meta
Normal file
11
Assets/Scripts/Editor/ability-editor-core.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75d10d37171d2d24d8d4069eba82bbe3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
133
Assets/Scripts/Editor/ability-editor-creation.cs
Normal file
133
Assets/Scripts/Editor/ability-editor-creation.cs
Normal file
@ -0,0 +1,133 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
public partial class AbilityEditorWindow
|
||||
{
|
||||
private void DrawAbilityCreation()
|
||||
{
|
||||
EditorGUILayout.BeginVertical("box");
|
||||
|
||||
EditorGUILayout.LabelField("Create New Ability", EditorStyles.boldLabel);
|
||||
DrawAbilityTypeSelection();
|
||||
|
||||
if (selectedAbilityType != null)
|
||||
{
|
||||
DrawBasicFields();
|
||||
DrawTypeSpecificFields();
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
if (GUILayout.Button("Create Ability"))
|
||||
{
|
||||
CreateAbility();
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void DrawAbilityTypeSelection()
|
||||
{
|
||||
EditorGUILayout.Space(10);
|
||||
EditorGUILayout.LabelField("Ability Type", EditorStyles.boldLabel);
|
||||
|
||||
string[] typeNames = abilityTypes.Keys.ToArray();
|
||||
int currentIndex = Array.IndexOf(typeNames, selectedAbilityType?.Name ?? "");
|
||||
int newIndex = EditorGUILayout.Popup("Select Type", currentIndex, typeNames);
|
||||
|
||||
if (newIndex != currentIndex && newIndex >= 0)
|
||||
{
|
||||
selectedAbilityType = abilityTypes[typeNames[newIndex]];
|
||||
abilityData.typeSpecificData.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBasicFields()
|
||||
{
|
||||
EditorGUILayout.Space(10);
|
||||
EditorGUILayout.LabelField("Basic Settings", EditorStyles.boldLabel);
|
||||
|
||||
abilityData.name = EditorGUILayout.TextField("Name", abilityData.name);
|
||||
abilityData.description = EditorGUILayout.TextArea(abilityData.description, GUILayout.Height(60));
|
||||
abilityData.icon = (Sprite)EditorGUILayout.ObjectField("Icon", abilityData.icon, typeof(Sprite), false);
|
||||
abilityData.animationType = (AbilityAnimationType)EditorGUILayout.EnumPopup("Animation Type", abilityData.animationType);
|
||||
|
||||
EditorGUILayout.Space(5);
|
||||
EditorGUILayout.LabelField("Costs and Timing", EditorStyles.boldLabel);
|
||||
abilityData.manaCost = EditorGUILayout.FloatField("Mana Cost", abilityData.manaCost);
|
||||
abilityData.healthCost = EditorGUILayout.FloatField("Health Cost", abilityData.healthCost);
|
||||
abilityData.cooldown = EditorGUILayout.FloatField("Cooldown", abilityData.cooldown);
|
||||
abilityData.castTime = EditorGUILayout.FloatField("Cast Time", abilityData.castTime);
|
||||
abilityData.castableWhileMoving = EditorGUILayout.Toggle("Castable While Moving", abilityData.castableWhileMoving);
|
||||
}
|
||||
|
||||
private void DrawTypeSpecificFields()
|
||||
{
|
||||
if (selectedAbilityType == null) return;
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
EditorGUILayout.LabelField("Type Specific Settings", EditorStyles.boldLabel);
|
||||
|
||||
if (selectedAbilityType == typeof(ProjectileAbility))
|
||||
{
|
||||
DrawProjectileFields();
|
||||
}
|
||||
else if (selectedAbilityType == typeof(AreaOfEffectAbility))
|
||||
{
|
||||
DrawAreaOfEffectFields();
|
||||
}
|
||||
else if (selectedAbilityType == typeof(ChanneledAbility))
|
||||
{
|
||||
DrawChanneledFields();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawProjectileFields()
|
||||
{
|
||||
float projectileSpeed = abilityData.GetOrCreateTypeSpecific<float>("projectileSpeed");
|
||||
projectileSpeed = EditorGUILayout.FloatField("Projectile Speed", projectileSpeed);
|
||||
abilityData.typeSpecificData["projectileSpeed"] = projectileSpeed;
|
||||
|
||||
float lifeSpan = abilityData.GetOrCreateTypeSpecific<float>("lifeSpan");
|
||||
lifeSpan = EditorGUILayout.FloatField("Life Span", lifeSpan);
|
||||
abilityData.typeSpecificData["lifeSpan"] = lifeSpan;
|
||||
|
||||
bool canPierce = abilityData.GetOrCreateTypeSpecific<bool>("canPierce");
|
||||
canPierce = EditorGUILayout.Toggle("Can Pierce", canPierce);
|
||||
abilityData.typeSpecificData["canPierce"] = canPierce;
|
||||
|
||||
GameObject projectilePrefab = abilityData.GetOrCreateTypeSpecific<GameObject>("projectilePrefab");
|
||||
projectilePrefab = (GameObject)EditorGUILayout.ObjectField("Projectile Prefab",
|
||||
projectilePrefab, typeof(GameObject), false);
|
||||
abilityData.typeSpecificData["projectilePrefab"] = projectilePrefab;
|
||||
}
|
||||
|
||||
private void DrawAreaOfEffectFields()
|
||||
{
|
||||
float radius = abilityData.GetOrCreateTypeSpecific<float>("radius");
|
||||
radius = EditorGUILayout.FloatField("Radius", radius);
|
||||
abilityData.typeSpecificData["radius"] = radius;
|
||||
|
||||
float duration = abilityData.GetOrCreateTypeSpecific<float>("duration");
|
||||
duration = EditorGUILayout.FloatField("Duration", duration);
|
||||
abilityData.typeSpecificData["duration"] = duration;
|
||||
|
||||
GameObject aoePrefab = abilityData.GetOrCreateTypeSpecific<GameObject>("aoePrefab");
|
||||
aoePrefab = (GameObject)EditorGUILayout.ObjectField("AoE Prefab",
|
||||
aoePrefab, typeof(GameObject), false);
|
||||
abilityData.typeSpecificData["aoePrefab"] = aoePrefab;
|
||||
}
|
||||
|
||||
private void DrawChanneledFields()
|
||||
{
|
||||
float channelDuration = abilityData.GetOrCreateTypeSpecific<float>("channelDuration");
|
||||
channelDuration = EditorGUILayout.FloatField("Channel Duration", channelDuration);
|
||||
abilityData.typeSpecificData["channelDuration"] = channelDuration;
|
||||
|
||||
bool canMove = abilityData.GetOrCreateTypeSpecific<bool>("canMove");
|
||||
canMove = EditorGUILayout.Toggle("Can Move While Channeling", canMove);
|
||||
abilityData.typeSpecificData["canMove"] = canMove;
|
||||
}
|
||||
}
|
11
Assets/Scripts/Editor/ability-editor-creation.cs.meta
Normal file
11
Assets/Scripts/Editor/ability-editor-creation.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86bffbad8290be14f98db3d5ac63a370
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
58
Assets/Scripts/Editor/ability-editor-data.cs
Normal file
58
Assets/Scripts/Editor/ability-editor-data.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[System.Serializable]
|
||||
public class AbilityCreationData
|
||||
{
|
||||
public string name;
|
||||
public string description;
|
||||
public Sprite icon;
|
||||
public AbilityAnimationType animationType;
|
||||
public float manaCost;
|
||||
public float healthCost;
|
||||
public float cooldown;
|
||||
public float castTime;
|
||||
public bool castableWhileMoving;
|
||||
public SerializedDictionary<string, object> typeSpecificData = new SerializedDictionary<string, object>();
|
||||
|
||||
public T GetOrCreateTypeSpecific<T>(string key)
|
||||
{
|
||||
if (!typeSpecificData.ContainsKey(key))
|
||||
{
|
||||
typeSpecificData[key] = default(T);
|
||||
}
|
||||
return (T)typeSpecificData[key];
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class SerializedDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
|
||||
{
|
||||
[SerializeField]
|
||||
private List<TKey> keys = new List<TKey>();
|
||||
|
||||
[SerializeField]
|
||||
private List<TValue> values = new List<TValue>();
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
keys.Clear();
|
||||
values.Clear();
|
||||
foreach(KeyValuePair<TKey, TValue> pair in this)
|
||||
{
|
||||
keys.Add(pair.Key);
|
||||
values.Add(pair.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
this.Clear();
|
||||
|
||||
if(keys.Count != values.Count)
|
||||
throw new System.Exception($"There are {keys.Count} keys and {values.Count} values after deserialization. Make sure that both key and value types are serializable.");
|
||||
|
||||
for(int i = 0; i < keys.Count; i++)
|
||||
this.Add(keys[i], values[i]);
|
||||
}
|
||||
}
|
11
Assets/Scripts/Editor/ability-editor-data.cs.meta
Normal file
11
Assets/Scripts/Editor/ability-editor-data.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36c5f08218aeb2c44b191463947d6160
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
149
Assets/Scripts/Editor/ability-editor-existing.cs
Normal file
149
Assets/Scripts/Editor/ability-editor-existing.cs
Normal file
@ -0,0 +1,149 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
public partial class AbilityEditorWindow
|
||||
{
|
||||
private void DrawExistingAbilities()
|
||||
{
|
||||
EditorGUILayout.LabelField("Existing Abilities", EditorStyles.boldLabel);
|
||||
|
||||
var abilities = GetAllAbilities();
|
||||
foreach (var ability in abilities)
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchQuery) || ability.name.ToLower().Contains(searchQuery.ToLower()))
|
||||
{
|
||||
EditorGUILayout.BeginVertical("box");
|
||||
DrawAbilityItem(ability);
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawAbilityItem(BaseAbility ability)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
if (ability.Icon != null)
|
||||
{
|
||||
GUILayout.Label(AssetPreview.GetAssetPreview(ability.Icon), GUILayout.Width(40), GUILayout.Height(40));
|
||||
}
|
||||
|
||||
EditorGUILayout.BeginVertical();
|
||||
EditorGUILayout.LabelField(ability.name, EditorStyles.boldLabel);
|
||||
EditorGUILayout.LabelField($"Type: {ability.GetType().Name}");
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (GUILayout.Button("Clone", GUILayout.Width(50)))
|
||||
{
|
||||
CloneAbility(ability);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Edit", GUILayout.Width(50)))
|
||||
{
|
||||
Selection.activeObject = ability;
|
||||
EditorUtility.FocusProjectWindow();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private void CloneAbility(BaseAbility sourceAbility)
|
||||
{
|
||||
string newName = $"{sourceAbility.name}_Clone";
|
||||
string path = EditorUtility.SaveFilePanelInProject(
|
||||
"Save Cloned Ability",
|
||||
newName,
|
||||
"asset",
|
||||
"Save cloned ability asset"
|
||||
);
|
||||
|
||||
if (string.IsNullOrEmpty(path)) return;
|
||||
|
||||
BaseAbility newAbility = (BaseAbility)CreateInstance(sourceAbility.GetType());
|
||||
EditorUtility.CopySerialized(sourceAbility, newAbility);
|
||||
newAbility.name = newName;
|
||||
|
||||
AssetDatabase.CreateAsset(newAbility, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = newAbility;
|
||||
}
|
||||
|
||||
private void CreateAbility()
|
||||
{
|
||||
if (selectedAbilityType == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Please select an ability type!", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(abilityData.name))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Ability name cannot be empty!", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
BaseAbility ability = (BaseAbility)CreateInstance(selectedAbilityType);
|
||||
ability.name = abilityData.name;
|
||||
ability.Icon = abilityData.icon;
|
||||
ability.animationType = abilityData.animationType;
|
||||
ability.manaCost = abilityData.manaCost;
|
||||
ability.healthCost = abilityData.healthCost;
|
||||
ability.cooldown = abilityData.cooldown;
|
||||
ability.castTime = abilityData.castTime;
|
||||
ability.castableWhileMoving = abilityData.castableWhileMoving;
|
||||
|
||||
ApplyTypeSpecificData(ability);
|
||||
|
||||
string path = EditorUtility.SaveFilePanelInProject(
|
||||
"Save Ability",
|
||||
abilityData.name,
|
||||
"asset",
|
||||
"Save ability asset"
|
||||
);
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
AssetDatabase.CreateAsset(ability, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = ability;
|
||||
abilityData = new AbilityCreationData();
|
||||
selectedAbilityType = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyTypeSpecificData(BaseAbility ability)
|
||||
{
|
||||
if (ability is ProjectileAbility projectileAbility)
|
||||
{
|
||||
projectileAbility.projectileSpeed = abilityData.GetOrCreateTypeSpecific<float>("projectileSpeed");
|
||||
projectileAbility.lifeSpan = abilityData.GetOrCreateTypeSpecific<float>("lifeSpan");
|
||||
projectileAbility.canPierce = abilityData.GetOrCreateTypeSpecific<bool>("canPierce");
|
||||
projectileAbility.projectilePrefab = abilityData.GetOrCreateTypeSpecific<GameObject>("projectilePrefab");
|
||||
}
|
||||
else if (ability is AreaOfEffectAbility aoeAbility)
|
||||
{
|
||||
aoeAbility.radius = abilityData.GetOrCreateTypeSpecific<float>("radius");
|
||||
aoeAbility.lifeSpan = abilityData.GetOrCreateTypeSpecific<float>("duration");
|
||||
aoeAbility.aoePrefab = abilityData.GetOrCreateTypeSpecific<GameObject>("aoePrefab");
|
||||
}
|
||||
else if (ability is ChanneledAbility channeledAbility)
|
||||
{
|
||||
channeledAbility.duration = abilityData.GetOrCreateTypeSpecific<float>("channelDuration");
|
||||
channeledAbility.castableWhileMoving = abilityData.GetOrCreateTypeSpecific<bool>("canMove");
|
||||
}
|
||||
}
|
||||
|
||||
private BaseAbility[] GetAllAbilities()
|
||||
{
|
||||
return AssetDatabase.FindAssets("t:BaseAbility")
|
||||
.Select(guid => AssetDatabase.LoadAssetAtPath<BaseAbility>(AssetDatabase.GUIDToAssetPath(guid)))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
11
Assets/Scripts/Editor/ability-editor-existing.cs.meta
Normal file
11
Assets/Scripts/Editor/ability-editor-existing.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a19e286df3408fa4f9e2f82a2d93d2b4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
420
Assets/Scripts/Editor/ability-effect-editor.cs
Normal file
420
Assets/Scripts/Editor/ability-effect-editor.cs
Normal file
@ -0,0 +1,420 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
public partial class AbilityEffectEditorWindow : EditorWindow
|
||||
{
|
||||
private Vector2 scrollPosition;
|
||||
private string searchQuery = "";
|
||||
private AbilityCreationData abilityData;
|
||||
private EffectCreationData effectData;
|
||||
private Type selectedAbilityType;
|
||||
private Type selectedEffectType;
|
||||
private Dictionary<string, Type> abilityTypes;
|
||||
private Dictionary<string, Type> effectTypes;
|
||||
|
||||
// Tabs
|
||||
private int selectedTab = 0;
|
||||
private readonly string[] tabNames = { "Abilities", "Effects" };
|
||||
|
||||
[MenuItem("Tools/Ability & Effect Editor")]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
GetWindow<AbilityEffectEditorWindow>("Ability & Effect Editor");
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
InitializeData();
|
||||
CacheTypes();
|
||||
}
|
||||
|
||||
private void InitializeData()
|
||||
{
|
||||
abilityData = new AbilityCreationData();
|
||||
effectData = new EffectCreationData();
|
||||
}
|
||||
|
||||
private void CacheTypes()
|
||||
{
|
||||
// Cache ability types
|
||||
abilityTypes = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(assembly => assembly.GetTypes())
|
||||
.Where(type => type.IsClass && !type.IsAbstract && typeof(BaseAbility).IsAssignableFrom(type))
|
||||
.ToDictionary(type => type.Name, type => type);
|
||||
|
||||
// Cache effect types
|
||||
effectTypes = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(assembly => assembly.GetTypes())
|
||||
.Where(type => type.IsClass && !type.IsAbstract && typeof(BaseEffect).IsAssignableFrom(type))
|
||||
.ToDictionary(type => type.Name, type => type);
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
DrawHeader();
|
||||
DrawSearchBar();
|
||||
|
||||
selectedTab = GUILayout.Toolbar(selectedTab, tabNames);
|
||||
|
||||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||||
|
||||
switch (selectedTab)
|
||||
{
|
||||
case 0: // Abilities Tab
|
||||
DrawAbilityCreation();
|
||||
EditorGUILayout.Space(20);
|
||||
DrawExistingAbilities();
|
||||
break;
|
||||
|
||||
case 1: // Effects Tab
|
||||
DrawEffectCreation();
|
||||
EditorGUILayout.Space(20);
|
||||
DrawExistingEffects();
|
||||
break;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
private void DrawHeader()
|
||||
{
|
||||
EditorGUILayout.Space(10);
|
||||
GUILayout.Label("Ability Effect Editor", EditorStyles.boldLabel);
|
||||
EditorGUILayout.Space(5);
|
||||
}
|
||||
private void DrawAbilityCreation()
|
||||
{
|
||||
EditorGUILayout.BeginVertical("box");
|
||||
|
||||
EditorGUILayout.LabelField("Create New Ability", EditorStyles.boldLabel);
|
||||
DrawAbilityTypeSelection();
|
||||
|
||||
if (selectedAbilityType != null)
|
||||
{
|
||||
DrawBasicFields();
|
||||
DrawTypeSpecificFields();
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
if (GUILayout.Button("Create Ability"))
|
||||
{
|
||||
CreateAbility();
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
private void DrawBasicFields()
|
||||
{
|
||||
EditorGUILayout.Space(10);
|
||||
EditorGUILayout.LabelField("Basic Settings", EditorStyles.boldLabel);
|
||||
|
||||
abilityData.name = EditorGUILayout.TextField("Name", abilityData.name);
|
||||
abilityData.description = EditorGUILayout.TextArea(abilityData.description, GUILayout.Height(60));
|
||||
abilityData.icon = (Sprite)EditorGUILayout.ObjectField("Icon", abilityData.icon, typeof(Sprite), false);
|
||||
abilityData.animationType = (AbilityAnimationType)EditorGUILayout.EnumPopup("Animation Type", abilityData.animationType);
|
||||
|
||||
EditorGUILayout.Space(5);
|
||||
EditorGUILayout.LabelField("Costs and Timing", EditorStyles.boldLabel);
|
||||
abilityData.manaCost = EditorGUILayout.FloatField("Mana Cost", abilityData.manaCost);
|
||||
abilityData.healthCost = EditorGUILayout.FloatField("Health Cost", abilityData.healthCost);
|
||||
abilityData.cooldown = EditorGUILayout.FloatField("Cooldown", abilityData.cooldown);
|
||||
abilityData.castTime = EditorGUILayout.FloatField("Cast Time", abilityData.castTime);
|
||||
abilityData.castableWhileMoving = EditorGUILayout.Toggle("Castable While Moving", abilityData.castableWhileMoving);
|
||||
}
|
||||
|
||||
private void DrawTypeSpecificFields()
|
||||
{
|
||||
if (selectedAbilityType == null) return;
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
EditorGUILayout.LabelField("Type Specific Settings", EditorStyles.boldLabel);
|
||||
|
||||
if (selectedAbilityType == typeof(ProjectileAbility))
|
||||
{
|
||||
DrawProjectileFields();
|
||||
}
|
||||
else if (selectedAbilityType == typeof(AreaOfEffectAbility))
|
||||
{
|
||||
DrawAreaOfEffectFields();
|
||||
}
|
||||
else if (selectedAbilityType == typeof(ChanneledAbility))
|
||||
{
|
||||
DrawChanneledFields();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawProjectileFields()
|
||||
{
|
||||
float projectileSpeed = abilityData.GetOrCreateTypeSpecific<float>("projectileSpeed");
|
||||
projectileSpeed = EditorGUILayout.FloatField("Projectile Speed", projectileSpeed);
|
||||
abilityData.typeSpecificData["projectileSpeed"] = projectileSpeed;
|
||||
|
||||
float lifeSpan = abilityData.GetOrCreateTypeSpecific<float>("lifeSpan");
|
||||
lifeSpan = EditorGUILayout.FloatField("Life Span", lifeSpan);
|
||||
abilityData.typeSpecificData["lifeSpan"] = lifeSpan;
|
||||
|
||||
bool canPierce = abilityData.GetOrCreateTypeSpecific<bool>("canPierce");
|
||||
canPierce = EditorGUILayout.Toggle("Can Pierce", canPierce);
|
||||
abilityData.typeSpecificData["canPierce"] = canPierce;
|
||||
|
||||
GameObject projectilePrefab = abilityData.GetOrCreateTypeSpecific<GameObject>("projectilePrefab");
|
||||
projectilePrefab = (GameObject)EditorGUILayout.ObjectField("Projectile Prefab",
|
||||
projectilePrefab, typeof(GameObject), false);
|
||||
abilityData.typeSpecificData["projectilePrefab"] = projectilePrefab;
|
||||
}
|
||||
|
||||
private void DrawAreaOfEffectFields()
|
||||
{
|
||||
float radius = abilityData.GetOrCreateTypeSpecific<float>("radius");
|
||||
radius = EditorGUILayout.FloatField("Radius", radius);
|
||||
abilityData.typeSpecificData["radius"] = radius;
|
||||
|
||||
float duration = abilityData.GetOrCreateTypeSpecific<float>("duration");
|
||||
duration = EditorGUILayout.FloatField("Duration", duration);
|
||||
abilityData.typeSpecificData["duration"] = duration;
|
||||
|
||||
GameObject aoePrefab = abilityData.GetOrCreateTypeSpecific<GameObject>("aoePrefab");
|
||||
aoePrefab = (GameObject)EditorGUILayout.ObjectField("AoE Prefab",
|
||||
aoePrefab, typeof(GameObject), false);
|
||||
abilityData.typeSpecificData["aoePrefab"] = aoePrefab;
|
||||
}
|
||||
|
||||
private void DrawChanneledFields()
|
||||
{
|
||||
float channelDuration = abilityData.GetOrCreateTypeSpecific<float>("channelDuration");
|
||||
channelDuration = EditorGUILayout.FloatField("Channel Duration", channelDuration);
|
||||
abilityData.typeSpecificData["channelDuration"] = channelDuration;
|
||||
|
||||
bool canMove = abilityData.GetOrCreateTypeSpecific<bool>("canMove");
|
||||
canMove = EditorGUILayout.Toggle("Can Move While Channeling", canMove);
|
||||
abilityData.typeSpecificData["canMove"] = canMove;
|
||||
}
|
||||
|
||||
private void CreateAbility()
|
||||
{
|
||||
if (selectedAbilityType == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Please select an ability type!", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(abilityData.name))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Ability name cannot be empty!", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
BaseAbility ability = (BaseAbility)CreateInstance(selectedAbilityType);
|
||||
ability.name = abilityData.name;
|
||||
ability.Icon = abilityData.icon;
|
||||
ability.animationType = abilityData.animationType;
|
||||
ability.manaCost = abilityData.manaCost;
|
||||
ability.healthCost = abilityData.healthCost;
|
||||
ability.cooldown = abilityData.cooldown;
|
||||
ability.castTime = abilityData.castTime;
|
||||
ability.castableWhileMoving = abilityData.castableWhileMoving;
|
||||
|
||||
ApplyTypeSpecificData(ability);
|
||||
|
||||
string path = EditorUtility.SaveFilePanelInProject(
|
||||
"Save Ability",
|
||||
abilityData.name,
|
||||
"asset",
|
||||
"Save ability asset"
|
||||
);
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
AssetDatabase.CreateAsset(ability, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = ability;
|
||||
abilityData = new AbilityCreationData();
|
||||
selectedAbilityType = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyTypeSpecificData(BaseAbility ability)
|
||||
{
|
||||
if (ability is ProjectileAbility projectileAbility)
|
||||
{
|
||||
projectileAbility.projectileSpeed = abilityData.GetOrCreateTypeSpecific<float>("projectileSpeed");
|
||||
projectileAbility.lifeSpan = abilityData.GetOrCreateTypeSpecific<float>("lifeSpan");
|
||||
projectileAbility.canPierce = abilityData.GetOrCreateTypeSpecific<bool>("canPierce");
|
||||
projectileAbility.projectilePrefab = abilityData.GetOrCreateTypeSpecific<GameObject>("projectilePrefab");
|
||||
}
|
||||
else if (ability is AreaOfEffectAbility aoeAbility)
|
||||
{
|
||||
aoeAbility.radius = abilityData.GetOrCreateTypeSpecific<float>("radius");
|
||||
aoeAbility.lifeSpan = abilityData.GetOrCreateTypeSpecific<float>("duration");
|
||||
aoeAbility.aoePrefab = abilityData.GetOrCreateTypeSpecific<GameObject>("aoePrefab");
|
||||
}
|
||||
else if (ability is ChanneledAbility channeledAbility)
|
||||
{
|
||||
channeledAbility.duration = abilityData.GetOrCreateTypeSpecific<float>("channelDuration");
|
||||
channeledAbility.castableWhileMoving = abilityData.GetOrCreateTypeSpecific<bool>("canMove");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawAbilityTypeSelection()
|
||||
{
|
||||
EditorGUILayout.Space(10);
|
||||
EditorGUILayout.LabelField("Ability Type", EditorStyles.boldLabel);
|
||||
|
||||
string[] typeNames = abilityTypes.Keys.ToArray();
|
||||
int currentIndex = Array.IndexOf(typeNames, selectedAbilityType?.Name ?? "");
|
||||
int newIndex = EditorGUILayout.Popup("Select Type", currentIndex, typeNames);
|
||||
|
||||
if (newIndex != currentIndex && newIndex >= 0)
|
||||
{
|
||||
selectedAbilityType = abilityTypes[typeNames[newIndex]];
|
||||
abilityData.typeSpecificData.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawAbilityItem(BaseAbility ability)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
if (ability.Icon != null)
|
||||
{
|
||||
GUILayout.Label(AssetPreview.GetAssetPreview(ability.Icon), GUILayout.Width(40), GUILayout.Height(40));
|
||||
}
|
||||
|
||||
EditorGUILayout.BeginVertical();
|
||||
EditorGUILayout.LabelField(ability.name, EditorStyles.boldLabel);
|
||||
EditorGUILayout.LabelField($"Type: {ability.GetType().Name}");
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (GUILayout.Button("Clone", GUILayout.Width(50)))
|
||||
{
|
||||
CloneAbility(ability);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Edit", GUILayout.Width(50)))
|
||||
{
|
||||
Selection.activeObject = ability;
|
||||
EditorUtility.FocusProjectWindow();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
private void CloneAbility(BaseAbility sourceAbility)
|
||||
{
|
||||
string newName = $"{sourceAbility.name}_Clone";
|
||||
string path = EditorUtility.SaveFilePanelInProject(
|
||||
"Save Cloned Ability",
|
||||
newName,
|
||||
"asset",
|
||||
"Save cloned ability asset"
|
||||
);
|
||||
|
||||
if (string.IsNullOrEmpty(path)) return;
|
||||
|
||||
BaseAbility newAbility = (BaseAbility)CreateInstance(sourceAbility.GetType());
|
||||
EditorUtility.CopySerialized(sourceAbility, newAbility);
|
||||
newAbility.name = newName;
|
||||
|
||||
AssetDatabase.CreateAsset(newAbility, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = newAbility;
|
||||
}
|
||||
|
||||
private void DrawExistingAbilities()
|
||||
{
|
||||
EditorGUILayout.LabelField("Existing Abilities", EditorStyles.boldLabel);
|
||||
|
||||
var abilities = GetAllAbilities();
|
||||
foreach (var ability in abilities)
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchQuery) || ability.name.ToLower().Contains(searchQuery.ToLower()))
|
||||
{
|
||||
EditorGUILayout.BeginVertical("box");
|
||||
DrawAbilityItem(ability);
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BaseAbility[] GetAllAbilities()
|
||||
{
|
||||
return AssetDatabase.FindAssets("t:BaseAbility")
|
||||
.Select(guid => AssetDatabase.LoadAssetAtPath<BaseAbility>(AssetDatabase.GUIDToAssetPath(guid)))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private void DrawSearchBar()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
searchQuery = EditorGUILayout.TextField("Search", searchQuery);
|
||||
if (GUILayout.Button("Clear", GUILayout.Width(50)))
|
||||
searchQuery = "";
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private void DrawEffectListForAbility(List<BaseEffect> effects)
|
||||
{
|
||||
EditorGUILayout.BeginVertical("box");
|
||||
EditorGUILayout.LabelField("Effects", EditorStyles.boldLabel);
|
||||
|
||||
for (int i = 0; i < effects.Count; i++)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
effects[i] = (BaseEffect)EditorGUILayout.ObjectField(effects[i], typeof(BaseEffect), false);
|
||||
|
||||
if (GUILayout.Button("Remove", GUILayout.Width(60)))
|
||||
{
|
||||
effects.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (GUILayout.Button("Add Effect"))
|
||||
{
|
||||
effects.Add(null);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Create New Effect"))
|
||||
{
|
||||
selectedTab = 1; // Switch to Effects tab
|
||||
effectData = new EffectCreationData();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
public class EffectCreationData
|
||||
{
|
||||
public string name;
|
||||
public string description;
|
||||
public float duration;
|
||||
public bool applyToTargetsHit = true;
|
||||
public bool applyToSelf;
|
||||
public List<GameTag> tags = new List<GameTag>();
|
||||
public List<StatInfluence> statInfluences = new List<StatInfluence>();
|
||||
public SerializedDictionary<string, object> typeSpecificData = new SerializedDictionary<string, object>();
|
||||
|
||||
public T GetOrCreateTypeSpecific<T>(string key)
|
||||
{
|
||||
if (!typeSpecificData.ContainsKey(key))
|
||||
{
|
||||
if (typeof(T) == typeof(List<StatInfluence>))
|
||||
typeSpecificData[key] = new List<StatInfluence>();
|
||||
else
|
||||
typeSpecificData[key] = default(T);
|
||||
}
|
||||
return (T)typeSpecificData[key];
|
||||
}
|
||||
}
|
11
Assets/Scripts/Editor/ability-effect-editor.cs.meta
Normal file
11
Assets/Scripts/Editor/ability-effect-editor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55d583c683871fd47ad6807ca5ce8edd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
177
Assets/Scripts/Editor/effect-editor-creation.cs
Normal file
177
Assets/Scripts/Editor/effect-editor-creation.cs
Normal file
@ -0,0 +1,177 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
public partial class AbilityEffectEditorWindow
|
||||
{
|
||||
private void DrawEffectCreation()
|
||||
{
|
||||
EditorGUILayout.BeginVertical("box");
|
||||
|
||||
EditorGUILayout.LabelField("Create New Effect", EditorStyles.boldLabel);
|
||||
DrawEffectTypeSelection();
|
||||
|
||||
if (selectedEffectType != null)
|
||||
{
|
||||
DrawEffectBasicFields();
|
||||
DrawEffectTypeSpecificFields();
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
if (GUILayout.Button("Create Effect"))
|
||||
{
|
||||
CreateEffect();
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void DrawEffectTypeSelection()
|
||||
{
|
||||
EditorGUILayout.Space(10);
|
||||
EditorGUILayout.LabelField("Effect Type", EditorStyles.boldLabel);
|
||||
|
||||
string[] typeNames = effectTypes.Keys.ToArray();
|
||||
int currentIndex = Array.IndexOf(typeNames, selectedEffectType?.Name ?? "");
|
||||
int newIndex = EditorGUILayout.Popup("Select Type", currentIndex, typeNames);
|
||||
|
||||
if (newIndex != currentIndex && newIndex >= 0)
|
||||
{
|
||||
selectedEffectType = effectTypes[typeNames[newIndex]];
|
||||
effectData.typeSpecificData.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEffectBasicFields()
|
||||
{
|
||||
EditorGUILayout.Space(10);
|
||||
EditorGUILayout.LabelField("Basic Settings", EditorStyles.boldLabel);
|
||||
|
||||
effectData.name = EditorGUILayout.TextField("Name", effectData.name);
|
||||
effectData.description = EditorGUILayout.TextArea(effectData.description, GUILayout.Height(60));
|
||||
|
||||
EditorGUILayout.Space(5);
|
||||
EditorGUILayout.LabelField("Target Settings", EditorStyles.boldLabel);
|
||||
effectData.applyToTargetsHit = EditorGUILayout.Toggle("Apply To Targets Hit", effectData.applyToTargetsHit);
|
||||
effectData.applyToSelf = EditorGUILayout.Toggle("Apply To Self", effectData.applyToSelf);
|
||||
|
||||
EditorGUILayout.Space(5);
|
||||
EditorGUILayout.LabelField("Duration Settings", EditorStyles.boldLabel);
|
||||
effectData.duration = EditorGUILayout.FloatField("Duration", effectData.duration);
|
||||
|
||||
// Draw tags
|
||||
EditorGUILayout.Space(5);
|
||||
EditorGUILayout.LabelField("Tags", EditorStyles.boldLabel);
|
||||
DrawTagsList(effectData.tags);
|
||||
}
|
||||
|
||||
private void DrawTagsList(List<GameTag> tags)
|
||||
{
|
||||
for (int i = 0; i < tags.Count; i++)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
tags[i] = (GameTag)EditorGUILayout.ObjectField(tags[i], typeof(GameTag), false);
|
||||
|
||||
if (GUILayout.Button("Remove", GUILayout.Width(60)))
|
||||
{
|
||||
tags.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Add Tag"))
|
||||
{
|
||||
tags.Add(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEffectTypeSpecificFields()
|
||||
{
|
||||
if (selectedEffectType == null) return;
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
EditorGUILayout.LabelField("Type Specific Settings", EditorStyles.boldLabel);
|
||||
|
||||
if (selectedEffectType == typeof(InstantValueEffect))
|
||||
{
|
||||
DrawInstantValueEffectFields();
|
||||
}
|
||||
else if (selectedEffectType == typeof(DamageOverTimeEffect))
|
||||
{
|
||||
DrawDamageOverTimeEffectFields();
|
||||
}
|
||||
else if (selectedEffectType == typeof(StatusEffect))
|
||||
{
|
||||
DrawStatusEffectFields();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawInstantValueEffectFields()
|
||||
{
|
||||
float baseValue = effectData.GetOrCreateTypeSpecific<float>("baseValue");
|
||||
baseValue = EditorGUILayout.FloatField("Base Value", baseValue);
|
||||
effectData.typeSpecificData["baseValue"] = baseValue;
|
||||
|
||||
DamageType damageType = effectData.GetOrCreateTypeSpecific<DamageType>("damageType");
|
||||
damageType = (DamageType)EditorGUILayout.EnumPopup("Damage Type", damageType);
|
||||
effectData.typeSpecificData["damageType"] = damageType;
|
||||
|
||||
float alliedMultiplier = effectData.GetOrCreateTypeSpecific<float>("alliedMultiplier");
|
||||
alliedMultiplier = EditorGUILayout.FloatField("Allied Target Multiplier", alliedMultiplier);
|
||||
effectData.typeSpecificData["alliedMultiplier"] = alliedMultiplier;
|
||||
|
||||
float enemyMultiplier = effectData.GetOrCreateTypeSpecific<float>("enemyMultiplier");
|
||||
enemyMultiplier = EditorGUILayout.FloatField("Enemy Target Multiplier", enemyMultiplier);
|
||||
effectData.typeSpecificData["enemyMultiplier"] = enemyMultiplier;
|
||||
}
|
||||
|
||||
private void DrawDamageOverTimeEffectFields()
|
||||
{
|
||||
float damagePerTick = effectData.GetOrCreateTypeSpecific<float>("damagePerTick");
|
||||
damagePerTick = EditorGUILayout.FloatField("Damage Per Tick", damagePerTick);
|
||||
effectData.typeSpecificData["damagePerTick"] = damagePerTick;
|
||||
|
||||
float tickRate = effectData.GetOrCreateTypeSpecific<float>("tickRate");
|
||||
tickRate = EditorGUILayout.FloatField("Tick Rate", tickRate);
|
||||
effectData.typeSpecificData["tickRate"] = tickRate;
|
||||
|
||||
DamageOverTimeType dotType = effectData.GetOrCreateTypeSpecific<DamageOverTimeType>("dotType");
|
||||
dotType = (DamageOverTimeType)EditorGUILayout.EnumPopup("DoT Type", dotType);
|
||||
effectData.typeSpecificData["dotType"] = dotType;
|
||||
}
|
||||
|
||||
private void DrawStatusEffectFields()
|
||||
{
|
||||
EditorGUILayout.LabelField("Stat Influences", EditorStyles.boldLabel);
|
||||
DrawStatInfluencesList(effectData.GetOrCreateTypeSpecific<List<StatInfluence>>("statInfluences"));
|
||||
}
|
||||
|
||||
private void DrawStatInfluencesList(List<StatInfluence> influences)
|
||||
{
|
||||
for (int i = 0; i < influences.Count; i++)
|
||||
{
|
||||
EditorGUILayout.BeginVertical("box");
|
||||
|
||||
influences[i].statTag = (GameTag)EditorGUILayout.ObjectField("Stat Tag",
|
||||
influences[i].statTag, typeof(GameTag), false);
|
||||
influences[i].percentInfluence = EditorGUILayout.FloatField("Percent Influence",
|
||||
influences[i].percentInfluence);
|
||||
|
||||
if (GUILayout.Button("Remove Influence"))
|
||||
{
|
||||
influences.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Add Stat Influence"))
|
||||
{
|
||||
influences.Add(new StatInfluence());
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/Editor/effect-editor-creation.cs.meta
Normal file
11
Assets/Scripts/Editor/effect-editor-creation.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c4d5e56b5f398a45923b42f9b343627
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
143
Assets/Scripts/Editor/effect-editor-existing.cs
Normal file
143
Assets/Scripts/Editor/effect-editor-existing.cs
Normal file
@ -0,0 +1,143 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
public partial class AbilityEffectEditorWindow
|
||||
{
|
||||
private void DrawExistingEffects()
|
||||
{
|
||||
EditorGUILayout.LabelField("Existing Effects", EditorStyles.boldLabel);
|
||||
|
||||
var effects = GetAllEffects();
|
||||
foreach (var effect in effects)
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchQuery) || effect.name.ToLower().Contains(searchQuery.ToLower()))
|
||||
{
|
||||
EditorGUILayout.BeginVertical("box");
|
||||
DrawEffectItem(effect);
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEffectItem(BaseEffect effect)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
EditorGUILayout.BeginVertical();
|
||||
EditorGUILayout.LabelField(effect.name, EditorStyles.boldLabel);
|
||||
EditorGUILayout.LabelField($"Type: {effect.GetType().Name}");
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (GUILayout.Button("Clone", GUILayout.Width(50)))
|
||||
{
|
||||
CloneEffect(effect);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Edit", GUILayout.Width(50)))
|
||||
{
|
||||
Selection.activeObject = effect;
|
||||
EditorUtility.FocusProjectWindow();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private void CreateEffect()
|
||||
{
|
||||
if (selectedEffectType == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Please select an effect type!", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(effectData.name))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Effect name cannot be empty!", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
BaseEffect effect = (BaseEffect)CreateInstance(selectedEffectType);
|
||||
effect.name = effectData.name;
|
||||
effect.tags = new List<GameTag>(effectData.tags);
|
||||
|
||||
// Apply type-specific data
|
||||
ApplyEffectTypeSpecificData(effect);
|
||||
|
||||
string path = EditorUtility.SaveFilePanelInProject(
|
||||
"Save Effect",
|
||||
effectData.name,
|
||||
"asset",
|
||||
"Save effect asset"
|
||||
);
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
AssetDatabase.CreateAsset(effect, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = effect;
|
||||
effectData = new EffectCreationData();
|
||||
selectedEffectType = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void CloneEffect(BaseEffect sourceEffect)
|
||||
{
|
||||
string newName = $"{sourceEffect.name}_Clone";
|
||||
string path = EditorUtility.SaveFilePanelInProject(
|
||||
"Save Cloned Effect",
|
||||
newName,
|
||||
"asset",
|
||||
"Save cloned effect asset"
|
||||
);
|
||||
|
||||
if (string.IsNullOrEmpty(path)) return;
|
||||
|
||||
BaseEffect newEffect = (BaseEffect)CreateInstance(sourceEffect.GetType());
|
||||
EditorUtility.CopySerialized(sourceEffect, newEffect);
|
||||
newEffect.name = newName;
|
||||
|
||||
AssetDatabase.CreateAsset(newEffect, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = newEffect;
|
||||
}
|
||||
|
||||
private void ApplyEffectTypeSpecificData(BaseEffect effect)
|
||||
{
|
||||
if (effect is InstantValueEffect instantEffect)
|
||||
{
|
||||
instantEffect.baseValue = effectData.GetOrCreateTypeSpecific<float>("baseValue");
|
||||
instantEffect.damageType = effectData.GetOrCreateTypeSpecific<DamageType>("damageType");
|
||||
instantEffect.AlliedTargetMultiplier = effectData.GetOrCreateTypeSpecific<float>("alliedMultiplier");
|
||||
instantEffect.EnemyTargetMultiplier = effectData.GetOrCreateTypeSpecific<float>("enemyMultiplier");
|
||||
}
|
||||
else if (effect is DamageOverTimeEffect dotEffect)
|
||||
{
|
||||
dotEffect.baseDamagePerTick = effectData.GetOrCreateTypeSpecific<float>("damagePerTick");
|
||||
dotEffect.tickRate = effectData.GetOrCreateTypeSpecific<float>("tickRate");
|
||||
dotEffect.damageType = effectData.GetOrCreateTypeSpecific<DamageOverTimeType>("dotType");
|
||||
}
|
||||
else if (effect is StatusEffect statusEffect)
|
||||
{
|
||||
statusEffect.duration = effectData.duration;
|
||||
statusEffect.applyToTargetsHit = effectData.applyToTargetsHit;
|
||||
statusEffect.applyToSelf = effectData.applyToSelf;
|
||||
|
||||
List<StatInfluence> influences = effectData.GetOrCreateTypeSpecific<List<StatInfluence>>("statInfluences");
|
||||
statusEffect.influencingStats = new List<StatInfluence>(influences);
|
||||
}
|
||||
}
|
||||
|
||||
private BaseEffect[] GetAllEffects()
|
||||
{
|
||||
return AssetDatabase.FindAssets("t:BaseEffect")
|
||||
.Select(guid => AssetDatabase.LoadAssetAtPath<BaseEffect>(AssetDatabase.GUIDToAssetPath(guid)))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
11
Assets/Scripts/Editor/effect-editor-existing.cs.meta
Normal file
11
Assets/Scripts/Editor/effect-editor-existing.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 586b6b091b57739439fb41c268b11672
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -94,7 +94,7 @@ Material:
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _Rotation: 284.16022
|
||||
- _Rotation: 433.6615
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user