268 lines
10 KiB
C#
268 lines
10 KiB
C#
// ─────────────────────────────────────────────────────────────────────────────
|
|
// WLEquipData.cs — FR(FirstRising) 기존 장비 시스템의 데이터 모델 이식 (#821 · 2026-10-08)
|
|
//
|
|
// 원본 = FR `Assets/Scripts/GameHub/JsonCommon.cs` (ItemJson · ItemLevelJson · ItemComposeJson ·
|
|
// ItemOptionJson · ItemDropGroup/Package · RawItem) 를 **필드 이름 그대로** 옮겼다 — FR 의 JSON
|
|
// 테이블(`Resources/WL/FR/*.json`)을 수정 없이 Newtonsoft 로 읽기 위해서다.
|
|
//
|
|
// PD 지시: 탕탕특공대식 — 본 아이템 1 + 같은 등급 재료 2(표 RequiredItemCount) → 등급 업 ·
|
|
// 등급마다 옵션 개방(ItemOptionTable) · 강화석+골드로 레벨업(Item_*.json) · 강등.
|
|
// 능력치 본체는 힘민지(ActorStatInfo) 그대로 쓰고, FR eAbility 는 WLEquipSettings.abilityMap 으로 대응한다.
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace WL.Equip
|
|
{
|
|
/// <summary>FR eAbility — 값(순서)이 JSON 의 정수와 일치해야 한다. BT47 이후 항목은 옮기지 않았다(PD 제외).</summary>
|
|
public enum eFRAbility
|
|
{
|
|
None,
|
|
ItemRange, // 1 아이템 획득 범위 %
|
|
Health, // 2 체력 %
|
|
RecoveryHealth, // 3 초당 체력 회복 %
|
|
Speed, // 4 이동 속도 %
|
|
Defence, // 5 모든 피해 감소 %
|
|
Attack, // 6 공격력 %
|
|
IncreaseDrop, // 7 경험치·골드·드랍율 %
|
|
Rolling, // 8 구르기
|
|
ProjectileSpeed, // 9 투사체 속도 %
|
|
SkillRange, // 10 스킬 범위 %
|
|
SkillDuration, // 11 스킬 지속 %
|
|
Cooltime, // 12 쿨타임 감소 %
|
|
AttackDefence, // 13 공격력+방어력 %
|
|
Passive, // 14 패시브 효과 %
|
|
Critical, // 15 치명타 확률 %
|
|
CriticalDamage, // 16 치명타 피해 %
|
|
Revive, // 17 부활 횟수
|
|
HeartRecover, // 18 하트 회복 %
|
|
SpeedValue, // 19 이동 속도 값
|
|
Excellent, // 20 액설런트 확률
|
|
ExcellentDamage, // 21 액설런트 피해
|
|
Max,
|
|
}
|
|
|
|
public enum eFRItemGrade { None = -1, Normal, Magic, Rare, Elite, Epic, Legend, Max }
|
|
public enum eFREquipmentType { None = 0, Weapon, Necklace, Glove, Armor, Belt, Shose, Max }
|
|
public enum eFRItemType { None = 0, Equipment, Buff, LevelUpScroll, EnchantScroll, Goods, Normal, RewardPoint, Max }
|
|
public enum eFRDropType { All = 0, Random = 1, Max }
|
|
|
|
[Serializable]
|
|
public class ItemJson
|
|
{
|
|
public int Index;
|
|
public string Item_name;
|
|
public string Desc;
|
|
public byte IsEquip;
|
|
public byte IsStack;
|
|
public int ItemCategory;
|
|
public eFRItemType ItemType;
|
|
public int WeaponType;
|
|
public eFREquipmentType EquipmentType;
|
|
public eFRItemGrade ItemGrade;
|
|
public int ItemClass;
|
|
public int ItemDropGroup_ID;
|
|
public int GradeLv;
|
|
public int GroupNo;
|
|
public int ItemMaxLv;
|
|
public int ItemLvAbilityID;
|
|
public int SkillIndex;
|
|
public int CostumeIndex;
|
|
// FR 의 `Equipments`(프리팹 이름)는 FR 전용이라 읽지 않는다.
|
|
|
|
public bool IsEquipment { get { return IsEquip == 1 && ItemType == eFRItemType.Equipment; } }
|
|
}
|
|
|
|
[Serializable]
|
|
public class ItemLevelInfo
|
|
{
|
|
public int Index;
|
|
public eFRItemGrade Grade;
|
|
public int GradeLv;
|
|
public int Level;
|
|
public int AttackAbility;
|
|
public int DefenceAbility;
|
|
public int HealthAbility;
|
|
public int ItemKeyRequired;
|
|
public int ItemCountRequired;
|
|
public int MoneyKeyRequired;
|
|
public int MoneyCountRequired;
|
|
}
|
|
|
|
[Serializable]
|
|
public class ItemLevelJson
|
|
{
|
|
public int Index;
|
|
public List<ItemLevelInfo> LevelInfos = new List<ItemLevelInfo>();
|
|
public ItemLevelJson(int index) { Index = index; }
|
|
public ItemLevelInfo FindLevelInfo(int level) { return LevelInfos.Find(i => i.Level == level); }
|
|
}
|
|
|
|
[Serializable]
|
|
public class ItemComposeJson
|
|
{
|
|
public int Index;
|
|
public int SameGroupNo;
|
|
public eFRItemGrade ItemGrade;
|
|
public eFRItemGrade ResultGrade;
|
|
public int RequiredGradeLevel;
|
|
public int ResultGradeLevel;
|
|
public int RequiredItemCount;
|
|
}
|
|
|
|
/// <summary>ItemOptionTable.json 의 한 행(엑셀 셀 병합 → 첫 행만 Index).</summary>
|
|
[Serializable]
|
|
public class ItemOptionReader
|
|
{
|
|
public int Index;
|
|
public string Desc;
|
|
public eFRItemGrade ItemGrade;
|
|
public string Ability;
|
|
public string AbilityValue;
|
|
public string ConditionalAbility;
|
|
public string ConditionValue0;
|
|
public string ConditionValue1;
|
|
public string ConditionValue2;
|
|
}
|
|
|
|
[Serializable]
|
|
public class ItemOptionAbility
|
|
{
|
|
public eFRAbility Ability;
|
|
public int AbilityValue;
|
|
public ItemOptionAbility(eFRAbility a, int v) { Ability = a; AbilityValue = v; }
|
|
}
|
|
|
|
[Serializable]
|
|
public class ConditionalItemOptionAbility
|
|
{
|
|
public int Ability; // FR eConditionalItemOptionAbility — WL 에서는 「미적용」(표시만)
|
|
public int ConditionValue0, ConditionValue1, ConditionValue2;
|
|
}
|
|
|
|
[Serializable]
|
|
public class ItemOptionElement
|
|
{
|
|
public eFRItemGrade ItemGrade;
|
|
public List<ItemOptionAbility> Abilities = new List<ItemOptionAbility>();
|
|
public List<ConditionalItemOptionAbility> ConditionalAbilities = new List<ConditionalItemOptionAbility>();
|
|
|
|
public ItemOptionElement(ItemOptionReader r)
|
|
{
|
|
ItemGrade = r.ItemGrade;
|
|
if (!string.IsNullOrEmpty(r.Ability))
|
|
{
|
|
var a = r.Ability.Split('\n');
|
|
var v = (r.AbilityValue ?? "").Split('\n');
|
|
for (int i = 0; i < a.Length; i++)
|
|
{
|
|
int ai, vi;
|
|
if (!int.TryParse(a[i].Trim(), out ai)) continue;
|
|
vi = i < v.Length && int.TryParse(v[i].Trim(), out vi) ? vi : 0;
|
|
Abilities.Add(new ItemOptionAbility((eFRAbility)ai, vi));
|
|
}
|
|
}
|
|
if (!string.IsNullOrEmpty(r.ConditionalAbility))
|
|
{
|
|
var a = r.ConditionalAbility.Split('\n');
|
|
var c0 = string.IsNullOrEmpty(r.ConditionValue0) ? null : r.ConditionValue0.Split('\n');
|
|
var c1 = string.IsNullOrEmpty(r.ConditionValue1) ? null : r.ConditionValue1.Split('\n');
|
|
var c2 = string.IsNullOrEmpty(r.ConditionValue2) ? null : r.ConditionValue2.Split('\n');
|
|
for (int i = 0; i < a.Length; i++)
|
|
{
|
|
var ca = new ConditionalItemOptionAbility();
|
|
int t;
|
|
if (int.TryParse(a[i].Trim(), out t)) ca.Ability = t;
|
|
if (c0 != null && i < c0.Length && int.TryParse(c0[i].Trim(), out t)) ca.ConditionValue0 = t;
|
|
if (c1 != null && i < c1.Length && int.TryParse(c1[i].Trim(), out t)) ca.ConditionValue1 = t;
|
|
if (c2 != null && i < c2.Length && int.TryParse(c2[i].Trim(), out t)) ca.ConditionValue2 = t;
|
|
ConditionalAbilities.Add(ca);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class ItemOptionJson
|
|
{
|
|
public int Index; // = ItemJson.GroupNo
|
|
public string Desc;
|
|
public List<ItemOptionElement> ItemOptions = new List<ItemOptionElement>();
|
|
public ItemOptionJson(int index, string desc) { Index = index; Desc = desc; }
|
|
}
|
|
|
|
[Serializable]
|
|
public class ItemDropGroupInfo
|
|
{
|
|
public int Index;
|
|
public string Name;
|
|
public eFRDropType DropType;
|
|
public int Rate; // 10000 분율
|
|
public int Package_ID;
|
|
}
|
|
|
|
[Serializable]
|
|
public class ItemDropGroupJson
|
|
{
|
|
public int Index;
|
|
public List<ItemDropGroupInfo> ItemDropGroupInfos = new List<ItemDropGroupInfo>();
|
|
public ItemDropGroupJson(int index) { Index = index; }
|
|
}
|
|
|
|
[Serializable]
|
|
public class ItemDropPackageInfo
|
|
{
|
|
public int Index;
|
|
public string Name;
|
|
public int Item_ID;
|
|
public int MinCount;
|
|
public int MaxCount;
|
|
public int Rate;
|
|
}
|
|
|
|
[Serializable]
|
|
public class ItemDropPackageJson
|
|
{
|
|
public int Index;
|
|
public int TotalRate;
|
|
public List<ItemDropPackageInfo> ItemDropPackageInfos = new List<ItemDropPackageInfo>();
|
|
public ItemDropPackageJson(int index) { Index = index; }
|
|
}
|
|
|
|
/// <summary>보유 아이템 1건(FR RawItem). `_id` 는 세이브 안 고유 번호.</summary>
|
|
[Serializable]
|
|
public class RawItem
|
|
{
|
|
public int index;
|
|
public int level;
|
|
public int count;
|
|
public int _id;
|
|
public RawItem() { }
|
|
public RawItem(int index, int level, int count, int id) { this.index = index; this.level = level; this.count = count; _id = id; }
|
|
}
|
|
|
|
/// <summary>RawItem + 표 행.</summary>
|
|
public class Item
|
|
{
|
|
public RawItem rawItem;
|
|
public ItemJson itemJson;
|
|
public Item(RawItem r, ItemJson j) { rawItem = r; itemJson = j; }
|
|
}
|
|
|
|
/// <summary>세이브 파일 본문(JSON).</summary>
|
|
[Serializable]
|
|
public class WLEquipSaveData
|
|
{
|
|
public int version = 2;
|
|
public int nextId = 1;
|
|
public long gold; // 섬(IslandManager)이 없을 때만 쓰는 예비 골드
|
|
public List<RawItem> items = new List<RawItem>();
|
|
public List<int> equipItems = new List<int>(); // 장착 중인 _id
|
|
// 장비 상자(PD 2026-10-09) — 열쇠 · 누적 개봉(에픽 확정 주기 기준) · 마지막 S급 뒤 개봉 수(천장 기준)
|
|
public int keys;
|
|
public int boxDraws;
|
|
public int sinceS;
|
|
}
|
|
}
|