638 lines
25 KiB
C#
638 lines
25 KiB
C#
|
|
using CodeStage.AntiCheat.ObscuredTypes;
|
||
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Linq;
|
||
|
|
using UnityEngine;
|
||
|
|
using Random = UnityEngine.Random;
|
||
|
|
|
||
|
|
public static class MyValue
|
||
|
|
{
|
||
|
|
public static string OnestoreURL = "https://onesto.re/0000759501";
|
||
|
|
|
||
|
|
public static int UTC = 9;
|
||
|
|
public static int ItemID_Gem = 101, ItemID_Gold = 201, ItemID_Soul = 301, ItemID_Potion = 401, ItemID_Exp = 501,
|
||
|
|
ItemID_EvolutionMaxStone = 601;
|
||
|
|
|
||
|
|
public static Dictionary<eEquipmentParts, int> dic_NeedEvolution = new Dictionary<eEquipmentParts, int>
|
||
|
|
{ { eEquipmentParts.Ring, 1 }, { eEquipmentParts.Necklace, 2 }, { eEquipmentParts.SubWeapon, 3 } };
|
||
|
|
public static int PCEvolutionMaxLv = 6, SealMixCount = 3;
|
||
|
|
public static float MaxAvoid = 0.9f, MaxCri = 0.9f;
|
||
|
|
|
||
|
|
public static string OptionKey_UserType = "Option_UserType"; // 0 구글, 1 애플, 2 게스트
|
||
|
|
public static string OptionKey_UserID = "Option_UserID";
|
||
|
|
|
||
|
|
public static string SaveDataFileName = "SaveData";
|
||
|
|
public static ServerData sdata => ServerInfo.Ins.m_ServerData;
|
||
|
|
|
||
|
|
public static MyStageData m_MyStageData = new MyStageData();
|
||
|
|
public static void Set_StageData(int chapter, int stage)
|
||
|
|
{
|
||
|
|
// 정인호 : 난이도, 챕터 정보도 필요
|
||
|
|
m_MyStageData.m_Diff = 1;
|
||
|
|
m_MyStageData.m_Chapter = chapter;
|
||
|
|
m_MyStageData.m_Stage = stage;
|
||
|
|
m_MyStageData.m_NodeIndex = -1;
|
||
|
|
m_MyStageData.m_GameMode = eGameMode.Stage;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static ActorStatInfo Get_PCActorStatInfo(int pcid)
|
||
|
|
{
|
||
|
|
var pc = InGameInfo.Ins.m_PCActor;
|
||
|
|
var pctdata = table_pclist.Ins.Get_Data_orNull(pcid);
|
||
|
|
pc.Set(0, pctdata, IngameUIManager.Ins.PC_HUD_HPShield, sdata);
|
||
|
|
return Get_ActorStatInfo(pc, pctdata);
|
||
|
|
}
|
||
|
|
public static ActorStatInfo Get_ActorStatInfo(Actor actor, ActorTableDataBase actordata)
|
||
|
|
{
|
||
|
|
var stat = new ActorStatInfo(actor, true);
|
||
|
|
|
||
|
|
stat.Set_Stat(eStat.AttackCoolTime, actordata.f_AttackCoolTime);
|
||
|
|
stat.Set_Stat(eStat.Attack_Min, actordata.n_AttackMin);
|
||
|
|
stat.Set_Stat(eStat.Attack_Max, actordata.n_AttackMax);
|
||
|
|
stat.Set_Stat(eStat.Cri, actordata.f_Cri);
|
||
|
|
stat.Set_Stat(eStat.CriDmg, actordata.f_CriDmg);
|
||
|
|
stat.Set_Stat(eStat.HitRate, 100);
|
||
|
|
|
||
|
|
if (actor.IsRole(eRole.Mob))
|
||
|
|
{
|
||
|
|
stat.Set_Stat(eStat.HP, actordata.n_HP, true);
|
||
|
|
stat.Set_Stat(eStat.Shield, actordata.n_Shield, true);
|
||
|
|
stat.Set_Stat(eStat.Avoid_Melee, actordata.n_Avoid_Meele * 100);
|
||
|
|
stat.Set_Stat(eStat.Avoid_Range, actordata.n_Avoid_Range * 100);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
var sdata = actor.Get_ServerData();
|
||
|
|
var pcid = actor.Get_Data().n_ID;
|
||
|
|
var addstats = new Dictionary<eStat, float>
|
||
|
|
{
|
||
|
|
{ eStat.Attack_Min, 0 }, { eStat.Attack_Max, 0 }, { eStat.MaxHP, 0 }, { eStat.MaxShield, 0 },
|
||
|
|
{ eStat.HitRate, 0 }, { eStat.Avoid_Melee, 0 }, { eStat.Avoid_Range, 0 }, { eStat.Cri, 0 }, { eStat.CriDmg, 0 },
|
||
|
|
};
|
||
|
|
|
||
|
|
// 2025. 12. 08 : 진화값 추가
|
||
|
|
var evolution = sdata.Get_PCEvolution(pcid);
|
||
|
|
for (int i = 1; i < evolution; i++)
|
||
|
|
{
|
||
|
|
var evolutionTdata = table_PCEvolution.Ins.Get_Data(pcid, i);
|
||
|
|
addstats[eStat.Attack_Min] += evolutionTdata.n_AttackValue;
|
||
|
|
addstats[eStat.Attack_Max] += evolutionTdata.n_AttackValue;
|
||
|
|
addstats[eStat.MaxHP] += evolutionTdata.n_MaxHPValue;
|
||
|
|
addstats[eStat.MaxShield] += evolutionTdata.n_MaxShieldValue;
|
||
|
|
addstats[eStat.HitRate] += evolutionTdata.n_HitRateValue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 2025. 12. 09 : 한계돌파값 추가
|
||
|
|
foreach (var key in addstats.Keys.ToList())
|
||
|
|
{
|
||
|
|
var lv = sdata.Get_PCEvolutionMax(pcid, key);
|
||
|
|
if (lv > 0)
|
||
|
|
{
|
||
|
|
var tData = table_PCEvolutionMax.Ins.Get_Data(key);
|
||
|
|
addstats[key] += lv *
|
||
|
|
(tData.e_Stat == eStat.Avoid_Melee || tData.e_Stat == eStat.Avoid_Range ? tData.f_Value * 100 :
|
||
|
|
tData.f_Value);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 2025.12.27 : 장비값 추가
|
||
|
|
var equipitems = sdata.Get_EquipItems(pcid);
|
||
|
|
for (int i = 0; i < equipitems.Count; i++)
|
||
|
|
{
|
||
|
|
var equip = equipitems[i];
|
||
|
|
if (equip == null || equip.ID == 0)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
var tdata = table_EquipmentList.Ins.Get_Data(equip.TableID);
|
||
|
|
if (tdata == null)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
int lv = equip.Lv;
|
||
|
|
|
||
|
|
// ===== Main Option =====
|
||
|
|
if (tdata.n_MainOtion > 0)
|
||
|
|
{
|
||
|
|
var mainOpt = table_StatusOptionSet.Ins.Get_Data(tdata.n_MainOtion);
|
||
|
|
if (mainOpt != null)
|
||
|
|
{
|
||
|
|
ApplyStat(stat, addstats, mainOpt.e_Stat1, tdata.Get_Value(eEquipmentStat.Main1, actordata.n_ID, lv));
|
||
|
|
ApplyStat(stat, addstats, mainOpt.e_Stat2, tdata.Get_Value(eEquipmentStat.Main2, actordata.n_ID, lv));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ===== Sub Options =====
|
||
|
|
ApplyStat(stat, addstats, tdata, tdata.n_SubOtion1, eEquipmentStat.Sub1, actordata.n_ID, lv);
|
||
|
|
ApplyStat(stat, addstats, tdata, tdata.n_SubOtion2, eEquipmentStat.Sub2, actordata.n_ID, lv);
|
||
|
|
ApplyStat(stat, addstats, tdata, tdata.n_SubOtion3, eEquipmentStat.Sub3, actordata.n_ID, lv);
|
||
|
|
ApplyStat(stat, addstats, tdata, tdata.n_SubOtion4, eEquipmentStat.Sub4, actordata.n_ID, lv);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 2026. 01. 02 : 장비 세트 옵션값 추가
|
||
|
|
var setitemData = sdata.Get_EquipSetItemData(actordata.n_ID);
|
||
|
|
if (setitemData != null)
|
||
|
|
foreach (var item in setitemData.dic_Stat)
|
||
|
|
ApplyStat(stat, addstats, item.Key, item.Value);
|
||
|
|
|
||
|
|
stat.Set_Stat(true, eStat.Attack_Min, addstats[eStat.Attack_Min]);
|
||
|
|
stat.Set_Stat(true, eStat.Attack_Max, addstats[eStat.Attack_Max]);
|
||
|
|
stat.Set_Stat(true, eStat.HitRate, addstats[eStat.HitRate]);
|
||
|
|
stat.Set_Stat(true, eStat.Cri, addstats[eStat.Cri]);
|
||
|
|
stat.Set_Stat(true, eStat.CriDmg, addstats[eStat.CriDmg]);
|
||
|
|
|
||
|
|
stat.Set_Stat(eStat.HP, actordata.n_HP + addstats[eStat.MaxHP], true);
|
||
|
|
stat.Set_Stat(eStat.Shield, actordata.n_Shield + addstats[eStat.MaxShield], true);
|
||
|
|
stat.Set_Stat(eStat.Avoid_Melee, actordata.n_Avoid_Meele + addstats[eStat.Avoid_Melee]);
|
||
|
|
stat.Set_Stat(eStat.Avoid_Range, actordata.n_Avoid_Range + addstats[eStat.Avoid_Range]);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 테스트 : 포션 임의 세팅
|
||
|
|
stat.Set_Stat(eStat.Potion, 5, true);
|
||
|
|
|
||
|
|
return stat;
|
||
|
|
}
|
||
|
|
static void ApplyStat(ActorStatInfo stat, Dictionary<eStat, float> addstats, eStat statType, float value)
|
||
|
|
{
|
||
|
|
if (addstats.ContainsKey(statType))
|
||
|
|
addstats[statType] += value;
|
||
|
|
else
|
||
|
|
stat.Set_Stat(true, statType, value);
|
||
|
|
}
|
||
|
|
static void ApplyStat(ActorStatInfo stat, Dictionary<eStat, float> addstats, EquipmentListTableData tdata,
|
||
|
|
int optionId, eEquipmentStat estat, int pcid, int lv)
|
||
|
|
{
|
||
|
|
if (optionId <= 0) return;
|
||
|
|
|
||
|
|
var optData = table_StatusOptionSet.Ins.Get_Data(optionId);
|
||
|
|
if (optData == null) return;
|
||
|
|
|
||
|
|
ApplyStat(stat, addstats, optData.e_Stat1, tdata.Get_Value(estat, pcid, lv));
|
||
|
|
}
|
||
|
|
|
||
|
|
public static Dictionary<eGrade, Color> dic_GradeColor = new Dictionary<eGrade, Color>
|
||
|
|
{
|
||
|
|
{ eGrade.None, new Color32(161,152,148,255) },
|
||
|
|
{ eGrade.Common, new Color32(161,152,148,255) },
|
||
|
|
{ eGrade.UnCommon, new Color32(158,215,35,255) },
|
||
|
|
{ eGrade.Rare, new Color32(25,197,240,255) },
|
||
|
|
{ eGrade.Hero, new Color32(191,106,219,255) },
|
||
|
|
{ eGrade.Legend, new Color32(252,218,32,255) },
|
||
|
|
{ eGrade.Grade6, new Color32(240,65,65,255) },
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
public enum eStageEnterType { Normal, Tool, Tool_Mob }
|
||
|
|
public class MyStageData
|
||
|
|
{
|
||
|
|
public eStageEnterType m_EnterType = eStageEnterType.Normal;
|
||
|
|
public eGameMode m_GameMode;
|
||
|
|
|
||
|
|
ObscuredInt _diff = 1; public int m_Diff { get { return _diff; } set { _diff = value; _diff.RandomizeCryptoKey(); } }
|
||
|
|
ObscuredInt _chapter = 1; public int m_Chapter { get { return _chapter; } set { _chapter = value; _chapter.RandomizeCryptoKey(); } }
|
||
|
|
ObscuredInt _stage; public int m_Stage { get { return _stage; } set { _stage = value; _stage.RandomizeCryptoKey(); } }
|
||
|
|
ObscuredInt _node; public int m_NodeIndex { get { return _node; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
_node = value;
|
||
|
|
_node.RandomizeCryptoKey();
|
||
|
|
|
||
|
|
// 스테이지 진행 상황 UI 갱신
|
||
|
|
if (_node > -1) IngameUIManager.Ins.m_DungeonInfo.m_DungeonProcess.Set();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
public IngameStageData m_StageData;
|
||
|
|
StageNodeData m_CurNode;
|
||
|
|
|
||
|
|
public void Set_CurNodeData()
|
||
|
|
{
|
||
|
|
m_CurNode = m_StageData.list_Nodedata.Count > m_NodeIndex ? m_StageData.list_Nodedata[m_NodeIndex] : null;
|
||
|
|
|
||
|
|
if (m_CurNode != null && m_CurNode.m_Type == eStageNodeType.Random)
|
||
|
|
{
|
||
|
|
var rdnnodedata = m_CurNode.Get_Data<StageNodeData_Random>();
|
||
|
|
var tabledata = table_RandomPatternConfig.Ins.Get_Data(rdnnodedata.RandomID);
|
||
|
|
|
||
|
|
int pick = -1;
|
||
|
|
int safety = 20; // 무한루프 방지
|
||
|
|
|
||
|
|
while (safety-- > 0)
|
||
|
|
{
|
||
|
|
var tmp = DSUtil.WeightedPickIndex(tabledata.list_Weight, x => x);
|
||
|
|
var type = eStageNodeType.Nothing;
|
||
|
|
switch (tmp)
|
||
|
|
{
|
||
|
|
case 1: type = eStageNodeType.Mob; break;
|
||
|
|
case 2: type = eStageNodeType.BuffDebuff; break;
|
||
|
|
case 3: type = eStageNodeType.Merchant; break;
|
||
|
|
case 4: type = eStageNodeType.Treasure; break;
|
||
|
|
case 5: type = eStageNodeType.NPC; break;
|
||
|
|
case 6: type = eStageNodeType.Sanctuary; break;
|
||
|
|
case 7: type = eStageNodeType.TwoWay; break;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 제한 걸린 타입이면 다시 뽑기
|
||
|
|
if (m_StageData.Use_RandomNodeLimit(type))
|
||
|
|
{
|
||
|
|
pick = tmp;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
switch (pick)
|
||
|
|
{
|
||
|
|
default: // 없음
|
||
|
|
m_CurNode.Set_Data(eStageNodeType.Nothing, new StageNodeData_Nothing());
|
||
|
|
break;
|
||
|
|
case 1: // 몬스터 등장
|
||
|
|
{
|
||
|
|
var mobnodedata = new StageNodeData_Mob();
|
||
|
|
var patternindex = DSUtil.WeightedPickIndex(m_StageData.list_PatternData, x => x.m_Weight);
|
||
|
|
var patterndata = m_StageData.list_PatternData[patternindex];
|
||
|
|
mobnodedata.PatternID = patterndata.m_PatternID;
|
||
|
|
mobnodedata.MobCount = Mathf.Max(1, patterndata.m_MobCount);
|
||
|
|
mobnodedata.list_MobID = new List<int>();
|
||
|
|
var moblst = m_StageData.Get_MonsterList(false);
|
||
|
|
for (int i = 0; i < mobnodedata.MobCount; i++)
|
||
|
|
{
|
||
|
|
var mobindex = DSUtil.WeightedPickIndex(moblst, x => x.m_Weight);
|
||
|
|
mobnodedata.list_MobID.Add(moblst[mobindex].m_MobID);
|
||
|
|
}
|
||
|
|
|
||
|
|
m_CurNode.Set_Data(eStageNodeType.Mob, mobnodedata);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case 2: // 버프/디버프
|
||
|
|
{
|
||
|
|
var nodedata = new StageNodeData_BuffDebuff();
|
||
|
|
nodedata.BuffID = table_BuffPatternConfig.Ins.Get_RandomData().n_BuffOptionID;
|
||
|
|
|
||
|
|
m_CurNode.Set_Data(eStageNodeType.BuffDebuff, nodedata);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case 3: // 암상인
|
||
|
|
{
|
||
|
|
var nodedata = new StageNodeData_Merchant();
|
||
|
|
nodedata.MerchantID = table_MerchantConfig.Ins.Get_RandomData().n_MerchantID;
|
||
|
|
|
||
|
|
m_CurNode.Set_Data(eStageNodeType.Merchant, nodedata);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case 4: // 보물 상자
|
||
|
|
{
|
||
|
|
var nodedata = new StageNodeData_Treasure();
|
||
|
|
var tdata = table_TreasureBoxConfig.Ins.Get_RandomData();
|
||
|
|
nodedata.BoxID = tdata.n_TreasureID;
|
||
|
|
nodedata.MimicRate = tdata.f_TreasureMimicRate;
|
||
|
|
|
||
|
|
m_CurNode.Set_Data(eStageNodeType.Treasure, nodedata);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case 5: // NPC
|
||
|
|
{
|
||
|
|
var nodedata = new StageNodeData_NPC();
|
||
|
|
var tdata = table_NPCConfig.Ins.Get_RandomData();
|
||
|
|
nodedata.NPCID = tdata.n_NPCID;
|
||
|
|
|
||
|
|
m_CurNode.Set_Data(eStageNodeType.NPC, nodedata);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case 6: // 성소
|
||
|
|
{
|
||
|
|
var nodedata = new StageNodeData_Mine();
|
||
|
|
var tdata = table_SanctuaryConfig.Ins.Get_RandomData();
|
||
|
|
nodedata.SanctuaryID = tdata.n_BuffOptionID;
|
||
|
|
|
||
|
|
m_CurNode.Set_Data(eStageNodeType.Sanctuary, nodedata);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case 7: // 갈림길
|
||
|
|
{ // TODO 정인호 : 갈림길 세부적인 건 추후에...
|
||
|
|
var nodedata = new StageNodeData_TwoWay();
|
||
|
|
nodedata.MapConfig1 = "";
|
||
|
|
nodedata.MapConfig2 = "";
|
||
|
|
nodedata.ChangeRate = 0.2f;
|
||
|
|
|
||
|
|
m_CurNode.Set_Data(eStageNodeType.TwoWay, nodedata);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
public StageNodeData Get_CurNodeData() { return m_CurNode; }
|
||
|
|
public int Get_MobID_onStage(eToolMobType type)
|
||
|
|
{
|
||
|
|
List<StageMonsterData> candidates = new List<StageMonsterData>();
|
||
|
|
|
||
|
|
if (type == eToolMobType.Melee)
|
||
|
|
{
|
||
|
|
foreach (var temp in m_StageData.list_MobData)
|
||
|
|
{
|
||
|
|
var mobdata = table_monsterlist.Ins.Get_Data_orNull(temp.m_MobID);
|
||
|
|
if (mobdata != null && mobdata.Get_AttackType() == eAttackType.Melee)
|
||
|
|
candidates.Add(temp);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (type == eToolMobType.Range)
|
||
|
|
{
|
||
|
|
foreach (var temp in m_StageData.list_MobData)
|
||
|
|
{
|
||
|
|
var mobdata = table_monsterlist.Ins.Get_Data_orNull(temp.m_MobID);
|
||
|
|
if (mobdata != null && mobdata.Get_AttackType() == eAttackType.Range)
|
||
|
|
candidates.Add(temp);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (candidates.Count == 0)
|
||
|
|
return 0; // 없을 때는 0 반환
|
||
|
|
|
||
|
|
// 가중치 합계
|
||
|
|
int totalWeight = 0;
|
||
|
|
foreach (var c in candidates)
|
||
|
|
totalWeight += c.m_Weight;
|
||
|
|
|
||
|
|
// 랜덤 뽑기
|
||
|
|
int rand = UnityEngine.Random.Range(1, totalWeight + 1);
|
||
|
|
int cumulative = 0;
|
||
|
|
|
||
|
|
foreach (var c in candidates)
|
||
|
|
{
|
||
|
|
cumulative += c.m_Weight;
|
||
|
|
if (rand <= cumulative)
|
||
|
|
return c.m_MobID;
|
||
|
|
}
|
||
|
|
|
||
|
|
return candidates[0].m_MobID; // fallback
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public class ActorStatInfo
|
||
|
|
{
|
||
|
|
public Actor m_Actor;
|
||
|
|
|
||
|
|
Dictionary<eStat, ObscuredDouble> dic_StatValue = new Dictionary<eStat, ObscuredDouble>();
|
||
|
|
Dictionary<eStat, ObscuredDouble> dic_StatValue_Buff = new Dictionary<eStat, ObscuredDouble>();
|
||
|
|
Dictionary<eStat, ObscuredDouble> dic_StatValue_Debuff = new Dictionary<eStat, ObscuredDouble>();
|
||
|
|
bool bInit = false;
|
||
|
|
public bool IsMainAttack;
|
||
|
|
|
||
|
|
void Init()
|
||
|
|
{
|
||
|
|
if (!bInit)
|
||
|
|
{
|
||
|
|
bInit = true;
|
||
|
|
for (eStat i = 0; i < eStat.Max; i++)
|
||
|
|
dic_StatValue.Add(i, 0d);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
public void Clear_All()
|
||
|
|
{
|
||
|
|
var keys = new List<eStat>(dic_StatValue.Keys);
|
||
|
|
foreach (var key in keys) dic_StatValue[key] = 0d;
|
||
|
|
Clear_BuffDebuff();
|
||
|
|
}
|
||
|
|
public void Clear_BuffDebuff()
|
||
|
|
{
|
||
|
|
dic_StatValue_Buff.Clear();
|
||
|
|
dic_StatValue_Debuff.Clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
public ActorStatInfo(Actor actor, bool mainattack)
|
||
|
|
{
|
||
|
|
Init();
|
||
|
|
m_Actor = actor;
|
||
|
|
IsMainAttack = mainattack;
|
||
|
|
}
|
||
|
|
|
||
|
|
public double Get_Stat(eStat key)
|
||
|
|
{
|
||
|
|
if (dic_StatValue.ContainsKey(key))
|
||
|
|
return dic_StatValue[key].GetDecrypted();
|
||
|
|
return 0d;
|
||
|
|
}
|
||
|
|
public double Get_TotalStat(eStat stat)
|
||
|
|
{
|
||
|
|
var rtn = Get_Stat(stat) + Get_BuffStat(stat) - Get_DebuffStat(stat);
|
||
|
|
|
||
|
|
switch (stat)
|
||
|
|
{
|
||
|
|
// 정수
|
||
|
|
case eStat.HP:
|
||
|
|
case eStat.Shield:
|
||
|
|
case eStat.Potion:
|
||
|
|
case eStat.HitRate:
|
||
|
|
return (int)rtn;
|
||
|
|
case eStat.MaxHP:
|
||
|
|
{
|
||
|
|
rtn += Get_BuffStat(eStat.MaxHP_Add);
|
||
|
|
var mul = Get_BuffStat(eStat.MaxHP_Mul);
|
||
|
|
return (int)(rtn + (rtn * mul));
|
||
|
|
}
|
||
|
|
case eStat.MaxShield:
|
||
|
|
{
|
||
|
|
rtn += Get_BuffStat(eStat.MaxShield_Add);
|
||
|
|
var mul = Get_BuffStat(eStat.MaxShield_Mul);
|
||
|
|
return (int)(rtn + (rtn * mul));
|
||
|
|
}
|
||
|
|
case eStat.Attack_Min:
|
||
|
|
{
|
||
|
|
rtn += Get_Stat(eStat.Attack) + Get_BuffStat(eStat.Attack) - Get_DebuffStat(eStat.Attack);
|
||
|
|
|
||
|
|
var card = m_Actor.Get_CardSkillData_orNull(eCardType.G5_FlatDamageMinMaxEqual);
|
||
|
|
if (card != null)
|
||
|
|
{
|
||
|
|
var comparestat = eStat.Attack_Max;
|
||
|
|
var maxdmg = Get_Stat(comparestat) + Get_BuffStat(comparestat) - Get_DebuffStat(comparestat);
|
||
|
|
rtn = Mathf.Max((int)rtn, (int)maxdmg);
|
||
|
|
}
|
||
|
|
|
||
|
|
var mul = Get_BuffStat(eStat.DmgMul);
|
||
|
|
return (int)(rtn + (rtn * mul));
|
||
|
|
}
|
||
|
|
case eStat.Attack_Max:
|
||
|
|
{
|
||
|
|
rtn += Get_Stat(eStat.Attack) + Get_BuffStat(eStat.Attack) - Get_DebuffStat(eStat.Attack);
|
||
|
|
|
||
|
|
var card = m_Actor.Get_CardSkillData_orNull(eCardType.G5_FlatDamageMinMaxEqual);
|
||
|
|
if (card != null)
|
||
|
|
{
|
||
|
|
var comparestat = eStat.Attack_Min;
|
||
|
|
var maxdmg = Get_Stat(comparestat) + Get_BuffStat(comparestat) - Get_DebuffStat(comparestat);
|
||
|
|
rtn = Mathf.Max((int)rtn, (int)maxdmg);
|
||
|
|
}
|
||
|
|
|
||
|
|
var mul = Get_BuffStat(eStat.DmgMul);
|
||
|
|
return (int)(rtn + (rtn * mul) + Get_BuffStat(eStat.MaxAttack_byShield));
|
||
|
|
}
|
||
|
|
|
||
|
|
// 정수 분기 (캐릭터 실수, 몬스터 정수)
|
||
|
|
case eStat.Avoid_Melee:
|
||
|
|
case eStat.Avoid_Range:
|
||
|
|
if (m_Actor.IsRole(eRole.PC))
|
||
|
|
{
|
||
|
|
var totalavoid = rtn * 0.01f + Get_BuffStat(eStat.AvoidAll_1Time);
|
||
|
|
totalavoid += Get_BuffStat(eStat.Avoid_G1_MaxDodgeWhenHpBelow);
|
||
|
|
totalavoid += Get_TotalStat(eStat.AllEvasion);
|
||
|
|
Set_Buff(eStat.AvoidAll_1Time, 0);
|
||
|
|
return Math.Min(MyValue.MaxAvoid, totalavoid);
|
||
|
|
}
|
||
|
|
return (int)rtn;
|
||
|
|
|
||
|
|
// 백분율
|
||
|
|
case eStat.Cri:
|
||
|
|
if (IsMainAttack)
|
||
|
|
{
|
||
|
|
rtn += Get_BuffStat(eStat.AddCri_1Time) + Get_BuffStat(eStat.AddCri_Once);
|
||
|
|
Set_Buff(eStat.AddCri_1Time, 0);
|
||
|
|
Set_Buff(eStat.AddCri_Once, 0);
|
||
|
|
}
|
||
|
|
rtn = Math.Min(MyValue.MaxCri, rtn);
|
||
|
|
break;
|
||
|
|
case eStat.CriDmg:
|
||
|
|
{
|
||
|
|
rtn += Get_BuffStat(eStat.AddCriDmg_1Time);
|
||
|
|
Set_Buff(eStat.AddCriDmg_1Time, 0);
|
||
|
|
}
|
||
|
|
return rtn;
|
||
|
|
|
||
|
|
case eStat.AttackCoolTime:
|
||
|
|
{
|
||
|
|
var slow = Get_DebuffStat(eStat.Slow);
|
||
|
|
rtn += rtn * slow;
|
||
|
|
var past = Get_BuffStat(eStat.AttackCoolTimeMul);
|
||
|
|
rtn -= rtn * past;
|
||
|
|
if (rtn <= 0) rtn = 0.1f;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return rtn;
|
||
|
|
}
|
||
|
|
public void Set_Stat(bool _add, eStat key, double _val)
|
||
|
|
{
|
||
|
|
if (key >= eStat.Max) return;
|
||
|
|
|
||
|
|
if (_add) dic_StatValue[key] += _val;
|
||
|
|
else dic_StatValue[key] -= _val;
|
||
|
|
|
||
|
|
if (key == eStat.HP)
|
||
|
|
{
|
||
|
|
var maxhp = Get_TotalStat(eStat.MaxHP);
|
||
|
|
if (dic_StatValue[key] > maxhp)
|
||
|
|
dic_StatValue[key] = maxhp;
|
||
|
|
else if (dic_StatValue[key] < 0)
|
||
|
|
dic_StatValue[key] = 0;
|
||
|
|
|
||
|
|
//if (m_Actor) m_Actor.Set_HUD();
|
||
|
|
}
|
||
|
|
else if (key == eStat.Shield)
|
||
|
|
{
|
||
|
|
var maxshield = Get_TotalStat(eStat.MaxShield);
|
||
|
|
if (dic_StatValue[key] > maxshield)
|
||
|
|
dic_StatValue[key] = maxshield;
|
||
|
|
else if (dic_StatValue[key] < 0)
|
||
|
|
dic_StatValue[key] = 0;
|
||
|
|
|
||
|
|
//if (m_Actor) m_Actor.Set_HUD();
|
||
|
|
}
|
||
|
|
else if (key == eStat.Potion)
|
||
|
|
{
|
||
|
|
var maxpotion = Get_TotalStat(eStat.MaxPotion);
|
||
|
|
if (dic_StatValue[key] > maxpotion)
|
||
|
|
dic_StatValue[key] = maxpotion;
|
||
|
|
else if (dic_StatValue[key] < 0)
|
||
|
|
dic_StatValue[key] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
dic_StatValue[key].RandomizeCryptoKey();
|
||
|
|
}
|
||
|
|
public void Set_Stat(eStat key, double _val, bool setmax = false)
|
||
|
|
{
|
||
|
|
dic_StatValue[key] = _val;
|
||
|
|
dic_StatValue[key].RandomizeCryptoKey();
|
||
|
|
|
||
|
|
if (setmax)
|
||
|
|
{
|
||
|
|
if (key == eStat.HP)
|
||
|
|
{
|
||
|
|
dic_StatValue[eStat.MaxHP] = _val;
|
||
|
|
dic_StatValue[eStat.MaxHP].RandomizeCryptoKey();
|
||
|
|
|
||
|
|
//if (m_Actor) m_Actor.Set_HUD();
|
||
|
|
}
|
||
|
|
else if (key == eStat.Shield)
|
||
|
|
{
|
||
|
|
dic_StatValue[eStat.MaxShield] = _val;
|
||
|
|
dic_StatValue[eStat.MaxShield].RandomizeCryptoKey();
|
||
|
|
|
||
|
|
//if (m_Actor) m_Actor.Set_HUD();
|
||
|
|
}
|
||
|
|
else if (key == eStat.Potion)
|
||
|
|
{
|
||
|
|
dic_StatValue[eStat.MaxPotion] = _val;
|
||
|
|
dic_StatValue[eStat.MaxPotion].RandomizeCryptoKey();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
public double Get_BuffStat(eStat stat) { return dic_StatValue_Buff.ContainsKey(stat) ? dic_StatValue_Buff[stat] : 0d; }
|
||
|
|
public void Set_Buff(eStat stat, double v)
|
||
|
|
{
|
||
|
|
if (stat >= eStat.Max) return;
|
||
|
|
|
||
|
|
if (!dic_StatValue_Buff.ContainsKey(stat))
|
||
|
|
dic_StatValue_Buff.Add(stat, v);
|
||
|
|
else
|
||
|
|
dic_StatValue_Buff[stat] = v;
|
||
|
|
dic_StatValue_Buff[stat].RandomizeCryptoKey();
|
||
|
|
}
|
||
|
|
public void Set_Buff(bool add, eStat stat, double v)
|
||
|
|
{
|
||
|
|
if (stat >= eStat.Max) return;
|
||
|
|
|
||
|
|
if (!dic_StatValue_Buff.ContainsKey(stat))
|
||
|
|
{
|
||
|
|
if (add) dic_StatValue_Buff.Add(stat, v);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (add) dic_StatValue_Buff[stat] += v;
|
||
|
|
else dic_StatValue_Buff[stat] -= v;
|
||
|
|
}
|
||
|
|
dic_StatValue_Buff[stat].RandomizeCryptoKey();
|
||
|
|
}
|
||
|
|
public double Get_DebuffStat(eStat stat) { return dic_StatValue_Debuff.ContainsKey(stat) ? dic_StatValue_Debuff[stat] : 0d; }
|
||
|
|
public void Set_Debuff(eStat stat, double v)
|
||
|
|
{
|
||
|
|
if (stat >= eStat.Max) return;
|
||
|
|
|
||
|
|
if (!dic_StatValue_Debuff.ContainsKey(stat))
|
||
|
|
dic_StatValue_Debuff.Add(stat, v);
|
||
|
|
else
|
||
|
|
dic_StatValue_Debuff[stat] = v;
|
||
|
|
dic_StatValue_Debuff[stat].RandomizeCryptoKey();
|
||
|
|
}
|
||
|
|
public void Set_Debuff(bool add, eStat stat, double v)
|
||
|
|
{
|
||
|
|
if (!dic_StatValue_Debuff.ContainsKey(stat))
|
||
|
|
{
|
||
|
|
if (add) dic_StatValue_Debuff.Add(stat, v);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (add) dic_StatValue_Debuff[stat] += v;
|
||
|
|
else dic_StatValue_Debuff[stat] -= v;
|
||
|
|
}
|
||
|
|
dic_StatValue_Debuff[stat].RandomizeCryptoKey();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Set_BuffDebuff(ActorStatInfo statinfo)
|
||
|
|
{
|
||
|
|
foreach (var item in dic_StatValue_Buff) statinfo.Set_Buff(item.Key, item.Value);
|
||
|
|
foreach (var item in dic_StatValue_Debuff) statinfo.Set_Debuff(item.Key, item.Value);
|
||
|
|
}
|
||
|
|
|
||
|
|
public int Get_Damage()
|
||
|
|
{
|
||
|
|
var dmg = Random.Range((int)Get_TotalStat(eStat.Attack_Min), (int)Get_TotalStat(eStat.Attack_Max) + 1);
|
||
|
|
return Mathf.Max(dmg, 1); // 최소 데미지 1 보장
|
||
|
|
}
|
||
|
|
public bool isFullHP() { return Get_TotalStat(eStat.HP) >= Get_TotalStat(eStat.MaxHP); }
|
||
|
|
}
|