using IVDataFormat; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Numerics; using Random = UnityEngine.Random; public static class DataHandler { #region System data public static dConst Const { get; private set; } = null; private static dAttend[] sysAttend; public static Dictionary SysAwakenRewards = new Dictionary(); public static Dictionary SysBoxes = new Dictionary(); private static Dictionary dicBg = new Dictionary(); private static Dictionary dicBgm = new Dictionary() { { BGM.intro, new dBgm(BGM.intro, "intro") }, { BGM.stage, new dBgm(BGM.stage, "stage") }, { BGM.goldDg, new dBgm(BGM.goldDg, "gold") }, { BGM.enhanceDg, new dBgm(BGM.enhanceDg, "reinstone") }, { BGM.petDg, new dBgm(BGM.petDg, "pet") }, { BGM.awakenStoneDg, new dBgm(BGM.awakenStoneDg, "awakenstone") }, { BGM.awakenDg, new dBgm(BGM.awakenDg, "awaken") }, { BGM.guardian, new dBgm(BGM.guardian, "guardian") }, { BGM.pvp, new dBgm(BGM.pvp, "pvp") }, }; private static dAdBuff[] sysBuff; private static Dictionary dicCosClothSet = new Dictionary(); private static Dictionary dicCosWeaponSet = new Dictionary(); public static dAwaken[] sysSkillAwakens = null; public static dTotalLvValue[] sysSkillLvEffects = null; public static dAwaken[] sysGearAwakens = null; public static dTotalLvValue[] sysGearLvEffects = null; public static dAwaken[] sysPetAwakens = null; public static dTotalLvValue[] sysPetLvEffects = null; private static int[] gearTreasureLvUpLvBounds = null; private static int[] gearTreasureLvUpSuccRates = null; private static Dictionary sysGuardian = new Dictionary(); public static Dictionary> sysRelicsGroupedByType = new Dictionary>(); private static int[] sysRelicEnhancePropLvs = null; private static int[] sysRelicEnhanceProp = null; private static Dictionary dicMonster = new Dictionary(); public static dArea[] sysAreas = null; private static dDungeonInfo sysDgAwaken = null; private static dDungeonInfo sysDgAwakenStone = null; private static dDungeonInfo sysDgGold = null; private static dDungeonInfo[] sysDgGuardian = null; private static dDungeonInfo sysDgPet = null; private static dDungeonInfo sysDgReinStone = null; private static dDungeonInfo sysDgRelic = null; public static dPvp sysPvp = null; private static dPvpRank[] pvpRanks = null; public static dPvpRank pvpMyRank = null; private static int[] extraRarityRates; private static Dictionary extraAbilities; private static Dictionary[] extraAbilityIds; private static Dictionary sysQuestDaily = new Dictionary(); private static Dictionary sysQuestRepeat = new Dictionary(); private static Dictionary sysQuestMission = new Dictionary(); private static dGachaLevel[] gachaWeaponLvs; private static int[] gachaWeaponGrades; private static dGachaLevel[] gachaArmorLvs; private static int[] gachaArmorGrades; private static dGachaLevel[] gachaAcceLvs; private static int[] gachaAcceGrades; private static Dictionary dicEvent = new Dictionary(); private static dEventInfo sysEventRoulette; private static dEventInfo sysEventTrade; private static dEventInfo sysEventRaise; private static dRewardEvent sysRewardEvent; private static Dictionary sysQuestEvent = new Dictionary(); private static dNotice[] sysNotices; private static dChatNotice[] sysChatNotices; #endregion System data #region Play data public static cPlayData PlayData { get; private set; } = null; private static cTotalRecord PlayerTotalRecord = null; private static cDailyRecord PlayerDailyRecord = null; public static cGoodsData Goods { get; private set; } = null; private static cAttend[] playAttend; public static cAwakenData PlayAwaken = null; private static cBoxData PlayBoxes { get; set; } = null; public static cAdBuffLevel PlayBuff { get; set; } = null; public static cPlayCostume PlayEquipCostume { get; private set; } = null; public static Dictionary PlayGuardian = new Dictionary(); public static Dictionary PlayRelic = new Dictionary(); public static cPlayerDungeonInfo PlayDgAwaken = null; public static cPlayerDungeonInfo PlayDgAwakenStone = null; public static cPlayerDungeonInfo PlayDgGold = null; public static Dictionary PlayDgGuardian = null; public static cPlayerDungeonInfo PlayDgPet = null; public static cPlayerDungeonInfo PlayDgReinStone = null; public static cPlayerDungeonInfo PlayDgRelic = null; public static cDungeonPreset PlayDgPreset = null; public static cPvpPlay playPvp = null; private static cQuestDaily[] playQuestDaily; private static cQuestRepeat[] playQuestRepeat; private static dMail[] playMails = null; private static cEventItem playEventRoulette; private static cEventItem playEventTrade; private static cEventItem playEventRaise; private static cRewardEvent playEventReward; private static cQuestAttend playQuestEventAttend; private static Dictionary playQuestEvent = new Dictionary(); #endregion #region Union data (System data + Play data) private static Dictionary dicProfileTitle = new Dictionary(); private static Dictionary dicProfileIcon = new Dictionary(); private static Dictionary dicCharStatEnhanceGold = new Dictionary(); private static Dictionary dicCharStatEnhancePoint = new Dictionary(); private static Dictionary dicCosCloth = new Dictionary(); private static Dictionary dicCosWeapon = new Dictionary(); private static Dictionary dicSkillActive = new Dictionary(); private static Dictionary dicSkillPassive = new Dictionary(); private static Dictionary> dicGearEquipment = new Dictionary>() { [cGoods.TBagWeapon] = new Dictionary(), [cGoods.TBagArmorCape] = new Dictionary(), [cGoods.TBagArmorHat] = new Dictionary(), [cGoods.TBagArmorShoes] = new Dictionary(), [cGoods.TBagAcceEar] = new Dictionary(), [cGoods.TBagAcceNeck] = new Dictionary(), [cGoods.TBagAcceRing] = new Dictionary() }; private static Dictionary dicGearTreasure = new Dictionary(); private static Dictionary dicPet = new Dictionary(); private static Dictionary dicShop = new Dictionary(); private static Dictionary dicPass = new Dictionary(); private static dPass passEvent = null; private static dPass passEventNext = null; #endregion #region ETC public static bool bLoadLocalData = false; public static bool IsNeedDataSave { get; private set; } = false; private static HashSet boxNew = new HashSet(); private static HashSet cosClothNew = new HashSet(); private static HashSet cosWeaponNew = new HashSet(); private static int currentTotalSkillLv = 0; private static Dictionary dicGearLast = new Dictionary() { [cGoods.TBagWeapon] = 1, [cGoods.TBagArmorCape] = 1, [cGoods.TBagArmorHat] = 1, [cGoods.TBagArmorShoes] = 1, [cGoods.TBagAcceEar] = 1, [cGoods.TBagAcceNeck] = 1, [cGoods.TBagAcceRing] = 1, }; private static Dictionary dicGearLastHave = new Dictionary() { [cGoods.TBagWeapon] = -1, [cGoods.TBagArmorCape] = -1, [cGoods.TBagArmorHat] = -1, [cGoods.TBagArmorShoes] = -1, [cGoods.TBagAcceEar] = -1, [cGoods.TBagAcceNeck] = -1, [cGoods.TBagAcceRing] = -1, }; private static Dictionary dicGearLv = new Dictionary() { [cGoods.TBagWeapon] = 0, [cGoods.TBagArmorCape] = 0, [cGoods.TBagArmorHat] = 0, [cGoods.TBagArmorShoes] = 0, [cGoods.TBagAcceEar] = 0, [cGoods.TBagAcceNeck] = 0, [cGoods.TBagAcceRing] = 0, }; private static Dictionary> dicGearNew = new Dictionary>() { [cGoods.TBagWeapon] = new HashSet(), [cGoods.TBagArmorCape] = new HashSet(), [cGoods.TBagArmorHat] = new HashSet(), [cGoods.TBagArmorShoes] = new HashSet(), [cGoods.TBagAcceEar] = new HashSet(), [cGoods.TBagAcceNeck] = new HashSet(), [cGoods.TBagAcceRing] = new HashSet() }; private static int[] arrHaveWeapon = new int[7]; private static int[,] arrHaveArmor = new int[3, 7]; private static int[,] arrHaveAcc = new int[3, 7]; public static DateTime PvpRankRefreshTime { get; private set; } private static HashSet petNew = new HashSet(); private static int petLv = 0; private static List[] shopGroupedByShopType = new List[] { new List(), new List(), new List(), new List(), new List(), new List(), new List(), new List() }; public static DateTime MailRefreshTime { get; private set; } public static int MailCount { get; private set; } public static DateTime MailReadRefreshTime { get; private set; } private static dMail[] readMails = null; private static List listBattleType = new List(); private static List listEquipmentType = new List(); private static List listSummonType = new List(); private static List listDungeonType = new List(); private static List listEtcType = new List(); #endregion #region Base public static IEnumerator InitSystemData(nSystemData systemData) { { Const = systemData.constData; sysAttend = systemData.sysAttend; LoadExtraAbility(systemData.sysExtraRarity, systemData.sysExtra); sysBuff = systemData.sysBuff; for (int i = 0; i < systemData.sysBox.Length; ++i) { dBox box = systemData.sysBox[i]; SysBoxes.Add(box.id, box); } for (int i = 0; i < systemData.sysProfileTitle.Length; ++i) { dTitle title = systemData.sysProfileTitle[i]; dicProfileTitle.SafeInsert(title.id, title); } for (int i = 0; i < systemData.sysProfileIcon.Length; i++) { dIcon icon = systemData.sysProfileIcon[i]; dicProfileIcon.SafeInsert(icon.id, icon); } for (int i = 0; i < systemData.sysBackground.Length; ++i) { dBg bg = systemData.sysBackground[i]; dicBg.SafeInsert(bg.id, bg); } } yield return null; { for (int i = 0; i < systemData.sysCharEnhanceGold.Length; ++i) { dCharStat stat = systemData.sysCharEnhanceGold[i]; dicCharStatEnhanceGold.SafeInsert(new KeyValuePair(stat.id, stat)); } for (int i = 0; i < systemData.sysCharEnhancePoint.Length; ++i) { dCharStat charStat = systemData.sysCharEnhancePoint[i]; dicCharStatEnhancePoint.SafeInsert(charStat.id, charStat); } for (int i = 0; i < systemData.sysAwaken.Length; ++i) { dAwakenReward reward = systemData.sysAwaken[i]; SysAwakenRewards.Add(i + 1, reward); } } yield return null; { sysPetAwakens = systemData.sysPetAwaken; sysPetLvEffects = systemData.sysPetEnhance; for (int i = 0; i < systemData.sysPet.Length; i++) { dPet pet = systemData.sysPet[i]; dicPet.SafeInsert(pet.id, pet); } for (int i = 0; i < systemData.sysGuardian.Length; i++) { dSysGuardian guardian = systemData.sysGuardian[i]; sysGuardian.SafeInsert(guardian.guardianType, guardian); } } yield return null; { sysSkillAwakens = systemData.sysCharSkillAwaken; sysSkillLvEffects = systemData.sysCharSkillEnhance; for (int i = 0; i < systemData.sysCharSkillPassive.Length; ++i) { dSkillPassive skill = systemData.sysCharSkillPassive[i]; dicSkillPassive.SafeInsert(new KeyValuePair(skill.id, skill)); } for (int i = 0; i < systemData.sysCharSkillActive.Length; ++i) { dSkillActive skill = systemData.sysCharSkillActive[i]; dicSkillActive.SafeInsert(new KeyValuePair(skill.id, skill)); } } yield return null; { for (int i = 0; i < systemData.sysCostumeOutfit.Length; ++i) { dCostume costume = systemData.sysCostumeOutfit[i]; dicCosCloth.SafeInsert(new KeyValuePair(costume.id, costume)); } for (int i = 0; i < systemData.sysCostumeOutfitSet.Length; ++i) { dCostumeSet cosSet = systemData.sysCostumeOutfitSet[i]; for (int j = 0; j < cosSet.set.Length; ++j) { // id가 음수이거나, 해당 코스튬이 없는 경우 -1로 설정. if (cosSet.set[j] >= 0 && !dicCosCloth.ContainsKey(cosSet.set[j])) cosSet.set[j] = -1; } dicCosClothSet.SafeInsert(new KeyValuePair(cosSet.id, cosSet)); } for (int i = 0; i < systemData.sysCostumeWeapon.Length; ++i) { dCostume costume = systemData.sysCostumeWeapon[i]; dicCosWeapon.SafeInsert(new KeyValuePair(costume.id, costume)); } for (int i = 0; i < systemData.sysCostumeWeaponSet.Length; i++) { dCostumeSet cosSet = systemData.sysCostumeWeaponSet[i]; for (int j = 0; j < cosSet.set.Length; ++j) { // id가 음수이거나, 해당 코스튬이 없는 경우 -1로 설정. if (cosSet.set[j] >= 0 && !dicCosWeapon.ContainsKey(cosSet.set[j])) cosSet.set[j] = -1; } dicCosWeaponSet.SafeInsert(new KeyValuePair(cosSet.id, cosSet)); } } yield return null; { sysGearAwakens = systemData.sysGearAwaken; sysGearLvEffects = systemData.sysGearEnhance; LoadSysGearEquipment(cGoods.TBagWeapon, systemData.sysGearWeapon); LoadSysGearEquipment(cGoods.TBagArmorCape, systemData.sysGearCape); LoadSysGearEquipment(cGoods.TBagArmorHat, systemData.sysGearHat); LoadSysGearEquipment(cGoods.TBagArmorShoes, systemData.sysGearShoes); LoadSysGearEquipment(cGoods.TBagAcceEar, systemData.sysGearEarring); LoadSysGearEquipment(cGoods.TBagAcceNeck, systemData.sysGearNecklace); LoadSysGearEquipment(cGoods.TBagAcceRing, systemData.sysGearRing); gearTreasureLvUpLvBounds = systemData.sysGearTreasureEnhance.lv; gearTreasureLvUpSuccRates = systemData.sysGearTreasureEnhance.props; for (int i = 0; i < systemData.sysGearTreasure.Length; ++i) { dTreasure treasure = systemData.sysGearTreasure[i]; dicGearTreasure.SafeInsert(treasure.id, treasure); } } yield return null; { sysRelicEnhancePropLvs = systemData.sysRelicEnhance.lv; sysRelicEnhanceProp = systemData.sysRelicEnhance.props; for (int i = 0; i < systemData.sysRelic.Length; ++i) { dSysRelic relic = systemData.sysRelic[i]; if(!sysRelicsGroupedByType.ContainsKey(relic.relicType)) sysRelicsGroupedByType.Add(relic.relicType, new List()); sysRelicsGroupedByType[relic.relicType].Add(relic); } } yield return null; { for (int i = 0; i < systemData.sysMonster.Length; ++i) { dMonster monster = systemData.sysMonster[i]; dicMonster.SafeInsert(monster.id, monster); } } yield return null; { sysAreas = systemData.sysArea; sysDgAwaken = systemData.sysDgAwaken; sysDgAwakenStone = systemData.sysDgAwakenStone; sysDgGold = systemData.sysDgGold; sysDgGuardian = systemData.sysDgGuardian; sysDgPet = systemData.sysDgPet; sysDgReinStone = systemData.sysDgReinStone; sysDgRelic = systemData.sysDgRelic; } yield return null; { sysPvp = systemData.sysPvp; } yield return null; { gachaWeaponLvs = systemData.sysGachaWeaponCount; gachaWeaponGrades = systemData.sysGachaWeaponGrade; gachaArmorLvs = systemData.sysGachaArmorCount; gachaArmorGrades = systemData.sysGachaArmorGrade; gachaAcceLvs = systemData.sysGachaAccCount; gachaAcceGrades = systemData.sysGachaAccGrade; // notice : call method order must be pass -> shop LoadPassSysData(systemData.sysPass); LoadShopSysData(systemData.sysShop); } yield return null; { for (int i = 0; i < systemData.sysQuestDaily.Length; ++i) { dQuest quest = systemData.sysQuestDaily[i]; sysQuestDaily.SafeInsert(quest.id, quest); } for (int i = 0; i < systemData.sysQuestRepeat.Length; ++i) { dQuest quest = systemData.sysQuestRepeat[i]; sysQuestRepeat.SafeInsert(quest.id, quest); } for (int i = 0; i < systemData.sysQuestMission.Length; ++i) { dMission mission = systemData.sysQuestMission[i]; sysQuestMission.SafeInsert(mission.id, mission); } } yield return null; { for (int i = 0; i < systemData.sysEvent.Length; ++i) { dEvent evn = systemData.sysEvent[i]; dicEvent.SafeInsert(evn.id, evn); } sysEventRoulette = systemData.sysEventRoulette; sysEventTrade = systemData.sysEventTrade; sysEventRaise = systemData.sysEventRaise; sysRewardEvent = systemData.sysEventReward; for (int i = 0; i < systemData.sysQuestEvent.Length; ++i) { dQuest quest = systemData.sysQuestEvent[i]; sysQuestEvent.SafeInsert(quest.id, quest); } } yield return null; { sysNotices = systemData.sysNotice; sysChatNotices = systemData.sysNoticeChat; } } public static IEnumerator InitPlayData(nPlayData playData) { LoadPlayData(playData.playUser); PlayerTotalRecord = playData.playRecordTotal; PlayerDailyRecord = playData.playRecordDaily; playAttend = playData.playAttend; LoadGoodsData(playData.playCurrency); LoadCostumeData(playData.playCostumeOutfit, playData.playCostumeWeapon); LoadPlayBoxData(playData.playBox); LoadPlayerTitlesData(playData.playProfileTitle); LoadPlayerIconsData(playData.playProfileIcon); yield return null; LoadAdBuffData(playData.playBuff); LoadCharStatsEnhanceGoldData(playData.playCharEnhanceGold); LoadCharStatsEnhancePointData(playData.playCharEnhancePoint); LoadAwakenData(playData.playAwaken); LoadCostumeEquipStatusData(playData.playCostumeInfo); yield return null; LoadPlayGearEquipment(cGoods.TBagWeapon, playData.playGearWeapon); LoadPlayGearEquipment(cGoods.TBagArmorCape, playData.playGearCape); LoadPlayGearEquipment(cGoods.TBagArmorHat, playData.playGearHat); LoadPlayGearEquipment(cGoods.TBagArmorShoes, playData.playGearShoes); LoadPlayGearEquipment(cGoods.TBagAcceEar, playData.playGearEarring); LoadPlayGearEquipment(cGoods.TBagAcceNeck, playData.playGearNecklace); LoadPlayGearEquipment(cGoods.TBagAcceRing, playData.playGearRing); LoadPlayGearTreasures(playData.playGearTreasure); yield return null; for (int i = 0; i < playData.playRelic.Length; ++i) { cPlayRelic relic = playData.playRelic[i]; PlayRelic.SafeInsert(relic.relicType, relic); } yield return null; LoadPetsPlay(playData.playPet); // load guardian datas for (int i = 0; i < playData.playGuardian.Length; ++i) { cPlayGuardian guardian = playData.playGuardian[i]; PlayGuardian.SafeInsert(playData.playGuardian[i].guardianType, guardian); } yield return null; LoadSkillsPlay(playData.playCharSkillPassive, playData.playCharSkillActive); yield return null; LoadAwakenDungeonData(playData.playDgAwaken); PlayDgAwakenStone = playData.playDgAwakenStone; PlayDgGold = playData.playDgGold; LoadGuardianDungeonData(playData.playDgGuardian); PlayDgPet = playData.playDgPet; PlayDgReinStone = playData.playDgReinStone; PlayDgRelic = playData.playDgRelic; PlayDgPreset = cDungeonPreset.Load(); yield return null; LoadPvpData(playData.playPvp, playData.rankPvp); yield return null; playQuestDaily = playData.playQuestDaily; playQuestRepeat = playData.playQuestRepeat; yield return null; // notice : call method order must be pass -> shop LoadPassPlayData(playData.playPass); LoadShopPlayData(playData.playShop); yield return null; playEventRoulette = playData.playEventRoulette; playEventTrade = playData.playEventTrade; playEventRaise = playData.playEventRaise; playEventReward = playData.playEventReward; playQuestEventAttend = playData.playQuestEventAttend; LoadPlayEventQuestPlay(playData.playQuestEvent); yield return null; SetMailCount(playData.mailCount); } // 실행 중에 사용한 모든 데이터 초기화. 디바이스에 저장된 데이터를 지우는게 아님. 게임 재시작 등에서 사용. public static void ResetAll() { Const = null; PlayData = null; PlayEquipCostume = null; PlayBuff = null; Goods = null; SysBoxes.Clear(); boxNew.Clear(); PlayBoxes = null; dicCosClothSet.Clear(); dicCosCloth.Clear(); cosClothNew.Clear(); dicCosWeaponSet.Clear(); dicCosWeapon.Clear(); cosWeaponNew.Clear(); sysAreas = null; dicMonster.Clear(); dicBg.Clear(); dicBgm.Clear(); dicCharStatEnhanceGold.Clear(); dicCharStatEnhancePoint.Clear(); PlayAwaken = null; sysSkillAwakens = null; sysSkillLvEffects = null; dicSkillPassive.Clear(); dicSkillActive.Clear(); currentTotalSkillLv = 0; sysPetAwakens = null; sysPetLvEffects = null; dicPet.Clear(); petNew.Clear(); petLv = 0; extraRarityRates = null; extraAbilities = null; extraAbilityIds = null; sysGearAwakens = null; sysGearLvEffects = null; foreach (var gears in dicGearEquipment.Values) { gears.Clear(); } foreach (var key in dicGearLast.Keys) { dicGearLast[key] = 1; } foreach (var key in dicGearLastHave.Keys) { dicGearLastHave[key] = -1; } foreach (var key in dicGearLv.Keys) { dicGearLv[key] = 0; } foreach (var gears in dicGearNew.Values) { gears.Clear(); } gearTreasureLvUpLvBounds = null; gearTreasureLvUpSuccRates = null; arrHaveWeapon = null; arrHaveArmor = null; arrHaveAcc = null; dicGearTreasure.Clear(); dicProfileTitle.Clear(); dicProfileIcon.Clear(); sysQuestDaily.Clear(); sysQuestRepeat.Clear(); playQuestDaily = null; playQuestRepeat = null; sysQuestMission.Clear(); sysDgGold = null; sysDgReinStone = null; sysDgPet = null; sysDgAwakenStone = null; sysDgAwaken = null; sysDgGuardian = null; sysGuardian = null; PlayGuardian = null; PlayDgGold = null; PlayDgReinStone = null; PlayDgPet = null; PlayDgAwakenStone = null; PlayDgAwaken = null; PlayDgPreset = null; gachaWeaponLvs = null; gachaWeaponGrades = null; gachaArmorLvs = null; gachaArmorGrades = null; gachaAcceLvs = null; gachaAcceGrades = null; sysBuff = null; sysAttend = null; playAttend = null; dicShop.Clear(); for (int i = 0; i < shopGroupedByShopType.Length; i++) shopGroupedByShopType[i].Clear(); dicPass.Clear(); sysPvp = null; playPvp = null; pvpMyRank = null; pvpRanks = null; PvpRankRefreshTime = TimeUtils.Now(); passEvent = null; passEventNext = null; sysRewardEvent = null; playEventReward = null; dicEvent.Clear(); sysEventTrade = null; MailRefreshTime = TimeUtils.Now(); MailReadRefreshTime = TimeUtils.Now(); MailCount = 0; playMails = null; readMails = null; sysNotices = null; sysChatNotices = null; BuffMgr.ResetAll(); } // 전부 삭제. 로그아웃 등에서 호출. public static void DeleteAll() { ES3.DeleteFile(FormatString.StringFormat(Global.ES3_Server, "1")); ES3.DeleteFile(FormatString.StringFormat(Global.ES3_Server, "2")); ES3.DeleteFile(Global.ES3_PlayDatas); ES3.DeleteFile(Global.ES3_PlayGoods); ES3.DeleteFile(Global.ES3_PlayBox); ES3.DeleteFile(Global.ES3_Pass); ES3.DeleteFile(Global.ES3_Notice); ES3.DeleteFile(Global.ES3_CharAwaken); ES3.DeleteFile(Global.ES3_AdBuff); ES3.DeleteFile(Global.ES3_DgPreset); ES3.DeleteFile(Global.ES3_StartMain); } // 데이터 저장. public static void SaveData() { PlayData.Save(); Goods.Save(PlayData.server); PlayBoxes.Save(PlayData.server); SavePass(); } // 데이터 서버 저장시 처리. public static void OnSaveDataServer() { IsNeedDataSave = false; } #endregion Base #region Play Data // 플레이 데이터 불러오기. public static void LoadPlayData(cPlayData playdata) { if (playdata == null && PlayData != null) return; if (playdata != null) { cPlayData localdata = cPlayData.Load(playdata.server); bLoadLocalData = !playdata.forceOverwrite && playdata.lastTime < localdata.lastTime; if (bLoadLocalData && localdata.lastTime > DateTime.MinValue) { playdata.playerLv = localdata.playerLv; playdata.playerExp = localdata.playerExp; playdata.playerIcon = localdata.playerIcon; playdata.curStage = localdata.curStage; playdata.usePreset = localdata.usePreset; playdata.skillPresets = localdata.skillPresets; playdata.usePetPreset = localdata.usePetPreset; playdata.petPresets = localdata.petPresets; playdata.lastTime = localdata.lastTime; } PlayData = playdata; PlayData.stageRepeat = localdata.stageRepeat; } else { PlayData = cPlayData.Load(1); } } // 플레이 광고버프레벨 데이터 불러오기. private static void LoadAdBuffData(cAdBuffLevel adbuffdata) { if (adbuffdata != null) { cAdBuffLevel localdata = cAdBuffLevel.Load(adbuffdata, PlayData.server); PlayBuff = adbuffdata; PlayBuff.atkExp = localdata.atkExp; PlayBuff.expExp = localdata.expExp; PlayBuff.goldExp = localdata.goldExp; PlayBuff.adTimer[0] = localdata.adTimer[0]; PlayBuff.adTimer[1] = localdata.adTimer[1]; PlayBuff.adTimer[2] = localdata.adTimer[2]; } else { PlayBuff = new cAdBuffLevel(); } } public static void SetPlayRewardEvent(cRewardEvent rewardEvent) { playEventReward.sid = rewardEvent.sid; } public static cRewardEvent GetPlayRewardEvent() { return playEventReward; } #endregion Play Data #region Goods 1 (SetGoods, AddGoods) // 플레이 재화 불러오기. public static void LoadGoodsData(cGoodsData goodsdata) { if (goodsdata == null && Goods != null) return; if (goodsdata != null) { cGoodsData localdata = cGoodsData.Load(PlayData.server); bLoadLocalData = PlayData.lastTime < localdata.lastTime; if (bLoadLocalData && localdata.lastTime > DateTime.MinValue) { goodsdata.gold = localdata.gold; goodsdata.goldUsed = localdata.gold; } Goods = goodsdata; } else { Goods = cGoodsData.Load(PlayData.server); } } // 재화 세팅. public static void SetGoods(cGoodsData playcurrency, bool localExclude) { if (localExclude) { playcurrency.gold = Goods.gold; playcurrency.goldUsed = Goods.goldUsed; } Goods = playcurrency; GameUIMgr.SSetGoods(); Goods.Save(PlayData.server); } // 재화 증가. blocalexclude : 로컬 관리 재화(골드) 증가 안 함. public static void AddGoods(nGoods[] result, cGoodsData playcurrency, bool localExclude) { #region result if (result != null) { // 스탯 재계산 필요. 보유효과, 통합 레벨 효과가 있는 아이템을 처음 획득했을 때 다시 계산. bool brecalcstat = false; for (int i = 0; i < result.Length; ++i) { int itype = result[i].propertyType; int icode = result[i].propertyId; BigInteger icount = result[i].propertyCount; switch (itype) { // 광고 제거. case cGoods.TAdsRemove: PlayData.adRemove = true; break; // 재화. case cGoods.TCurrency: { switch (icode) { case cGoods.CGold: if (localExclude) AddGold(icount); break; } } break; // 장비 획득. case cGoods.TBagWeapon: case cGoods.TBagArmorCape: case cGoods.TBagArmorHat: case cGoods.TBagArmorShoes: case cGoods.TBagAcceEar: case cGoods.TBagAcceNeck: case cGoods.TBagAcceRing: brecalcstat |= AddGearEquip(itype, icode, (int)icount); break; // 보물 획득. case cGoods.TBagTreasure: brecalcstat |= AddGearTreasure(icode, (int)icount); break; // 펫 획득. case cGoods.TPet: brecalcstat |= AddPet(icode); break; // 펫 스피릿 획득. case cGoods.TPetSpirit: AddPetSpirit(icode, (int)icount); break; //던전 티켓 획득 case cGoods.TDgTicketGold: PlayDgGold.ticket += (int)icount; break; case cGoods.TDgTicketPet: PlayDgPet.ticket += (int)icount; break; case cGoods.TDgTicketEnhance: PlayDgReinStone.ticket += (int)icount; break; case cGoods.TDgTicketAwaken: PlayDgAwakenStone.ticket += (int)icount; break; case cGoods.TDgTicketRelic: PlayDgRelic.ticket += (int)icount; break; // 결투장 티켓 획득. case cGoods.TPvpTicket: playPvp.ticket += (int)icount; break; // 코스튬. case cGoods.TCosCloth: brecalcstat |= AddCosCloth(icode); break; case cGoods.TCosWeapon: brecalcstat |= AddCosWeapon(icode); break; // 상자 획득. case cGoods.TBox: AddBox(icode, (int)icount); break; // 아이콘 획득. case cGoods.TProfileIcon: ProfileMgr.SGetIcon(icode); break; // 칭호 획득. case cGoods.TProfileTitle: ProfileMgr.SGetTitle(icode); break; } } } #endregion result // 재화 획득 처리. 동료 영혼석 자동 변환 등 때문에 아래에 위치. if (playcurrency != null) SetGoods(playcurrency, localExclude); } #endregion Goods 1 (SetGoods, AddGoods) #region Goods 2 (Add/Sub Local) // 골드 세팅. public static void SetGold(BigInteger curvalue, BigInteger usedvalue) { Goods.gold = curvalue; Goods.goldUsed = usedvalue; GameUIMgr.SSetGold(Goods.gold); Goods.Save(PlayData.server); } // 골드 증가. public static void AddGold(BigInteger addvalue) { Goods.gold += addvalue; GameUIMgr.SSetGold(Goods.gold); Goods.Save(PlayData.server); } // 골드 감소. public static void SubGold(BigInteger subvalue) { Goods.gold -= subvalue; Goods.goldUsed += subvalue; GameUIMgr.SSetGold(Goods.gold); Goods.Save(PlayData.server); } // 보석 세팅. public static void SetDia(int curvaluep, int curvaluef) { Goods.diaPaid = curvaluep; Goods.diaFree = curvaluef; GameUIMgr.SSetDia(Goods.Dia); Goods.Save(PlayData.server); } // 보석 사용. public static void SubDia(int subvalue) { if (subvalue <= Goods.diaFree) { Goods.diaFree -= subvalue; } else { int subdia = subvalue - Goods.diaFree; Goods.diaFree = 0; Goods.diaPaid -= subdia; } GameUIMgr.SSetDia(Goods.Dia); Goods.Save(PlayData.server); } // 레벨 포인트 세팅. public static void SetLvPoint(int curvalue) { Goods.point = curvalue; GameUIMgr.SSetLvPoint(Goods.point); Goods.Save(PlayData.server); } // 레벨 포인트 획득. public static void AddLvPoint(int addvalue) { IsNeedDataSave = true; Goods.point += addvalue; GameUIMgr.SSetLvPoint(Goods.point); Goods.Save(PlayData.server); } // 레벨 포인트 사용. public static void SubLvPoint(int subvalue) { Goods.point -= subvalue; GameUIMgr.SSetLvPoint(Goods.point); Goods.Save(PlayData.server); } // 강화석 세팅. public static void SetEnhanceStone(int curvalue) { Goods.gearReinStone = curvalue; GameUIMgr.SSetEnhanceStone(Goods.gearReinStone); Goods.Save(PlayData.server); } // 강화석 획득. public static void AddEnhanceStone(int addvalue) { Goods.gearReinStone += addvalue; GameUIMgr.SSetEnhanceStone(Goods.gearReinStone); Goods.Save(PlayData.server); } // 강화석 사용. public static void SubEnhanceStone(int subvalue) { Goods.gearReinStone -= subvalue; GameUIMgr.SSetEnhanceStone(Goods.gearReinStone); Goods.Save(PlayData.server); } // 스킬 강화석 세팅 public static void SetSkillStone(int curvalue) { Goods.skillReinStone = curvalue; GameUIMgr.SSetSkillStone(Goods.skillReinStone); Goods.Save(PlayData.server); } // 스킬 강화석 획득 public static void AddSkillStone(int addvalue) { Goods.skillReinStone += addvalue; GameUIMgr.SSetSkillStone(Goods.skillReinStone); Goods.Save(PlayData.server); } // 스킬 강화석 사용 public static void SubSkillStone(int subvalue) { Goods.skillReinStone -= subvalue; GameUIMgr.SSetSkillStone(Goods.skillReinStone); Goods.Save(PlayData.server); } // 각성석 세팅. public static void SetAwakenStone(int curvalue) { Goods.gearAwakenStone = curvalue; GameUIMgr.SSetAwakenStone(Goods.gearAwakenStone); Goods.Save(PlayData.server); } // 각성석 획득. public static void AddAwakenStone(int addvalue) { Goods.gearAwakenStone += addvalue; GameUIMgr.SSetAwakenStone(Goods.gearAwakenStone); Goods.Save(PlayData.server); } // 각성석 사용. public static void SubAwakenStone(int subvalue) { Goods.gearAwakenStone -= subvalue; GameUIMgr.SSetAwakenStone(Goods.gearAwakenStone); Goods.Save(PlayData.server); } public static void SetAwakenSkillStone(int curvalue) { Goods.skillAwakenStone = curvalue; GameUIMgr.SSetAwakenSkillStone(Goods.skillAwakenStone); Goods.Save(PlayData.server); } public static void AddAwakenSkillStone(int addvalue) { Goods.skillAwakenStone += addvalue; GameUIMgr.SSetAwakenSkillStone(Goods.skillAwakenStone); Goods.Save(PlayData.server); } public static void SubAwakenSkillStone(int subvalue) { Goods.skillAwakenStone -= subvalue; GameUIMgr.SSetAwakenSkillStone(Goods.skillAwakenStone); Goods.Save(PlayData.server); } // 변경석 세팅. public static void SetChangeStone(int curvalue) { Goods.changeStone = curvalue; GameUIMgr.SSetChangeStone(Goods.changeStone); Goods.Save(PlayData.server); } // 변경석 획득. public static void AddChangeStone(int addvalue) { Goods.changeStone += addvalue; GameUIMgr.SSetChangeStone(Goods.changeStone); Goods.Save(PlayData.server); } // 변경석 사용. public static void SubChangeStone(int subvalue) { Goods.changeStone -= subvalue; GameUIMgr.SSetChangeStone(Goods.changeStone); Goods.Save(PlayData.server); } // 푸딩 세팅. public static void SetPudding(int curvalue) { Goods.pudding = curvalue; GameUIMgr.SSetPudding(Goods.pudding); Goods.Save(PlayData.server); } // 푸딩 획득. public static void AddPudding(int addvalue) { Goods.pudding += addvalue; GameUIMgr.SSetPudding(Goods.pudding); Goods.Save(PlayData.server); } // 푸딩 사용. public static void SubPudding(int subvalue) { Goods.pudding -= subvalue; GameUIMgr.SSetPudding(Goods.pudding); Goods.Save(PlayData.server); } #endregion Goods 2 (Add/Sub Local) #region Goods 3 (Box) // 플레이 상자 불러오기. private static void LoadPlayBoxData(nIdCnt[] boxdatas) { if (boxdatas == null && PlayBoxes != null) return; if (boxdatas != null) { if (bLoadLocalData) PlayBoxes = cBoxData.Load(PlayData.server); else PlayBoxes = new cBoxData(boxdatas); } else { PlayBoxes = cBoxData.Load(PlayData.server); } foreach (var box in SysBoxes) { if (!PlayBoxes.dicBoxCount.ContainsKey(box.Key)) { PlayBoxes.dicBoxCount.Add(box.Key, 0); } } PlayBoxes.Save(PlayData.server); } // 모든 상자 수. public static nIdCnt[] GetBoxPlayDatas() { if (PlayBoxes == null) return null; return PlayBoxes.GetPlayData(); } // 상자 수. public static Dictionary GetBoxCounts() { return PlayBoxes.dicBoxCount; } // 현재 상자 소지수. public static int GetBoxCount(int key) { if (PlayBoxes.dicBoxCount.ContainsKey(key)) return PlayBoxes.dicBoxCount[key]; return 0; } // 상자 소지수 증가. public static void AddBox(int key, int addvalue) { PlayBoxes.dicBoxCount[key] += addvalue; IsNeedDataSave = true; if (!boxNew.Contains(key)) boxNew.Add(key); // 0개에서 증가하였으면. if (PlayBoxes.dicBoxCount[key] == addvalue) BagMgr.SSetUpdateConsume(); PlayBoxes.Save(PlayData.server); } // 상자 소지수 감소. public static void SubBox(int key, int subvalue) { if (PlayBoxes.dicBoxCount.ContainsKey(key)) { PlayBoxes.dicBoxCount[key] -= subvalue; // 0개로 감소하였으면. if (PlayBoxes.dicBoxCount[key] <= 0) { boxNew.Remove(key); BagMgr.SSetUpdateConsume(); } } PlayBoxes.Save(PlayData.server); } public static bool IsBoxNewHave() { return boxNew.Count > 0; } public static bool IsBoxNew(int key) { return boxNew.Contains(key); } public static bool RemoveBoxNew(int key) { return boxNew.Remove(key); } #endregion Goods 3 (Box) #region Costume // 플레이 코스튬 데이터 불러오기. public static void LoadCostumeEquipStatusData(cPlayCostume costumedata) { if (PlayEquipCostume != null) return; if (costumedata != null) { PlayEquipCostume = costumedata; } else { PlayEquipCostume = new cPlayCostume(); } } // 코스튬 소지 상태. public static void LoadCostumeData(int[] clplaydatas, int[] wpplaydatas) { // 의상 소지 상태 적용. for (int i = 0; i < clplaydatas.Length; ++i) { if (dicCosCloth.TryGetValue(clplaydatas[i], out dCostume costume)) { costume.have = true; BuffMgr.Instance.AddCostumeEfc(costume.abilityType1, costume.abilityValue1, false); BuffMgr.Instance.AddCostumeEfc(costume.abilityType2, costume.abilityValue2, false); } } // 의상 세트 효과 적용. foreach (var set in dicCosClothSet.Values) { if (IsActiveClothCosSetEffect(set.id)) BuffMgr.Instance.AddCostumeEfc(set.abilityType, set.abilityValue, false); } // 무기 소지 상태 적용. for (int i = 0; i < wpplaydatas.Length; ++i) { if (dicCosWeapon.TryGetValue(wpplaydatas[i], out dCostume costume)) { costume.have = true; BuffMgr.Instance.AddCostumeEfc(costume.abilityType1, costume.abilityValue1, false); BuffMgr.Instance.AddCostumeEfc(costume.abilityType2, costume.abilityValue2, false); } } // 무기 세트 효과 적용. foreach (var set in dicCosWeaponSet.Values) { if (IsActiveWeaponCosSetEffect(set.id)) BuffMgr.Instance.AddCostumeEfc(set.abilityType, set.abilityValue, false); } } public static Dictionary GetCosClothSets() => dicCosClothSet; public static Dictionary GetCosWeaponSets() => dicCosWeaponSet; public static dCostumeSet GetCosClothSet(int setkey) { if (dicCosClothSet.ContainsKey(setkey)) return dicCosClothSet[setkey]; return dicCosClothSet[cGoods.CCosClothSetBase]; } public static dCostumeSet GetCosWeaponSet(int setkey) { if (dicCosWeaponSet.ContainsKey(setkey)) return dicCosWeaponSet[setkey]; return dicCosWeaponSet[cGoods.CCosWeaponSetBase]; } public static dCostumeSet GetCosClothSetByItem(int key) { foreach (var item in dicCosClothSet) { int[] keys = item.Value.set; for (int i = 0; i < keys.Length; i++) { if (keys[i] == key) return item.Value; } } return dicCosClothSet[cGoods.CCosClothSetBase]; } public static dCostumeSet GetCosWeaponSetByItem(int key) { foreach (var item in dicCosWeaponSet) { int[] keys = item.Value.set; for (int i = 0; i < keys.Length; i++) { if (keys[i] == key) return item.Value; } } return dicCosWeaponSet[cGoods.CCosWeaponSetBase]; } public static int GetCosClothId(int key, int ichildindex) { if (dicCosClothSet.ContainsKey(key)) return dicCosClothSet[key].set[ichildindex]; return dicCosClothSet[cGoods.CCosClothSetBase].set[ichildindex]; } public static int GetCosWeaponId(int key, int ichildindex) { if (dicCosWeapon.ContainsKey(key)) return dicCosWeaponSet[key].set[ichildindex]; return dicCosWeaponSet[cGoods.CCosWeaponSetBase].set[ichildindex]; } public static dCostume GetCosCloth(int key) { if (dicCosCloth.ContainsKey(key)) return dicCosCloth[key]; return dicCosCloth[cGoods.CCosClothBase]; } public static dCostume GetCosWeapon(int key) { if (dicCosWeapon.ContainsKey(key)) return dicCosWeapon[key]; return dicCosWeapon[cGoods.CCosWeaponBase]; } public static string GetCosClothPath(int key) { if (dicCosCloth.ContainsKey(key)) return FormatString.CombineAllString(AddressableMgr.PCosCloth, key.ToString()); return AddressableMgr.PCosClothBase; } public static string GetCosWeaponPath(int key) { if (dicCosWeapon.ContainsKey(key)) return FormatString.CombineAllString(AddressableMgr.PCosWeapon, key.ToString()); return AddressableMgr.PCosWeaponBase; } public static bool IsCosClothHave(int key) { if (dicCosCloth.ContainsKey(key)) return dicCosCloth[key].have; return false; } public static bool IsCosWeaponHave(int key) { if (dicCosWeapon.ContainsKey(key)) return dicCosWeapon[key].have; return false; } // 의상 세트 이펙트 활성화 상태 체크. public static bool IsActiveClothCosSetEffect(int setkey) { if (!dicCosClothSet.ContainsKey(setkey)) return false; int[] costumes = dicCosClothSet[setkey].set; for (int i = 0; i < costumes.Length; i++) { if (costumes[i] < 0) continue; if (!dicCosCloth[costumes[i]].have) { return false; } } return true; } // 무기 세트 이펙트 활성화 상태 체크. public static bool IsActiveWeaponCosSetEffect(int setkey) { if (!dicCosWeaponSet.ContainsKey(setkey)) return false; int[] costumes = dicCosWeaponSet[setkey].set; for (int k = 0; k < costumes.Length; k++) { if (costumes[k] < 0) continue; if (!dicCosWeapon[costumes[k]].have) { return false; } } return true; } // 의상 획득. public static bool AddCosCloth(int key) { if (!dicCosCloth.ContainsKey(key)) return false; if (dicCosCloth[key].have) return false; dCostume data = dicCosCloth[key]; data.have = true; cosClothNew.Add(key); BuffMgr.Instance.AddCostumeEfc(data.abilityType1, data.abilityValue1, false); BuffMgr.Instance.AddCostumeEfc(data.abilityType2, data.abilityValue2, false); dCostumeSet costumeset = GetCosClothSetByItem(key); if (IsActiveClothCosSetEffect(costumeset.id)) BuffMgr.Instance.AddCostumeEfc(costumeset.abilityType, costumeset.abilityValue, false); return true; } // 무기 획득. public static bool AddCosWeapon(int key) { if (!dicCosWeapon.ContainsKey(key)) return false; if (dicCosWeapon[key].have) return false; dCostume data = dicCosWeapon[key]; data.have = true; cosWeaponNew.Add(key); BuffMgr.Instance.AddCostumeEfc(data.abilityType1, data.abilityValue1, false); BuffMgr.Instance.AddCostumeEfc(data.abilityType2, data.abilityValue2, false); dCostumeSet costumeset = GetCosWeaponSetByItem(key); if (IsActiveWeaponCosSetEffect(costumeset.id)) BuffMgr.Instance.AddCostumeEfc(costumeset.abilityType, costumeset.abilityValue, false); return true; } // 코스튬 변경. public static void ChangeCustomize(int icloth, int iweapon, int iclrhair, int iclrtop, int iclreye) { PlayEquipCostume.outfitId = icloth; PlayEquipCostume.weaponId = iweapon; PlayEquipCostume.hairColor = iclrhair; PlayEquipCostume.topColor = iclrtop; PlayEquipCostume.eyeColor = iclreye; } #endregion Costume #region Area & Monster public static dArea GetArea(int iareastage) { if (iareastage <= 100) return sysAreas[0]; int iarea = (iareastage / 100) - 1; if (iareastage >= sysAreas.Length) return sysAreas[sysAreas.Length - 1]; return sysAreas[(iarea * 50 + iareastage % 100) - 1]; } public static string GetMonsterPath(int idx) { if (dicMonster.ContainsKey(idx)) return dicMonster[idx].path; return "null"; } public static int GetMonsterSpeed(int idx) { if (dicMonster.ContainsKey(idx)) return dicMonster[idx].speed; return 0; } public static int GetMonsterGroup(int idx) { if (dicMonster.ContainsKey(idx)) return dicMonster[idx].group; return 0; } public static dBg GetBg(int idx) { if (dicBg.ContainsKey(idx)) return dicBg[idx]; return dicBg[1]; } public static bool IsAvailBgm(BGM bgm) => dicBgm.ContainsKey(bgm); public static string GetBgmPath(BGM bgm) { if (dicBgm.TryGetValue(bgm, out dBgm targetBgm)) return targetBgm.path; else return "intro"; } #endregion Area & Monster #region Stage public static bool ClearStage(bool bgonext) { bool stageClear = false; bool bareachange = false; if (PlayData.curStage > PlayData.clearStage) { PlayData.clearStage = PlayData.curStage; stageClear = true; SetPassProgress(eCondition.StageClear, PlayData.clearStage); } if (bgonext) { // 플레이 데이터의 스테이지 값은 (지역번호 * 100) + 스테이지 번호. int iarea = PlayData.curStage / 100; int istage = PlayData.curStage % 100; if (istage < Const.stageMax) { PlayData.curStage++; } else if (iarea < sysAreas.Length) { bareachange = true; iarea++; PlayData.curStage = iarea * 100 + 1; } } BattleMgr.SStageMoveSave(stageClear); PlayData.Save(); return bareachange; } public static void FailStage() { // 플레이 데이터의 스테이지 값은 (지역번호 * 100) + 스테이지 번호. int iarea = PlayData.curStage / 100; int istage = PlayData.curStage % 100; if (istage > 1) { PlayData.curStage--; } else if (iarea > 1) { iarea--; PlayData.curStage = iarea * 100 + Const.stageMax; } PlayData.Save(); } public static void GoToStage(int iarea, int istage) { if (iarea > sysAreas.Length) iarea = sysAreas.Length; if (istage > Const.stageMax) istage = Const.stageMax; int iareastage = iarea * 100 + istage; int imaxareastage = SettingMgr.SGetTest() ? iareastage : GetMaxStage(); if (iareastage <= imaxareastage) PlayData.curStage = iareastage; else PlayData.curStage = imaxareastage; PlayData.Save(); } // 플레이 가능한 스테이지인지. public static bool IsAvailStage(int iareastage) { return iareastage <= GetMaxStage(); } // 클리어한 스테이지인지. public static bool IsClearStage(int iareastage) { return iareastage <= PlayData.clearStage; } // 플레이 가능한 최고 스테이지. public static int GetMaxStage() { // 플레이 데이터의 스테이지 값은 (지역번호 * 100) + 스테이지 번호. int iarea = PlayData.clearStage / 100; int istage = PlayData.clearStage % 100; if (istage < Const.stageMax) return PlayData.clearStage + 1; if (iarea < sysAreas.Length) return (iarea + 1) * 100 + 1; return PlayData.clearStage; } #endregion Stage #region Player Level public static BigInteger CalcCharLvUpPriceAccum1(int curlevel, int addlevel, double buyingCntInc, BigInteger buyingCnt) { if (addlevel < 1) return buyingCnt; double targetlv = curlevel + addlevel - 1d; targetlv = System.Math.Pow(buyingCntInc, targetlv) - 1d; double curlv = curlevel - 1d; curlv = System.Math.Pow(buyingCntInc, curlv) - 1d; targetlv -= curlv; targetlv *= buyingCntInc; targetlv /= (buyingCntInc - 1d); return buyingCnt * (BigInteger)(targetlv * 100) / 100; } public static float GetPlayerExpRate() { if (PlayData == null) return 0f; int imaxlv = Const.playerMaxLv; int iplayerLv = PlayData.playerLv; BigInteger bimaxExp = CalcCharLvUpPriceAccum1(PlayData.playerLv % 1000, 1, (double)Const.playerLvExpInc / dConst.RateMax, DataHandler.PlayerLevelInterval(PlayData.playerLv)); if ((iplayerLv == imaxlv && PlayData.playerExp >= bimaxExp) || iplayerLv > imaxlv) return 1f; BigInteger birate = PlayData.playerExp * dConst.RateMax / bimaxExp; return (float)birate / dConst.RateMaxFloat; } public static bool AddPlayerExp(BigInteger iaddexp) { if (PlayData == null) return false; // 최대 레벨이며 경험치 가득 찼을 경우. int imaxlv = Const.playerMaxLv; int iplayerLv = PlayData.playerLv; BigInteger bimaxExp = CalcCharLvUpPriceAccum1(PlayData.playerLv % 1000, 1, (double)Const.playerLvExpInc / dConst.RateMax, DataHandler.PlayerLevelInterval(PlayData.playerLv)); if ((iplayerLv == imaxlv && PlayData.playerExp >= bimaxExp) || iplayerLv > imaxlv) { return false; } // 현재 레벨부터 최대 레벨 직전 레벨까지. int ilvpointadd = 0; BigInteger ibefexp = PlayData.playerExp; for (int i = iplayerLv - 1; i <= imaxlv; i++) { BigInteger isubexp = bimaxExp - ibefexp - iaddexp; // 레벨업을 못할 경우. if (isubexp > 0) { PlayData.playerExp = ibefexp + iaddexp; if (ilvpointadd > 0) { AddLvPoint(ilvpointadd); PlayData.Save(); } EnhanceMgr.RefreshPlayerExpInfo(); return ilvpointadd > 0; } // 최대 레벨일 경우. if (i == imaxlv) { PlayData.playerExp = bimaxExp; if (ilvpointadd > 0) { AddLvPoint(ilvpointadd); PlayData.Save(); } EnhanceMgr.RefreshPlayerExpInfo(); return ilvpointadd > 0; } // 레벨업 할 경우. PlayData.playerLv++; // 포인트는 현재 상수로 1씩 ilvpointadd += 1; iaddexp = iaddexp - (bimaxExp - ibefexp); ibefexp = 0; SetPassProgress(eCondition.PlayerLv, PlayData.playerLv); EnhanceMgr.RefreshPlayerExpInfo(); BattleMgr.LevelUpEffectOn(); EnhanceMgr.levelUpScrolRefresh(); bimaxExp = CalcCharLvUpPriceAccum1(PlayData.playerLv % 1000, 1, (double)Const.playerLvExpInc / dConst.RateMax, DataHandler.PlayerLevelInterval(PlayData.playerLv)); CheckSkillsOpen(); } if (ilvpointadd > 0) { AddLvPoint(ilvpointadd); PlayData.Save(); } return ilvpointadd > 0; } #endregion Player Level #region Char Stats public static void LoadCharStatsEnhanceGoldData(nIdLv[] playdatas) { for (int i = 0; i < playdatas.Length; ++i) { if (dicCharStatEnhanceGold.TryGetValue(playdatas[i].sid, out dCharStat charStat)) { charStat.level = playdatas[i].lv; // 해금 조건이 없거나, 있는데 해금 조건을 만족했을 경우. if (charStat.condType == 0 || GetCharStatLevel(charStat.condType) >= charStat.condValue) { BuffMgr.Instance.ChangeCharStat(charStat.abilityType, charStat.abilityValue + (charStat.abilityValueInc * charStat.level), false); } } } } public static Dictionary GetCharStats() { return dicCharStatEnhanceGold; } public static dCharStat GetCharStat(int key) { if (dicCharStatEnhanceGold.ContainsKey(key)) return dicCharStatEnhanceGold[key]; return null; } public static int GetCharStatLevel(int key) { if (dicCharStatEnhanceGold.ContainsKey(key)) return dicCharStatEnhanceGold[key].level; return 0; } public static int GetCharStatUnlockID(eEffectType unlockType) { int condKey = 1; switch (unlockType) { case eEffectType.None: condKey = 1; break; case eEffectType.AtkBase: condKey = 1; break; case eEffectType.HpBase: condKey = 2; break; case eEffectType.CrtRate: condKey = 3; break; default: break; } return condKey; } public static bool LvUpCharStatMulti(int key, int ilevel, int cost, int nextStat) { if (!dicCharStatEnhanceGold.ContainsKey(key)) return false; int iprice = cost; if (iprice > Goods.gold) return false; SubGold(cost); dicCharStatEnhanceGold[key].level = ilevel; //BuffMgr.Instance.ChangeCharStat(dicCharStat[key].abilityType, dicCharStat[key].abilityValue + (dicCharStat[key].abilityValueInc * ilevel)); BuffMgr.Instance.ChangeCharStat(dicCharStatEnhanceGold[key].abilityType, nextStat, true); return true; } public static void LvUpCharStatServer(int key, int ilevel, BigInteger biprice, int nextStat) { if (!dicCharStatEnhanceGold.ContainsKey(key)) return; SubGold(biprice); dicCharStatEnhanceGold[key].level = ilevel; BuffMgr.Instance.ChangeCharStat(dicCharStatEnhanceGold[key].abilityType, nextStat, true); } #endregion Char Stats #region Char LvPoints public static void LoadCharStatsEnhancePointData(nIdLv[] playdatas) { for (int i = 0; i < playdatas.Length; ++i) { nIdLv idlv = playdatas[i]; if (dicCharStatEnhancePoint.TryGetValue(idlv.sid, out dCharStat targetStat)) { targetStat.level = idlv.lv; if (PlayData.playerLv >= targetStat.condValue) { BuffMgr.Instance.ChangeCharLvPoint(targetStat.abilityType, targetStat.abilityValue + (targetStat.abilityValueInc * targetStat.level), false); } } } } public static Dictionary GetCharLvPoints() { return dicCharStatEnhancePoint; } public static dCharStat GetCharLvPoint(int key) => dicCharStatEnhancePoint.SafeGet(key); public static int GetCharLvPointLevel(int key) { if (dicCharStatEnhancePoint.ContainsKey(key)) return dicCharStatEnhancePoint[key].level; return 0; } public static bool LvUpCharLvPointMulti(int key, int ilevel, int cost, int nextStat) { if (!dicCharStatEnhancePoint.ContainsKey(key)) return false; int iprice = cost; if (iprice > Goods.point) return false; SubLvPoint(iprice); dicCharStatEnhancePoint[key].level = ilevel; //BuffMgr.Instance.ChangeCharLvPoint(dicCharLvPoint[key].abilityType, dicCharLvPoint[key].abilityValue + (dicCharLvPoint[key].abilityValueInc * ilevel)); BuffMgr.Instance.ChangeCharLvPoint(dicCharStatEnhancePoint[key].abilityType, nextStat, true); return true; } public static void LvUpCharPointServer(int key, int ilevel, int iprice, int nextStat) { if (!dicCharStatEnhancePoint.ContainsKey(key)) return; //SubLvPoint(iprice); dicCharStatEnhancePoint[key].level = ilevel; BuffMgr.Instance.ChangeCharLvPoint(dicCharStatEnhancePoint[key].abilityType, nextStat, true); } public static void AllResetLvPoint() { foreach (var item in dicCharStatEnhancePoint) { dicCharStatEnhancePoint[item.Key].level = 1; } } #endregion Char LvPoints #region DungeonInfo public static Dictionary GetSysGuardians() { return sysGuardian; } public static dSysGuardian GetSysGuardian(int type) { return sysGuardian[type]; } public static dDungeonInfo GetDungeonTypeInfo(DungeonMgr.DungeonKind type) { switch (type) { case DungeonMgr.DungeonKind.GoldDG: return sysDgGold; case DungeonMgr.DungeonKind.EnhanceStoneDG: return sysDgReinStone; case DungeonMgr.DungeonKind.PetDG: return sysDgPet; case DungeonMgr.DungeonKind.AwakenStoneDG: return sysDgAwakenStone; case DungeonMgr.DungeonKind.AwakenDG: return sysDgAwaken; case DungeonMgr.DungeonKind.GuardianDG: int guardian = (DungeonMgr.GetDungeonKind() == DungeonMgr.DungeonKind.GuardianDG) ? GuardianMgr.GetGuardianId() : 0; return sysDgGuardian[guardian - 1]; case DungeonMgr.DungeonKind.relicDG: return sysDgRelic; default: return null; } } public static int GetDungeonTicketCount(DungeonMgr.DungeonKind type) { switch (type) { case DungeonMgr.DungeonKind.GoldDG: return PlayDgGold.ticket; case DungeonMgr.DungeonKind.EnhanceStoneDG: return PlayDgReinStone.ticket; case DungeonMgr.DungeonKind.PetDG: return PlayDgPet.ticket; case DungeonMgr.DungeonKind.AwakenStoneDG: return PlayDgAwakenStone.ticket; case DungeonMgr.DungeonKind.AwakenDG: return PlayDgAwaken.ticket; case DungeonMgr.DungeonKind.relicDG: return PlayDgRelic.ticket; default: return 0; } } #endregion #region DungeonClear public static void LoadAwakenDungeonData(cPlayerDungeonInfo data) { PlayDgAwaken = data; if (data.lv != 1) BuffMgr.Instance.ChangeAwakenDungeonStat(data.lv - 1); } public static void LoadGuardianDungeonData(cPlayerDungeonInfo[] data) { if (PlayDgGuardian == null) { PlayDgGuardian = new Dictionary(); } for (int i = 0; i < data.Length; ++i) { PlayDgGuardian.SafeInsert(data[i].sid, data[i]); } } public static cPlayerDungeonInfo GetPlayerDungeonInfo(int i) { return PlayDgGuardian[i]; } public static cPlayerDungeonInfo GetPlayerDungeonInfoKind(DungeonMgr.DungeonKind kind, int guardian = 0) { switch (kind) { case DungeonMgr.DungeonKind.GoldDG: return PlayDgGold; case DungeonMgr.DungeonKind.EnhanceStoneDG: return PlayDgReinStone; case DungeonMgr.DungeonKind.PetDG: return PlayDgPet; case DungeonMgr.DungeonKind.AwakenStoneDG: return PlayDgAwakenStone; case DungeonMgr.DungeonKind.AwakenDG: return PlayDgAwaken; case DungeonMgr.DungeonKind.GuardianDG: return PlayDgGuardian[guardian]; case DungeonMgr.DungeonKind.relicDG: return PlayDgRelic; default: return null; } } public static Dictionary GetPlayDungeonGuardians() { return PlayDgGuardian; } public static int GetDungeonClearLevel(DungeonMgr.DungeonKind i) { switch (i) { case DungeonMgr.DungeonKind.GoldDG: return PlayDgGold.lv - 1; case DungeonMgr.DungeonKind.EnhanceStoneDG: return PlayDgReinStone.lv - 1; case DungeonMgr.DungeonKind.PetDG: return PlayDgPet.lv - 1; case DungeonMgr.DungeonKind.AwakenStoneDG: return PlayDgAwakenStone.lv - 1; case DungeonMgr.DungeonKind.AwakenDG: return PlayDgAwaken.lv - 1; case DungeonMgr.DungeonKind.relicDG: return PlayDgRelic.lv - 1; default: return 0; } } #endregion #region Awaken public static void LoadAwakenData(cAwakenData data) { cAwakenData localdata = cAwakenData.Load(data); PlayAwaken = data; data.OnAfterDeserialize(); PlayAwaken.usePreset = localdata.usePreset; PlayAwaken.awakenUnlock = localdata.awakenUnlock; EnhanceMgr.StartSetAwakenPreset(); } public static void SaveAwakenPreset() { PlayAwaken.Save(); } public static cAwakenData GetServerAwakenSlots() { return PlayAwaken; } public static void SetServerAwakenSlot(cAwakenData data, int preset) { PlayAwaken = data; PlayAwaken.usePreset = preset; } public static void AwakenSlotUnlock(int key) { //enhanceAwakenSlot.awaken++; EnhanceMgr.SetSelected(key); EnhanceMgr.UnlockSlot(key); } public static void btnAwakenPresetSet(int preset, bool isSave) { PlayAwaken.usePreset = preset; if (isSave) { PlayAwaken.Save(); } } public static Dictionary GetPlayGuardians() { return PlayGuardian; } public static cPlayGuardian GetPlayGuardian(int i) { if (!PlayGuardian.ContainsKey(i)) { return null; } return PlayGuardian[i]; } public static void SetPlayGuardian(int type, cPlayGuardian data) { PlayGuardian[type] = data; } public static void SetPlayGuardianExtra(int type, int[] extra) { PlayGuardian[type].extras = extra; } #endregion #region MaskRelic public static IList GetSysRelicGroup(int relicType) { return sysRelicsGroupedByType[relicType]; } public static cPlayRelic GetPlayRelic(int relicType) { return PlayRelic[relicType]; } public static void SetPlayRelic(int tab, cPlayRelic saveRelic) { PlayRelic[tab] = saveRelic; } public static bool LvUpRelicEnhance(int key) { if (!PlayRelic.ContainsKey(key)) return false; int iprop = GetRelicEnhanceProp(PlayRelic[key].ancientLv); if (Random.Range(0, dConst.RateMax) >= iprop) return false; return true; } public static int GetRelicEnhanceProp(int ilevel) { int imaxindex = sysRelicEnhancePropLvs.Length - 1; if (ilevel >= sysRelicEnhancePropLvs[imaxindex]) return sysRelicEnhanceProp[imaxindex]; for (int i = 1; i <= imaxindex; i++) { if (ilevel < sysRelicEnhancePropLvs[i]) return sysRelicEnhanceProp[i - 1]; } return 0; } #endregion #region Extra Ability public static void LoadExtraAbility(dExtraRarity[] rates, dExtraAbility[] abilities) { extraRarityRates = new int[rates.Length]; extraAbilityIds = new Dictionary[rates.Length]; extraAbilities = new Dictionary(); for (int i = 0; i < rates.Length; i++) { extraAbilityIds[i] = new Dictionary(); extraRarityRates[i] = rates[i].prop; } for (int i = 0; i < abilities.Length; i++) { int key = abilities[i].id; extraAbilities.SafeInsert(new KeyValuePair(key, abilities[i])); eEffectType type = abilities[i].abilityType; if (extraAbilityIds[0].ContainsKey(type)) { extraAbilityIds[abilities[i].rarity - 1][type] = key; } else { for (int j = 0; j < rates.Length; j++) { extraAbilityIds[j].Add(type, key); } } } BuffMgr.Instance.InitExtra(); } // 희귀도별 확률. public static int GetExtraRarityRate(int irarity) { if (irarity <= 0 || irarity > cGoods.RMyth) return 0; return extraRarityRates[irarity - 1]; } // 전체 희귀도 효과 값. public static Dictionary[] GetExtraAbilityIds() { return extraAbilityIds; } // 희귀도별 효과 정보. public static dExtraAbility GetExtraAbility(int key) { if (extraAbilities.ContainsKey(key)) return extraAbilities[key]; return null; } // 희귀도별 효과 정보. public static dExtraAbility GetExtraAbilityByType(int irarity, eEffectType type) { if (irarity <= 0 || irarity > cGoods.RMyth) return null; if (!extraAbilityIds[irarity - 1].ContainsKey(type)) return null; int key = extraAbilityIds[irarity - 1][type]; return extraAbilities[key]; } // 희귀도별 효과 값. public static int GetExtraAbilityValue(int key) { if (extraAbilities.ContainsKey(key)) return extraAbilities[key].abilityValue; return 0; } // 희귀도별 효과 값. public static int GetExtraAbilityValueByType(int irarity, eEffectType type) { if (irarity <= 0 || irarity > cGoods.RMyth) return 0; if (!extraAbilityIds[irarity - 1].ContainsKey(type)) return 0; int key = extraAbilityIds[irarity - 1][type]; return extraAbilities[key].abilityValue; } #endregion Extra Ability #region Bag - Equip static void LoadSysGearEquipment(int equipmentType, dGear[] datas) { if (!dicGearEquipment.TryGetValue(equipmentType, out Dictionary targetDic)) return; int ilastid = 1; int irarity = cGoods.RMyth; int igrade = 0; for (int i = 0; i < datas.Length; ++i) { dGear gear = datas[i]; targetDic.SafeInsert(gear.id, gear); if ((irarity < gear.rarity) || (irarity == gear.rarity && igrade < gear.grade)) { ilastid = gear.id; irarity = gear.rarity; igrade = gear.grade; } } if(dicGearLast.ContainsKey(equipmentType)) { dicGearLast[equipmentType] = ilastid; } } static void LoadPlayGearEquipment(int equipmentType, nIdLvInfo[] datas) { if (!dicGearEquipment.TryGetValue(equipmentType, out Dictionary targetDic)) return; int totalLevelOfPossession = 0; int ilastid = -1; int irarity = cGoods.RNone; int igrade = 0; for (int i = 0; i < datas.Length; i++) { nIdLvInfo lvInfo = datas[i]; if (!targetDic.TryGetValue(lvInfo.sid, out dGear targetGear)) continue; targetGear.have = lvInfo.have; targetGear.count = lvInfo.cnt; targetGear.awaken = lvInfo.awaken; targetGear.level = lvInfo.lv; targetGear.extraEffects = targetGear.maxAwaken > 1 ? lvInfo.extras : null; if (targetGear.have) { totalLevelOfPossession += targetGear.level; if ((irarity < targetGear.rarity) || (irarity == targetGear.rarity && igrade < targetGear.grade)) { ilastid = targetGear.id; irarity = targetGear.rarity; igrade = targetGear.grade; } } } if (dicGearLastHave.ContainsKey(equipmentType)) { dicGearLastHave[equipmentType] = ilastid; } CalcGearLevelEffect(equipmentType, totalLevelOfPossession, false); CalcGearEquipEffect(equipmentType); CalcGearEquipExtra(equipmentType); } // 현재 장착중인 장비. public static int GetEquipedGear(int itype) { switch (itype) { case cGoods.TBagWeapon: return PlayData.weapon; case cGoods.TBagArmorCape: return PlayData.cape; case cGoods.TBagArmorHat: return PlayData.hat; case cGoods.TBagArmorShoes: return PlayData.shoes; case cGoods.TBagAcceEar: return PlayData.earring; case cGoods.TBagAcceNeck: return PlayData.necklace; case cGoods.TBagAcceRing: return PlayData.ring; default: return 0; } } // 장비 장착. public static bool EquipGear(int itype, int key) { if (!dicGearEquipment.TryGetValue(itype, out Dictionary gears) || !gears.TryGetValue(key, out dGear targetGear) || !targetGear.have) return false; switch (itype) { case cGoods.TBagWeapon: PlayData.weapon = key; break; case cGoods.TBagArmorCape: PlayData.cape = key; break; case cGoods.TBagArmorHat: PlayData.hat = key; break; case cGoods.TBagArmorShoes: PlayData.shoes = key; break; case cGoods.TBagAcceEar: PlayData.earring = key; break; case cGoods.TBagAcceNeck: PlayData.necklace = key; break; case cGoods.TBagAcceRing: PlayData.ring = key; break; } PlayData.Save(); CalcGearEquipEffect(itype); CalcGearEquipExtra(itype); return true; } // 장비 플레이 정보 업데이트(합성 후 호출). public static void UpdateGearEquipsPlay(int itype, nIdLvInfo[] datas) { int ilvadd = 0; int ilastid = dicGearLastHave[itype]; int irarity = cGoods.RNone; int igrade = 0; if (ilastid >= 0) { irarity = dicGearEquipment[itype][ilastid].rarity; igrade = dicGearEquipment[itype][ilastid].grade; } for (int i = 0; i < datas.Length; i++) { int key = datas[i].sid; if (!dicGearEquipment[itype].ContainsKey(key)) continue; if (!datas[i].have) continue; dGear data = dicGearEquipment[itype][key]; if (!data.have) { data.have = true; ilvadd += datas[i].lv; if ((irarity < data.rarity) || (irarity == data.rarity && igrade < data.grade)) { ilastid = key; irarity = data.rarity; igrade = data.grade; } } data.count = datas[i].cnt; data.awaken = datas[i].awaken; data.level = datas[i].lv; if (data.maxAwaken > 1) data.extraEffects = datas[i].extras; } dicGearLastHave[itype] = ilastid; LoadCurGearHave(); // 레벨 효과 계산. CalcGearLevelEffect(itype, ilvadd, false); } // 장비 최고 레벨. public static int GetGearMaxLv(int itype, int key) { int index = dicGearEquipment[itype][key].awaken - 1; if (index >= sysGearAwakens.Length) index = sysGearAwakens.Length - 1; else if (index < 0) index = 0; return sysGearAwakens[index].maxLv; } // 장비 각성 단계 정보. public static dAwaken GetGearAwakenNext(int itype, int key) { int index = dicGearEquipment[itype][key].awaken; if (index >= sysGearAwakens.Length) index = sysGearAwakens.Length - 1; else if (index < 0) index = 0; return sysGearAwakens[index]; } // 장비 각성 필요 재료. public static int[] GetGearAwakenNeeds(int itype, int key) { int[] ineeds = new int[3] { key, -1, -1 }; dGear gear = dicGearEquipment[itype][key]; int irarity1 = gear.rarity; int igrade1 = gear.grade - 1; if (igrade1 <= 0) { irarity1--; igrade1 += cGoods.GMax; } int irarity2 = gear.rarity; int igrade2 = gear.grade - 2; if (igrade2 <= 0) { irarity2--; igrade2 += cGoods.GMax; } foreach (var item in dicGearEquipment[itype]) { if (item.Value.rarity == irarity1 && item.Value.grade == igrade1) { ineeds[1] = item.Key; if (ineeds[2] >= 0) break; } if (item.Value.rarity == irarity2 && item.Value.grade == igrade2) { ineeds[2] = item.Key; if (ineeds[1] >= 0) break; } } return ineeds; } // 장비 통합 레벨 효과 계산 및 적용. private static bool CalcGearLevelEffect(int itype, int iaddlv, bool brecalc) { int prevlv = dicGearLv[itype]; dicGearLv[itype] += iaddlv; int nextlv = dicGearLv[itype]; int prevefc = -1; int nextefc = -1; for (int i = sysGearLvEffects.Length - 1; i >= 0; i--) { if (nextefc < 0 && nextlv >= sysGearLvEffects[i].totalLv) { nextefc = i; } if (prevefc < 0 && prevlv >= sysGearLvEffects[i].totalLv) { prevefc = i; break; } } // 이전 효과와 다르고 적용 효과가 있을 경우. if (nextefc != prevefc && nextefc >= 0) { BuffMgr.Instance.SetGearLv(itype, sysGearLvEffects[nextefc].value, true); return true; } return false; } /// /// 장비 통합 레벨 정보. /// /// 장비 타입. cGoods.TBagX /// 0:현재 통합 레벨, 1:현재 단계, 2:현재 단계 효과 값, 3:다음 단계 통합 레벨. public static int[] GetGearTotalLevels(int itype) { int[] ilvs = new int[4]; ilvs[0] = dicGearLv[itype]; for (int i = sysGearLvEffects.Length - 1; i >= 0; i--) { if (ilvs[0] >= sysGearLvEffects[i].totalLv) { ilvs[1] = i + 1; ilvs[2] = sysGearLvEffects[i].value; if (i < (sysGearLvEffects.Length - 1)) ilvs[3] = sysGearLvEffects[i + 1].totalLv; else ilvs[3] = sysGearLvEffects[i].totalLv; break; } } return ilvs; } // 장비 장착 효과 계산 및 적용. private static void CalcGearEquipEffect(int itype) { int key; switch (itype) { case cGoods.TBagWeapon: key = PlayData.weapon; break; case cGoods.TBagArmorCape: key = PlayData.cape; break; case cGoods.TBagArmorHat: key = PlayData.hat; break; case cGoods.TBagArmorShoes: key = PlayData.shoes; break; case cGoods.TBagAcceEar: key = PlayData.earring; break; case cGoods.TBagAcceNeck: key = PlayData.necklace; break; case cGoods.TBagAcceRing: key = PlayData.ring; break; default: return; } if (key < 0) return; dGear gear = dicGearEquipment[itype][key]; if (gear.abilityType3 != eEffectType.None) { long ivalue = gear.abilityValue3 + ((gear.abilityValue3 * gear.abilityValueInc3 / dConst.RateDivideLong) * (gear.level - 1));//// (long)MathF.Pow(dConst.RateDivideInt2, gear.level); // (gear.level - 1) * gear.abilityValueInc3 + gear.abilityValue3; BuffMgr.Instance.SetGearEquip(itype, gear.abilityType3, ivalue, false); } if (gear.abilityType2 != eEffectType.None) { long ivalue = gear.abilityValue2 + ((gear.abilityValue2 * gear.abilityValueInc2 / dConst.RateDivideLong) * (gear.level - 1));// (long)MathF.Pow(dConst.RateDivideInt2, gear.level); BuffMgr.Instance.SetGearEquip(itype, gear.abilityType2, ivalue, false); } if (gear.abilityType1 != eEffectType.None) { long ivalue = gear.abilityValue1 + ((gear.abilityValue1 * gear.abilityValueInc1 / dConst.RateDivideLong) * (gear.level - 1));// (long)MathF.Pow(dConst.RateDivideInt2, gear.level); BuffMgr.Instance.SetGearEquip(itype, gear.abilityType1, ivalue, true); } } // 장비 추가 효과 계산 및 적용. public static void CalcGearEquipExtra(int itype) { int key; switch (itype) { case cGoods.TBagWeapon: key = PlayData.weapon; break; case cGoods.TBagArmorCape: key = PlayData.cape; break; case cGoods.TBagArmorHat: key = PlayData.hat; break; case cGoods.TBagArmorShoes: key = PlayData.shoes; break; case cGoods.TBagAcceEar: key = PlayData.earring; break; case cGoods.TBagAcceNeck: key = PlayData.necklace; break; case cGoods.TBagAcceRing: key = PlayData.ring; break; default: return; } if (key < 0) return; dGear gear = dicGearEquipment[itype][key]; if (gear.awaken <= 1 || gear.extraEffects == null) { BuffMgr.Instance.SetGearExtra(itype, 2, eEffectType.None, 0L, false); BuffMgr.Instance.SetGearExtra(itype, 1, eEffectType.None, 0L, false); BuffMgr.Instance.SetGearExtra(itype, 0, eEffectType.None, 0L, true); return; } int[] extras = gear.extraEffects; for (int i = extras.Length - 1; i >= 0; i--) { if (extras[i] < 0) { BuffMgr.Instance.SetGearExtra(itype, i, eEffectType.None, 0L, i == 0); } else { dExtraAbility ability = GetExtraAbility(extras[i]); BuffMgr.Instance.SetGearExtra(itype, i, ability.abilityType, ability.abilityValue, i == 0); } } } public static Dictionary GetGearEquips(int itype) { return dicGearEquipment[itype]; } public static dGear GetGearEquip(int itype, int key) { if (dicGearEquipment[itype].ContainsKey(key)) return dicGearEquipment[itype][key]; return null; } public static int GetGearEquipByGrade(int itype, int irarity, int igrade) { Dictionary datas = dicGearEquipment[itype]; foreach (var item in datas) { if (item.Value.rarity == irarity && item.Value.grade == igrade) return item.Key; } return -1; } public static int GetGearEquipLast(int itype) { return dicGearLast[itype]; } public static int GetGearEquipRarity(int itype, int key) { if (dicGearEquipment[itype].ContainsKey(key)) return dicGearEquipment[itype][key].rarity; return 0; } public static bool AddGearEquip(int itype, int key, int icount) { if (!dicGearEquipment[itype].ContainsKey(key)) return false; if (dicGearEquipment[itype][key].have) { dicGearEquipment[itype][key].count += icount; return false; } dGear data = dicGearEquipment[itype][key]; data.have = true; data.level = 1; data.awaken = 1; data.count = icount - 1; addHaveGear(itype, data.rarity); if (data.maxAwaken > 1) data.extraEffects = new int[3] { -1, -1, -1 }; dicGearNew[itype].Add(key); if (dicGearLastHave[itype] < 0) { dicGearLastHave[itype] = data.id; } else { dGear datalasthave = dicGearEquipment[itype][dicGearLastHave[itype]]; if ((datalasthave.rarity < data.rarity) || (datalasthave.rarity == data.rarity && datalasthave.grade < data.grade)) dicGearLastHave[itype] = data.id; } CalcGearLevelEffect(itype, 1, false); return true; } public static bool SubGearEquip(int itype, int key, int icount) { if (!dicGearEquipment[itype].ContainsKey(key)) return false; if (dicGearEquipment[itype][key].count < icount) return false; dGear data = dicGearEquipment[itype][key]; data.count -= icount; return true; } public static int GetGearLastHaveId(int itype) { return dicGearLastHave[itype]; } public static bool IsGearComposable(int itype) { foreach (var item in dicGearEquipment[itype]) { if (item.Value.count >= Const.gearComposePrice) return true; } return false; } public static bool IsGearNewHave(int itype) { return dicGearNew[itype].Count > 0; } public static bool IsGearNew(int itype, int key) { //addHaveGear(itype, GetGearEquip(itype,key).rarity); return dicGearNew[itype].Contains(key); } public static bool RemoveGearNew(int itype, int key) { return dicGearNew[itype].Remove(key); } public static void LvUpGearEquip(int itype, int key, int ilevel, bool bcalcstat) { dGear data = dicGearEquipment[itype][key]; int iaddlevel = ilevel - data.level; data.level = ilevel; CalcGearLevelEffect(itype, iaddlevel, bcalcstat); if (bcalcstat && key == GetEquipedGear(itype)) CalcGearEquipEffect(itype); } public static void ChangeGearExtras(int itype, int key, int[] extras) { dicGearEquipment[itype][key].extraEffects = extras; } public static void LoadCurGearHave() { for (int i = 0; i < GetGearEquips(cGoods.TBagWeapon).Count; i++) { if (GetGearEquip(cGoods.TBagWeapon, i + 1).have) addHaveGear(cGoods.TBagWeapon, GetGearEquip(cGoods.TBagWeapon, i + 1).rarity); } for (int i = 0; i < GetGearEquips(cGoods.TBagArmorCape).Count; i++) { if (GetGearEquip(cGoods.TBagArmorCape, i + 1).have) addHaveGear(cGoods.TBagArmorCape, GetGearEquip(cGoods.TBagArmorCape, i + 1).rarity); } for (int i = 0; i < GetGearEquips(cGoods.TBagArmorHat).Count; i++) { if (GetGearEquip(cGoods.TBagArmorHat, i + 1).have) addHaveGear(cGoods.TBagArmorHat, GetGearEquip(cGoods.TBagArmorHat, i + 1).rarity); } for (int i = 0; i < GetGearEquips(cGoods.TBagArmorShoes).Count; i++) { if (GetGearEquip(cGoods.TBagArmorShoes, i + 1).have) addHaveGear(cGoods.TBagArmorShoes, GetGearEquip(cGoods.TBagArmorShoes, i + 1).rarity); } for (int i = 0; i < GetGearEquips(cGoods.TBagAcceEar).Count; i++) { if (GetGearEquip(cGoods.TBagAcceEar, i + 1).have) addHaveGear(cGoods.TBagAcceEar, GetGearEquip(cGoods.TBagAcceEar, i + 1).rarity); } for (int i = 0; i < GetGearEquips(cGoods.TBagAcceNeck).Count; i++) { if (GetGearEquip(cGoods.TBagAcceNeck, i + 1).have) addHaveGear(cGoods.TBagAcceNeck, GetGearEquip(cGoods.TBagAcceNeck, i + 1).rarity); } for (int i = 0; i < GetGearEquips(cGoods.TBagAcceRing).Count; i++) { if (GetGearEquip(cGoods.TBagAcceRing, i + 1).have) addHaveGear(cGoods.TBagAcceRing, GetGearEquip(cGoods.TBagAcceRing, i + 1).rarity); } } public static void addHaveGear(int type, int rarity) { switch (type) { case cGoods.TBagWeapon: arrHaveWeapon[rarity - 1]++; break; case cGoods.TBagArmorCape: arrHaveArmor[0, rarity - 1]++; break; case cGoods.TBagArmorHat: arrHaveArmor[1, rarity - 1]++; break; case cGoods.TBagArmorShoes: arrHaveArmor[2, rarity - 1]++; break; case cGoods.TBagAcceEar: arrHaveAcc[0, rarity - 1]++; break; case cGoods.TBagAcceNeck: arrHaveAcc[1, rarity - 1]++; break; case cGoods.TBagAcceRing: arrHaveAcc[2, rarity - 1]++; break; } } #endregion Bag - Equip #region Bag - Treasure public static void LoadPlayGearTreasures(nIdLvInfo[] playdatas) { for (int i = 0; i < playdatas.Length; i++) { var lvInfo = playdatas[i]; if (!dicGearTreasure.TryGetValue(lvInfo.sid, out dTreasure treasure)) continue; treasure.have = lvInfo.have; treasure.count = lvInfo.cnt; treasure.level = 0; if (treasure.have) { treasure.level = lvInfo.lv; BuffMgr.Instance.SetGearTreasure(treasure.abilityType, GetGearTreasureEffect(treasure.abilityValue, treasure.abilityValueInc, treasure.level), true); } } } public static void UpdateGearTreasurePlay(nIdLvInfo trsdata) { dTreasure data = dicGearTreasure[trsdata.sid]; data.have = trsdata.have; data.level = trsdata.lv; data.count = trsdata.cnt; BuffMgr.Instance.SetGearTreasure(data.abilityType, GetGearTreasureEffect(data.abilityValue, data.abilityValueInc, data.level), true); } public static void UpdateGearTreasure(int key, int ilevel, int icount) { dTreasure data = dicGearTreasure[key]; data.level = ilevel; data.count = icount; BuffMgr.Instance.SetGearTreasure(data.abilityType, GetGearTreasureEffect(data.abilityValue, data.abilityValueInc, data.level), true); } public static Dictionary GetGearTreasures() { return dicGearTreasure; } public static dTreasure GetGearTreasure(int key) { if (dicGearTreasure.ContainsKey(key)) return dicGearTreasure[key]; return null; } public static bool AddGearTreasure(int key, int icount) { if (!dicGearTreasure.ContainsKey(key)) return false; if (dicGearTreasure[key].have) { dicGearTreasure[key].count += icount; return false; } dTreasure data = dicGearTreasure[key]; data.have = true; data.level = 1; data.count = icount - 1; BuffMgr.Instance.SetGearTreasure(data.abilityType, GetGearTreasureEffect(data.abilityValue, data.abilityValueInc, data.level), true); return true; } public static bool allTreasureMax() { dTreasure curTreasure = new dTreasure(); for (int i = 0; i < GetGearTreasures().Count; i++) { curTreasure = GetGearTreasure(i+1); if (curTreasure.level != curTreasure.maxLv) return false; } return true; } public static bool LvUpGearTreasure(int key) { if (!dicGearTreasure.ContainsKey(key)) return false; if (dicGearTreasure[key].count <= 0) return false; dicGearTreasure[key].count--; int iprop = GetGearTreasureProp(dicGearTreasure[key].level); if (Random.Range(0, dConst.RateMax) >= iprop) return false; dicGearTreasure[key].level++; return true; } // 보물 효과. public static long GetGearTreasureEffect(long ibase, long iinc, int ilevel) { if (ilevel <= 0) return 0; ilevel--; return (ilevel * iinc) + ibase; } // 보물 레벨업 확률. public static int GetGearTreasureProp(int ilevel) { int result = 0; for (int i = gearTreasureLvUpLvBounds.Length - 1; i >= 0; --i) { if (ilevel >= gearTreasureLvUpLvBounds[i]) { result = gearTreasureLvUpSuccRates[i]; break; } } return result; } #endregion Bag - Treasure #region Skill public static void LoadSkillsPlay(nIdLvInfo[] playpassives, nIdLvInfo[] playactives) { int iaddlv = 0; for (int i = 0; i < playpassives.Length; ++i) { // 스킬 id가 존재하고 플레이어 레벨이 오픈 레벨 이상일 경우. if (dicSkillPassive.TryGetValue(playactives[i].sid, out var skill) && PlayData.playerLv >= skill.openLv) { skill.level = playactives[i].lv; iaddlv += skill.level; long totalStat = skill.abilityValue + (skill.abilityValueInc * (skill.level - 1)); BuffMgr.Instance.ChangePassiveStat(skill.abilityType, totalStat, false); } } for (int i = 0; i < playactives.Length; ++i) { // 스킬 id가 존재하고 플레이어 레벨이 오픈 레벨 이상일 경우. if (dicSkillActive.TryGetValue(playactives[i].sid, out var skill) && PlayData.playerLv >= skill.openLv) { skill.level = playactives[i].lv; skill.awaken = playactives[i].awaken; iaddlv += skill.level; } } CalcSkillLevelEffect(iaddlv); } private static void CheckSkillsOpen() { foreach (var item in dicSkillPassive) { if (item.Value.level > 0) continue; if (PlayData.playerLv < item.Value.openLv) continue; item.Value.level = 1; } foreach (var item in dicSkillActive) { if (item.Value.level > 0) continue; if (PlayData.playerLv < item.Value.openLv) continue; item.Value.level = 1; item.Value.awaken = 1; } } // 스킬 각성 단계 정보. public static dAwaken[] GetSkillAwakens() { return sysSkillAwakens; } // 스킬 최고 레벨. public static int GetSkillMaxLv(int itype, int key) { if (itype == cGoods.TSkillPassive) { return dicSkillPassive[key].maxLv; } int index = dicSkillActive[key].awaken - 1; if (index >= sysSkillAwakens.Length) index = sysSkillAwakens.Length - 1; else if (index < 0) index = 0; return sysSkillAwakens[index].maxLv; } // 스킬 각성 단계 정보. public static dAwaken GetSkillAwakenNext(int itype, int key) { if (itype != cGoods.TSkillActive) return null; int index = dicSkillActive[key].awaken; if (index >= sysSkillAwakens.Length) index = sysSkillAwakens.Length - 1; else if (index < 0) index = 0; return sysSkillAwakens[index]; } // 스킬 각성 필요 재료. 같은 희귀도의 모자, 망토, 신발. public static int[] GetSkillAwakenNeeds(int itype, int key) { if (itype != cGoods.TSkillActive) return null; int[] ineeds = new int[3]; int irarity = dicSkillActive[key].rarity; int igrade = dicSkillActive[key].awaken + 1; ineeds[0] = GetGearEquipByGrade(cGoods.TBagArmorHat, irarity, igrade); ineeds[1] = GetGearEquipByGrade(cGoods.TBagArmorCape, irarity, igrade); ineeds[2] = GetGearEquipByGrade(cGoods.TBagArmorShoes, irarity, igrade); return ineeds; } // 스킬 통합 레벨 효과 계산 및 적용. private static bool CalcSkillLevelEffect(int iaddlv) { int iprevlv = currentTotalSkillLv; currentTotalSkillLv += iaddlv; int inextlv = currentTotalSkillLv; int iprevefc = -1; int inextefc = -1; for (int i = sysSkillLvEffects.Length - 1; i >= 0; i--) { if (inextefc < 0 && inextlv >= sysSkillLvEffects[i].totalLv) { inextefc = i; } if (iprevefc < 0 && iprevlv >= sysSkillLvEffects[i].totalLv) { iprevefc = i; break; } } BuffMgr.Instance.SetSkillLv(sysSkillLvEffects[inextefc].value); // 이전 효과와 다르고 적용 효과가 있을 경우. if (inextefc != iprevefc && inextefc >= 0) { return true; } return false; } /// /// 스킬 통합 레벨 정보. /// /// 0:현재 통합 레벨, 1:현재 단계, 2:현재 단계 효과 값, 3:다음 단계 통합 레벨. public static int[] GetSkillTotalLevels() { int[] ilvs = new int[4]; ilvs[0] = currentTotalSkillLv; for (int i = sysSkillLvEffects.Length - 1; i >= 0; i--) { if (ilvs[0] >= sysSkillLvEffects[i].totalLv) { ilvs[1] = i + 1; ilvs[2] = sysSkillLvEffects[i].value; if (i < (sysSkillLvEffects.Length - 1)) ilvs[3] = sysSkillLvEffects[i + 1].totalLv; else ilvs[3] = sysSkillLvEffects[i].totalLv; break; } } return ilvs; } public static Dictionary GetSkillPassives() => dicSkillPassive; public static Dictionary GetSkillActives() => dicSkillActive; public static dSkillPassive GetSkillPassive(int key) => dicSkillPassive.SafeGet(key); public static dSkillActive GetSkillActive(int key) => dicSkillActive.SafeGet(key); public static int GetSkillRarity(int itype, int key) { if (itype == cGoods.TSkillActive && dicSkillActive.ContainsKey(key)) return dicSkillActive[key].rarity; if (itype == cGoods.TSkillPassive && dicSkillPassive.ContainsKey(key)) return dicSkillPassive[key].rarity; return 0; } public static float GetSkillCool(int key) { if (!dicSkillActive.ContainsKey(key)) return 99f; float fawaken = 0f; int iawaken = dicSkillActive[key].awaken; for (int i = 1; i < iawaken; i++) { fawaken += sysSkillAwakens[i].coolTimeDec / dConst.RateMaxFloat; } float ftime = 1f - fawaken; if (ftime <= 0f) ftime = 0.1f; ftime *= dicSkillActive[key].coolTime; return ftime; } public static float GetSkillCool(int key, int iawaken) { if (!dicSkillActive.ContainsKey(key)) return 99f; float fawaken = 0f; for (int i = 1; i < iawaken; i++) { fawaken += sysSkillAwakens[i].coolTimeDec / dConst.RateMaxFloat; } float ftime = 1f - fawaken; if (ftime <= 0f) ftime = 0.1f; ftime *= dicSkillActive[key].coolTime; return ftime; } public static void LvUpSkill(int itype, int key, int ilevel) { // 액티브. if (itype == cGoods.TSkillActive) { if (!dicSkillActive.ContainsKey(key)) return; CalcSkillLevelEffect(ilevel - dicSkillActive[key].level); dicSkillActive[key].level = ilevel; return; } // 패시브. if (!dicSkillPassive.ContainsKey(key)) return; CalcSkillLevelEffect(ilevel - dicSkillPassive[key].level); dicSkillPassive[key].level = ilevel; long totalStat = dicSkillPassive[key].abilityValue + (dicSkillPassive[key].abilityValueInc * (dicSkillPassive[key].level - 1)); BuffMgr.Instance.ChangePassiveStat(dicSkillPassive[key].abilityType, totalStat, true); } public static void AwakenSkill(int itype, int key, int iawaken) { if (itype != cGoods.TSkillActive) return; // 액티브. if (!dicSkillActive.ContainsKey(key)) return; dicSkillActive[key].awaken = iawaken; } // 사용중인 프리셋 변경. 플레이 데이터 저장은 별도로 호출 필요. public static void ChangeSkillPreset(int presetindex) { PlayData.usePreset = presetindex; } // 프리셋 변경. 플레이 데이터 저장은 별도로 호출 필요. public static void EditSkillPreset(int presetindex, int islotindex, int iskillid) { PlayData.skillPresets[presetindex][islotindex] = iskillid; } #endregion Skill #region Pet public static void LoadPetsPlay(nIdLvInfo[] playpets) { int addlv = 0; for (int i = 0; i < playpets.Length; ++i) { if (!dicPet.TryGetValue(playpets[i].sid, out var pet)) continue; pet.have = playpets[i].have; pet.awaken = playpets[i].awaken; pet.level = playpets[i].lv; pet.count = playpets[i].cnt; if (pet.have) addlv += pet.level; if (pet.maxAwaken > 1) pet.extraEffects = playpets[i].extras; } // 레벨 효과 계산. CalcPetLevelEffect(addlv, false); // 장착 & 추가 효과 계산. CalcPetEquipExtra(PlayData.usePetPreset); } // 펫 플레이 정보 업데이트(스피릿 합성 후 호출). public static void UpdatePetsPlay(nIdLvInfo[] datas) { int ilvadd = 0; for (int i = 0; i < datas.Length; ++i) { if (!dicPet.TryGetValue(datas[i].sid, out dPet data)) continue; data.count = datas[i].cnt; if (datas[i].have) { if (!data.have) { data.have = true; ilvadd += datas[i].lv; } data.awaken = datas[i].awaken; data.level = datas[i].lv; if (data.maxAwaken > 1) data.extraEffects = datas[i].extras; } } // 레벨 효과 계산. CalcPetLevelEffect(ilvadd, false); } // 펫 각성 단계 정보. public static dAwaken[] GetPetAwakens() { return sysPetAwakens; } // 펫 최고 레벨. public static int GetPetMaxLv(int key) { int index = dicPet[key].awaken - 1; if (index >= sysPetAwakens.Length) index = sysPetAwakens.Length - 1; else if (index < 0) index = 0; return sysPetAwakens[index].maxLv; } // 펫 각성 단계 정보. public static dAwaken GetPetAwakenNext(int key) { int index = dicPet[key].awaken; if (index >= sysPetAwakens.Length) index = sysPetAwakens.Length - 1; else if (index < 0) index = 0; return sysPetAwakens[index]; } // 펫 통합 레벨 효과 계산 및 적용. private static bool CalcPetLevelEffect(int iaddlv, bool brecalc) { int iprevlv = petLv; petLv += iaddlv; int inextlv = petLv; int iprevefc = -1; int inextefc = -1; for (int i = sysPetLvEffects.Length - 1; i >= 0; i--) { if (inextefc < 0 && inextlv >= sysPetLvEffects[i].totalLv) { inextefc = i; } if (iprevefc < 0 && iprevlv >= sysPetLvEffects[i].totalLv) { iprevefc = i; break; } } // 이전 효과와 다르고 적용 효과가 있을 경우. if (inextefc != iprevefc && inextefc >= 0) { BuffMgr.Instance.SetPetLv(sysPetLvEffects[inextefc].value, brecalc); return true; } return false; } /// /// 펫 통합 레벨 정보. /// /// 0:현재 통합 레벨, 1:현재 단계, 2:현재 단계 효과 값, 3:다음 단계 통합 레벨. public static int[] GetPetTotalLevels() { int[] ilvs = new int[4]; ilvs[0] = petLv; for (int i = sysPetLvEffects.Length - 1; i >= 0; i--) { if (ilvs[0] >= sysPetLvEffects[i].totalLv) { ilvs[1] = i + 1; ilvs[2] = sysPetLvEffects[i].value; if (i < (sysPetLvEffects.Length - 1)) ilvs[3] = sysPetLvEffects[i + 1].totalLv; else ilvs[3] = sysPetLvEffects[i].totalLv; break; } } return ilvs; } // 펫 장착 효과 계산 및 적용. private static void CalcPetEffect(int presetindex, int slotindex, bool brecalc) { int key = PlayData.petPresets[presetindex][slotindex]; if (key < 0) { BuffMgr.Instance.SetPetEquip(slotindex, eEffectType.None, 0L, eEffectType.None, 0L, eEffectType.None, 0L, brecalc); return; } dPet pet = dicPet[key]; int ilevel = pet.level - 1; BuffMgr.Instance.SetPetEquip(slotindex, pet.abilityType1, ilevel * pet.abilityValueInc1 + pet.abilityValue1, pet.abilityType2, ilevel * pet.abilityValueInc2 + pet.abilityValue2, pet.abilityType3, ilevel * pet.abilityValueInc3 + pet.abilityValue3, brecalc); } // 펫 추가 효과 계산 및 적용. public static void CalcPetExtra(int presetindex, int slotindex, bool brecalc) { int key = PlayData.petPresets[presetindex][slotindex]; if (key < 0) { BuffMgr.Instance.SetPetExtra(slotindex, 2, eEffectType.None, 0L, false); BuffMgr.Instance.SetPetExtra(slotindex, 1, eEffectType.None, 0L, false); BuffMgr.Instance.SetPetExtra(slotindex, 0, eEffectType.None, 0L, false); BuffMgr.Instance.SetPetExtra(slotindex, 3, eEffectType.None, 0L, brecalc); return; } dPet pet = dicPet[key]; if (pet.awaken <= 1 || pet.extraEffects == null) { BuffMgr.Instance.SetPetExtra(slotindex, 2, eEffectType.None, 0L, false); BuffMgr.Instance.SetPetExtra(slotindex, 1, eEffectType.None, 0L, false); BuffMgr.Instance.SetPetExtra(slotindex, 0, eEffectType.None, 0L, false); BuffMgr.Instance.SetPetExtra(slotindex, 3, eEffectType.None, 0L, brecalc); return; } bool bopenoption = true; int[] extras = pet.extraEffects; for (int i = extras.Length - 1; i >= 0; i--) { if (extras[i] < 0) { BuffMgr.Instance.SetPetExtra(slotindex, i, eEffectType.None, 0L, false); bopenoption = false; } else { dExtraAbility ability = GetExtraAbility(extras[i]); BuffMgr.Instance.SetPetExtra(slotindex, i, ability.abilityType, ability.abilityValue, false); if (ability.rarity < cGoods.RLegend) bopenoption = false; } } // 옵션 보유 효과. if (bopenoption) BuffMgr.Instance.SetPetExtra(slotindex, extras.Length, pet.abilityTypeOption, pet.abilityValueOption, brecalc); else BuffMgr.Instance.SetPetExtra(slotindex, extras.Length, eEffectType.None, 0L, brecalc); } // 펫 장착 & 추가 효과 계산 및 적용. public static void CalcPetEquipExtra(int presetindex) { // 장착 효과 계산. CalcPetEffect(presetindex, 0, false); CalcPetEffect(presetindex, 1, false); CalcPetEffect(presetindex, 2, true); // 추가 효과 계산. CalcPetExtra(presetindex, 0, false); CalcPetExtra(presetindex, 1, false); CalcPetExtra(presetindex, 2, true); } public static Dictionary GetPets() { return dicPet; } public static dPet GetPet(int key) { if (dicPet.ContainsKey(key)) return dicPet[key]; return null; } public static int GetPetSpiritCount(int key) { if (dicPet.ContainsKey(key)) return dicPet[key].count; return 0; } public static int GetPetRarity(int key) { if (dicPet.ContainsKey(key)) return dicPet[key].rarity; return 0; } public static bool AddPet(int key) { if (!dicPet.ContainsKey(key)) return false; if (dicPet[key].have) { return false; } dPet data = dicPet[key]; data.have = true; data.level = 1; data.awaken = 1; if (data.maxAwaken > 1) data.extraEffects = new int[3] { -1, -1, -1 }; petNew.Add(key); CalcPetLevelEffect(1, false); PetMgr.SSetBadge(); return true; } public static bool AddPetSpirit(int key, int icount) { if (!dicPet.ContainsKey(key)) return false; dicPet[key].count += icount; return true; } public static bool SubPetSpirit(int key, int icount) { if (!dicPet.ContainsKey(key)) return false; if (dicPet[key].count < icount) return false; dicPet[key].count -= icount; return true; } // 선택한 희귀도가 합성 가능한지. public static bool IsPetSpiritComposable(fRangeRarity rarities) { if (rarities == fRangeRarity.None) return false; bool[] brarities = new bool[cGoods.RMyth + 1] { false, rarities.HasFlag(fRangeRarity.Normal), rarities.HasFlag(fRangeRarity.Rare), rarities.HasFlag(fRangeRarity.Epic), rarities.HasFlag(fRangeRarity.Unique), rarities.HasFlag(fRangeRarity.Hero), rarities.HasFlag(fRangeRarity.Legend), rarities.HasFlag(fRangeRarity.Myth) }; foreach (var item in dicPet) { if (!brarities[item.Value.rarity]) continue; if (item.Value.count >= Const.petSpiritComposePrice) return true; } return false; } public static int GetPetSlot(int key) { int[] presets = PlayData.petPresets[PlayData.usePetPreset]; for (int i = 0; i < presets.Length; i++) { if (key == presets[i]) return i; } return -1; } public static bool IsPetNewHave() { return petNew.Count > 0; } public static bool IsPetNew(int key) { return petNew.Contains(key); } public static bool RemovePetNew(int key) { return petNew.Remove(key); } public static void LvUpPet(int key, int ilevel, bool bcalcstat) { dPet data = dicPet[key]; int iaddlevel = ilevel - data.level; data.level = ilevel; int slotindex = GetEquipedPetIndex(key); CalcPetLevelEffect(iaddlevel, bcalcstat); if (bcalcstat && slotindex >= 0) CalcPetEffect(PlayData.usePetPreset, slotindex, true); } public static void AwakenPet(int key, int iawaken, int ispritcnt) { if (!dicPet.ContainsKey(key)) return; dicPet[key].awaken = iawaken; dicPet[key].count = ispritcnt; } public static void ChangePetExtras(int key, int[] extras) { dicPet[key].extraEffects = extras; } public static int GetEquipedPetIndex(int key) { int[] presets = PlayData.petPresets[PlayData.usePetPreset]; for (int i = 0; i < presets.Length; i++) { if (key == presets[i]) return i; } return -1; } // 사용중인 프리셋 변경. 플레이 데이터 저장은 별도로 호출 필요. public static void ChangePetPreset(int presetindex) { PlayData.usePetPreset = presetindex; } // 프리셋 변경. 플레이 데이터 저장은 별도로 호출 필요. public static void EditPetPreset(int presetindex, int islotindex, int ipetid) { PlayData.petPresets[presetindex][islotindex] = ipetid; } #endregion Pet #region Gacha // 최대 소환 레벨. public static int GetGachaMaxLv(int itype) { // 0:무기, 1:방어구, 2:악세. if (itype == 0) return gachaWeaponLvs.Length; else if (itype == 1) return gachaArmorLvs.Length; else if (itype == 2) return gachaAcceLvs.Length; else return 1; } // 소환 레벨별 데이터 가져오기. public static dGachaLevel GetGachaLv(int itype, int ilv) { dGachaLevel[] lvdata; // 0:무기, 1:방어구, 2:악세. if (itype == 0) lvdata = gachaWeaponLvs; else if (itype == 1) lvdata = gachaArmorLvs; else if (itype == 2) lvdata = gachaAcceLvs; else return null; if (ilv >= lvdata.Length) return lvdata[lvdata.Length - 1]; else return lvdata[ilv - 1]; } // 소환 등급별 확률 데이터 가져오기. public static int[] GetGachaGrades(int itype) { // 0:무기, 1:방어구, 2:악세. if (itype == 0) return gachaWeaponGrades; else if (itype == 1) return gachaArmorGrades; else if (itype == 2) return gachaAcceGrades; else return new int[0]; } // 가챠 레벨, 경험치 세팅. public static void SetGachaLvExp(int itype, int ilv, int iexp) { // 0:무기, 1:방어구, 2:악세. if (itype == 0) { PlayData.gachaWeaponLv = ilv; PlayData.gachaWeaponExp = iexp; } else if (itype == 1) { PlayData.gachaArmorLv = ilv; PlayData.gachaArmorExp = iexp; } else if (itype == 2) { PlayData.gachaAccLv = ilv; PlayData.gachaAccExp = iexp; } } // 가챠 보상 레벨 증가. public static bool GachaRewardLvUp(int itype) { // 0:무기, 1:방어구, 2:악세. if (itype == 0) return ++PlayData.gachaWeaponReward < PlayData.gachaWeaponLv; else if (itype == 1) return ++PlayData.gachaArmorReward < PlayData.gachaArmorLv; else if (itype == 2) return ++PlayData.gachaAccReward < PlayData.gachaAccLv; else return false; } #endregion Gacha #region Diary Trip & Life //public static void initTrip() //{ // //int iclearChapter = PlayData.clearTripPiece / (Const.TripMaxsize * Const.TripPieceMaxsize); // //int iclearTrip = (PlayData.clearTripPiece % (Const.TripMaxsize * Const.TripPieceMaxsize)) / Const.TripPieceMaxsize; // //int iclearTripPiece = (PlayData.clearTripPiece % (Const.TripMaxsize * Const.TripPieceMaxsize)) % Const.TripPieceMaxsize; // int icurMaxStage = DataHandler.GetMaxStage(); // int ichapter = Const.TripMaxsize * Const.TripPieceMaxsize; // int itrip = Const.TripPieceMaxsize; // int iclear = (icurMaxStage - 100) / 100; // for (int i = 0; i 0) // 해금이 잠겨있고, 클리어해야할 스테이지를 넘었을 경우 // { // return true; // } // } // return false; //} //public static int GetTripStage(int id, int idx) //{ // int istageNum; // istageNum = ((idx) * (100) * Const.TripPieceMaxsize * Const.TripMaxsize) + (dicTrip[id][idx].tripPieceCount + 1) * 100 + Const.stageMax; // return istageNum; //} //// 다음 여정 조각 해금 //public static void tripPieceUnlock(int id, int idx) //{ // if (dicTrip[id][idx] != null) // { // if (dicTrip[id][idx].tripPieceCount < DataHandler.Const.TripPieceMaxsize && PlayData.tripPiece > 0) // { // SubTripPiece(); // dicTrip[id][idx].islock[dicTrip[id][idx].tripPieceCount] = true; // DiaryMgr.AllCheckCircle(); // dicTrip[id][idx].tripPieceCount++; // } // } //} //// 챕터를 어디까지 열수 있나 체크 bool [] 로 반환 ex) true true false false false 면 1~6장까지 있을때 2,3장 가능 4, 5, 6장 불가능 //public static bool[] tripChapterIslock() //{ // bool[] barr = new bool[Const.TripChapterMaxsize - 1]; // for (int i = 0; i < Const.TripChapterMaxsize - 1; i++) // { // if (dicTrip[i][Const.TripMaxsize - 1].tripPieceCount == Const.TripPieceMaxsize) // barr[i] = true; // else // barr[i] = false; // } // return barr; //} //// 여정 조각이 어디까지 해금되어있나 체크 //public static int GetTripPieceIslock(int id, int idx) //{ // return dicTrip[id][idx].tripPieceCount; //} //// id idx 번째 여정의 여정 조각이 어디까지 해금 가능한가 체크 //public static int GetTripPieceIslockCount(int id, int idx) //{ // int icurMaxStage = DataHandler.GetMaxStage(); // //[id][idx] 의 최대 스테이지 // int iStageMax = id * 3000 + (idx + 1) * Const.TripPieceMaxsize * 100 + Const.stageMax; // //[id][idx] 의 최소 스테이지 // int iStageMin = id * 3000 + (idx + 1) * 100 + Const.stageMax; // // 현재 클리어한 스테이지가 [id][idx] 의 최대 스테이지 보다 크면 // if (icurMaxStage > iStageMax) // return Const.TripPieceMaxsize <= PlayData.tripPiece ? Const.TripPieceMaxsize : PlayData.tripPiece; // // 현재 클리어한 스테이지가 [id][idx] 의 최소 스테이지 보다 크면 // if (icurMaxStage > iStageMin && icurMaxStage < iStageMax) // return (icurMaxStage - iStageMin + Const.stageMax)/100; // else // return 0; //} //public static void AddTripPiece() //{ // if(PlayData.curStage == GetMaxStage()) //+여기서 마지막 스테이지인거 체크 // { // if(PlayData.curStage % 100 == Const.stageMax) // { // PlayData.tripPiece += 1; // DiaryMgr.AllCheckCircle(); // return; // } // } //} //public static void SubTripPiece() //{ // PlayData.tripPiece -= 1; // PlayData.Save(); //} //public static void LoadLife(dLife[][] datas) //{ // dicLife = datas; //} //public static dLife[][] GetLifeStep() //{ // return dicLife; //} //// 일 가져오기 //public static dLife[] GetLives(int id) //{ // if (dicLife[id] != null) // return dicLife[id]; // return null; //} //public static dLife GetLife(int id, int idx) //{ // return dicLife[id][idx]; //} //public static bool nextLifePieceIslock(int id, int idx) //{ // for (int i = 0; i < DataHandler.Const.LifePieceMaxsize; i++) // { // if (!dicLife[id][idx].islock[i] && dicLifePiece[id, idx] > 0) // 해금이 잠겨있고 조각이 하나 이상 있으면 // { // return true; // } // } // return false; //} //public static void AddLifePiece(int id, int idx, int inum) //{ // if(dicLife[id][idx].lifePieceCount >= Const.LifePieceMaxsize) // { // // 다이아 주는 코드AddDia() // } // else // dicLifePiece[id,idx] += inum; //} //// 여정조각 해금 //public static void LifePieceUnlock(int id, int idx) //{ // if (dicLife[id][idx] != null) // { // if (dicLifePiece[id,idx] > 0) // { // dicLife[id][idx].islock[dicLife[id][idx].lifePieceCount] = true; // if (dicLife[id][idx].lifePieceCount < DataHandler.Const.LifePieceMaxsize) // { // dicLifePiece[id, idx]--; // dicLife[id][idx].lifePieceCount++; // } // } // } //} //// 플레이가능한 챕터는 어디까지 인가? //public static bool[] lifeChapterIslock() //{ // bool[] barr = new bool[Const.LifeChapterMaxsize - 1]; // for (int i = 0; i < Const.LifeChapterMaxsize - 1; i++) // { // if (dicLife[i][Const.LifeMaxsize - 1].lifePieceCount == Const.LifePieceMaxsize) // barr[i] = true; // else // barr[i] = false; // } // return barr; //} //// 일상 조각이 어디까지 해금 가능한가 체크 //public static int GetLifePieceIslockCount(int id, int idx) //{ // int icount = dicLifePiece[id, idx] + dicLife[id][idx].lifePieceCount; // return icount; //} #endregion #region Title // 획득한 칭호 불러오기 public static void LoadPlayerTitlesData(int[] titles) { for (int i = 0; i < titles.Length; ++i) { int titleID = titles[i]; if (dicProfileTitle.TryGetValue(titleID, out dTitle targetTitle)) { targetTitle.have = true; BuffMgr.Instance.AddTitleEfc(targetTitle.abilityType, targetTitle.abilityValue, false); } } foreach (var title in dicProfileTitle.Values) { if (title.have) continue; var achievement = new nAchivement(title); switch (title.category) { case eContent.Battle: listBattleType.Add(achievement); break; case eContent.Equipment: listEquipmentType.Add(achievement); break; case eContent.Summon: listSummonType.Add(achievement); break; case eContent.Dungeon: listDungeonType.Add(achievement); break; case eContent.Etc: listEtcType.Add(achievement); break; } } } public static dTitle GetPlayerTitle(int key) => dicProfileTitle.SafeGet(key); public static Dictionary GetAllPlayerTitle() => dicProfileTitle; public static dTitle[] GetAllPlayerTitleArr() { dTitle[] datas = new dTitle[dicProfileTitle.Count]; for(int i = 0; i 0) arrSum[(int)(dicProfileTitle[i + 1].category) - 1]++; } ProfileMgr.addTitleBadge(eContent.Battle, arrSum[0]); ProfileMgr.addTitleBadge(eContent.Equipment, arrSum[1]); ProfileMgr.addTitleBadge(eContent.Summon, arrSum[2]); ProfileMgr.addTitleBadge(eContent.Dungeon, arrSum[3]); ProfileMgr.addTitleBadge(eContent.Etc, arrSum[4]); } #endregion #region Icon // 획득한 아이콘 불러오기 public static void LoadPlayerIconsData(int[] icons) { for (int i = 0; i < icons.Length; ++i) { int iconID = icons[i]; if (dicProfileIcon.TryGetValue(iconID, out dIcon targetIcon)) targetIcon.have = true; } foreach (var icon in dicProfileIcon.Values) { if (!icon.have) listEtcType.Add(new nAchivement(icon)); } } public static void AddIconBadge() { int badgeCount = 0; foreach (var icon in dicProfileIcon.Values) { if (!icon.have && isClearAchievements(new nAchivement(icon)) > 0) ++badgeCount; } ProfileMgr.addIconBadge(badgeCount); } public static void EquipPlayerIcon(int key) { PlayData.playerIcon = key; PlayData.Save(); } public static Dictionary GetAllplayerIcon() => dicProfileIcon; public static dIcon GetPlayerIcon(int key) => dicProfileIcon.SafeGet(key); public static bool AddPlayerIcon(int key) { if (!dicProfileIcon.TryGetValue(key, out dIcon targetIcon) || targetIcon.have) return false; targetIcon.have = true; return true; } #endregion #region Record public static cTotalRecord GetTotalRecord() { return PlayerTotalRecord; } public static cDailyRecord GetDailyRecord() { return PlayerDailyRecord; } public static void CheckAllAchivement() { CheckAchivement(eContent.Battle); CheckAchivement(eContent.Equipment); CheckAchivement(eContent.Summon); CheckAchivement(eContent.Dungeon); CheckAchivement(eContent.Etc); } public static void CheckAchivement(eContent content) { List targetList = null; switch (content) { case eContent.Battle: targetList = listBattleType; break; case eContent.Equipment: targetList = listEquipmentType; break; case eContent.Summon: targetList = listSummonType; break; case eContent.Dungeon: targetList = listDungeonType; break; case eContent.Etc: targetList = listEtcType; break; default: return; } int result = targetList.SwapElements((achievement) => isClearAchievements(achievement) <= 0); if (result > -1) targetList.RemoveRange(result, targetList.Count - result); } public static void AddRecord(eCondition condition, int icount = 1) { switch (condition) { case eCondition.PlayAtttend: PlayerDailyRecord.attendCnt += icount; break; case eCondition.MonsterCnt: PlayerDailyRecord.monsterKill += icount; PlayerTotalRecord.monsterKill += icount; if(GetQuestMission(PlayerTotalRecord.missionLv) != null && GetQuestMission(PlayerTotalRecord.missionLv).condType == eCondition.MonsterCnt) { MissionMgr.SSetMissionMonCnt(); MissionMgr.checkCurMission(); } break; case eCondition.PlayTimeM: PlayerDailyRecord.playTime += icount; PlayerTotalRecord.playTime += icount; break; case eCondition.EnhanceGoldAtk: PlayerDailyRecord.enhanceGoldAtk += icount; break; case eCondition.EnhanceGoldHp: PlayerDailyRecord.enhanceGoldHp += icount; break; case eCondition.GachaWeapon: PlayerDailyRecord.gachaWeaponCnt += icount; PlayerTotalRecord.gachaWeaponCnt += icount; break; case eCondition.GachaArmor: PlayerDailyRecord.gachaArmorCnt += icount; PlayerTotalRecord.gachaArmorCnt += icount; break; case eCondition.GachaAcc: PlayerDailyRecord.gachaAccCnt += icount; PlayerTotalRecord.gachaAccCnt += icount; break; case eCondition.GachaTreasure: PlayerDailyRecord.gachaTreasureCnt += icount; PlayerTotalRecord.gachaTreasureCnt += icount; break; case eCondition.EquipComposeWeapon: PlayerDailyRecord.composeWeaponCnt += icount; PlayerTotalRecord.composeWeaponCnt += icount; break; case eCondition.EquipComposeArmor: PlayerDailyRecord.composeArmorCnt += icount; PlayerTotalRecord.composeArmorCnt += icount; break; case eCondition.EquipComposeAcc: PlayerDailyRecord.composeAccCnt += icount; PlayerTotalRecord.composeAccCnt += icount; break; //case eCondition.ComposeIris: // PlayerTotalRecord.composeIris += icount; // break; case eCondition.DailyQuestClear: PlayerDailyRecord.clearDailyQuest += icount; break; case eCondition.DailyQuestClearTotal: PlayerTotalRecord.clearDailyQuest += icount; break; case eCondition.MissionClearLv: PlayerTotalRecord.missionLv += icount; break; case eCondition.PetspiritCompose: PlayerTotalRecord.composePetSpirit += icount; break; default: break; } } // 타입과 값을 받고 클리어 유무를 1이상의 int값으로 반환 1 = 1번클리어 2 = 2번클리어 public static int isClearAchievements(nAchivement achive, int clearAllDay = 0) { int bClear = 0; switch (achive.condition) { case eCondition.PlayerAwaken: return PlayDgAwaken.lv > achive.condValue ? 1 : 0; case eCondition.MonsterCnt: if (achive.contentType == eContentType.DailyQuest) return achive.condValue <= PlayerDailyRecord.monsterKill ? 1 : 0; else if (achive.contentType == eContentType.RepeatQuest) { int sum = achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.monsterKill >= sum ? ((PlayerTotalRecord.monsterKill - sum) / achive.condValue) : 0; } else return PlayerTotalRecord.monsterKill >= achive.condValue ? 1 : 0; case eCondition.GachaAll: if (achive.contentType == eContentType.DailyQuest) return achive.condValue <= PlayerDailyRecord.gachaWeaponCnt + PlayerDailyRecord.gachaArmorCnt + PlayerDailyRecord.gachaAccCnt + PlayerDailyRecord.gachaTreasureCnt? 1 : 0; else return PlayerTotalRecord.gachaWeaponCnt + PlayerTotalRecord.gachaArmorCnt + PlayerTotalRecord.gachaAccCnt + PlayerTotalRecord.gachaTreasureCnt> achive.condValue ? 1 : 0; case eCondition.GachaWeapon: if (achive.contentType == eContentType.RepeatQuest) { int sum = achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.gachaWeaponCnt >= sum ? ((PlayerTotalRecord.gachaWeaponCnt - sum) / achive.condValue) : 0; } else return PlayerTotalRecord.gachaWeaponCnt >= achive.condValue ? 1 : 0; case eCondition.GachaArmor: if (achive.contentType == eContentType.RepeatQuest) { int sum = achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.gachaArmorCnt >= sum ? ((PlayerTotalRecord.gachaArmorCnt - sum) / achive.condValue) : 0; } else return PlayerTotalRecord.gachaArmorCnt >= achive.condValue ? 1 : 0; case eCondition.GachaAcc: if (achive.contentType == eContentType.RepeatQuest) { int sum = achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.gachaAccCnt >= sum ? ((PlayerTotalRecord.gachaAccCnt - sum) / achive.condValue) : 0; } else return PlayerTotalRecord.gachaAccCnt >= achive.condValue ? 1 : 0; case eCondition.GachaTreasure: if (achive.contentType == eContentType.RepeatQuest) { int sum = achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.gachaTreasureCnt >= sum ? ((PlayerTotalRecord.gachaTreasureCnt - sum) / achive.condValue) : 0; } else return PlayerTotalRecord.gachaTreasureCnt >= achive.condValue ? 1 : 0; case eCondition.EnhanceGoldAtk: if (achive.contentType == eContentType.RepeatQuest) { int sum = achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return GetCharStat(1).level >= sum ? ((GetCharStat(1).level - sum) / achive.condValue) : 0; } else return GetCharStat(1).level >= achive.condValue ? 1 : 0; case eCondition.EnhanceGoldHp: if (achive.contentType == eContentType.RepeatQuest) { int sum = achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return GetCharStat(2).level >= sum ? ((GetCharStat(2).level - sum) / achive.condValue) : 0; } else return GetCharStat(2).level >= achive.condValue ? 1 : 0; case eCondition.EnhanceGoldAtkCount: { int sum = achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return GetCharStat(1).level >= sum ? ((GetCharStat(1).level - sum) / achive.condValue) : 0; } case eCondition.EnhanceGoldHpCount: { int sum = achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return GetCharStat(2).level >= sum ? ((GetCharStat(2).level - sum) / achive.condValue) : 0; } case eCondition.DgStagePet: return PlayDgPet.lv > (achive.condValue / 100 - 1) * 10 + achive.condValue % 100 ? 1 : 0; case eCondition.EquipComposeAll: if (achive.contentType == eContentType.DailyQuest) return achive.condValue <= PlayerDailyRecord.composeWeaponCnt + PlayerDailyRecord.composeArmorCnt + PlayerDailyRecord.composeAccCnt ? 1 : 0; else return bClear; case eCondition.EquipComposeWeapon: if (achive.contentType == eContentType.RepeatQuest) { int sum = achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.composeWeaponCnt >= sum ? (PlayerTotalRecord.composeWeaponCnt - sum) / achive.condValue : 0; } else return PlayerTotalRecord.composeWeaponCnt >= achive.condValue ? 1 : 0; case eCondition.EquipComposeArmor: if (achive.contentType == eContentType.RepeatQuest) { int sum = achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.composeArmorCnt >= sum ? (PlayerTotalRecord.composeArmorCnt - sum) / achive.condValue : 0; } else return PlayerTotalRecord.composeArmorCnt >= achive.condValue ? 1 : 0; case eCondition.EquipComposeAcc: if (achive.contentType == eContentType.RepeatQuest) { int sum = achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.composeAccCnt >= sum ? (PlayerTotalRecord.composeAccCnt - sum) / achive.condValue : 0; } else return PlayerTotalRecord.composeAccCnt >= achive.condValue ? 1 : 0; case eCondition.EventQuestDayClear: return GetPlayEventQuestDayClearCount(clearAllDay) >= achive.condValue ? 1 : 0; default: return GetAchievementValue(achive) >= achive.condValue ? 1 : 0; } } public static int GetAchievementValue(nAchivement achive) { int ivalue = 0; int cnt = 0; int sum = 0; switch (achive.condition) { // 스테이지, 레벨, 각성, 플레이 시간(분), 플레이 시간, 출석 case eCondition.StageClear: return GetMaxStage(); case eCondition.PlayerLv: return PlayData.playerLv; case eCondition.PlayerAwaken: return PlayDgAwaken.lv - 1; case eCondition.PlayTimeM: return achive.contentType == eContentType.DailyQuest ? PlayerDailyRecord.playTime : PlayerTotalRecord.playTime; case eCondition.PlayTimeH: return PlayerTotalRecord.playTime / 60; case eCondition.PlayAtttend: return (achive.contentType == eContentType.DailyQuest || achive.contentType == eContentType.QuestMission) ? PlayerDailyRecord.attendCnt : PlayerTotalRecord.attendCnt; // 몬스터 처치 횟수 case eCondition.MonsterCnt: if (achive.contentType == eContentType.DailyQuest) return PlayerDailyRecord.monsterKill; else if (achive.contentType == eContentType.RepeatQuest) return PlayerTotalRecord.monsterKill - achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; else return PlayerTotalRecord.monsterKill; case eCondition.EliteCnt: case eCondition.BossCnt: return ivalue; // 소환 횟수 case eCondition.GachaAll: if (achive.contentType == eContentType.DailyQuest) return PlayerDailyRecord.gachaWeaponCnt + PlayerDailyRecord.gachaArmorCnt + PlayerDailyRecord.gachaAccCnt + PlayerDailyRecord.gachaTreasureCnt; else if (achive.contentType == eContentType.RepeatQuest) return (PlayerTotalRecord.gachaWeaponCnt + PlayerTotalRecord.gachaArmorCnt + PlayerTotalRecord.gachaAccCnt) - achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; else return PlayerTotalRecord.gachaWeaponCnt + PlayerTotalRecord.gachaArmorCnt + PlayerTotalRecord.gachaAccCnt; case eCondition.GachaWeapon: if(achive.contentType == eContentType.RepeatQuest) return PlayerTotalRecord.gachaWeaponCnt - achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.gachaWeaponCnt; case eCondition.GachaArmor: if (achive.contentType == eContentType.RepeatQuest) return PlayerTotalRecord.gachaArmorCnt - achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.gachaArmorCnt; case eCondition.GachaAcc: if (achive.contentType == eContentType.RepeatQuest) return PlayerTotalRecord.gachaAccCnt - achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.gachaAccCnt; case eCondition.GachaTreasure: return PlayerTotalRecord.gachaTreasureCnt; case eCondition.GachaWeaponLv: return PlayData.gachaWeaponLv; case eCondition.GachaArmorLv: return PlayData.gachaArmorLv; case eCondition.GachaAccLv: return PlayData.gachaAccLv; // 골드 강화 레벨 case eCondition.EnhanceGoldAll: return GetCharStat(1).level + GetCharStat(2).level + GetCharStat(3).level; case eCondition.EnhanceGoldAtk: if (achive.contentType == eContentType.RepeatQuest) return GetCharStat(1).level - achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return GetCharStat(1).level; case eCondition.EnhanceGoldHp: if (achive.contentType == eContentType.RepeatQuest) return GetCharStat(2).level - achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return GetCharStat(2).level; case eCondition.EnhanceGoldAtkCount: return GetCharStat(1).level - achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; case eCondition.EnhanceGoldHpCount: return GetCharStat(2).level - achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; // 포인트 강화 레벨 case eCondition.EnhancePointAll: Dictionary lvpoints = GetCharLvPoints(); for (int i = 1; i < lvpoints.Count; i++) { sum += (lvpoints[i].level - 1); } return sum; case eCondition.EnhancePointAtk: return GetCharLvPoint(1).level; case eCondition.EnhancePointHp: return GetCharLvPoint(2).level; // 스킬 case eCondition.SkillEquip: for (int i = 0; i < 4; i++) { if (PlayData.skillPresets[PlayData.usePreset][i] != -1) return 1; } return 0; case eCondition.SkillLvAll: return GetSkillTotalLevels()[0]; case eCondition.SkillLvActive: for (int i = 0; i < dicSkillActive.Count; i++) { if (dicSkillActive[i + 1].openLv <= PlayData.playerLv) sum += dicSkillActive[i + 1].level - 1; } return sum; case eCondition.SkillLvPassive: for (int i = 0; i < dicSkillPassive.Count; i++) { sum += dicSkillPassive[i + 1].level - 1; } return sum; // 잠재 능력 case eCondition.ChangeAbility: for (int i = 0; i < 6; i++) { if (PlayAwaken.extras[PlayAwaken.usePreset][i] != -1) return 1; } return 0; // 특정 코스튬 획득 case eCondition.CosHave: return GetCosCloth(achive.condValue).have ? 1 : 0; case eCondition.CosCnt: cnt = 0; for (int i = 1; i < dicCosCloth.Count + 1; i++) { int key = dicCosCloth[i].id; if (GetCosCloth(key).have) cnt++; } return cnt; case eCondition.CosSetHave: return IsActiveClothCosSetEffect(achive.condValue) ? 1 : 0; case eCondition.CosSetCnt: for (int i = 1; i < dicCosClothSet.Count + 1; i++) { int key = dicCosClothSet[i].id; if (IsActiveClothCosSetEffect(key)) cnt++; } return cnt; // 모든 장비 획득 case eCondition.EquipHaveAll: if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveWeaponAll, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveArmorAll, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveAccAll, 1, 1)) <= 0) return 0; return 1; case eCondition.EquipHaveD: if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveWeaponD, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveArmorD, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveAccD, 1, 1)) <= 0) return 0; return 1; case eCondition.EquipHaveC: if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveWeaponC, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveArmorC, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveAccC, 1, 1)) <= 0) return 0; return 1; case eCondition.EquipHaveB: if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveWeaponB, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveArmorB, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveAccB, 1, 1)) <= 0) return 0; return 1; case eCondition.EquipHaveA: if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveWeaponA, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveArmorA, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveAccA, 1, 1)) <= 0) return 0; return 1; case eCondition.EquipHaveS: if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveWeaponS, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveArmorS, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveAccS, 1, 1)) <= 0) return 0; return 1; case eCondition.EquipHaveSS: if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveWeaponSS, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveArmorSS, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveAccSS, 1, 1)) <= 0) return 0; return 1; case eCondition.EquipHaveSR: if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveWeaponSR, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveArmorSR, 1, 1)) <= 0) return 0; if (GetAchievementValue(new nAchivement(eContentType.Title, eCondition.EquipHaveAccSR, 1, 1)) <= 0) return 0; return 1; // 모든 무기 획득 case eCondition.EquipHaveWeaponAll: sum = 0; for (int i = 0; i < arrHaveWeapon.Length; i++) { sum += arrHaveWeapon[i]; } return sum >= 28 ? 1 : 0; case eCondition.EquipHaveWeaponD: return arrHaveWeapon[0] >= 4 ? 1 : 0; case eCondition.EquipHaveWeaponC: return arrHaveWeapon[1] >= 4 ? 1 : 0; case eCondition.EquipHaveWeaponB: return arrHaveWeapon[2] >= 4 ? 1 : 0; case eCondition.EquipHaveWeaponA: return arrHaveWeapon[3] >= 4 ? 1 : 0; case eCondition.EquipHaveWeaponS: return arrHaveWeapon[4] >= 4 ? 1 : 0; case eCondition.EquipHaveWeaponSS: return arrHaveWeapon[5] >= 4 ? 1 : 0; case eCondition.EquipHaveWeaponSR: return arrHaveWeapon[6] >= 4 ? 1 : 0; // 모든 방어구 획득 case eCondition.EquipHaveArmorAll: sum = 0; foreach (var item in arrHaveArmor) { sum += item; } return sum >= 84 ? 1 : 0; case eCondition.EquipHaveArmorD: return arrHaveArmor[0, 0] >= 4 && arrHaveArmor[1, 0] >= 4 && arrHaveArmor[2, 0] >= 4 ? 1 : 0; case eCondition.EquipHaveArmorC: return arrHaveArmor[0, 1] >= 4 && arrHaveArmor[1, 1] >= 4 && arrHaveArmor[2, 1] >= 4 ? 1 : 0; case eCondition.EquipHaveArmorB: return arrHaveArmor[0, 2] >= 4 && arrHaveArmor[1, 2] >= 4 && arrHaveArmor[2, 2] >= 4 ? 1 : 0; case eCondition.EquipHaveArmorA: return arrHaveArmor[0, 3] >= 4 && arrHaveArmor[1, 3] >= 4 && arrHaveArmor[2, 3] >= 4 ? 1 : 0; case eCondition.EquipHaveArmorS: return arrHaveArmor[0, 4] >= 4 && arrHaveArmor[1, 4] >= 4 && arrHaveArmor[2, 4] >= 4 ? 1 : 0; case eCondition.EquipHaveArmorSS: return arrHaveArmor[0, 5] >= 4 && arrHaveArmor[1, 5] >= 4 && arrHaveArmor[2, 5] >= 4 ? 1 : 0; case eCondition.EquipHaveArmorSR: return arrHaveArmor[0, 6] >= 4 && arrHaveArmor[1, 6] >= 4 && arrHaveArmor[2, 6] >= 4 ? 1 : 0; // 모든 장신구 획득 case eCondition.EquipHaveAccAll: sum = 0; foreach (var item in arrHaveAcc) { sum += item; } return sum >= 84 ? 1 : 0; case eCondition.EquipHaveAccD: return arrHaveAcc[0, 0] >= 4 && arrHaveAcc[1, 0] >= 4 && arrHaveAcc[2, 0] >= 4 ? 1 : 0; case eCondition.EquipHaveAccC: return arrHaveAcc[0, 1] >= 4 && arrHaveAcc[1, 1] >= 4 && arrHaveAcc[2, 1] >= 4 ? 1 : 0; case eCondition.EquipHaveAccB: return arrHaveAcc[0, 2] >= 4 && arrHaveAcc[1, 2] >= 4 && arrHaveAcc[2, 2] >= 4 ? 1 : 0; case eCondition.EquipHaveAccA: return arrHaveAcc[0, 3] >= 4 && arrHaveAcc[1, 3] >= 4 && arrHaveAcc[2, 3] >= 4 ? 1 : 0; case eCondition.EquipHaveAccS: return arrHaveAcc[0, 4] >= 4 && arrHaveAcc[1, 4] >= 4 && arrHaveAcc[2, 4] >= 4 ? 1 : 0; case eCondition.EquipHaveAccSS: return arrHaveAcc[0, 5] >= 4 && arrHaveAcc[1, 5] >= 4 && arrHaveAcc[2, 5] >= 4 ? 1 : 0; case eCondition.EquipHaveAccSR: return arrHaveAcc[0, 6] >= 4 && arrHaveAcc[1, 6] >= 4 && arrHaveAcc[2, 6] >= 4 ? 1 : 0; // 특정 등급의 무기 1개 이상 case eCondition.EquipHaveWeaponNOne: return arrHaveWeapon[0] >= 1 ? 1 : 0; case eCondition.EquipHaveWeaponROne: return arrHaveWeapon[1] >= 1 ? 1 : 0; case eCondition.EquipHaveWeaponEOne: return arrHaveWeapon[2] >= 1 ? 1 : 0; case eCondition.EquipHaveWeaponUOne: return arrHaveWeapon[3] >= 1 ? 1 : 0; case eCondition.EquipHaveWeaponLOne: return arrHaveWeapon[4] >= 1 ? 1 : 0; case eCondition.EquipHaveWeaponHOne: return arrHaveWeapon[5] >= 1 ? 1 : 0; case eCondition.EquipHaveWeaponMOne: return arrHaveWeapon[6] >= 1 ? 1 : 0; //특정 등급 귀걸이 1개 이상 case eCondition.EquipHaveEarNOne: return arrHaveAcc[0, 0] >= 1 ? 1 : 0; case eCondition.EquipHaveEarROne: return arrHaveAcc[0, 1] >= 1 ? 1 : 0; case eCondition.EquipHaveEarEOne: return arrHaveAcc[0, 2] >= 1 ? 1 : 0; case eCondition.EquipHaveEarUOne: return arrHaveAcc[0, 3] >= 1 ? 1 : 0; case eCondition.EquipHaveEarLOne: return arrHaveAcc[0, 4] >= 1 ? 1 : 0; case eCondition.EquipHaveEarHOne: return arrHaveAcc[0, 5] >= 1 ? 1 : 0; case eCondition.EquipHaveEarMOne: return arrHaveAcc[0, 6] >= 1 ? 1 : 0; //던전 도전 횟수 case eCondition.DgTryAll: return PlayDgGold.totalTry + PlayDgReinStone.totalTry + PlayDgAwakenStone.totalTry + PlayDgPet.totalTry; case eCondition.DgTryGold: return PlayDgGold.totalTry; case eCondition.DgTryEnhance: return PlayDgReinStone.totalTry; case eCondition.DgTryAwaken: return PlayDgAwakenStone.totalTry; case eCondition.DgTryPet: return PlayDgPet.totalTry; // 던전 스테이지 클리어 case eCondition.DgClearAll: return PlayDgGold.totalClear + PlayDgReinStone.totalClear + PlayDgAwakenStone.totalClear + PlayDgPet.totalClear; case eCondition.DgClearGold: return PlayDgGold.totalClear; case eCondition.DgClearEnhance: return PlayDgReinStone.totalClear; case eCondition.DgClearAwaken: return PlayDgAwakenStone.totalClear; case eCondition.DgClearPet: return PlayDgPet.totalClear; case eCondition.DgStageGold: return PlayDgGold.lv; case eCondition.DgStageEnhance: return PlayDgReinStone.lv; case eCondition.DgStageAwaken: return PlayDgAwakenStone.lv; case eCondition.DgStagePet: return PlayDgPet.lv; // 장비 합성 case eCondition.EquipComposeAll: if (achive.contentType == eContentType.DailyQuest) return PlayerDailyRecord.composeWeaponCnt + PlayerDailyRecord.composeArmorCnt + PlayerDailyRecord.composeAccCnt; else return PlayerTotalRecord.composeWeaponCnt + PlayerTotalRecord.composeArmorCnt + PlayerTotalRecord.composeAccCnt; case eCondition.EquipComposeWeapon: if (achive.contentType == eContentType.RepeatQuest) return PlayerTotalRecord.composeWeaponCnt - achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.composeWeaponCnt; case eCondition.EquipComposeArmor: if (achive.contentType == eContentType.RepeatQuest) return PlayerTotalRecord.composeArmorCnt - achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.composeArmorCnt; case eCondition.EquipComposeAcc: if (achive.contentType == eContentType.RepeatQuest) return PlayerTotalRecord.composeAccCnt - achive.condValue * playQuestRepeat[achive.id - 1].totalCnt; return PlayerTotalRecord.composeAccCnt; // 장비 강화 레벨 case eCondition.EquipLvAll: return GetGearTotalLevels(cGoods.TBagWeapon)[0] + GetGearTotalLevels(cGoods.TBagArmorCape)[0] + GetGearTotalLevels(cGoods.TBagArmorHat)[0] + GetGearTotalLevels(cGoods.TBagArmorShoes)[0] + GetGearTotalLevels(cGoods.TBagAcceEar)[0] + GetGearTotalLevels(cGoods.TBagAcceNeck)[0] + GetGearTotalLevels(cGoods.TBagAcceRing)[0]; case eCondition.EquipLvWeapon: return GetGearTotalLevels(cGoods.TBagWeapon)[0]; case eCondition.EquipLvArmor: return GetGearTotalLevels(cGoods.TBagArmorCape)[0] + GetGearTotalLevels(cGoods.TBagArmorHat)[0] + GetGearTotalLevels(cGoods.TBagArmorShoes)[0]; case eCondition.EquipLvAcc: return GetGearTotalLevels(cGoods.TBagAcceEar)[0] + GetGearTotalLevels(cGoods.TBagAcceNeck)[0] + GetGearTotalLevels(cGoods.TBagAcceRing)[0]; case eCondition.EquipLvTreasure: return ivalue; // 장비 장착 case eCondition.EquipWeapon: return PlayData.weapon != -1 ? 1 : 0; case eCondition.EquipArmorCape: return PlayData.cape != -1 ? 1 : 0; case eCondition.EquipArmorHat: return PlayData.hat != -1 ? 1 : 0; case eCondition.EquipArmorShoes: return PlayData.shoes != -1 ? 1 : 0; case eCondition.EquipAccEar: return PlayData.earring != -1 ? 1 : 0; case eCondition.EquipAccNeck: return PlayData.necklace != -1 ? 1 : 0; case eCondition.EquipAccRing: return PlayData.ring != -1 ? 1 : 0; // 장비 강화 case eCondition.EnhanceGear: return ivalue; case eCondition.EnhanceWeapon: sum = 0; for (int i = 0; i < dicGearEquipment[cGoods.TBagWeapon].Count; i++) { if(dicGearEquipment[cGoods.TBagWeapon][i + 1].have) sum += dicGearEquipment[cGoods.TBagWeapon][i + 1].level - 1; } return sum; case eCondition.EnhanceArmor: sum = 0; for (int i = 0; i < dicGearEquipment[cGoods.TBagArmorCape].Count; i++) { if (dicGearEquipment[cGoods.TBagArmorCape][i + 1].have) sum += dicGearEquipment[cGoods.TBagArmorCape][i + 1].level - 1; } for (int i = 0; i < dicGearEquipment[cGoods.TBagArmorHat].Count; i++) { if (dicGearEquipment[cGoods.TBagArmorHat][i + 1].have) sum += dicGearEquipment[cGoods.TBagArmorHat][i + 1].level - 1; } for (int i = 0; i < dicGearEquipment[cGoods.TBagArmorShoes].Count; i++) { if (dicGearEquipment[cGoods.TBagArmorShoes][i + 1].have) sum += dicGearEquipment[cGoods.TBagArmorShoes][i + 1].level - 1; } return sum; case eCondition.EnhanceArmorCape: sum = 0; for (int i = 0; i < dicGearEquipment[cGoods.TBagArmorCape].Count; i++) { if(dicGearEquipment[cGoods.TBagWeapon][i + 1].have) sum += dicGearEquipment[cGoods.TBagWeapon][i + 1].level - 1; } return sum; case eCondition.EnhanceArmorHat: sum = 0; for (int i = 0; i < dicGearEquipment[cGoods.TBagArmorHat].Count; i++) { if(dicGearEquipment[cGoods.TBagArmorHat][i + 1].have) sum += dicGearEquipment[cGoods.TBagArmorHat][i + 1].level - 1; } return sum; case eCondition.EnhanceArmorShoes: sum = 0; for (int i = 0; i < dicGearEquipment[cGoods.TBagArmorShoes].Count; i++) { if(dicGearEquipment[cGoods.TBagArmorShoes][i + 1].have) sum += dicGearEquipment[cGoods.TBagArmorShoes][i + 1].level - 1; } return sum; case eCondition.EnhanceAcc: sum = 0; for (int i = 0; i < dicGearEquipment[cGoods.TBagAcceEar].Count; i++) { if(dicGearEquipment[cGoods.TBagAcceEar][i + 1].have) sum += dicGearEquipment[cGoods.TBagAcceEar][i + 1].level - 1; } for (int i = 0; i < dicGearEquipment[cGoods.TBagAcceNeck].Count; i++) { if(dicGearEquipment[cGoods.TBagAcceNeck][i + 1].have) sum += dicGearEquipment[cGoods.TBagAcceNeck][i + 1].level - 1; } for (int i = 0; i < dicGearEquipment[cGoods.TBagAcceRing].Count; i++) { if(dicGearEquipment[cGoods.TBagAcceRing][i + 1].have) sum += dicGearEquipment[cGoods.TBagAcceRing][i + 1].level - 1; } return sum; case eCondition.EnhanceAccEar: sum = 0; for (int i = 0; i < dicGearEquipment[cGoods.TBagAcceEar].Count; i++) { if(dicGearEquipment[cGoods.TBagAcceEar][i + 1].have) sum += dicGearEquipment[cGoods.TBagAcceEar][i + 1].level - 1; } return sum; case eCondition.EnhanceAccNeck: sum = 0; for (int i = 0; i < dicGearEquipment[cGoods.TBagAcceNeck].Count; i++) { if (dicGearEquipment[cGoods.TBagAcceNeck][i + 1].have) sum += dicGearEquipment[cGoods.TBagAcceNeck][i + 1].level - 1; } return sum; case eCondition.EnhanceAccRing: sum = 0; for (int i = 0; i < dicGearEquipment[cGoods.TBagAcceRing].Count; i++) { if (dicGearEquipment[cGoods.TBagAcceRing][i + 1].have) sum += dicGearEquipment[cGoods.TBagAcceRing][i + 1].level - 1; } return sum; case eCondition.EnhanceTreasure: sum = 0; for (int i = 0; i < dicGearTreasure.Count; i++) { if(dicGearTreasure[i + 1].have) sum += dicGearTreasure[i + 1].level - 1; } return sum; // 펫 case eCondition.PetEnhance: for (int i = 0; i < dicPet.Count; i++) { if (dicPet[i + 1].have) { sum += dicPet[i + 1].level - 1; } } return sum; case eCondition.PetHave: return dicPet[achive.condValue].have ? 1 : 0; case eCondition.PetspiritCompose: return PlayerTotalRecord.composePetSpirit; // 일일 퀘스트 case eCondition.DailyQuestClear: return PlayerDailyRecord.clearDailyQuest; // 아이콘, 칭호 장착 case eCondition.EquipIcon: return PlayData.playerIcon == achive.condValue ? 1 : 0; case eCondition.EquipTitle: return PlayData.playerTitle == achive.condValue ? 1 : 0; // 보석, 색상석 사용 case eCondition.UseDia: return ivalue; // 자동 전투 활성화 case eCondition.AutoBattle: return BattleMgr.GetAuto() ? 1 : 0; // 닉네임 변경 case eCondition.RenameCnt: return PlayerTotalRecord.renameCnt; // 광고 버프 case eCondition.ActivateADbuff: return PlayBuff.adTimer[0] > 0 || PlayBuff.adTimer[1] > 0 || PlayBuff.adTimer[2] > 0 ? 1 : 0; case eCondition.ActivateADbuffAtk: return PlayBuff.adTimer[0] > 0 ? 1 : 0; case eCondition.ActivateADbuffExp: return PlayBuff.adTimer[1] > 0 ? 1 : 0; case eCondition.ActivateADbuffGold:return PlayBuff.adTimer[2] > 0 ? 1 : 0; case eCondition.ADbuffAtkLv: return PlayBuff.atkLv; case eCondition.ADbuffExpLv: return PlayBuff.expLv; case eCondition.ADbuffGoldLv: return PlayBuff.goldLv; case eCondition.Etc: if (achive.contentType == eContentType.Title) ivalue = dicProfileTitle[achive.id].have ? 1 : 0; else if (achive.contentType == eContentType.Icon) ivalue = dicProfileIcon[achive.id].have ? 1 : 0; else ivalue = 0; return ivalue; default: return -1; } } public static int GetAchievementValueWithDay(nAchivement achive, int day) { switch (achive.condition) { case eCondition.EventQuestDayClear: return GetPlayEventQuestDayClearCount(day); default: return -1; } } #endregion #region Quest public static dQuest GetDailyQuest(int id) { return sysQuestDaily[id]; } public static Dictionary GetDailyQuests() { return sysQuestDaily; } public static dQuest GetRepeatQuest(int id) { return sysQuestRepeat[id]; } public static Dictionary GetRepeatQuests() { return sysQuestRepeat; } public static void SetDailyQuestPlay(cQuestDaily data) { playQuestDaily[data.sid - 1] = data; } public static void SetDailyQuestAllPlay(cQuestDaily[] datas) { playQuestDaily = datas; } public static cQuestDaily GetDailyQuestPlay(int id) { return playQuestDaily[id - 1]; } public static void SetRepeatQuestPlay(cQuestRepeat data) { playQuestRepeat[data.sid - 1] = data; } public static void SetRepeatQuestAllPlay(cQuestRepeat[] datas) { playQuestRepeat = datas; } public static void LoadPlayEventQuestPlay(cQuestEvent[] datas) { for (int i = 0; i < datas.Length; ++i) { cQuestEvent quest = datas[i]; playQuestEvent.SafeInsert(quest.sid, quest); } } public static cQuestEvent GetPlayEventQuestPlay(int sid) { return playQuestEvent[sid]; } public static void SetPlayEventQuestPlay(cQuestEvent eventQuest) { playQuestEvent[eventQuest.sid] = eventQuest; } public static int GetPlayEventQuestDayClearCount(int day) { int count = 0; foreach (var quest in sysQuestEvent.Values) { if (quest.day == day && playQuestEvent[quest.id].cond > 0) ++count; } return count; } public static cQuestAttend GetPlayEventQuestAttendPlay() { return playQuestEventAttend; } #endregion #region Mission public static dMission[] GetAllQuestMission() { return sysQuestMission.Values.ToArray(); } public static dMission GetQuestMission(int key) { if (!sysQuestMission.ContainsKey(key)) return null; return sysQuestMission[key]; } #endregion #region AdBuff public static dAdBuff[] GetSysAdBuffs() { return sysBuff; } public static dAdBuff GetSysAdBuffLevel(int ilv) { if (ilv >= sysBuff.Length) { return sysBuff[sysBuff.Length - 1]; } return sysBuff[ilv - 1]; } public static int GetSysAdBuffMaxLevel() { return sysBuff.Length; } #endregion #region Attend public static dAttend[] GetSysAttend() { return sysAttend; } #endregion #region Event public static Dictionary GetEvents() { return dicEvent; } public static dEvent GetEvent(int key) => dicEvent.SafeGet(key); public static dEvent GetEventByKind(eEventMoveType eventkind) { foreach (var item in dicEvent) { if (eventkind == item.Value.moveType) return item.Value; } return null; } public static Dictionary GetSysEventQuest() { return sysQuestEvent; } public static dQuest GetSysEventGetCompleteAllQuest(int day)//어느 퀘스트가 모두 완료 형식의 퀘스트인지 분간하는 용도. 모두 완료 형식은 날짜 첫번째 퀘스트가 되어야 한다. { for (int i = 0; i < sysQuestEvent.Count; i++) { if (day == sysQuestEvent[i + 1].day) { return sysQuestEvent[i + 1]; } } return sysQuestEvent[1]; } public static dQuest GetSysEventQuest(int key) { if (!sysQuestEvent.ContainsKey(key)) return null; return sysQuestEvent[key]; } public static dEventInfo GetSysEventTrade() { return sysEventTrade; } public static dEventInfo GetSysEventRaise() { return sysEventRaise; } public static dEventInfo GetSysEventRoulette() { return sysEventRoulette; } public static cEventItem GetPlayEventTrade() { return playEventTrade; } public static cEventItem GetPlayEventRaise() { return playEventRaise; } public static void LoadPlayEventRaise(cEventItem eventItem) { playEventRaise = eventItem; } public static void LoadPlayEventRoulette(cEventItem eventItem) { playEventRoulette = eventItem; } public static cEventItem GetPlayEventRoulette() { return playEventRoulette; } public static void SetPlayEventTrade(cEventItem trade) { playEventTrade = trade; } public static dRewardEvent GetRewardEvent() { return sysRewardEvent; } #endregion #region Shop // 상점 시스템 데이터. public static void LoadShopSysData(dShop[] datas) { for (int i = 0; i < datas.Length; ++i) { dShop shopItem = datas[i]; if (shopItem.rewards.Length == 0) continue; shopItem.refreshAt = DateTime.MaxValue; dicShop.SafeInsert(shopItem.id, shopItem); int groupIdx = (int)shopItem.shopType; if (groupIdx >= 0 && groupIdx < shopGroupedByShopType.Length) { shopGroupedByShopType[groupIdx].Add(shopItem); } else if (shopItem.shopType == eShopType.Pass) { if (TryGetPassById(shopItem.rewards[0].rewardId, out dPass pass)) { int ipage = (int)shopItem.rewards[0].rewardCount; if (ipage >= 0 && ipage < pass.shopIds.Length) pass.shopIds[ipage] = shopItem.id; } } } } // 상점 플레이 데이터. public static void LoadShopPlayData(sShopPlay[] playdatas) { for (int i = 0; i < playdatas.Length; ++i) { if (!dicShop.TryGetValue(playdatas[i].sid, out dShop targetShop)) continue; targetShop.buyCnt = playdatas[i].buyCnt; targetShop.totalCnt = playdatas[i].totalCnt; targetShop.refreshAt = playdatas[i].refreshAt; if (targetShop.refreshAt <= TimeUtils.Now()) { targetShop.buyCnt = 0; targetShop.refreshAt = DateTime.MaxValue; } } // 보석/의상/무기/일반/마일리지 정렬. SortShopIdsOrder(eShopType.Dia); SortShopIdsOrder(eShopType.CostumeCloth); SortShopIdsOrder(eShopType.CostumeWeapon); SortShopIdsOrder(eShopType.General); SortShopIdsOrder(eShopType.Mileage); // 이벤트/특별패키지/코스튬패키지만 정렬함. SortShopIdsOrderLimit(eShopType.Event); SortShopIdsOrderLimit(eShopType.SpecialPack); SortShopIdsOrderLimit(eShopType.CostumePack); } // 상점 아이템 sortOrder 따라 정렬. 플레이 데이터 로딩 후, 구매 제한 횟수 충족 후 호출. 보석/의상/무기/일반/마일리지 정렬. private static void SortShopIdsOrder(eShopType shoptype) { var targetGroup = GetShopGroup(shoptype); targetGroup.InsertionSort((s1, s2) => s1.sortOrder >= s2.sortOrder); } // 상점 아이템 sortOrder, 구매 완료에 따라 정렬. 플레이 데이터 로딩 후, 구매 제한 횟수 충족 후 호출. 이벤트/특별패키지/코스튬패키지만 정렬함. private static void SortShopIdsOrderLimit(eShopType shoptype) { var targetGroup = GetShopGroup(shoptype); targetGroup.InsertionSort((s1, s2) => { int s1SortOrder = s1.sortOrder + (s1.buyCnt >= s1.limitCnt ? 100000 : 0); int s2SortOrder = s2.sortOrder + (s2.buyCnt >= s2.limitCnt ? 100000 : 0); return s1SortOrder >= s2SortOrder; }); } // 상점 정렬된 ID 목록 가져오기. public static List GetShopGroup(eShopType shoptype) { int groupIdx = (int)shoptype; if (groupIdx < 0 || groupIdx >= shopGroupedByShopType.Length) return new List(); return shopGroupedByShopType[groupIdx]; } // 상점 데이터 가져오기. public static dShop GetShop(int key) { return dicShop[key]; } // 인덱스로 상점 데이터 가져오기. public static dShop GetShopByIndex(eShopType shoptype, int index) { var targetGroup = GetShopGroup(shoptype); if (targetGroup is null) return null; else return targetGroup[index]; } // 상점 구매 초기화 처리. public static void ResetShop() { foreach (var item in dicShop.Values) { if (item.refreshAt <= TimeUtils.Now()) { item.buyCnt = 0; item.refreshAt = DateTime.MaxValue; } } } // 가격 텍스트 가져오기. public static string GetShopPrice(int key, int icount) { if (key < 0 || !dicShop.ContainsKey(key)) return FormatString.TextPriceCash(9999); dShop data = dicShop[key]; if (data.buyingType == cGoods.TAds) return LocalizationText.GetText("adbuff_playad"); if (data.buyingType == cGoods.TCash) { if (string.IsNullOrEmpty(data.productId)) return FormatString.TextPriceCash(data.buyingCnt * icount); string strprice = IapMgr.SGetPrice(data.productId); if (!string.IsNullOrEmpty(strprice)) return strprice; return FormatString.TextPriceCash(data.buyingCnt * icount); } return FormatString.TextInt(data.buyingCnt * icount); } // 구매 후 처리. public static void BuyShop(int key, int ibuycnt, int itotalcnt, DateTime refreshtime) { if (key < 0 || !dicShop.ContainsKey(key)) return; dShop data = dicShop[key]; data.buyCnt = ibuycnt; data.totalCnt = itotalcnt; if (data.refreshType == eRefreshType.None || data.refreshType == eRefreshType.Account) data.refreshAt = DateTime.MaxValue; else data.refreshAt = refreshtime; // 이벤트/특별패키지/코스튬패키지만 정렬함. if (data.buyCnt >= data.limitCnt && data.shopType == eShopType.Event || data.shopType == eShopType.SpecialPack || data.shopType == eShopType.CostumePack) SortShopIdsOrderLimit(data.shopType); } #endregion Shop #region Pass // 패스 시스템 데이터. 패스ID가 아닌 조건을 키로 사용. public static void LoadPassSysData(dPass[] datas) { for (int i = 0; i < datas.Length; ++i) { dPass pass = datas[i]; int len = ((pass.levels.Length - 1) / pass.passUnit) + 1; pass.isPaid = new bool[len]; pass.haveLvFrees = new int[len]; pass.haveLvPaids = new int[len]; pass.shopIds = new int[len]; pass.shopIds.SetElements(-1); pass.refreshAt = pass.endAt; // 1. 일회성 패스, 2. 이벤트 패스. if (pass.passType == 1) { dicPass.SafeInsert(pass.condType, pass); } else if (pass.passType == 2) { if (pass.startAt <= TimeUtils.Now()) passEvent = pass; else passEventNext = pass; } } } // 패스 플레이 데이터. public static void LoadPassPlayData(sPassPlay[] playdatas) { for (int i = 0; i < playdatas.Length; ++i) { sPassPlay playData = playdatas[i]; if (!TryGetPassById(playData.sid, out dPass sysData)) continue; if (playData.refreshAt < sysData.endAt) sysData.refreshAt = playData.refreshAt; // 달성도 세팅. switch (sysData.condType) { case eCondition.StageClear: sysData.progress = PlayData.clearStage; break; case eCondition.PlayerLv: sysData.progress = PlayData.playerLv; break; default: if (bLoadLocalData) sysData.progress = ES3.Load(playData.sid.ToString(), Global.ES3_Pass, 0); else sysData.progress = playData.progress; break; } // 유료 구매, 보상 수령 상태. if (playData.isPaid != null) Array.Copy(playdatas[i].isPaid, sysData.isPaid, sysData.isPaid.Length); if (playData.haveLvFrees != null) Array.Copy(playdatas[i].haveLvFrees, sysData.haveLvFrees, sysData.haveLvFrees.Length); if (playData.haveLvPaids != null) Array.Copy(playdatas[i].haveLvPaids, sysData.haveLvPaids, sysData.haveLvPaids.Length); // 달성도 레벨 계산. sysData.availLevel = 0; while (sysData.progress >= sysData.levels[sysData.availLevel].condValue) { if (++sysData.availLevel >= sysData.levels.Length) break; } } } // 패스 목록 가져오기. public static Dictionary GetPasses() { return dicPass; } // 아이디로 패스 가져오기. public static bool TryGetPassById(int id, out dPass result) { result = null; if (passEvent != null && id == passEvent.id) result = passEvent; else if (passEventNext != null && id == passEventNext.id) result = passEventNext; else { foreach (var item in dicPass.Values) { if (id == item.id) { result = item; break; } } } return result != null; } // 패스 정보 가져오기. public static bool TryGetPass(int passtype, eCondition condtype, out dPass result) { result = null; // 1. 일회성 패스. 2. 이벤트 패스. if (passtype == 1 && dicPass.TryGetValue(condtype, out result)) { } else if (passtype == 2 && passEvent?.condType == condtype) result = passEvent; return result != null; } public static IList GetPassesByCond(eCondition condtype) { var result = new List(); if (dicPass.TryGetValue(condtype, out dPass pass)) result.Add(pass); if (passEvent?.condType == condtype) result.Add(passEvent); return result; } // 패스 진행도. 일반 몬스터 처치 등 자주 처리되는 것이 있을 수 있으므로 여기서 바로 저장하지는 않음. public static void SetPassProgress(eCondition condtype, int ivalue) { foreach (var item in GetPassesByCond(condtype)) { item.progress = ivalue; } } // 패스 진행도. 일반 몬스터 처치 등 자주 처리되는 것이 있을 수 있으므로 여기서 바로 저장하지는 않음. public static void AddPassProgress(eCondition condtype, int ivalue) { foreach (var item in GetPassesByCond(condtype)) { item.progress += ivalue; } } // 패스 진행도 계산. 보상 획득 시점, 뱃지 갱신할때 호출. public static void CalcPassProgress(int passtype, eCondition condtype) { if (!TryGetPass(passtype, condtype, out dPass targetPass)) return; // 이미 최고 단계까지 달성했을 경우. if (targetPass.availLevel >= targetPass.levels.Length) return; // 달성 단계 다시 계산. while (targetPass.progress >= targetPass.levels[targetPass.availLevel].condValue) { if (++targetPass.availLevel >= targetPass.levels.Length) break; } } // 패스 수령 가능한 보상이 있는지. public static bool IsPassRewardAvail(int passtype, eCondition condtype) { if (!TryGetPass(passtype, condtype, out dPass targetPass)) return false; for (int i = 0; i < targetPass.isPaid.Length; ++i) { if(IsPassRewardAvail(passtype, condtype, i)) return true; } return false; } // 패스 현재 페이지에 수령 가능한 보상이 있는지. public static bool IsPassRewardAvail(int passtype, eCondition condtype, int pageindex) { if (!TryGetPass(passtype, condtype, out dPass targetPass)) return false; if (pageindex >= targetPass.isPaid.Length) return false; int minindexinc = pageindex * targetPass.passUnit; // 수령 가능한 최대 항목이 페이지 처음 항목 이전일 경우. if (targetPass.availLevel <= minindexinc) return false; int[] targetHaveLv; if (targetPass.isPaid[pageindex]) targetHaveLv = targetPass.haveLvPaids; else targetHaveLv = targetPass.haveLvFrees; // 페이지에서 수령한 항목이 페이지의 마지막 항목 이전일 경우. int maxindexexc = (pageindex + 1) * targetPass.passUnit; if (targetHaveLv[pageindex] < maxindexexc) { // 수령 가능한 항목이 있을 경우. if (targetHaveLv[pageindex] < targetPass.availLevel) return true; } return false; } // 패스 보상 획득시 처리. public static void RecvPassReward(int passtype, eCondition condtype, int pageindex, int level) { if(!TryGetPass(passtype, condtype, out dPass targetPass)) return; targetPass.haveLvFrees[pageindex] = level; if (targetPass.isPaid[pageindex]) targetPass.haveLvPaids[pageindex] = level; } // 패스 구매. public static void BuyPass(int passtype, eCondition condtype, int pageindex) { if (!TryGetPass(passtype, condtype, out dPass targetPass)) return; targetPass.isPaid[pageindex] = true; } // 패스 저장. private static void SavePass() { // 일회성 패스. foreach (var item in dicPass) ES3.Save(item.Value.id.ToString(), item.Value.progress, Global.ES3_Pass); // 이벤트 패스. if (passEvent != null) ES3.Save(passEvent.id.ToString(), passEvent.progress, Global.ES3_Pass); } // 이벤트/반복 패스 갱신(초기화). public static bool ResetPass() { bool breset = false; // 이벤트 패스 갱신. // 현재 이벤트 패스가 존재함. if (passEvent != null) { // 이벤트 패스가 종료되었을 때. if (passEvent.endAt <= TimeUtils.Now()) { breset = true; // 다음 이벤트 패스가 없음. if (passEventNext == null) { passEvent = null; } // 다음 이벤트 패스가 존재하고, 시작 시간이 되었을 때. 이벤트 패스 교체. else if (passEventNext != null && passEventNext.startAt >= TimeUtils.Now()) { passEvent = passEventNext; passEventNext = null; } // 다음 이벤트 패스가 존재하지만, 아직 시작 시간이 아닐 때. else { passEvent = null; } } } // 현재 이벤트 패스가 없으며, 다음 이벤트 패스가 존재하고, 시작 시간이 되었을 때. 이벤트 패스 교체. else if (passEventNext != null && passEventNext.startAt >= TimeUtils.Now()) { breset = true; passEvent = passEventNext; passEventNext = null; } // 다음 이벤트 패스가 존재하지만, 아직 시작 시간이 아닐 때. else { breset = true; passEvent = null; } return breset; } #endregion Pass #region Mail // 우편 데이터 로드. public static void LoadMail(dMail[] mails, bool bupdatecount, bool bserver) { if (mails == null) mails = new dMail[0]; playMails = mails; if (bupdatecount) MailCount = playMails.Length; if (bserver) MailRefreshTime = TimeUtils.Now().AddMinutes(5d); } // 읽은 우편 데이터 로드. public static void LoadMailRead(dMail[] reads, bool bserver) { if (reads == null) reads = new dMail[0]; readMails = reads; if (bserver) MailReadRefreshTime = TimeUtils.Now().AddMinutes(5d); } // 우편 수. public static void SetMailCount(int icnt) { MailCount = icnt; if (playMails != null && MailCount != playMails.Length) MailRefreshTime = TimeUtils.Now(); } // 우편 내역 갱신 시간 수정. public static void UpdateMailReadTime() { if (readMails != null) MailReadRefreshTime = TimeUtils.Now(); } // 우편 목록. public static dMail[] GetMails() { return playMails; } // 읽은 우편 목록. public static dMail[] GetMailReads() { return readMails; } // 우편(인덱스). public static dMail GetMailByIndex(int itype, int index) { if (playMails == null) return null; // 읽지 않은 우편. if (itype == 0) { if (index >= playMails.Length) return null; return playMails[index]; } // 읽은 우편. if (index >= readMails.Length) return null; return readMails[index]; } // 우편(인덱스). public static dMail GetMailByIndex(int index) { if (playMails == null || index >= playMails.Length) return null; return playMails[index]; } // 읽은 우편(인덱스). public static dMail GetMailReadByIndex(int index) { if (readMails == null || index >= readMails.Length) return null; return readMails[index]; } #endregion Mail #region Pvp // 결투장 데이터. public static void LoadPvpData(cPvpPlay _playPvp, dPvpRank pvpmyrank) { playPvp = _playPvp; pvpMyRank = pvpmyrank; playPvp.availWeeklyIndex = -1; for (int i = sysPvp.missions.Length - 1; i >= 0; --i) { if (playPvp.weeklyTry >= sysPvp.missions[i].condValue) { playPvp.availWeeklyIndex = i; break; } } dPvpTier tier = GetPvpTier(pvpMyRank.tier); BuffMgr.Instance.SetPvpTier(tier.abilityValue1, tier.abilityValue2, tier.abilityValue3, tier.abilityValue4); } // 결투장 플레이 데이터 업데이트. public static void UpdatePvpPlay(cPvpPlay pvpplay) { playPvp = pvpplay; playPvp.availWeeklyIndex = -1; for (int i = sysPvp.missions.Length - 1; i >= 0; i--) { if (playPvp.weeklyTry >= sysPvp.missions[i].condValue) { playPvp.availWeeklyIndex = i; break; } } } // 결투장 프리셋 변경. public static void UpdatePvpPreset(int skillpreset, int petpreset, int awakenpreset) { playPvp.usePreset = skillpreset; playPvp.usePetPreset = petpreset; playPvp.useExtraPreset = awakenpreset; } // 결투장 플레이 랭킹 업데이트. public static void UpdatePvpMyRank(dPvpRank pvpmyrank) { int itierprev = pvpMyRank.tier; pvpMyRank = pvpmyrank; // 티어 변경 시 능력치 변경. if (itierprev != pvpMyRank.tier) { dPvpTier tier = GetPvpTier(pvpMyRank.tier); BuffMgr.Instance.SetPvpTier(tier.abilityValue1, tier.abilityValue2, tier.abilityValue3, tier.abilityValue4); } } // 결투장 랭킹 업데이트. public static void UpdatePvpRank(dPvpRank[] pvpRanks) { DataHandler.pvpRanks = pvpRanks; PvpRankRefreshTime = TimeUtils.Now().AddMinutes(5d); } // 결투장 보상 데이터 가져오기. public static dPvpRew GetPvpReward(int index) => sysPvp.missions.ClampGet(index); // 결투장 티어 목록 가져오기. public static dPvpTier[] GetPvpTiers() => sysPvp.tier; // 결투장 티어 가져오기. public static dPvpTier GetPvpTier(int tier) => sysPvp.tier.ClampGet(tier - 1); // 결투장 티어 가져오기. public static bool TryGetPvpRank(int rank, out dPvpRank result) { result = null; int idx = rank - 1; if (idx >= 0 && idx < pvpRanks.Length) result = pvpRanks[idx]; return result != null; } #endregion Pvp #region Notice public static void SetNewNotices(dNotice[] newNotices) => sysNotices = newNotices; public static dNotice[] GetNotices() => sysNotices; public static bool TryGetNotice(int index, out dNotice result) => sysNotices.TryGetValueAt(index, out result); public static void SetNewChatNotices(dChatNotice[] newNotices) => sysChatNotices = newNotices; public static dChatNotice[] GetChatNotices() => sysChatNotices; #endregion Notice #region LevelUpInterval static List goldAtkLevel1000Interval = new List(); static List goldHPLevel1000Interval = new List(); static List exp1000Interval = new List(); public static BigInteger GetGoldLevelInterval(int Level) { if (Level / 1000