using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace BulletHellTemplate
{
///
/// ScriptableObject representing a quest item with its rewards and requirements.
///
[CreateAssetMenu(fileName = "NewQuestItem", menuName = "Quest/Quest Item", order = 51)]
public class QuestItem : ScriptableObject
{
[Tooltip("Unique identifier for the quest")]
public int questId;
[Tooltip("Quest icon")]
public Sprite icon;
[Tooltip("Quest title")]
public string title;
[Tooltip("Localized quest titles")]
public NameTranslatedByLanguage[] titleTranslated;
[Tooltip("Quest description")]
public string description;
[Tooltip("Localized quest descriptions")]
public DescriptionTranslatedByLanguage[] descriptionTranslated;
[Tooltip("Currency type rewarded")]
public string currencyReward = "GO";
[Tooltip("Amount of currency rewarded")]
public int currencyAmount;
[Tooltip("Battle pass experience points")]
public int battlePassExp;
[Tooltip("Account experience points")]
public int accountExp;
[Tooltip("Experience points for selected character")]
public int selectedCharacterExp;
[Tooltip("Type of reward for the quest")]
public QuestReward questReward;
[Tooltip("Data for character reward")]
public CharacterData characterData;
[Tooltip("Icon item reward")]
public IconItem iconItem;
[Tooltip("Frame item reward")]
public FrameItem frameItem;
[Tooltip("Inventory item reward")]
public InventoryItem inventoryItem;
[Tooltip("Single quest requirement")]
public QuestRequirement requirement = new QuestRequirement();
[Tooltip("Type of quest")]
public QuestType questType;
}
///
/// Enumeration of quest requirement types.
///
public enum QuestRequirementType
{
KillMonster,
CompleteMap,
LevelUpAccount,
KillMonsterWithSpecificCharacter,
CompleteMapWithSpecificCharacter,
LevelUpCharacter
}
///
/// Class representing a quest requirement.
///
[System.Serializable]
public class QuestRequirement
{
[Tooltip("Type of quest requirement")]
public QuestRequirementType requirementType;
[Tooltip("Number required for the quest (renamed according to the requirement type)")]
public int targetAmount;
[Header("Required for map-related quests")]
[Tooltip("Map required for completion")]
public MapInfoData targetMap;
[Header("Required for character-specific quests")]
[Tooltip("Specific character required")]
public CharacterData targetCharacter;
}
///
/// Enumeration of quest rewards.
///
[System.Serializable]
public enum QuestReward
{
None,
CharacterReward,
IconReward,
FrameReward,
ItemReward
}
///
/// Enumeration of quest types.
///
[System.Serializable]
public enum QuestType
{
Normal,
Daily,
Repeat
}
#if UNITY_EDITOR
///
/// Custom editor for QuestItem that organizes properties into boxes and conditionally displays fields.
///
[CustomEditor(typeof(QuestItem))]
public class QuestItemEditor : Editor
{
///
/// Overrides the default Inspector GUI to provide custom layout and conditional property drawing.
///
public override void OnInspectorGUI()
{
serializedObject.Update();
// ======================
// BASIC PROPERTIES BOX
// ======================
EditorGUILayout.BeginVertical("box");
EditorGUILayout.PropertyField(serializedObject.FindProperty("questId"), new GUIContent("Quest ID", "Unique identifier for the quest"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("icon"), new GUIContent("Icon", "Quest icon"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("title"), new GUIContent("Title", "Quest title"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("titleTranslated"), new GUIContent("Title Translated", "Localized quest titles"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("description"), new GUIContent("Description", "Quest description"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("descriptionTranslated"), new GUIContent("Description Translated", "Localized quest descriptions"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("currencyReward"), new GUIContent("Currency Reward", "Currency type rewarded"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("currencyAmount"), new GUIContent("Currency Amount", "Amount of currency rewarded"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("battlePassExp"), new GUIContent("Battle Pass Exp", "Battle pass experience points"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("accountExp"), new GUIContent("Account Exp", "Account experience points"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("selectedCharacterExp"), new GUIContent("Selected Character Exp", "Experience points for selected character"));
EditorGUILayout.EndVertical();
// ===============
// QUEST REWARD BOX
// ===============
EditorGUILayout.BeginVertical("box");
EditorGUILayout.PropertyField(serializedObject.FindProperty("questReward"), new GUIContent("Quest Reward", "Type of reward for the quest"));
// Show the relevant reward field(s) based on the selected QuestReward
var questRewardProp = serializedObject.FindProperty("questReward");
var questRewardValue = (QuestReward)questRewardProp.enumValueIndex;
switch (questRewardValue)
{
case QuestReward.CharacterReward:
EditorGUILayout.PropertyField(serializedObject.FindProperty("characterData"), new GUIContent("Character Data", "Data for character reward"));
break;
case QuestReward.IconReward:
EditorGUILayout.PropertyField(serializedObject.FindProperty("iconItem"), new GUIContent("Icon Item", "Icon item reward"));
break;
case QuestReward.FrameReward:
EditorGUILayout.PropertyField(serializedObject.FindProperty("frameItem"), new GUIContent("Frame Item", "Frame item reward"));
break;
case QuestReward.ItemReward:
EditorGUILayout.PropertyField(serializedObject.FindProperty("inventoryItem"), new GUIContent("Inventory Item", "Inventory item reward"));
break;
case QuestReward.None:
default:
// Do not display any item-based fields
break;
}
EditorGUILayout.EndVertical();
// ======================
// QUEST REQUIREMENT BOX
// ======================
EditorGUILayout.BeginVertical("box");
SerializedProperty requirementProp = serializedObject.FindProperty("requirement");
// Draw the requirementType first
EditorGUILayout.PropertyField(requirementProp.FindPropertyRelative("requirementType"), new GUIContent("Requirement Type", "Type of quest requirement"));
// Based on requirementType, rename and display the relevant fields
var reqTypeIndex = requirementProp.FindPropertyRelative("requirementType").enumValueIndex;
var requirementTypeEnum = (QuestRequirementType)reqTypeIndex;
// We'll store references for easier reading
SerializedProperty targetAmountProp = requirementProp.FindPropertyRelative("targetAmount");
SerializedProperty targetMapProp = requirementProp.FindPropertyRelative("targetMap");
SerializedProperty targetCharacterProp = requirementProp.FindPropertyRelative("targetCharacter");
// Use a switch to rename targetAmount and show/hide fields
switch (requirementTypeEnum)
{
case QuestRequirementType.KillMonster:
EditorGUILayout.PropertyField(
targetAmountProp,
new GUIContent("Monsters Amount", "Number of monsters to kill")
);
// No map or character needed
break;
case QuestRequirementType.CompleteMap:
EditorGUILayout.PropertyField(
targetAmountProp,
new GUIContent("Times to Complete", "Number of times the map must be completed")
);
EditorGUILayout.PropertyField(
targetMapProp,
new GUIContent("Map Required", "Map required for completion")
);
// No character needed
break;
case QuestRequirementType.LevelUpAccount:
EditorGUILayout.PropertyField(
targetAmountProp,
new GUIContent("Level Required", "Account level required")
);
// No map or character needed
break;
case QuestRequirementType.KillMonsterWithSpecificCharacter:
EditorGUILayout.PropertyField(
targetAmountProp,
new GUIContent("Monsters Amount", "Number of monsters to kill")
);
EditorGUILayout.PropertyField(
targetCharacterProp,
new GUIContent("Required Character", "Specific character required for killing monsters")
);
// No map needed
break;
case QuestRequirementType.CompleteMapWithSpecificCharacter:
EditorGUILayout.PropertyField(
targetAmountProp,
new GUIContent("Times to Complete", "Number of times the map must be completed")
);
EditorGUILayout.PropertyField(
targetMapProp,
new GUIContent("Map Required", "Map required for completion")
);
EditorGUILayout.PropertyField(
targetCharacterProp,
new GUIContent("Required Character", "Specific character required for map completion")
);
break;
case QuestRequirementType.LevelUpCharacter:
EditorGUILayout.PropertyField(
targetAmountProp,
new GUIContent("Character Level Required", "Character level required")
);
EditorGUILayout.PropertyField(
targetCharacterProp,
new GUIContent("Required Character", "Specific character to level up")
);
// No map needed
break;
}
EditorGUILayout.EndVertical();
// =============
// QUEST TYPE BOX
// =============
EditorGUILayout.BeginVertical("box");
EditorGUILayout.PropertyField(serializedObject.FindProperty("questType"), new GUIContent("Quest Type", "Type of quest"));
EditorGUILayout.EndVertical();
// Apply any modified properties to the serialized object
serializedObject.ApplyModifiedProperties();
}
}
#endif
}