You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

6176 lines
212 KiB

using DG.Tweening;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using IVDataFormat;
using Spine;
using Spine.Unity;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Numerics;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI;
using static CreatureBase;
using Random = UnityEngine.Random;
using Sequence = DG.Tweening.Sequence;
using Vector2 = UnityEngine.Vector2;
using Vector3 = UnityEngine.Vector3;
// 전투 제어 매니저.
public class BattleMgr : Singleton<BattleMgr>
{
#region Const & Values
public static int I_InitCos { get; private set; } = 1;
private const int I_MonTypeNormal = 2;
private const int I_MonTypeElite = 2;
private const int I_MonTypeBoss = 1;
private const int I_MonTypeBigBoss = 1;
private const int I_SummonMin = 5;
private const int I_SummonMax = 50;
private const int I_SummonEliteMin = 1;
private const int I_SummonEliteMax = 3;
private const int I_ObjMonCnt = (I_MonTypeNormal * I_SummonMax) + (I_MonTypeElite * I_SummonEliteMax) + I_MonTypeBoss + I_MonTypeBigBoss;
private const int I_ObjDamCnt = 200;
private static readonly Vector3 V3_CharOrigin = new Vector3(-0f, -2f, -12f);
private static readonly Vector3 V3_CharPvp = new Vector3(-10f, 0f, 0f);
private static readonly Vector3 V3_CharEnemyPvp = new Vector3(10f, 0f, 0f);
private static readonly Vector3 V3_SummonMin = new Vector3(-20f, 6f, -40f);//5 -2
private static readonly Vector3 V3_SummonMax = new Vector3(20f, 8f, 40f);//13 6
private static readonly Vector3 V3_DgSummonMin = new Vector3(-20f, 5f, -16f);
private static readonly Vector3 V3_DgSummonMax = new Vector3(20f, 13f, -16f);
private static readonly Vector3[] V3_AddSummons = new Vector3[10]
{
new Vector3(-4.5f, 0f, 0f),
new Vector3(-1.5f, 0f, 0f),
new Vector3(1.5f, 0f, 0f),
new Vector3(4.5f, 0f, 0f),
new Vector3(-3f, 3f, 0f),
new Vector3(0f, 3f, 0f),
new Vector3(3f, 3f, 0f),
new Vector3(-3f, -3f, 0f),
new Vector3(0f, -3f, 0f),
new Vector3(3f, -3f, 0f)
};
private static readonly Color CLR_DamNormal = new Color(1f, 1f, 1f);
private static readonly Color CLR_DamCritical = new Color(1f, 56f / 255f, 0f);
private static readonly Color CLR_CharDam = new Color(0.8f, 0.8f, 0.8f);
private const float F_DamNormal = 24f;
private const float F_DamCritical = 32f;
private const float F_AddYCharHp = 2.5f;
private const float F_AddYNormalHp = 2.2f;
private const float F_AddYEliteHp = 3.5f;
private const float F_AddYBossHp = 5.5f;
private const float F_AddYAwakenStoneBossHp = 7f;
private const float F_AddXAwakenStoneBossHp = 5.5f;
private const float F_AddYCharDam = 3.4f;
private const float F_AddYNormalDam = 2.6f;
private const float F_AddYEliteDam = 3.9f;
private const float F_AddYBossDam = 5.9f;
private const float F_AddYCharTalk = 2f;
private const float F_CharRangePvp = 3600000f;
private const float F_MonRangeNormal = 2500000f;
private const float F_MonRangeElite = 3000000f;
private const float F_MonRangeBoss = 3500000f;
public static bool doNotInterupt { get; private set; } = false;
#endregion Const & Values
#region Battle UI
[Header("Battle UI")]
private Camera camMain;
private Camera camUI;
[SerializeField]
private Transform trfStageInfo;
private TextMeshProUGUI txtBattleStage;
private TextMeshProUGUI txtBattleTime;
private Button btnBattleRetry;
private Image imgBattleRetry;
[SerializeField]
private Sprite sprBattleRetry, sprBattleGo, sprBossElite, sprBoss, sprAuto, sprAutoOff;
[SerializeField]
private TextMeshProUGUI txtRetry;
private Image imgBattleWave;
Image imgWaveBoss;
GameObject goWaveBossArrow;
Image[] imgWaveCapsule;
GameObject[] goWaveCapsuleArrow;
[Header("Pvp")]
[SerializeField]
private Transform trfPvp;
private TextMeshProUGUI txtPvpTime;
private Slider sldPvpMyHp, sldPvpEnemyHp;
[Header("Skill")]
[SerializeField]
private Transform trfRB;
private ButtonIV[] btnSkillPresets;
private Button[] btnSkills;
private GameObject[] goSkillEmptys;
private Image[] imgSkills;
private Image[] imgSkillBg;
private Image[] imgSkillCovers;
private TextMeshProUGUI[] txtSkills;
private Image imgBtnAuto;
private GameObject goAuto;
[SerializeField]
private TextMeshProUGUI[] txtTestDps;
[SerializeField]
private TextMeshProUGUI[] txtTestDpsDam;
[SerializeField]
private TextMeshProUGUI txtNormalAttackDpsDam;
private BigInteger[] TestDps = new BigInteger[18];
private BigInteger TestNormalAttackDps = new BigInteger();
private int timeSec = 0;
[Header("Battle Obj")]
[SerializeField]
private Canvas canvasUI;
private Image imgBattleCover;
private HpBar hpBarChar;
private HpBar hpBarCharEnemy;
private RectTransform trfHpBars;
[SerializeField]
private GameObject prfHpEnemy;
private HpBar[] hpBarEnemies;
private RectTransform trfDamages, trfCharDamages;
[SerializeField]
private GameObject prfDmgTxt;
private GameObject[] goDmgTxts;
private RectTransform[] trfDmgTxts;
private TextMeshProUGUI[] txtDmgTxts;
private DOTweenAnimation[] dtaDmgTxts;
[SerializeField]
private GameObject prfCharDmgTxt;
private GameObject[] goCharDmgTxts;
private RectTransform[] trfCharDmgTxts;
private TextMeshProUGUI[] txtCharDmgTxts;
private DOTweenAnimation[] dtaCharDmgTxts;
private RectTransform trfTxts;
private TalkBox talkBox;
#endregion Battle UI
#region UI Values
private int iLayerBg;
private int iLayerChar;
private int iLayerEffect;
#endregion UI Values
#region Battle Scene
[Header("Battle Scene")]
[SerializeField]
private SpriteRenderer srBg;
[SerializeField]
private BoxCollider colBg;
[SerializeField]
private SpriteRenderer srSkillFade;
private GameObject goBgEffect;
[Header("Battle Scene Friendly")]
[SerializeField]
private Transform trfFriendlies;
[SerializeField]
private IVCharacter ivChar;
private Transform trfChar;
[SerializeField]
private IVPet[] ivPets;
[SerializeField]
private IVGuardian ivGuardian;
[SerializeField]
private Light2D lightGlobal;
[SerializeField]
private Light2D lightChar;
[SerializeField]
private IVSummon[] ivsummons;
[Header("Battle Scene Enemy Char")]
[SerializeField]
private IVCharacter ivCharEnemy;
private Transform trfCharEnemy;
[SerializeField]
private IVPet[] ivPetsEnemy;
[SerializeField]
private IVGuardian ivGuardianEnemy;
[SerializeField]
private IVSummon[] ivsummonsEnemy;
[Header("Battle Scene Enemy")]
[SerializeField]
private Transform trfEnemies;
[SerializeField]
private GameObject prfEnemy;
private GameObject[] goMonsters;
private Transform[] trfMonsters;
private IVMonster[] ivMonsters;
#endregion Battle Scene
#region Battle Sound
[Header("Battle Sound")]
[SerializeField]
private AudioSource asSummon;
[SerializeField]
private AudioSource asUnsummon;
[SerializeField]
private AudioSource asNormalAttack;
#endregion Battle Sound
#region Battle Effect
[Header("Battle Scene Effect")]
[SerializeField]
private Transform trfEffects;
[SerializeField]
private ParticleSystem ptcLvUpChar;
private Transform trfLvUpChar;
[SerializeField]
private ParticleSystem[] ptcGoldDrops;
private Transform[] trfGoldDrops;
private TweenerCore<Vector3, Vector3, VectorOptions>[] twcGoldDropMoves;
private TweenerCore<Vector3, Vector3, VectorOptions>[] twcGoldDropScales;
[SerializeField]
private SerializedDictionary<int, IVSkill> dicIvSkill = new SerializedDictionary<int, IVSkill>();
[SerializeField]
private SerializedDictionary<int, IVSkill> dicIvSkillEnemy = new SerializedDictionary<int, IVSkill>();
#endregion Battle Scene
#region Battle Values
public bool BattlePause { get; set; } = false;
private int iLoading = 1;
private float fTick = 0f;
private float fTickSec = 0f;
private int iCosCloth = -1;
private int iCosWp = -1;
private int iCosClothEnemy = -1;
private int iCosWpEnemy = -1;
private int iCosHairEnemy = -1;
private int iCosTopEnemy = -1;
private int iCosEyeEnemy = -1;
private Texture2D tx2dCloth = null;
private Texture2D tx2dClothEnemy = null;
private int[] iSkillIds;
private float[] fSkillTimes;
private float[] fSkillTicks;
private bool bAutoSkill = true;
private bool bAutoSkillPrev = true;
private Dictionary<int, int> dicSkillIndex;
private float[] fSkillEnemyTicks;
private Dictionary<int, int> dicSkillEnemyIndex;
private int iBgId = -1;
private AsyncOperationHandle<Sprite> handleBg;
private AsyncOperationHandle<SkeletonDataAsset>[] handleSpines = new AsyncOperationHandle<SkeletonDataAsset>[8];
private int iStageTimeLeft = 90;
private int iWave = 1;
private int iTotalWave = 3;
private bool bRetry = false;
private bool bClear = false;
private bool bChangeArea = false;
private int iMonsterCount = 0;
private float[] fMonSpeedN;
private float[] fMonSpeedE;
private float[] fMonSpeedB;
private int[] iMonGroupN;
private int[] iMonGroupE;
private int[] iMonGroupB;
private BigInteger biMonAtk;
private BigInteger biMonHp;
private Sequence seqStartStage = null;
private Sequence seqDieStage = null;
private Sequence seqChangeStage = null;
private Sequence seqChangeArea = null;
private Sequence seqDungeonArea = null;
private Sequence seqDungeonStageArea = null;
private int iTalkChar = -1;
private int iTalkMax = 8;
private int iFadeCnt = 0;
private bool BgAndCameraChange = false;
private int iUseSkillid = -1;
public enum BattleType
{
Stage = 0,
GoldDungeon,
EnhanceStoneDungeon,
PetDungeon,
AwakenStoneDungeon,
AwakenDungeon,
GuardianDungeon,
RelicDungeon,
Pvp = 9
}
public static BattleType CurrentBattleType { get; private set; } = BattleType.Stage;
dPvpSpec specEnemy = null;
// 내가 상대에게 준 총 데미지.
private BigInteger biBattleDmg;
// 상대가 나에게 준 총 데미지.
private BigInteger biBattleDmgEnemy;
#endregion Battle Values
#region Level Up
[SerializeField]
LevelUpEffect levelUpEffect;
public static void LevelUpEffectOn()
{
Instance.levelUpEffect.ShowLevelUp(2f);
}
#endregion
#region Boss
[SerializeField]
SkeletonAnimation bossIncoming;
#endregion
#region Drop Item
public enum DropItemKind
{
Gold,
Exp,
Box,
ColorFlower,
MemoryPiece,
TradeEventCoin,
RaiseEventCoin,
RouletteEventCoin
}
[SerializeField]
Transform trfDropItem;
[SerializeField]
DropItemObject prfDropItem;
DropItemObject[] dropItemPool;
int dropItemPoolCount = 100;
int dropItemPoolCountNow = 0;
int[] dropItemCount = new int[8];
Stack<int> dropChestKey = new Stack<int>();
#endregion
#region StageSuccessOrFail
[Header("Success & Fail")]
[SerializeField]
GameObject stageSuccessWindow;
GoodsItem[] stageSuccessGoodsItem;
[SerializeField]
GameObject awakenSuccessWindow;
TextMeshProUGUI awakenNumber;
[SerializeField]
Canvas canvasStageFail;
GameObject groupButtonFailed;
TextMeshProUGUI[] txtLevelUpKind;
TextMeshProUGUI[] txtLevelUpGo;
TextMeshProUGUI txtJellySad;
TextMeshProUGUI txtFailed;
TextMeshProUGUI txtClose;
[SerializeField]
GameObject[] canvasStageUnlock;
TextMeshProUGUI[] txtUnlockTitle;
TextMeshProUGUI[] txtUnlockExplain;
TextMeshProUGUI[] txtBtnOk;
TextMeshProUGUI[] txtBtnGo;
DOTweenAnimation[] dotUnlock;
[SerializeField]
Sprite[] sprUnlockContent;
#endregion
int bgShitf = 0;
#region Option Values
[HideInInspector] public bool bOnSkillEffect;
[HideInInspector] public bool bOnDamageText;
#endregion Option Values
#region Time
private void Update()
{
if (BattlePause) return;
fTick += Time.deltaTime;
fTickSec += Time.deltaTime;
if (Input.GetKeyDown(KeyCode.K))
SetBgCol();
// 현재 모드 타임 아웃 체크
if (fTickSec >= 1f)
{
fTickSec -= 1f;
iStageTimeLeft--;
if (CurrentBattleType == BattleType.Pvp)
{
txtPvpTime.text = iStageTimeLeft.ToString();
if (iStageTimeLeft <= 0)
{
EndPvp();
}
}
else
{
txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft);
if (iStageTimeLeft <= 0)
{
FailTimeOut();
}
}
}
// 자동 스킬 쿨타임 감소 및 자동 사용 체크 시 시전 대기 스택에 넣기
if (fTick >= 0.1f)
{
fTick -= 0.1f;
for (int i = 0; i < fSkillTicks.Length; i++)
{
if (iSkillIds[i] < 0)
continue;
if (fSkillTicks[i] >= 0f)
{
fSkillTicks[i] -= 0.1f;
SetSkillUi(i);
if (fSkillTicks[i] <= 0f)
{
if (bAutoSkill)
ivChar.AddSkillAvail(iSkillIds[i]);
}
}
}
if (CurrentBattleType == BattleType.Pvp)
{
for (int i = 0; i < fSkillEnemyTicks.Length; i++)
{
if (specEnemy.skillPreset[i] < 0)
continue;
if (fSkillEnemyTicks[i] >= 0f)
{
fSkillEnemyTicks[i] -= 0.1f;
if (fSkillEnemyTicks[i] <= 0f)
{
ivCharEnemy.AddSkillAvail(specEnemy.skillPreset[i]);
}
}
}
}
}
}
#endregion Time
#region Init
public static void SLocalize() => Instance.Localize();
private void Localize()
{
txtLevelUpKind[0].text = FormatString.StringFormat("{0}", LocalizationText.GetText("recommand_grow"));
txtLevelUpKind[1].text = FormatString.StringFormat("{0} {1}", LocalizationText.GetText("bag_weapon"), LocalizationText.GetText("all_enhance"));
txtLevelUpKind[2].text = FormatString.StringFormat("{0} {1}", LocalizationText.GetText("skill_title"), LocalizationText.GetText("all_enhance"));
txtLevelUpKind[3].text = FormatString.StringFormat("{0} {1}", LocalizationText.GetText("pet_title"), LocalizationText.GetText("all_enhance"));
for (int i = 0; i < 5; i++)
{
txtLevelUpGo[i].text = LocalizationText.GetText("shortcut");
}
txtJellySad.text = LocalizationText.GetText("stage_fail_jelly_dialogue");
txtFailed.text = LocalizationText.GetText("fail_recommand");
txtClose.text = LocalizationText.GetText("click_to_close");
SetDpsSkill();
SetRetry();
bRetry = DataHandler.PlayData.stageRepeat;
txtUnlockTitle = new TextMeshProUGUI[canvasStageUnlock.Length];
txtUnlockExplain = new TextMeshProUGUI[canvasStageUnlock.Length];
txtBtnOk = new TextMeshProUGUI[canvasStageUnlock.Length];
txtBtnGo = new TextMeshProUGUI[canvasStageUnlock.Length];
dotUnlock = new DOTweenAnimation[canvasStageUnlock.Length];
for (int i = 0; i < canvasStageUnlock.Length; i++)
{
txtUnlockTitle[i] = canvasStageUnlock[i].transform.Find("txtTitle").GetComponent<TextMeshProUGUI>();
txtUnlockExplain[i] = canvasStageUnlock[i].transform.Find("txtExplain").GetComponent<TextMeshProUGUI>();
txtBtnOk[i] = canvasStageUnlock[i].transform.Find("btnOk").transform.Find("txt").GetComponent<TextMeshProUGUI>();
txtBtnGo[i] = canvasStageUnlock[i].transform.Find("btnGo").transform.Find("txt").GetComponent<TextMeshProUGUI>();
dotUnlock[i] = canvasStageUnlock[i].GetComponent<DOTweenAnimation>();
txtBtnOk[i].text = LocalizationText.GetText("all_confirm");
txtBtnGo[i].text = LocalizationText.GetText("mission_go");
}
txtUnlockTitle[0].text = LocalizationText.GetText("unlock_gold_dg");
txtUnlockExplain[0].text = LocalizationText.GetText("unlock_gold_explain");
txtUnlockTitle[1].text = LocalizationText.GetText("unlock_enhancestone_dg");
txtUnlockExplain[1].text = LocalizationText.GetText("unlock_enhancestone_explain");
txtUnlockTitle[2].text = LocalizationText.GetText("unlock_pet_dg");
txtUnlockExplain[2].text = LocalizationText.GetText("unlock_pet_explain");
txtUnlockTitle[3].text = LocalizationText.GetText("unlock_awakenstone_dg");
txtUnlockExplain[3].text = LocalizationText.GetText("unlock_awakenstone_explain");
txtUnlockTitle[4].text = LocalizationText.GetText("unlock_awaken_dg");
txtUnlockExplain[4].text = LocalizationText.GetText("unlock_awaken_explain");
txtUnlockTitle[5].text = LocalizationText.GetText("unlock_acc");
txtUnlockExplain[5].text = LocalizationText.GetText("unlock_acc_explain");
txtUnlockTitle[6].text = LocalizationText.GetText("unlock_treasure");
txtUnlockExplain[6].text = LocalizationText.GetText("unlock_treasure_explain");
}
// 클래스 초기화. 게임 처음 시작 시 호출.
public static void SInit(Camera camui)
{
IVCameraController.SSetTrace(false);
Instance.camMain = Camera.main;
Instance.camUI = camui;
Instance.InitObject();
CustomizeMgr.SInitSkin(Instance.ivChar.GetSkeleton());
}
// 캐릭터 의상 초기화. 클래스 초기화(SInit) 완료 후 (스파인 머테리얼 자동 변경 대기를 위해) 한 프레임 건너뛰고 호출.
public static void SInitCostume()
{
Instance.StartCoroutine(nameof(InitCostume));
}
private IEnumerator InitCostume()
{
SetEnemyCostume(DataHandler.PlayEquipCostume.weaponId, DataHandler.PlayEquipCostume.outfitId, 1, 1, 1);
I_InitCos++;
iCosWp = DataHandler.PlayEquipCostume.weaponId;
AddressableMgr.LoadWeaponSpine(iCosWp, ALoadWeaponComp);
AddressableMgr.LoadWeaponAdd(iCosWp);
I_InitCos++;
iCosCloth = DataHandler.PlayEquipCostume.outfitId;
AddressableMgr.LoadClothSpine(iCosCloth, ALoadClothComp);
AddressableMgr.LoadClothAdd(iCosCloth);
while (I_InitCos > 1)
yield return null;
yield return null;
AddressableMgr.ReleaseClothSpine(iCosClothEnemy);
AddressableMgr.ReleaseWeaponSpine(iCosWpEnemy);
iCosClothEnemy = -1;
iCosWpEnemy = -1;
yield return null;
ivChar.gameObject.SetActive(false);
ivCharEnemy.gameObject.SetActive(false);
yield return null;
I_InitCos--;
}
public static void SInitStage()
{
Instance.InitStage();
}
// 스테이지 초기화. 게임 시작시 전투 시작해도 되는 타이밍에 호출(다른 초기화 완료 후).
private void InitStage()
{
iStageTimeLeft = DataHandler.Const.stageTimeout;
txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft);
iWave = 1;
iTotalWave = GetWaveTotal();
SetWaveCapsule(iTotalWave);
GetStageItemAndGetPercent();
SetStageAreaWave(DataHandler.PlayData.curStage, iWave);
SetRetry();
iTalkChar = Random.Range(3, iTalkMax);
seqStartStage.Play();
}
private void InitDungeonStage(int dungeonLevel)//던전 진입
{
SetDungeonSetting(true);
txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft);
SetSkillPreset();
ResetSkillCooltime();
iWave = 1;
bgShitf = 0;
shim = 0;
SetWaveCapsule(iTotalWave);
SetDungeonWave(dungeonLevel, iWave);
SetRetry();
}
Vector3 summonPos;
// 전투 오브젝트 초기화. 클래스 초기화(SInit)에서 호출.
private void InitObject()
{
iLayerBg = LayerMask.NameToLayer("BG");
iLayerChar = LayerMask.NameToLayer("Character");
iLayerEffect = LayerMask.NameToLayer("Effect");
#region Char
trfChar = ivChar.transform;
IVCameraController.SSetTarget(trfChar);
Transform trfbattleui = canvasUI.transform;
imgBattleCover = trfbattleui.Find("cover").GetComponent<Image>();
trfHpBars = trfbattleui.Find("HpBars").GetComponent<RectTransform>();
hpBarChar = trfHpBars.GetChild(0).GetComponent<HpBar>();
trfDamages = trfbattleui.Find("Damages").GetComponent<RectTransform>();
trfCharDamages = trfbattleui.Find("CharDamages").GetComponent<RectTransform>();
trfTxts = trfbattleui.Find("Txts").GetComponent<RectTransform>();
talkBox = trfTxts.GetChild(0).GetComponent<TalkBox>();
hpBarChar.SetCameraTarget(camMain, camUI, trfHpBars, ivChar.transform, F_AddYCharHp);
talkBox.SetCameraTarget(camMain, camUI, trfTxts, ivChar.transform, F_AddYCharTalk);
levelUpEffect.SetCameraTarget(camMain, camUI, trfTxts, ivChar.transform, 4f);
ivChar.Init();
ivChar.SetComponent(this, hpBarChar);
ivChar.SetFriendly(true);
ivChar.SetClassIndex(CreatureBase.eCreatureClass.character, 0);
for(int i = 0; i < ivsummons.Length; i++)
ivsummons[i].SetInit(this);
for(int i = 0; i < ivPets.Length; i++)
{
ivPets[i].Init();
ivPets[i].OffPet();
}
ivGuardian.Init();
ivGuardian.OffGuardian();
#endregion Char
#region Enemy Char
trfCharEnemy = ivCharEnemy.transform;
hpBarCharEnemy = trfHpBars.GetChild(1).GetComponent<HpBar>();
hpBarCharEnemy.SetCameraTarget(camMain, camUI, trfHpBars, ivCharEnemy.transform, F_AddYCharHp);
ivCharEnemy.Init();
ivCharEnemy.SetComponent(this, hpBarCharEnemy);
ivCharEnemy.SetFriendly(false);
ivCharEnemy.SetClassIndex(CreatureBase.eCreatureClass.charEnemy, 0);
for(int i = 0; i < ivsummons.Length; i++)
ivsummonsEnemy[i].SetInit(this);
for(int i = 0; i < ivPetsEnemy.Length; i++)
{
ivPetsEnemy[i].Init();
ivPetsEnemy[i].OffPet();
}
ivGuardianEnemy.Init();
ivGuardianEnemy.OffGuardian();
#endregion Enemy Char
#region Monsters
hpBarEnemies = new HpBar[I_ObjMonCnt];
goMonsters = new GameObject[I_ObjMonCnt];
trfMonsters = new Transform[I_ObjMonCnt];
ivMonsters = new IVMonster[I_ObjMonCnt];
int inormalmax = I_MonTypeNormal * I_SummonMax;
int ielitemax = inormalmax + (I_MonTypeElite * I_SummonEliteMax);
int ibossmax = inormalmax + (I_MonTypeElite * I_SummonEliteMax) + I_MonTypeBoss;
for (int i = 0; i < I_ObjMonCnt; i++)
{
goMonsters[i] = Instantiate(prfEnemy, trfEnemies);
goMonsters[i].name = FormatString.CombineAllString("enemy", i.ToString());
trfMonsters[i] = goMonsters[i].transform;
ivMonsters[i] = goMonsters[i].GetComponent<IVMonster>();
GameObject gohpbar = Instantiate(prfHpEnemy, trfHpBars);
gohpbar.transform.localScale = Vector3.one;
gohpbar.name = FormatString.CombineAllString("hpbar", i.ToString());
hpBarEnemies[i] = gohpbar.GetComponent<HpBar>();
ivMonsters[i].Init();
ivMonsters[i].SetComponent(this, hpBarEnemies[i]);
if (i < inormalmax)
{
hpBarEnemies[i].SetCameraTarget(camMain, camUI, trfHpBars, trfMonsters[i], F_AddYNormalHp);
ivMonsters[i].SetClassIndex(CreatureBase.eCreatureClass.normal, i);
}
else if (i < ielitemax)
{
hpBarEnemies[i].SetCameraTarget(camMain, camUI, trfHpBars, trfMonsters[i], F_AddYEliteHp);
ivMonsters[i].SetClassIndex(CreatureBase.eCreatureClass.elite, i);
}
else if(i<ibossmax)
{
hpBarEnemies[i].SetCameraTarget(camMain, camUI, trfHpBars, trfMonsters[i], F_AddYBossHp);
ivMonsters[i].SetClassIndex(CreatureBase.eCreatureClass.boss, i);
}
else
{
hpBarEnemies[i].SetCameraTarget(camMain, camUI, trfHpBars, trfMonsters[i], F_AddYAwakenStoneBossHp);
ivMonsters[i].SetClassIndex(CreatureBase.eCreatureClass.bigboss, i);
}
goMonsters[i].SetActive(false);
hpBarEnemies[i].gameObject.SetActive(false);
}
#endregion Monsters
#region Effects
trfLvUpChar = ptcLvUpChar.transform;
trfGoldDrops = new Transform[ptcGoldDrops.Length];
twcGoldDropMoves = new TweenerCore<Vector3, Vector3, VectorOptions>[ptcGoldDrops.Length];
twcGoldDropScales = new TweenerCore<Vector3, Vector3, VectorOptions>[ptcGoldDrops.Length];
for (int i = 0; i < ptcGoldDrops.Length; i++)
{
trfGoldDrops[i] = ptcGoldDrops[i].transform;
twcGoldDropMoves[i] = trfGoldDrops[i].DOMove(trfChar.position, 0.3f).SetEase(Ease.InQuad)
.OnComplete(() =>
{
ptcGoldDrops[i].Stop();
trfGoldDrops[i].gameObject.SetActive(false);
}).SetAutoKill(false).Pause();
twcGoldDropScales[i] = trfGoldDrops[i].DOScale(Global.V3_001, 0.25f).SetEase(Ease.InQuad).SetAutoKill(false).Pause();
}
foreach (var item in dicIvSkill)
item.Value.Init(this);
foreach (var item in dicIvSkillEnemy)
item.Value.Init(this);
#endregion Effects
#region Drop Item
//poolCount 는 변수목록에 있음
dropItemPool = new DropItemObject[dropItemPoolCount];
for (int i = 0; i < dropItemPoolCount; i++)
{
dropItemPool[i] = Instantiate(prfDropItem, trfDropItem);
dropItemPool[i].gameObject.SetActive(false);
}
#endregion
#region UI
int ipresetlen = DataHandler.PlayData.skillPresets.Length;
int iskilllen = DataHandler.PlayData.skillPresets[0].Length;
btnSkillPresets = new ButtonIV[ipresetlen];
btnSkills = new Button[iskilllen];
goSkillEmptys = new GameObject[iskilllen];
imgSkills = new Image[iskilllen];
imgSkillBg = new Image[iskilllen];
imgSkillCovers = new Image[iskilllen];
txtSkills = new TextMeshProUGUI[iskilllen];
iSkillIds = new int[iskilllen];
fSkillTimes = new float[iskilllen];
fSkillTicks = new float[iskilllen];
dicSkillIndex = new Dictionary<int, int>();
fSkillEnemyTicks = new float[iskilllen];
dicSkillEnemyIndex = new Dictionary<int, int>();
int irblen = trfRB.childCount;
for (int i = 0; i < irblen; i++)
{
int index = i;
if (i < ipresetlen)
{
btnSkillPresets[index] = trfRB.GetChild(i).GetComponent<ButtonIV>();
continue;
}
index -= ipresetlen;
if (index >= iskilllen)
break;
btnSkills[index] = trfRB.GetChild(i).GetComponent<Button>();
goSkillEmptys[index] = btnSkills[index].transform.Find("ic").gameObject;
imgSkills[index] = btnSkills[index].transform.Find("icon").GetComponent<Image>();
imgSkillBg[index] = btnSkills[index].transform.Find("bg").GetComponent<Image>();
imgSkillCovers[index] = btnSkills[index].transform.Find("cover").GetComponent<Image>();
txtSkills[index] = btnSkills[index].transform.Find("txtSec").GetComponent<TextMeshProUGUI>();
btnSkills[index].interactable = false;
}
SetSkillPreset();
imgBtnAuto = trfRB.Find("btnAuto").GetComponent<Image>();
goAuto = imgBtnAuto.transform.GetChild(0).gameObject;
if (bAutoSkill)
{
imgBtnAuto.sprite = sprAuto;
goAuto.SetActive(true);
}
else
{
imgBtnAuto.sprite = sprAutoOff;
goAuto.SetActive(false);
}
txtBattleStage = trfStageInfo.Find("txtStage").GetComponent<TextMeshProUGUI>();
txtBattleTime = trfStageInfo.Find("txtTime").GetComponent<TextMeshProUGUI>();
btnBattleRetry = trfStageInfo.Find("btnRetry").GetComponent<Button>();
imgBattleRetry = btnBattleRetry.GetComponent<Image>();
Transform trfwave = trfStageInfo.Find("WaveBar");
imgBattleWave = trfwave.Find("WaveBarFill").GetComponent<Image>();
imgWaveBoss = trfwave.Find("WaveBoss").GetComponent<Image>();
goWaveBossArrow = trfwave.Find("BossArrow").gameObject;
Sequence seqboss = DOTween.Sequence()
.SetAutoKill(false)
.SetUpdate(true)
.Append(imgWaveBoss.GetComponent<RectTransform>().DOScale(new Vector3(1.08f, 1.08f, 1f), 0.12f))
.Append(imgWaveBoss.GetComponent<RectTransform>().DOScale(Vector3.one, 0.12f))
.AppendInterval(0.76f)
.SetLoops(-1)
.Play();
Transform trfwavecapsule = trfwave.Find("Content");
int icaplen = trfwavecapsule.childCount;
imgWaveCapsule = new Image[icaplen];
goWaveCapsuleArrow = new GameObject[icaplen];
for (int i = 0; i < icaplen; i++)
{
imgWaveCapsule[i] = trfwavecapsule.GetChild(i).GetComponent<Image>();
goWaveCapsuleArrow[i] = imgWaveCapsule[i].transform.GetChild(0).gameObject;
}
stageSuccessGoodsItem = stageSuccessWindow.transform.Find("bg").Find("GetGoodsScroll").GetChild(0).GetComponentsInChildren<GoodsItem>(true);
awakenNumber = awakenSuccessWindow.transform.Find("bg").Find("GetGoodsScroll").GetChild(0).GetChild(1).GetChild(0).GetChild(0).GetComponent<TextMeshProUGUI>();
Transform trffail = canvasStageFail.transform;
groupButtonFailed = trffail.Find("GroupButtonFailed").gameObject;
txtFailed = trffail.Find("txtFailed").GetComponent<TextMeshProUGUI>();
txtJellySad = trffail.Find("sadJelly").GetChild(0).GetComponent<TextMeshProUGUI>();
txtClose = trffail.Find("imgClose").GetChild(0).GetComponent<TextMeshProUGUI>();
txtLevelUpKind = new TextMeshProUGUI[5];
txtLevelUpGo = new TextMeshProUGUI[5];
TextMeshProUGUI[] txtListKindGo = groupButtonFailed.GetComponentsInChildren<TextMeshProUGUI>(true);
for (int i = 0; i < txtListKindGo.Length; i += 2)
{
txtLevelUpKind[i / 2] = txtListKindGo[i];
txtLevelUpGo[i / 2] = txtListKindGo[i + 1];
}
txtPvpTime = trfPvp.Find("txtTime").GetComponent<TextMeshProUGUI>();
sldPvpMyHp = trfPvp.Find("sldMyHp").GetComponent<Slider>();
sldPvpEnemyHp = trfPvp.Find("sldEnemyHp").GetComponent<Slider>();
UnlockCheck();
Localize();
#endregion UI
#region Txts
goDmgTxts = new GameObject[I_ObjDamCnt];
trfDmgTxts = new RectTransform[I_ObjDamCnt];
txtDmgTxts = new TextMeshProUGUI[I_ObjDamCnt];
dtaDmgTxts = new DOTweenAnimation[I_ObjDamCnt];
goCharDmgTxts = new GameObject[I_ObjDamCnt];
trfCharDmgTxts = new RectTransform[I_ObjDamCnt];
txtCharDmgTxts = new TextMeshProUGUI[I_ObjDamCnt];
dtaCharDmgTxts = new DOTweenAnimation[I_ObjDamCnt];
for (int i = 0; i < I_ObjDamCnt; i++)
{
goDmgTxts[i] = Instantiate(prfDmgTxt, trfDamages);
goCharDmgTxts[i] = Instantiate(prfCharDmgTxt, trfCharDamages);
goDmgTxts[i].name = FormatString.CombineAllString("txtdam", i.ToString());
goCharDmgTxts[i].name = FormatString.CombineAllString("txtdam", i.ToString());
trfDmgTxts[i] = goDmgTxts[i].GetComponent<RectTransform>();
txtDmgTxts[i] = goDmgTxts[i].GetComponent<TextMeshProUGUI>();
dtaDmgTxts[i] = goDmgTxts[i].GetComponent<DOTweenAnimation>();
trfCharDmgTxts[i] = goCharDmgTxts[i].GetComponent<RectTransform>();
txtCharDmgTxts[i] = goCharDmgTxts[i].GetComponent<TextMeshProUGUI>();
dtaCharDmgTxts[i] = goCharDmgTxts[i].GetComponent<DOTweenAnimation>();
goDmgTxts[i].gameObject.SetActive(false);
goCharDmgTxts[i].gameObject.SetActive(false);
}
#endregion Txts
#region On Game Start
seqStartStage = DOTween.Sequence()
.SetAutoKill(false)
.SetUpdate(false)
.AppendCallback(() =>
{
imgBattleCover.color = Color.black;
imgBattleCover.gameObject.SetActive(true);
IVCameraController.SMoveCamera(V3_CharOrigin);
iStageTimeLeft = DataHandler.Const.stageTimeout;
txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft);
iWave = 1;
iTotalWave = GetWaveTotal();
SetWaveCapsule(iTotalWave);
SetBg(DataHandler.GetArea(DataHandler.PlayData.curStage).bgId);
InitMonArea();
SetStageAreaWave(DataHandler.PlayData.curStage, iWave);
})
.Append(imgBattleCover.DOFade(0f, 1f))
.AppendCallback(() =>
{
imgBattleCover.gameObject.SetActive(false);
ivChar.ResetDebuff();
ivChar.SetStatus(BuffMgr.Instance.GetCharAtk(), BuffMgr.Instance.GetCharHp(),
BuffMgr.Instance.GetCharCrtDam(), BuffMgr.Instance.GetCharCrtRate(), BuffMgr.Instance.GetCharMov(), BuffMgr.Instance.GetCharSpd(), GameProperty.Instance.PlayerCharacterAttackRange);
ivChar.Summon(new Vector3(10000f, 10000f, 0f), true);
StartCoroutine(nameof(LightCharOn));
SkillFade(false, true);
})
.AppendInterval(0.3f)
.AppendCallback(() =>
{
ivChar.transform.position = V3_CharOrigin;
if (SoundMgr.EfcOn)
asSummon.Play();
})
.AppendInterval(0.5f)
.AppendCallback(() =>
{
ShowTalkBox();
SummonMonStage();
IVCameraController.SSetTrace(true);
BattlePause = false;
for (int i = 0; i < ivPets.Length; i++)
{
ivPets[i].Summon();
}
ivGuardian.Summon();
})
.Pause();
#endregion On Game Start
#region On Die Stage
seqDieStage = DOTween.Sequence()
.SetAutoKill(false)
.SetUpdate(false)
.AppendCallback(() =>
{
doNotInterupt = true;
// 배틀 멈춤, 카메라 멈춤.
BattlePause = true;
IVCameraController.SSetTrace(false);
StartCoroutine(nameof(LightCharOff));
})
.AppendInterval(1f)
.AppendCallback(() =>
{
imgBattleCover.gameObject.SetActive(true);
})
.Append(imgBattleCover.DOFade(1f, 0.5f))
.AppendCallback(() =>
{
StopAllSkill();
UnsummonMon();
for(int i = 0; i < ivPets.Length; ++i)
{
ivPets[i].OffPet();
}
OpenFailScroll();
talkBox.HideObject();
if (BgAndCameraChange)
{
ResetBgScroll();
IVCameraController.CameraXRangeChange(25);
BgAndCameraChange = false;
}
Vector3 v3spos = (V3_CharOrigin);
v3spos.z = v3spos.y * 2;
trfChar.position = v3spos;
// 카메라 이동.
IVCameraController.SMoveToCamera(0.8f, trfChar.position);
iStageTimeLeft = DataHandler.Const.stageTimeout;
txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft);
iWave = 1;
iTotalWave = GetWaveTotal();
SetWaveCapsule(iTotalWave);
GetStageItemAndGetPercent();
if (bChangeArea)
{
SetBg(DataHandler.GetArea(DataHandler.PlayData.curStage).bgId);
InitMonArea();
}
SetStageAreaWave(DataHandler.PlayData.curStage, iWave);
StageMgr.SRefreshStage();
SoundMgr.SPlayBgm(IVDataFormat.BGM.stage);
SkillFade(false, true);
})
.Append(imgBattleCover.DOFade(0f, 0.5f))
.AppendInterval(2.5f)
.AppendCallback(() =>
{
CloseFailScroll();
if (bChangeArea)
{
AddressableMgr.SForceUnload();
}
imgBattleCover.gameObject.SetActive(false);
ivChar.ResetDebuff();
ivChar.SetStatus(BuffMgr.Instance.GetCharAtk(), BuffMgr.Instance.GetCharHp(),
BuffMgr.Instance.GetCharCrtDam(), BuffMgr.Instance.GetCharCrtRate(), BuffMgr.Instance.GetCharMov(), BuffMgr.Instance.GetCharSpd(), GameProperty.Instance.PlayerCharacterAttackRange);
summonPos = ivChar.transform.position;
ivChar.transform.position = new Vector3(10000f, 10000f, 0f);
ivChar.Summon();
StartCoroutine(nameof(LightCharOn));
})
.AppendInterval(0.3f)//캐릭터를 소환할때 애니메이션상으로 소환이 안 되는데, 이 타이밍에 옷을 갈아끼우고 애니메이션이 나오도록 함.
.AppendCallback(() =>
{
BattleMgr.SRefreshCharCloth();
ivChar.transform.position = summonPos;
if (SoundMgr.EfcOn)
asSummon.Play();
})
.AppendInterval(0.5f)
.AppendCallback(() =>
{
ShowTalkBox();
SummonMonStage();
IVCameraController.SSetTrace(true);
BattlePause = false;
SetCharCostume();
for (int i = 0; i < ivPets.Length; i++)
{
ivPets[i].Summon();
}
ivGuardian.Summon();
doNotInterupt = false;
})
.Pause();
#endregion On Die Stage
#region On Stage Change
seqChangeStage = DOTween.Sequence()//반복
.SetAutoKill(false)
.SetUpdate(false)
.AppendCallback(() =>
{
doNotInterupt = true;
// 배틀 멈춤, 카메라 멈춤.
BattlePause = true;
IVCameraController.SSetTrace(false);
if (bClear)
{
bool blvup = AddStageExpGold();
MissionMgr.SRefreshMission();
if (blvup)
{
PlayPtcLvUp(trfChar.position);
GameUIMgr.SSetPlayerLv();
}
bClear = false;
}
})
.AppendInterval(0.8f)
.AppendCallback(() =>
{
// 소환 해제.
UnsummonMon();
if (SoundMgr.EfcOn)
asUnsummon.Play();
ivChar.Unsummon();
allDisableSummons(true);
for (int i = 0; i < ivPets.Length; i++)
{
ivPets[i].Unsummon();
}
ivGuardian.Unsummon();
StartCoroutine(nameof(LightCharOff));
})
.AppendInterval(1.2f)
.AppendCallback(() =>
{
CloseSuccessWindow();
StopAllSkill();
talkBox.HideObject();
})
.AppendInterval(0.8f)
.AppendCallback(() =>
{
if (isUnlockCheck)
{
ContentUnlockCheck(DataHandler.PlayData.clearStage);
}
iStageTimeLeft = DataHandler.Const.stageTimeout;
txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft);
iWave = 1;
iTotalWave = GetWaveTotal();
SetWaveCapsule(iTotalWave);
GetStageItemAndGetPercent();
SetStageAreaWave(DataHandler.PlayData.curStage, iWave);
ivChar.ResetDebuff();
ivChar.SetStatus(BuffMgr.Instance.GetCharAtk(), BuffMgr.Instance.GetCharHp(),
BuffMgr.Instance.GetCharCrtDam(), BuffMgr.Instance.GetCharCrtRate(), BuffMgr.Instance.GetCharMov(), BuffMgr.Instance.GetCharSpd(), GameProperty.Instance.PlayerCharacterAttackRange);
Vector3 v3spos = (V3_CharOrigin);
v3spos.z = v3spos.y * 2;
ivChar.Summon(v3spos, true);
IVCameraController.SMoveToCamera(0.8f, trfChar.position);
StartCoroutine(nameof(LightCharOn));
StageMgr.SRefreshStage();
SoundMgr.SPlayBgm(IVDataFormat.BGM.stage);
SkillFade(false, true);
})
.AppendInterval(0.3f)
.AppendCallback(() =>
{
if (SoundMgr.EfcOn)
asSummon.Play();
})
.AppendInterval(0.5f)
.AppendCallback(() =>
{
ShowTalkBox();
SummonMonStage();
IVCameraController.SSetTrace(true);
BattlePause = false;
SetCharCostume();
for (int i = 0; i < ivPets.Length; i++)
{
ivPets[i].Summon();
}
ivGuardian.Summon();
doNotInterupt = false;
})
.Pause();
#endregion On Stage Change
#region On Area Change
seqChangeArea = DOTween.Sequence()//진행
.SetAutoKill(false)
.SetUpdate(false)
.AppendCallback(() =>
{
doNotInterupt = true;
// 배틀 멈춤, 카메라 멈춤.
BattlePause = true;
IVCameraController.SSetTrace(false);
if (bClear)
{
MissionMgr.SRefreshMission();
bool blvup = AddStageExpGold();
if (blvup)
{
PlayPtcLvUp(trfChar.position);
GameUIMgr.SSetPlayerLv();
}
bClear = false;
}
})
.AppendInterval(0.8f)
.AppendCallback(() =>
{
// 소환 해제.
UnsummonMon();
if (SoundMgr.EfcOn)
asUnsummon.Play();
ivChar.Unsummon();
allDisableSummons(true);
for (int i = 0; i < ivPets.Length; i++)
{
ivPets[i].Unsummon();
}
ivGuardian.Unsummon();
StartCoroutine("LightCharOff");
})
.AppendInterval(1.2f)
.AppendCallback(() =>
{
imgBattleCover.gameObject.SetActive(true);
CloseSuccessWindow();
})
.Append(imgBattleCover.DOFade(1f, 0.5f))
.AppendCallback(() =>
{
StopAllSkill();
talkBox.HideObject();
if (BgAndCameraChange)
{
ResetBgScroll();
IVCameraController.CameraXRangeChange(25);
BgAndCameraChange = false;
}
// 캐릭터 위치 랜덤.
//Vector3 v3spos = new Vector3(Random.Range(V3_SummonMin.x, V3_SummonMax.x), Random.Range(V3_SummonMin.y, V3_SummonMax.y), 0f);
Vector3 v3spos = (V3_CharOrigin);
v3spos.z = v3spos.y * 2;
trfChar.position = v3spos;
// 카메라 이동.
IVCameraController.SMoveCamera(trfChar.position);
if (isUnlockCheck)
{
ContentUnlockCheck(DataHandler.PlayData.clearStage);
}
iStageTimeLeft = DataHandler.Const.stageTimeout;
txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft);
iWave = 1;
iTotalWave = GetWaveTotal();
SetWaveCapsule(iTotalWave);
GetStageItemAndGetPercent();
SetBg(DataHandler.GetArea(DataHandler.PlayData.curStage).bgId);
InitMonArea();
SetStageAreaWave(DataHandler.PlayData.curStage, iWave);
StageMgr.SRefreshStage();
SoundMgr.SPlayBgm(IVDataFormat.BGM.stage);
SkillFade(false, true);
})
.AppendInterval(0.2f)
.Append(imgBattleCover.DOFade(0f, 0.5f))
.AppendCallback(() =>
{
AddressableMgr.SForceUnload();
imgBattleCover.gameObject.SetActive(false);
ivChar.ResetDebuff();
ivChar.SetStatus(BuffMgr.Instance.GetCharAtk(), BuffMgr.Instance.GetCharHp(),
BuffMgr.Instance.GetCharCrtDam(), BuffMgr.Instance.GetCharCrtRate(), BuffMgr.Instance.GetCharMov(), BuffMgr.Instance.GetCharSpd(), GameProperty.Instance.PlayerCharacterAttackRange);
ivChar.Summon();
StartCoroutine("LightCharOn");
})
.AppendInterval(0.3f)//캐릭터를 소환할때 애니메이션상으로 소환이 안 되는데, 이 타이밍에 옷을 갈아끼우고 애니메이션이 나오도록 함.
.AppendCallback(() =>
{
BattleMgr.SRefreshCharCloth();
if (SoundMgr.EfcOn)
asSummon.Play();
})
.AppendInterval(0.5f)
.AppendCallback(() =>
{
ShowTalkBox();
SummonMonStage();
IVCameraController.SSetTrace(true);
BattlePause = false;
for (int i = 0; i < ivPets.Length; i++)
{
ivPets[i].Summon();
}
ivGuardian.Summon();
doNotInterupt = false;
})
.Pause();
#endregion On Area Change
#region On Dungeon Change
seqDungeonArea = DOTween.Sequence()//던전 진입시 실행
.SetAutoKill(false)
.SetUpdate(false)
.AppendCallback(() =>
{
doNotInterupt = true;
// 배틀 멈춤, 카메라 멈춤.
BattlePause = true;
IVCameraController.SSetTrace(false);
if (bClear)
{
bClear = false;
}
})
.AppendInterval(0.8f)
.AppendCallback(() =>
{
// 소환 해제.
UnsummonMon();
if (SoundMgr.EfcOn)
asUnsummon.Play();
ivChar.Unsummon();
allDisableSummons(true);
for (int i = 0; i < ivPets.Length; i++)
{
ivPets[i].Unsummon();
}
ivGuardian.Unsummon();
})
.AppendInterval(0.8f)
.AppendCallback(() =>
{
imgBattleCover.gameObject.SetActive(true);
CloseSuccessWindow();
})
.Append(imgBattleCover.DOFade(1f, 0.5f))
.AppendCallback(() =>
{
SetBg(DungeonMgr.GetDungeonBg());
if (BgAndCameraChange)
{
ResetBgScroll();
IVCameraController.CameraXRangeChange(25);
BgAndCameraChange = false;
}
StopAllSkill();
Vector3 v3spos;
// 캐릭터 위치 랜덤.
if (DungeonMgr.GetDungeonKind() == DungeonMgr.DungeonKind.EnhanceStoneDG)
{
v3spos = new Vector3(-20f, 2f, 0f);
IVCameraController.CameraXRangeChange(1000);
BgAndCameraChange = true;
}
else if (DungeonMgr.GetDungeonKind() == DungeonMgr.DungeonKind.GuardianDG)
{
v3spos = new Vector3(-20f, -6f, 0f);
GuardianMgr.setActiveRobot(true);
}
else
{
v3spos = new Vector3(Random.Range(V3_DgSummonMin.x, V3_DgSummonMax.x), Random.Range(V3_DgSummonMin.y, V3_DgSummonMax.y), 0f);
}
v3spos.z = v3spos.y * 2;
trfChar.position = v3spos;
// 카메라 이동.
IVCameraController.SMoveCamera(trfChar.position);
//현재 적과 제한시간과 배경 등등을 설정
SetDungeonSetting(false);
txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft);
iWave = 1;
InitMonDungeon();
switch (DungeonMgr.GetDungeonKind())
{
case DungeonMgr.DungeonKind.GoldDG:
SoundMgr.SPlayBgm(IVDataFormat.BGM.goldDg);//진입브금 * 1부터 시작함(배열상으로는 0)
break;
case DungeonMgr.DungeonKind.EnhanceStoneDG:
SoundMgr.SPlayBgm(IVDataFormat.BGM.enhanceDg);
break;
case DungeonMgr.DungeonKind.PetDG:
SoundMgr.SPlayBgm(IVDataFormat.BGM.petDg);
break;
case DungeonMgr.DungeonKind.AwakenStoneDG:
SoundMgr.SPlayBgm(IVDataFormat.BGM.awakenStoneDg);
break;
case DungeonMgr.DungeonKind.AwakenDG:
SoundMgr.SPlayBgm(IVDataFormat.BGM.awakenDg);
break;
case DungeonMgr.DungeonKind.GuardianDG:
SoundMgr.SPlayBgm(IVDataFormat.BGM.guardian);
break;
default:
break;
}
SkillFade(false, true);
})
.AppendInterval(0.2f)
.Append(imgBattleCover.DOFade(0f, 0.5f))
.AppendCallback(() =>
{
imgBattleCover.gameObject.SetActive(false);
ivChar.ResetDebuff();
ivChar.SetStatus(BuffMgr.Instance.GetCharAtk(), BuffMgr.Instance.GetCharHp(),
BuffMgr.Instance.GetCharCrtDam(), BuffMgr.Instance.GetCharCrtRate(), BuffMgr.Instance.GetCharMov(), BuffMgr.Instance.GetCharSpd(), GameProperty.Instance.PlayerCharacterAttackRange);
ivChar.Summon();
})
.AppendInterval(0.3f)
.AppendCallback(() =>
{
BattleMgr.SRefreshCharCloth();
if (SoundMgr.EfcOn)
asSummon.Play();
})
.AppendInterval(0.5f)
.AppendCallback(() =>
{
ShowTalkBox();
SummonMonDungeon();
IVCameraController.SSetTrace(true);
BattlePause = false;
DungeonMgr.OnOffBtnDungeonOut(true);
for (int i = 0; i < ivPets.Length; i++)
{
ivPets[i].Summon();
}
ivGuardian.Summon();
doNotInterupt = false;
})
.Pause();
#endregion
#region On Dungeon Stage Change
seqDungeonStageArea = DOTween.Sequence()//던전 진입시 실행
.SetAutoKill(false)
.SetUpdate(false)
.AppendCallback(() =>
{
doNotInterupt = true;
// 배틀 멈춤, 카메라 멈춤.
BattlePause = true;
IVCameraController.SSetTrace(false);
})
.AppendInterval(0.8f)
.AppendCallback(() =>
{
// 골드 획득.
// 소환 해제.
UnsummonMon();
if (SoundMgr.EfcOn)
asUnsummon.Play();
ivChar.Unsummon();
allDisableSummons(true);
for (int i = 0; i < ivPets.Length; i++)
{
ivPets[i].Unsummon();
}
ivGuardian.Unsummon();
})
.AppendInterval(0.8f)
.AppendCallback(() =>
{
StopAllSkill();
talkBox.HideObject();
// 캐릭터 위치 랜덤.
Vector3 v3spos = new Vector3(Random.Range(V3_SummonMin.x, V3_SummonMax.x), Random.Range(V3_SummonMin.y, V3_SummonMax.y), 0f);
v3spos.z = v3spos.y * 2;
trfChar.position = v3spos;
// 카메라 이동.
IVCameraController.SMoveToCamera(0.8f, trfChar.position);
})
.AppendInterval(0.8f)
.AppendCallback(() =>
{
SetDungeonSetting(false);
txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft);
iWave = 1;
SetDungeonWave(DungeonMgr.GetDungeonLevel(), iWave);
ivChar.ResetDebuff();
ivChar.SetStatus(BuffMgr.Instance.GetCharAtk(), BuffMgr.Instance.GetCharHp(),
BuffMgr.Instance.GetCharCrtDam(), BuffMgr.Instance.GetCharCrtRate(), BuffMgr.Instance.GetCharMov(), BuffMgr.Instance.GetCharSpd(), GameProperty.Instance.PlayerCharacterAttackRange);
ivChar.Summon();
SkillFade(false, true);
//ResetFade();
})
.AppendInterval(0.3f)
.AppendCallback(() =>
{
BattleMgr.SRefreshCharCloth();
//for (int i = 0; i < ivPets.Length; i++)
//{
// ivPets[i].Summon();
//}
if (SoundMgr.EfcOn)
asSummon.Play();
})
.AppendInterval(0.5f)
.AppendCallback(() =>
{
ShowTalkBox();
SummonMonDungeon();
IVCameraController.SSetTrace(true);
BattlePause = false;
for (int i = 0; i < ivPets.Length; i++)
{
ivPets[i].Summon();
}
ivGuardian.Summon();
doNotInterupt = false;
})
.Pause();
#endregion
iLoading--;
}
private bool AddStageExpGold()
{
if (CurrentBattleType != BattleType.Stage) return false;
dArea areadata = DataHandler.GetArea(DataHandler.PlayData.curStage);
BigInteger gold = areadata.gold;
gold = gold * (BigInteger)BuffMgr.Instance.GetGoldDropRate() / dConst.RateMax;
BigInteger exp = areadata.exp;
exp = exp * (BigInteger)BuffMgr.Instance.GetExpDropRate() / dConst.RateMax;
DataHandler.AddGold(gold);
if (!EnhanceMgr.IsMainEnhanceBedgeOn())
EnhanceMgr.CheckBedge();
return DataHandler.AddPlayerExp(exp);
}
#endregion Init
#region Base
// 백버튼 처리.
public static bool SCloseMenu()
{
return Instance.CloseMenu();
}
private bool CloseMenu()
{
// 스테이지 실패 팝업.
if (canvasStageFail.enabled)
{
CloseFailScroll();
return true;
}
return false;
}
#endregion Base
#region Control Scene
// 전투 카메라 켜기.
public static void SSetCameraOn(bool bvalue)
{
if (bvalue)
{
Instance.camMain.cullingMask |= 1 << Instance.iLayerBg;
Instance.camMain.cullingMask |= 1 << Instance.iLayerChar;
Instance.camMain.cullingMask |= 1 << Instance.iLayerEffect;
}
else
{
Instance.camMain.cullingMask = 0;
}
}
// 전투 UI 켜기.
public static void SSetBattleUiOn(bool bvalue)
{
Instance.canvasUI.enabled = bvalue;
}
// 스테이지 클리어/실패 UI 켜기.
public static void SSetClearFailUiOn(bool bvalue)
{
Instance.stageSuccessWindow.GetComponent<Canvas>().enabled = bvalue;
//Instance.canvasStageFail.enabled = bvalue;
}
public static void StatRecalc()
{
Instance.ivChar.SetStatus(BuffMgr.Instance.GetCharAtk(), BuffMgr.Instance.GetCharHp(),
BuffMgr.Instance.GetCharCrtDam(), BuffMgr.Instance.GetCharCrtRate(), BuffMgr.Instance.GetCharMov(), BuffMgr.Instance.GetCharSpd(), GameProperty.Instance.PlayerCharacterAttackRange, true);
}
#endregion Control Scene
#region Summon
// 모든 적 소환 해제.
private void UnsummonMon()
{
if (ivCharEnemy.gameObject.activeSelf)
{
ivCharEnemy.gameObject.SetActive(false);
for(int i = 0; i < ivPetsEnemy.Length; ++i)
{
ivPetsEnemy[i].OffPet();
}
}
for (int i = 0; i < I_ObjMonCnt; ++i)
{
if (goMonsters[i].activeSelf)
{
goMonsters[i].SetActive(false);
hpBarEnemies[i].HideHpBar();
}
}
iMonsterCount = 0;
}
// 지역별 몬스터 종류 초기화(일반, 엘리트, 보스). 게임 시작시, 지역 변경시 호출.
private void InitMonArea()
{
for (int i = 0; i < I_ObjMonCnt; i++)
ivMonsters[i].SetLoading();
dArea areadata = DataHandler.GetArea(DataHandler.PlayData.curStage);
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[0]))).Completed += ALoadMNm1Com;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[1]))).Completed += ALoadMNm2Comp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterEpic[0]))).Completed += ALoadMEl1Comp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterEpic[1]))).Completed += ALoadMEl2Comp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterBoss[0]))).Completed += ALoadMBsComp;
}
private void InitMonDungeon()
{
for (int i = 0; i < I_ObjMonCnt; i++)
ivMonsters[i].SetLoading();
dDungeonInfo areadata = DataHandler.GetDungeonTypeInfo(DungeonMgr.GetDungeonKind());
switch (DungeonMgr.GetDungeonKind())
{
case DungeonMgr.DungeonKind.GoldDG:
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[0]))).Completed += ALoadMDg1Comp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterBoss[0]))).Completed += ALoadMBsDgComp;
break;
case DungeonMgr.DungeonKind.EnhanceStoneDG:
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[0]))).Completed += ALoadMDg1Comp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[1]))).Completed += ALoadMDg2Comp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[2]))).Completed += ALoadMDg3Comp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[3]))).Completed += ALoadMDg4Comp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[4]))).Completed += ALoadMDg5Comp;
break;
case DungeonMgr.DungeonKind.PetDG:
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[0]))).Completed += ALoadMDg1Comp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[1]))).Completed += ALoadMDg2Comp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterEpic[0]))).Completed += ALoadMEl1DgComp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterBoss[0]))).Completed += ALoadMBsDgComp;
break;
case DungeonMgr.DungeonKind.AwakenStoneDG:
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[0]))).Completed += ALoadMAwBsDgComp;
break;
case DungeonMgr.DungeonKind.AwakenDG:
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[0]))).Completed += ALoadMDg1Comp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[1]))).Completed += ALoadMDg2Comp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[2]))).Completed += ALoadMDg3Comp;
break;
case DungeonMgr.DungeonKind.GuardianDG:
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[0]))).Completed += ALoadMBsDgComp;
break;
case DungeonMgr.DungeonKind.relicDG:
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterNormal[0]))).Completed += ALoadMDg1Comp;
Addressables.LoadAssetAsync<SkeletonDataAsset>(FormatString.StringFormat(AddressableMgr.PathMon, DataHandler.GetMonsterPath(areadata.monsterBoss[0]))).Completed += ALoadMBsDgComp;
break;
default:
break;
}
}
// 일반 몬스터1 로드 완료.
private void ALoadMNm1Com(AsyncOperationHandle<SkeletonDataAsset> obj)
{
int istartindex = 0;
int iendindex = istartindex + I_SummonMax;
for (int i = istartindex; i < iendindex; i++)
ivMonsters[i].SetMonsterAni(obj.Result);
if (handleSpines[0].IsValid())
Addressables.Release(handleSpines[0]);
handleSpines[0] = obj;
}
// 일반 몬스터2 로드 완료.
private void ALoadMNm2Comp(AsyncOperationHandle<SkeletonDataAsset> obj)
{
int istartindex = I_SummonMax;
int iendindex = istartindex + I_SummonMax;
for (int i = istartindex; i < iendindex; i++)
ivMonsters[i].SetMonsterAni(obj.Result);
if (handleSpines[1].IsValid())
Addressables.Release(handleSpines[1]);
handleSpines[1] = obj;
}
// 엘리트 몬스터1 로드 완료.
private void ALoadMEl1Comp(AsyncOperationHandle<SkeletonDataAsset> obj)
{
int istartindex = I_MonTypeNormal * I_SummonMax;
int iendindex = istartindex + I_SummonEliteMax;
for (int i = istartindex; i < iendindex; i++)
ivMonsters[i].SetMonsterAni(obj.Result);
if (handleSpines[2].IsValid())
Addressables.Release(handleSpines[2]);
handleSpines[2] = obj;
}
// 엘리트 몬스터2 로드 완료.
private void ALoadMEl2Comp(AsyncOperationHandle<SkeletonDataAsset> obj)
{
int istartindex = (I_MonTypeNormal * I_SummonMax) + I_SummonEliteMax;
int iendindex = istartindex + I_SummonEliteMax;
for (int i = istartindex; i < iendindex; i++)
ivMonsters[i].SetMonsterAni(obj.Result);
if (handleSpines[3].IsValid())
Addressables.Release(handleSpines[3]);
handleSpines[3] = obj;
}
// 보스 몬스터 로드 완료.
private void ALoadMBsComp(AsyncOperationHandle<SkeletonDataAsset> obj)
{
int index = (I_MonTypeNormal * I_SummonMax) + (I_MonTypeElite * I_SummonEliteMax);
ivMonsters[index].SetMonsterAni(obj.Result);
if (handleSpines[4].IsValid())
Addressables.Release(handleSpines[4]);
handleSpines[4] = obj;
}
// 던전 몬스터1 로드 완료.
private void ALoadMDg1Comp(AsyncOperationHandle<SkeletonDataAsset> obj)
{
int istartindex = 0;
int iendindex = 14;
for (int i = istartindex; i < iendindex; i++)
ivMonsters[i].SetMonsterAni(obj.Result);
if (handleSpines[0].IsValid())
Addressables.Release(handleSpines[0]);
handleSpines[0] = obj;
}
// 던전 몬스터2 로드 완료.
private void ALoadMDg2Comp(AsyncOperationHandle<SkeletonDataAsset> obj)
{
int istartindex = 14;
int iendindex = 22;
for (int i = istartindex; i < iendindex; i++)
ivMonsters[i].SetMonsterAni(obj.Result);
if (handleSpines[1].IsValid())
Addressables.Release(handleSpines[1]);
handleSpines[1] = obj;
}
// 던전 몬스터3 로드 완료.
private void ALoadMDg3Comp(AsyncOperationHandle<SkeletonDataAsset> obj)
{
int istartindex = 22;
int iendindex = 23;
for (int i = istartindex; i < iendindex; i++)
ivMonsters[i].SetMonsterAni(obj.Result);
if (handleSpines[2].IsValid())
Addressables.Release(handleSpines[2]);
handleSpines[2] = obj;
}
// 던전 몬스터4 로드 완료.
private void ALoadMDg4Comp(AsyncOperationHandle<SkeletonDataAsset> obj)
{
int istartindex = 23;
int iendindex = 24;
for (int i = istartindex; i < iendindex; i++)
ivMonsters[i].SetMonsterAni(obj.Result);
if (handleSpines[3].IsValid())
Addressables.Release(handleSpines[3]);
handleSpines[3] = obj;
}
// 던전 몬스터5 로드 완료.
private void ALoadMDg5Comp(AsyncOperationHandle<SkeletonDataAsset> obj)
{
int istartindex = 24;
int iendindex = 25;
for (int i = istartindex; i < iendindex; i++)
ivMonsters[i].SetMonsterAni(obj.Result);
if (handleSpines[4].IsValid())
Addressables.Release(handleSpines[4]);
handleSpines[4] = obj;
}
// 엘리트 몬스터1 로드 완료.
private void ALoadMEl1DgComp(AsyncOperationHandle<SkeletonDataAsset> obj)
{
int istartindex = 25;
int iendindex = 26;
for (int i = istartindex; i < iendindex; i++)
ivMonsters[i].SetMonsterAni(obj.Result);
if (handleSpines[5].IsValid())
Addressables.Release(handleSpines[5]);
handleSpines[5] = obj;
}
// 보스 몬스터 로드 완료.
private void ALoadMBsDgComp(AsyncOperationHandle<SkeletonDataAsset> obj)
{
int istartindex = 26;
int iendindex = 27;
for (int i = istartindex; i < iendindex; i++)
ivMonsters[i].SetMonsterAni(obj.Result);
if (handleSpines[6].IsValid())
Addressables.Release(handleSpines[6]);
handleSpines[6] = obj;
}
// 각성석 보스 몬스터 로드 완료.
private void ALoadMAwBsDgComp(AsyncOperationHandle<SkeletonDataAsset> obj)
{
int index = 27;
ivMonsters[index].SetMonsterAni(obj.Result);
if (handleSpines[7].IsValid())
Addressables.Release(handleSpines[7]);
handleSpines[7] = obj;
}
// 각 웨이브 시작시에 몬스터 소환.
private void SummonMonStage()
{
// 소환할 몬스터 수.
int itotalcount = I_SummonMax;//Random.Range(I_SummonMin, I_SummonMax + 1);
int ielitecount = 0;
int ibosscount = 0;
if (iWave == iTotalWave)
{
if (DataHandler.PlayData.curStage % DataHandler.Const.stageMax == 0)
ibosscount = 1;
else
ielitecount = I_SummonEliteMin;//Random.Range(, I_SummonEliteMax + 1);
bossIncoming.gameObject.SetActive(true);
bossIncoming.AnimationState.SetAnimation(0, "animation", false);
//bossIncoming.DOPlay();
SoundMgr.PlaySfx(SoundName.SummonBoss);
}
int spawn = 0;
#region Base Position
// 캐릭터 위치를 참조한 몬스터 소환 위치.
float fcharx = trfChar.localPosition.x;
float fchary = trfChar.localPosition.y;
Vector3 v3posbase = Vector3.zero;
Vector3 v3posbase2 = Vector3.zero;
bool bsamex = true;
//// 캐릭터가 왼쪽에 있을 경우 오른쪽에만 몬스터 소환.
//if (fcharx <= -12f)
//{
// v3posbase.x = Random.Range(fcharx + 20f, fcharx + 30f); // 10 ~ 20
// v3posbase2.x = v3posbase.x + 25f; // 15f
//}
//// 캐릭터가 오른쪽에 있을 경우 왼쪽에만 몬스터 소환.
//else if (fcharx >= 12f)
//{
// v3posbase.x = Random.Range(fcharx - 30f, fcharx - 20f);
// v3posbase2.x = v3posbase.x - 25f;
//}
// 캐릭터가 중앙에 있을 경우 랜덤으로 좌우 결정.
//else
{
if (spawn == 0/*Random.Range(0, 2) == 1*/)
{
v3posbase.x = fcharx - 25f;// Random.Range(fcharx - 30f, fcharx - 20f);
// 첫 번째 랜덤 좌표와 두 번째 랜덤 좌표를 비교해서 같은 방향인지 체크.
//if (Random.Range(0, 2) == 1)
//{
// v3posbase2.x = Random.Range(fcharx - 30f, fcharx - 20f);
//}
//else
//{
bsamex = false;
v3posbase2.x = Random.Range(fcharx + 30f, fcharx + 20f);
//}
spawn++;
}
else
{
v3posbase.x = fcharx + 25f;// Random.Range(fcharx + 20f, fcharx + 30f);
// 첫 번째 랜덤 좌표와 두 번째 랜덤 좌표를 비교해서 같은 방향인지 체크.
//if (Random.Range(0, 2) == 1)
//{
bsamex = false;
v3posbase2.x = Random.Range(fcharx - 30f, fcharx - 20f);
//}
//else
//{
// v3posbase2.x = Random.Range(fcharx + 20f, fcharx + 30f);
//}
spawn--;
}
}
// X축으로 같은 방향에 소환될 경우.
if (bsamex)
{
// 캐릭터 위치가 아래쪽이면 간격을 두고 위쪽에만 소환.
if (fchary <= -13f)
{
v3posbase.y = Random.Range(fchary + 7f, fchary + 12f);
v3posbase2.y = v3posbase.y + 10f;
}
// 캐릭터 위치가 위쪽이면 간격을 두고 아래쪽에만 소환.
else if (fchary >= 7f)
{
v3posbase.y = Random.Range(fchary - 12f, fchary - 7f);
v3posbase2.y = v3posbase.y - 10f;
}
// 캐릭터 위치가 중앙 아래쪽이면 서로 반대 방향에 소환.
else if (fchary <= -3f)
{
v3posbase.y = Random.Range(fchary + 7f, fchary + 12f);
v3posbase2.y = Random.Range(fchary - 12f, fchary - 7f);
}
// 캐릭터 위치가 중앙 위쪽이면 서로 반대 방향에 소환.
else
{
v3posbase.y = Random.Range(fchary - 12f, fchary - 7f);
v3posbase2.y = Random.Range(fchary + 7f, fchary + 12f);
}
}
// X축으로 다른 방향에 소환될 경우.
else
{
// 캐릭터 위치가 아래쪽이면 위쪽에만 소환.
if (fchary <= -13f)
{
v3posbase.y = Random.Range(fchary + 7f, fchary + 12f);
v3posbase2.y = Random.Range(fchary + 7f, fchary + 12f);
}
// 캐릭터 위치가 위쪽이면 아래쪽에만 소환.
else if (fchary >= 7f)
{
v3posbase.y = Random.Range(fchary - 12f, fchary - 7f);
v3posbase2.y = Random.Range(fchary - 12f, fchary - 7f);
}
// 캐릭터 위치가 중앙 아래쪽이면 랜덤으로 소환.
else if (fchary <= -3f)
{
if (Random.Range(0, 2) == 1)
v3posbase.y = Random.Range(fchary + 7f, fchary + 12f);
else
v3posbase.y = Random.Range(fchary - 12f, fchary - 7f);
if (Random.Range(0, 2) == 1)
v3posbase2.y = Random.Range(fchary + 7f, fchary + 12f);
else
v3posbase2.y = Random.Range(fchary - 12f, fchary - 7f);
}
// 캐릭터 위치가 중앙 위쪽이면 랜덤으로 소환.
else
{
if (Random.Range(0, 2) == 1)
v3posbase.y = Random.Range(fchary + 7f, fchary + 12f);
else
v3posbase.y = Random.Range(fchary - 12f, fchary - 7f);
if (Random.Range(0, 2) == 1)
v3posbase2.y = Random.Range(fchary + 7f, fchary + 12f);
else
v3posbase2.y = Random.Range(fchary - 12f, fchary - 7f);
}
}
v3posbase.x = Mathf.Clamp(v3posbase.x, V3_SummonMin.x, V3_SummonMax.x);
v3posbase.y = Mathf.Clamp(v3posbase.y, V3_SummonMin.y, V3_SummonMax.y);
v3posbase.z = Mathf.Clamp(v3posbase.z, V3_SummonMin.z, V3_SummonMax.z);
//v3posbase = v3posbase.Clamp(V3_SummonMin, V3_SummonMax);
v3posbase2.x = Mathf.Clamp(v3posbase2.x, V3_SummonMin.x, V3_SummonMax.x);
v3posbase2.y = Mathf.Clamp(v3posbase2.y, V3_SummonMin.y, V3_SummonMax.y);
v3posbase2.z = Mathf.Clamp(v3posbase2.z, V3_SummonMin.z, V3_SummonMax.z);
//v3posbase2 = v3posbase2.Clamp(V3_SummonMin, V3_SummonMax);
// 몬스터 별 위치.
List<int> indexlist = new List<int>();//V3_AddSummons.Length
for (int i = 0; i < I_SummonMax; i++)
indexlist.Add(i);
#endregion Base Position
for (int i = 0; i < itotalcount; i++)
{
int index;
BigInteger biatk;
//float fdef;
BigInteger fhp;
float frange;
float fspeed;
int igroup;
// 일반 몬스터.
if (i >= ielitecount + ibosscount)
{
int ran = Random.Range(0, I_MonTypeNormal);
index = GetAvailMonsterIndex(CreatureBase.eCreatureClass.normal, ran);
biatk = biMonAtk;
//fdef = fMonDef;
fhp = biMonHp;
frange = F_MonRangeNormal;
fspeed = fMonSpeedN[ran];
igroup = iMonGroupN[ran];
}
// 엘리트 몬스터.
else if (i >= ibosscount)
{
int ran = Random.Range(0, I_MonTypeElite);
index = GetAvailMonsterIndex(CreatureBase.eCreatureClass.elite, ran);
biatk = biMonAtk * DataHandler.Const.monEliteAtk / dConst.RateMax;
//fdef = fMonDef * DataHandler.Const.monEliteDef / dConst.RateMax;
fhp = biMonHp * DataHandler.Const.monEliteHp / dConst.RateMax;
frange = F_MonRangeElite;
fspeed = fMonSpeedE[ran];
igroup = iMonGroupE[ran];
}
// 보스 몬스터.
else
{
index = GetAvailMonsterIndex(CreatureBase.eCreatureClass.boss, 0);
biatk = biMonAtk * DataHandler.Const.monBossAtk / dConst.RateMax;
//fdef = fMonDef * DataHandler.Const.monBossDef / dConst.RateMax;
fhp = biMonHp * DataHandler.Const.monBossHp / dConst.RateMax;
frange = F_MonRangeBoss;
fspeed = fMonSpeedB[0];
igroup = iMonGroupB[0];
}
if (index < 0)
continue;
BigInteger debufbiatk = new BigInteger(BuffMgr.Instance.GetEnemyAtkDec());
biatk -= debufbiatk;
if (biatk < 0)
biatk = 1;
//fdef -= BuffMgr.Instance.GetEnemyDefDec();
//if (fdef < 0f)
// fdef = 1f;
BigInteger debuffHp = new BigInteger(BuffMgr.Instance.GetEnemyHpDec());
fhp -= debuffHp;
if (fhp < 0)
fhp = 1;
int irand = Random.Range(0, indexlist.Count);
Vector3 v3pos = V3_CharOrigin;//V3_AddSummons[indexlist[irand]%10];
if (Random.Range(0, 2) == 1)
{
v3pos.x += Random.Range(0, 2) == 1 ? 20 : -20;
v3pos.x += Random.Range(-5f, 5f);
v3pos.y += Random.Range(-20f, 16f);
}
else
{
v3pos.y += Random.Range(0, 2) == 1 ? 13 : -15;
v3pos.y += Random.Range(-3f, 3f);
v3pos.x += Random.Range(-20f, 20f);
}
indexlist.RemoveAt(irand);
//v3pos += Random.Range(0, 2) == 1 ? v3posbase : v3posbase2;
//v3pos.x += Random.Range(-0.7f, 0.7f);
//v3pos.y += Random.Range(-10f, 10f);
v3pos.z = v3pos.y * 0.1f;
if (iWave == iTotalWave)
{
if(ivMonsters[index].GetCreatureClass() == eCreatureClass.elite)
{
ivMonsters[index].ResetDebuff();
ivMonsters[index].SetStatus(biatk, fhp, dConst.RateMaxFloat, 0, dConst.RateMaxFloat * 0.1f * fspeed, dConst.RateMax, frange, igroup: igroup);
hpBarEnemies[i].ReSetoffsetY(ivMonsters[index].GetMonType());
ivMonsters[index].Summon(v3pos, trfChar.position.x > v3pos.x);
iMonsterCount++;
}
if (ivMonsters[index].GetCreatureClass() == eCreatureClass.boss)
{
ivMonsters[index].ResetDebuff();
ivMonsters[index].SetStatus(biatk, fhp, dConst.RateMaxFloat, 0, dConst.RateMaxFloat * 0.1f * fspeed, dConst.RateMax, frange, igroup: igroup);
hpBarEnemies[i].ReSetoffsetY(ivMonsters[index].GetMonType());
ivMonsters[index].Summon(v3pos, trfChar.position.x > v3pos.x);
iMonsterCount++;
}
}
else
{
ivMonsters[index].ResetDebuff();
ivMonsters[index].SetStatus(biatk, fhp, dConst.RateMaxFloat, 0, dConst.RateMaxFloat * 0.1f * fspeed, dConst.RateMax, frange, igroup: igroup);
hpBarEnemies[i].ReSetoffsetY(ivMonsters[index].GetMonType());
ivMonsters[index].Summon(v3pos, trfChar.position.x > v3pos.x);
iMonsterCount++;
}
if (indexlist.Count == 0)
break;
}
}
//던전에서 몹 소환하기. 총합 카운트에서 나머지 카운트를 뺸 값이 일반몹 1 이 나오는 양이다.
private void SummonMonDungeon()
{
// 소환할 몬스터 수.
int itotalcount = 10;
int dgNorm2Count = 0;
int dgNorm3Count = 0;
int dgNorm4Count = 0;
int dgNorm5Count = 0;
int ielitecount = 0;
int ibosscount = 0;
int ibigbosscount = 0;
switch (DungeonMgr.GetDungeonKind())
{
case DungeonMgr.DungeonKind.GoldDG:
// 소환할 몬스터 수.
itotalcount = 10;
dgNorm2Count = 0;
dgNorm3Count = 0;
dgNorm4Count = 0;
dgNorm5Count = 0;
ielitecount = 0;
ibosscount = 0;
if (iWave == iTotalWave)
{
ibosscount = 1;
}
break;
case DungeonMgr.DungeonKind.EnhanceStoneDG:
// 소환할 몬스터 수.
itotalcount = 1;
dgNorm2Count = 0;
dgNorm3Count = 0;
dgNorm4Count = 0;
dgNorm5Count = 0;
ielitecount = 0;
ibosscount = 0;
switch (iWave)
{
case 2:
dgNorm2Count = 1;
dgNorm3Count = 0;
dgNorm4Count = 0;
dgNorm5Count = 0;
break;
case 3:
dgNorm2Count = 0;
dgNorm3Count = 1;
dgNorm4Count = 0;
dgNorm5Count = 0;
break;
case 4:
dgNorm2Count = 0;
dgNorm3Count = 0;
dgNorm4Count = 1;
dgNorm5Count = 0;
break;
case 5:
dgNorm2Count = 0;
dgNorm3Count = 0;
dgNorm4Count = 0;
dgNorm5Count = 1;
break;
}
break;
case DungeonMgr.DungeonKind.PetDG:
// 소환할 몬스터 수.
itotalcount = 5;
dgNorm2Count = Random.Range(1, 4);
dgNorm3Count = 0;
dgNorm4Count = 0;
dgNorm5Count = 0;
ielitecount = 0;
ibosscount = 0;
if (iWave == iTotalWave)
{
if (DungeonMgr.GetDungeonLevel() % 5 == 0)
{
ibosscount = 1;
}
else
{
ielitecount = 1;
}
}
break;
case DungeonMgr.DungeonKind.AwakenStoneDG://5053 번 언저릿 줄에서 받은 normal 몬스터를 보스 정보로 변환하는 곳이 있다.
itotalcount = 1;
dgNorm2Count = 0;
dgNorm3Count = 0;
dgNorm4Count = 0;
dgNorm5Count = 0;
ielitecount = 0;
ibosscount = 0;
ibigbosscount = 1;
break;
case DungeonMgr.DungeonKind.AwakenDG:
itotalcount = 3;
dgNorm2Count = 1;
dgNorm3Count = 1;
dgNorm4Count = 0;
dgNorm5Count = 0;
ielitecount = 0;
ibosscount = 0;
break;
case DungeonMgr.DungeonKind.GuardianDG://normal 몬스터 정보로 바꾸고 싶다면 5053 언저릿 줄에 있는 변환하는 코드를 지우고 이쪽의 보스 카운트도 0으로 맞추면 된다.
itotalcount = 1;
dgNorm2Count = 0;
dgNorm3Count = 0;
dgNorm4Count = 0;
dgNorm5Count = 0;
ielitecount = 0;
ibosscount = 1;
break;
case DungeonMgr.DungeonKind.relicDG:
// 소환할 몬스터 수.
itotalcount = 10;
dgNorm2Count = 0;
dgNorm3Count = 0;
dgNorm4Count = 0;
dgNorm5Count = 0;
ielitecount = 0;
ibosscount = 0;
if (iWave == iTotalWave)
{
ibosscount = 1;
}
break;
default:
break;
}
float fcharx = trfChar.localPosition.x;
float fchary = trfChar.localPosition.y;
Vector3 v3posbase = Vector3.zero;
Vector3 v3posbase2 = Vector3.zero;
bool bsamex = true;
List<int> indexlist = new List<int>(V3_AddSummons.Length);
switch (DungeonMgr.GetDungeonKind())
{
case DungeonMgr.DungeonKind.GoldDG:
case DungeonMgr.DungeonKind.PetDG:
case DungeonMgr.DungeonKind.AwakenDG:
case DungeonMgr.DungeonKind.relicDG:
#region Base Position
// 캐릭터 위치를 참조한 몬스터 소환 위치.
fcharx = trfChar.localPosition.x;
fchary = trfChar.localPosition.y;
v3posbase = Vector3.zero;
v3posbase2 = Vector3.zero;
bsamex = true;
// 캐릭터가 왼쪽에 있을 경우 오른쪽에만 몬스터 소환.
if (fcharx <= -12f)
{
v3posbase.x = Random.Range(fcharx + 10f, fcharx + 20f);
v3posbase2.x = v3posbase.x + 15f;
}
// 캐릭터가 오른쪽에 있을 경우 왼쪽에만 몬스터 소환.
else if (fcharx >= 12f)
{
v3posbase.x = Random.Range(fcharx - 20f, fcharx - 10f);
v3posbase2.x = v3posbase.x - 15f;
}
// 캐릭터가 중앙에 있을 경우 랜덤으로 좌우 결정.
else
{
if (Random.Range(0, 2) == 1)
{
v3posbase.x = Random.Range(fcharx - 15f, fcharx - 10f);
// 첫 번째 랜덤 좌표와 두 번째 랜덤 좌표를 비교해서 같은 방향인지 체크.
if (Random.Range(0, 2) == 1)
{
v3posbase2.x = Random.Range(fcharx - 15f, fcharx - 10f);
}
else
{
bsamex = false;
v3posbase2.x = Random.Range(fcharx + 10f, fcharx + 15f);
}
}
else
{
v3posbase.x = Random.Range(fcharx + 10f, fcharx + 15f);
// 첫 번째 랜덤 좌표와 두 번째 랜덤 좌표를 비교해서 같은 방향인지 체크.
if (Random.Range(0, 2) == 1)
{
bsamex = false;
v3posbase2.x = Random.Range(fcharx - 15f, fcharx - 10f);
}
else
{
v3posbase2.x = Random.Range(fcharx + 10f, fcharx + 15f);
}
}
}
// X축으로 같은 방향에 소환될 경우.
if (bsamex)
{
// 캐릭터 위치가 아래쪽이면 간격을 두고 위쪽에만 소환.
if (fchary <= -13f)
{
v3posbase.y = Random.Range(fchary + 7f, fchary + 12f);
v3posbase2.y = v3posbase.y + 10f;
}
// 캐릭터 위치가 위쪽이면 간격을 두고 아래쪽에만 소환.
else if (fchary >= 7f)
{
v3posbase.y = Random.Range(fchary - 12f, fchary - 7f);
v3posbase2.y = v3posbase.y - 10f;
}
// 캐릭터 위치가 중앙 아래쪽이면 서로 반대 방향에 소환.
else if (fchary <= -3f)
{
v3posbase.y = Random.Range(fchary + 7f, fchary + 12f);
v3posbase2.y = Random.Range(fchary - 12f, fchary - 7f);
}
// 캐릭터 위치가 중앙 위쪽이면 서로 반대 방향에 소환.
else
{
v3posbase.y = Random.Range(fchary - 12f, fchary - 7f);
v3posbase2.y = Random.Range(fchary + 7f, fchary + 12f);
}
}
// X축으로 다른 방향에 소환될 경우.
else
{
// 캐릭터 위치가 아래쪽이면 위쪽에만 소환.
if (fchary <= -13f)
{
v3posbase.y = Random.Range(fchary + 7f, fchary + 12f);
v3posbase2.y = Random.Range(fchary + 7f, fchary + 12f);
}
// 캐릭터 위치가 위쪽이면 아래쪽에만 소환.
else if (fchary >= 7f)
{
v3posbase.y = Random.Range(fchary - 12f, fchary - 7f);
v3posbase2.y = Random.Range(fchary - 12f, fchary - 7f);
}
// 캐릭터 위치가 중앙 아래쪽이면 랜덤으로 소환.
else if (fchary <= -3f)
{
if (Random.Range(0, 2) == 1)
v3posbase.y = Random.Range(fchary + 7f, fchary + 12f);
else
v3posbase.y = Random.Range(fchary - 12f, fchary - 7f);
if (Random.Range(0, 2) == 1)
v3posbase2.y = Random.Range(fchary + 7f, fchary + 12f);
else
v3posbase2.y = Random.Range(fchary - 12f, fchary - 7f);
}
// 캐릭터 위치가 중앙 위쪽이면 랜덤으로 소환.
else
{
if (Random.Range(0, 2) == 1)
v3posbase.y = Random.Range(fchary + 7f, fchary + 12f);
else
v3posbase.y = Random.Range(fchary - 12f, fchary - 7f);
if (Random.Range(0, 2) == 1)
v3posbase2.y = Random.Range(fchary + 7f, fchary + 12f);
else
v3posbase2.y = Random.Range(fchary - 12f, fchary - 7f);
}
}
v3posbase.x = Mathf.Clamp(v3posbase.x, V3_SummonMin.x, V3_SummonMax.x);
v3posbase.y = Mathf.Clamp(v3posbase.y, V3_DgSummonMin.y, V3_DgSummonMax.y);
v3posbase.z = Mathf.Clamp(v3posbase.z, V3_SummonMin.z, V3_SummonMax.z);
//v3posbase = v3posbase.Clamp(V3_SummonMin, V3_SummonMax);
v3posbase2.x = Mathf.Clamp(v3posbase2.x, V3_SummonMin.x, V3_SummonMax.x);
v3posbase2.y = Mathf.Clamp(v3posbase2.y, V3_DgSummonMin.y, V3_DgSummonMax.y);
v3posbase2.z = Mathf.Clamp(v3posbase2.z, V3_SummonMin.z, V3_SummonMax.z);
//v3posbase2 = v3posbase2.Clamp(V3_SummonMin, V3_SummonMax);
// 몬스터 별 위치.
for (int i = 0; i < V3_AddSummons.Length; i++)
indexlist.Add(i);
#endregion Base Position
break;
case DungeonMgr.DungeonKind.AwakenStoneDG:
#region Base Position
// 캐릭터 위치를 참조한 몬스터 소환 위치.
float charX = trfChar.localPosition.x;
if (charX < 0)
{
fcharx = -5;
}
else
{
fcharx = 5;
}
fchary = 0;
v3posbase = Vector3.zero;
v3posbase2 = Vector3.zero;
bsamex = true;
v3posbase.x = fcharx;
v3posbase2.x = v3posbase.x;
//v3posbase.x = Mathf.Clamp(v3posbase.x, V3_SummonMin.x, 999f);
//v3posbase.y = Mathf.Clamp(v3posbase.y, 2f, 2f);
v3posbase.z = Mathf.Clamp(v3posbase.z, V3_SummonMin.z, V3_SummonMax.z);
//v3posbase = v3posbase.Clamp(V3_SummonMin, V3_SummonMax);
//v3posbase2.x = Mathf.Clamp(v3posbase2.x, V3_SummonMin.x, 999f);
//v3posbase2.y = Mathf.Clamp(v3posbase2.y, 2f, 2f);
v3posbase2.z = Mathf.Clamp(v3posbase2.z, V3_SummonMin.z, V3_SummonMax.z);
//v3posbase2 = v3posbase2.Clamp(V3_SummonMin, V3_SummonMax);
// 몬스터 별 위치.
for (int i = 0; i < 1; i++)
indexlist.Add(1);
#endregion Base Position
break;
case DungeonMgr.DungeonKind.EnhanceStoneDG:
#region Base Position
// 캐릭터 위치를 참조한 몬스터 소환 위치.
fcharx = trfChar.localPosition.x;
fchary = trfChar.localPosition.y;
v3posbase = Vector3.zero;
v3posbase2 = Vector3.zero;
bsamex = true;
v3posbase.x = -15f + (35f * iWave);
v3posbase2.x = v3posbase.x + 1f;
v3posbase.x = Mathf.Clamp(v3posbase.x, V3_SummonMin.x, 999f);
v3posbase.y = Mathf.Clamp(v3posbase.y, 2f, 2f);
v3posbase.z = Mathf.Clamp(v3posbase.z, V3_SummonMin.z, V3_SummonMax.z);
//v3posbase = v3posbase.Clamp(V3_SummonMin, V3_SummonMax);
v3posbase2.x = Mathf.Clamp(v3posbase2.x, V3_SummonMin.x, 999f);
v3posbase2.y = Mathf.Clamp(v3posbase2.y, 2f, 2f);
v3posbase2.z = Mathf.Clamp(v3posbase2.z, V3_SummonMin.z, V3_SummonMax.z);
//v3posbase2 = v3posbase2.Clamp(V3_SummonMin, V3_SummonMax);
// 몬스터 별 위치.
for (int i = 0; i < 1; i++)
indexlist.Add(3);
#endregion Base Position
break;
case DungeonMgr.DungeonKind.GuardianDG:
#region Base Position
// 캐릭터 위치를 참조한 몬스터 소환 위치.
fcharx = trfChar.localPosition.x;
fchary = trfChar.localPosition.y;
v3posbase = Vector3.zero;
v3posbase2 = Vector3.zero;
bsamex = true;
v3posbase.x = -3.8f;
v3posbase2.x = -3.8f;
v3posbase.x = Mathf.Clamp(v3posbase.x, V3_SummonMin.x, 999f);
v3posbase.y = Mathf.Clamp(v3posbase.y, -5.6f, -5.6f);
v3posbase.z = Mathf.Clamp(v3posbase.z, V3_SummonMin.z, V3_SummonMax.z);
//v3posbase = v3posbase.Clamp(V3_SummonMin, V3_SummonMax);
v3posbase2.x = Mathf.Clamp(v3posbase2.x, V3_SummonMin.x, 999f);
v3posbase2.y = Mathf.Clamp(v3posbase2.y, -5.6f, -5.6f);
v3posbase2.z = Mathf.Clamp(v3posbase2.z, V3_SummonMin.z, V3_SummonMax.z);
//v3posbase2 = v3posbase2.Clamp(V3_SummonMin, V3_SummonMax);
// 몬스터 별 위치.
for (int i = 0; i < 1; i++)
indexlist.Add(3);
#endregion Base Position
break;
default:
break;
}
for (int i = 0; i < itotalcount; i++)
{
int index;
BigInteger biatk;
BigInteger fhp;
float frange;
float fspeed;
int igroup;
// 일반 몬스터.
if (i >= dgNorm2Count + dgNorm3Count + dgNorm4Count + dgNorm5Count + ielitecount + ibosscount + ibigbosscount)
{
index = GetAvailDgMonsterIndex(CreatureBase.eDgCreatureClass.DgN1);
biatk = biMonAtk;
fhp = biMonHp;
frange = F_MonRangeNormal;
fspeed = fMonSpeedN[0];
igroup = iMonGroupN[0];
}
else if (i >= dgNorm3Count + dgNorm4Count + dgNorm5Count + ielitecount + ibosscount + ibigbosscount)
{
index = GetAvailDgMonsterIndex(CreatureBase.eDgCreatureClass.DgN2);
biatk = biMonAtk;
fhp = biMonHp;
frange = F_MonRangeNormal;
fspeed = fMonSpeedN[1];
igroup = iMonGroupN[1];
}
else if (i >= dgNorm4Count + dgNorm5Count + ielitecount + ibosscount + ibigbosscount)
{
index = GetAvailDgMonsterIndex(CreatureBase.eDgCreatureClass.DgN3);
biatk = biMonAtk;
fhp = biMonHp;
frange = F_MonRangeNormal;
fspeed = fMonSpeedN[2];
igroup = iMonGroupN[2];
}
else if (i >= dgNorm5Count + ielitecount + ibosscount + ibigbosscount)
{
index = GetAvailDgMonsterIndex(CreatureBase.eDgCreatureClass.DgN4);
biatk = biMonAtk;
fhp = biMonHp;
frange = F_MonRangeNormal;
fspeed = fMonSpeedN[3];
igroup = iMonGroupN[3];
}
else if (i >= ielitecount + ibosscount + ibigbosscount)
{
index = GetAvailDgMonsterIndex(CreatureBase.eDgCreatureClass.DgN5);
biatk = biMonAtk;
fhp = biMonHp;
frange = F_MonRangeNormal;
fspeed = fMonSpeedN[4];
igroup = iMonGroupN[4];
}
// 엘리트 몬스터.
else if (i >= ibosscount + ibigbosscount)
{
index = GetAvailDgMonsterIndex(CreatureBase.eDgCreatureClass.DgE1);
biatk = biMonAtk * DataHandler.Const.monEliteAtk / dConst.RateMax;
fhp = biMonHp * DataHandler.Const.monEliteHp / dConst.RateMax;
frange = F_MonRangeElite;
fspeed = fMonSpeedE[0];
igroup = iMonGroupE[0];
}
// 보스 몬스터.
else if(i >= ibigbosscount)
{
index = GetAvailDgMonsterIndex(CreatureBase.eDgCreatureClass.DgBs);
biatk = biMonAtk * DataHandler.Const.monBossAtk / dConst.RateMax;
fhp = biMonHp * DataHandler.Const.monBossHp / dConst.RateMax;
frange = F_MonRangeBoss;
fspeed = fMonSpeedB[0];
igroup = iMonGroupB[0];
}
//각성석
else
{
index = GetAvailDgMonsterIndex(CreatureBase.eDgCreatureClass.DgAwBs);
biatk = biMonAtk * DataHandler.Const.monBossAtk / dConst.RateMax;
fhp = biMonHp * DataHandler.Const.monBossHp / dConst.RateMax;
frange = F_MonRangeBoss;
fspeed = fMonSpeedB[0];
igroup = iMonGroupB[0];
}
if (index < 0)
continue;
int irand = Random.Range(0, indexlist.Count);
Vector3 v3pos = V3_AddSummons[indexlist[irand]];
indexlist.RemoveAt(irand);
v3pos += Random.Range(0, 2) == 1 ? v3posbase : v3posbase2;
v3pos.x += Random.Range(-0.7f, 0.7f);
v3pos.y += Random.Range(-0.7f, 0.7f);
v3pos.z = v3pos.y * 2f;
ivMonsters[index].ResetDebuff();
ivMonsters[index].SetStatus(biatk, fhp, dConst.RateMaxFloat, 0, dConst.RateMaxFloat * 0.1f * fspeed, dConst.RateMax, frange, igroup: igroup);
if (CurrentBattleType == BattleType.AwakenDungeon)
{
if(index == GetAvailDgMonsterIndex(CreatureBase.eDgCreatureClass.DgN3))
{
ivMonsters[index].SetStatus(biatk, fhp, dConst.RateMaxFloat, 0, dConst.RateMaxFloat * 0.1f * fspeed, dConst.RateMax, frange,false, false, igroup: igroup);
}
}
hpBarEnemies[index].ReSetoffsetY(ivMonsters[index].GetMonType());
ivMonsters[index].Summon(v3pos, trfChar.position.x > v3pos.x);
iMonsterCount++;
if (indexlist.Count == 0)
break;
}
}
// 몬스터 종류별로 소환 가능한 인덱스 가져오기.
private int GetAvailMonsterIndex(CreatureBase.eCreatureClass cls, int itype)
{
switch (cls)
{
case CreatureBase.eCreatureClass.normal:
int itypeminn = itype * I_SummonMax;
int itypemaxn = itypeminn + I_SummonMax;
for (int i = itypeminn; i < itypemaxn; i++)
{
if (!goMonsters[i].activeSelf)
return i;
}
break;
case CreatureBase.eCreatureClass.elite:
int itypemine = (I_MonTypeNormal * I_SummonMax) + itype * I_SummonEliteMax;
int itypemaxe = itypemine + I_SummonEliteMax;
for (int i = itypemine; i < itypemaxe; i++)
{
if (!goMonsters[i].activeSelf)
return i;
}
break;
case CreatureBase.eCreatureClass.boss:
return (I_MonTypeNormal * I_SummonMax) + (I_MonTypeElite * I_SummonEliteMax);
}
return -1;
}
// 몬스터 던전 종류별로 소환 가능한 인덱스 가져오기.
private int GetAvailDgMonsterIndex(CreatureBase.eDgCreatureClass cls)
{
int itypeminn = 0;
int itypemaxn = 14;
switch (cls)
{
case CreatureBase.eDgCreatureClass.DgN1:
itypeminn = 0;
itypemaxn = 14;
for (int i = itypeminn; i < itypemaxn; i++)
{
if (!goMonsters[i].activeSelf)
return i;
}
break;
case CreatureBase.eDgCreatureClass.DgN2:
itypeminn = 14;
itypemaxn = 22;
for (int i = itypeminn; i < itypemaxn; i++)
{
if (!goMonsters[i].activeSelf)
return i;
}
break;
case CreatureBase.eDgCreatureClass.DgN3:
itypeminn = 22;
itypemaxn = 23;
for (int i = itypeminn; i < itypemaxn; i++)
{
if (!goMonsters[i].activeSelf)
return i;
}
break;
case CreatureBase.eDgCreatureClass.DgN4:
itypeminn = 23;
itypemaxn = 24;
for (int i = itypeminn; i < itypemaxn; i++)
{
if (!goMonsters[i].activeSelf)
return i;
}
break;
case CreatureBase.eDgCreatureClass.DgN5:
itypeminn = 24;
itypemaxn = 25;
for (int i = itypeminn; i < itypemaxn; i++)
{
if (!goMonsters[i].activeSelf)
return i;
}
break;
case CreatureBase.eDgCreatureClass.DgE1:
itypeminn = 25;
itypemaxn = 26;
for (int i = itypeminn; i < itypemaxn; i++)
{
if (!goMonsters[i].activeSelf)
return i;
}
break;
case CreatureBase.eDgCreatureClass.DgBs:
itypeminn = 26;
itypemaxn = 27;
for (int i = itypeminn; i < itypemaxn; i++)
{
if (!goMonsters[i].activeSelf)
return i;
}
break;
case CreatureBase.eDgCreatureClass.DgAwBs:
return 27;
}
return -1;
}
#endregion Summon
#region Die & Fail
// 시간 경과로 아군 패배.
private void FailTimeOut()
{
ivChar.ChangeState(CreatureBase.eState.die);
}
// 아군 사망시 처리.
public void DieFriendly()
{
iTalkChar = 1; // 패배.
ShowTalkBox();
if (Random.Range(0, 2) == 0)
iTalkChar = Random.Range(3, iTalkMax);
int iarea = DataHandler.PlayData.curStage / 100;
int istage = DataHandler.PlayData.curStage % 100;
if (CurrentBattleType != BattleType.Stage)
bChangeArea = true;
else
bChangeArea = istage == 1 && iarea > 1;
GameUIMgr.ClosePopupSet();
switch (CurrentBattleType)
{
case BattleType.Stage:
DataHandler.FailStage();
bRetry = true;
DataHandler.PlayData.stageRepeat = bRetry;
DataHandler.PlayData.Save();
SetRetry();
break;
case BattleType.GoldDungeon:
case BattleType.EnhanceStoneDungeon:
case BattleType.PetDungeon:
case BattleType.AwakenStoneDungeon:
case BattleType.AwakenDungeon:
case BattleType.RelicDungeon:
CurrentBattleType = BattleType.Stage;
GameUIMgr.SSetActiveHotTime(true);
GameUIMgr.SReturnToPreservePreset();
GameUIMgr.SOnOffDungeonButton(true);
DungeonMgr.GetSuccessOrFail(false);
break;
case BattleType.GuardianDungeon:
CurrentBattleType = BattleType.Stage;
GameUIMgr.SSetActiveHotTime(true);
GameUIMgr.SReturnToPreservePreset();
GameUIMgr.SOnOffDungeonButton(true);
//여기요
DungeonMgr.GetSuccessOrFail(false);
break;
case BattleType.Pvp:
EndPvp();
return;
}
NoReward();
seqDieStage.Restart();
}
int waveMonCount = 0;
int shim = 0;
// 적 사망시 처리.
public void DieEnemy(CreatureBase.eCreatureClass cls, int index)
{
iMonsterCount--;
if (CurrentBattleType == BattleType.Pvp)
{
iTalkChar = 0; // 승리.
ShowTalkBox();
EndPvp();
return;
}
if (CurrentBattleType == BattleType.Stage)
{
DataHandler.AddPassProgress(eCondition.MonsterCnt, 1);
DataHandler.AddRecord(eCondition.MonsterCnt);
if (cls == CreatureBase.eCreatureClass.normal)
{
waveMonCount++;
if (waveMonCount >= 5)
{
DropItem(1, index, DropItemKind.Gold);
DropItem(1, index, DropItemKind.Exp);
waveMonCount = 0;
}
if (dropItemCount[(int)DropItemKind.Box] > 0)
{
int chestPercent = Random.Range(0, 100);
if (chestPercent > 95)
{
DropItem(1, index, DropItemKind.Box);
dropItemCount[(int)DropItemKind.Box]--;
}
}
if (dropItemCount[(int)DropItemKind.TradeEventCoin] > 0)
{
int eventPercent = Random.Range(0, 100);
if (eventPercent > 95)
{
DropItem(1, index, DropItemKind.TradeEventCoin);
dropItemCount[(int)DropItemKind.TradeEventCoin]--;
}
}
if (dropItemCount[(int)DropItemKind.RaiseEventCoin] > 0)
{
int eventPercent = Random.Range(0, 100);
if (eventPercent > 95)
{
DropItem(1, index, DropItemKind.RaiseEventCoin);
dropItemCount[(int)DropItemKind.RaiseEventCoin]--;
}
}
if (dropItemCount[(int)DropItemKind.RouletteEventCoin] > 0)
{
int eventPercent = Random.Range(0, 100);
if (eventPercent > 95)
{
DropItem(1, index, DropItemKind.RouletteEventCoin);
dropItemCount[(int)DropItemKind.RouletteEventCoin]--;
}
}
}
else if (cls == CreatureBase.eCreatureClass.elite)
{
DropItem(1, index, DropItemKind.Gold);
DropItem(1, index, DropItemKind.Exp);
while (dropItemCount[(int)DropItemKind.Box] > 0)
{
DropItem(1, index, DropItemKind.Box);
dropItemCount[(int)DropItemKind.Box]--;
}
while (dropItemCount[(int)DropItemKind.TradeEventCoin] > 0)
{
DropItem(1, index, DropItemKind.TradeEventCoin);
dropItemCount[(int)DropItemKind.TradeEventCoin]--;
}
while (dropItemCount[(int)DropItemKind.RaiseEventCoin] > 0)
{
DropItem(1, index, DropItemKind.RaiseEventCoin);
dropItemCount[(int)DropItemKind.RaiseEventCoin]--;
}
while (dropItemCount[(int)DropItemKind.RouletteEventCoin] > 0)
{
DropItem(1, index, DropItemKind.RouletteEventCoin);
dropItemCount[(int)DropItemKind.RouletteEventCoin]--;
}
}
else
{
DropItem(1, index, DropItemKind.Gold);
DropItem(1, index, DropItemKind.Exp);
DropItem(1, index, DropItemKind.MemoryPiece);
dropItemCount[(int)DropItemKind.MemoryPiece]++;
}
}
if (iMonsterCount <= 0)
{
if (iWave >= iTotalWave)
{
bClear = true;
bChangeArea = false;
ivChar.ChangeState(CreatureBase.eState.idle);
switch (CurrentBattleType)
{
case BattleType.Stage:
bChangeArea = !bRetry && DataHandler.PlayData.curStage >= DataHandler.Const.stageMax;
DataHandler.ClearStage(!bRetry);
if (bChangeArea)
{
iTalkChar = 0; // 승리.
ShowTalkBox();
seqChangeArea.Restart(); //?-1 교체
ClearReward();
}
else
{
seqChangeStage.Restart();//1-? 교체
ClearReward();
}
break;
case BattleType.GoldDungeon:
case BattleType.EnhanceStoneDungeon:
case BattleType.PetDungeon:
case BattleType.AwakenStoneDungeon:
case BattleType.RelicDungeon:
iTalkChar = 0; // 승리.
GameUIMgr.ClosePopupSet();
ShowTalkBox();
if (DungeonMgr.GetAutoProgress() && DungeonMgr.IsDungeonProgressOK(1))
{
//seqChangeArea.Restart();
}
else
{
seqChangeArea.Restart(); //?-1 교체
}
DungeonMgr.GetSuccessOrFail(true);
break;
case BattleType.AwakenDungeon:
iTalkChar = 0; // 승리.
ShowTalkBox();
seqChangeArea.Restart(); //?-1 교체
DungeonMgr.GetSuccessOrFail(true);
break;
case BattleType.GuardianDungeon:
iTalkChar = 0; // 승리.
ShowTalkBox();
seqChangeArea.Restart(); //?-1 교체
DungeonMgr.GetSuccessOrFail(true);
break;
}
if (Random.Range(0, 2) == 0)
iTalkChar = Random.Range(3, iTalkMax);
EventMgr.SBadgeCheck();
}
else
{
iWave++;
ivChar.SetStatus(BuffMgr.Instance.GetCharAtk(), BuffMgr.Instance.GetCharHp(),
BuffMgr.Instance.GetCharCrtDam(), BuffMgr.Instance.GetCharCrtRate(), BuffMgr.Instance.GetCharMov(), BuffMgr.Instance.GetCharSpd(), GameProperty.Instance.PlayerCharacterAttackRange, true);
switch (CurrentBattleType)
{
case BattleType.Stage:
SummonMonStage();//중간왕과 끝판왕이 있음
SetStageAreaWave(DataHandler.PlayData.curStage, iWave);
break;
case BattleType.GoldDungeon:
case BattleType.EnhanceStoneDungeon:
case BattleType.PetDungeon:
case BattleType.AwakenStoneDungeon:
case BattleType.AwakenDungeon:
case BattleType.GuardianDungeon:
case BattleType.RelicDungeon:
SetDungeonWave(DungeonMgr.GetDungeonLevel(), iWave);
SummonMonDungeon();//왕이 나올지 안 나올지 모름
break;
}
}
}
}
void UnlockCheck()
{
PetMgr.IsUnlock();
TreasureMgr.IsUnlock();
DungeonMgr.IsUnlock();
}
#endregion Die & Fail
bool doNotUnlockCheck = false;
int goToContent = 0;
void ContentUnlockCheck(int stage)
{
if (doNotUnlockCheck)
{
return;
}
UnlockCheck();
if (stage == DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.GoldDG).openStage)
{
goToContent = 0;
}
else if (stage == DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.EnhanceStoneDG).openStage)
{
goToContent = 1;
}
else if (stage == DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.PetDG).openStage)
{
goToContent = 2;
}
else if (stage == DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.AwakenStoneDG).openStage)
{
goToContent = 3;
}
else if (stage == DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.AwakenDG).openStage)
{
goToContent = 4;
}
else if (stage == DataHandler.Const.gearAccOpenStage)
{
goToContent = 5;
}
else if (stage == DataHandler.Const.gearTreasureOpenStage)
{
goToContent = 6;
}
else if(stage > DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.GoldDG).openStage &&
stage > DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.EnhanceStoneDG).openStage &&
stage > DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.PetDG).openStage &&
stage > DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.AwakenStoneDG).openStage &&
stage > DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.AwakenDG).openStage &&
stage > DataHandler.Const.gearAccOpenStage &&
stage > DataHandler.Const.gearTreasureOpenStage)
{
doNotUnlockCheck = true;
return;
}
dotUnlock[goToContent].DORewind();
canvasStageUnlock[goToContent].SetActive(true);
dotUnlock[goToContent].DOPlay();
isUnlockCheck = false;
}
public void ContentUnlockClose(int index)
{
canvasStageUnlock[index].SetActive(false);
}
public static void SContetnUnlockCloseAll()
{
for(int i = 0; i < Instance.canvasStageUnlock.Length; i++)
{
if (Instance.canvasStageUnlock[i].activeSelf)
Instance.canvasStageUnlock[i].SetActive(false);
}
}
public void ContentUnlockGoto(int index)
{
switch (index)
{
case 0:
SingleMgr.MoveContent(eEventMoveType.DgGold);
break;
case 1:
SingleMgr.MoveContent(eEventMoveType.DgStone);
break;
case 2:
SingleMgr.MoveContent(eEventMoveType.DgPet);
break;
case 3:
SingleMgr.MoveContent(eEventMoveType.DgAwaken);
break;
case 4:
SingleMgr.MoveContent(eEventMoveType.EnhanceAwakne);
break;
case 5:
SingleMgr.MoveContent(eEventMoveType.BagAccEar);
break;
case 6:
SingleMgr.MoveContent(eEventMoveType.BagTreasure);
break;
}
ContentUnlockClose(index);
}
#region Item Drop
public void DropItem(int spawnNum, int index, DropItemKind spriteNum)
{
for (int i = 0; i < spawnNum; i++)
{
if (dropItemPoolCount <= dropItemPoolCountNow) return;
dropItemPool[dropItemPoolCountNow].ItemAppear(trfMonsters[index].position, (int)spriteNum);
dropItemPoolCountNow++;
}
}
public static void ClearReward()
{
for (int i = 0; i < Instance.dropItemPoolCountNow; i++)
{
Instance.dropItemPool[i].itemDisappear(Instance.trfChar.position);
}
Instance.stageSuccessWindow.SetActive(true);
SoundMgr.PlaySfx(SoundName.GetGoods);
dArea areadata = DataHandler.GetArea(DataHandler.PlayData.curStage);
BigInteger gold = areadata.gold;
gold = gold * (BigInteger)BuffMgr.Instance.GetGoldDropRate() / dConst.RateMax;
BigInteger exp = areadata.exp;
exp = exp * (BigInteger)BuffMgr.Instance.GetExpDropRate() / dConst.RateMax;
Instance.stageSuccessGoodsItem[0].SetGoods(cGoods.TCurrency, cGoods.CGold, gold);
Instance.stageSuccessGoodsItem[1].SetGoods(cGoods.TExp, 0, exp);
while (Instance.dropChestKey.Count != 0)
{
DataHandler.AddBox(Instance.dropChestKey.Pop(), 1);
}
if (DataHandler.GetSysEventTrade().id != 0)
{
DataHandler.GetPlayEventTrade().item += Instance.tradeEventItemCount;//이벤트템 획득
}
if (DataHandler.GetSysEventRaise().id != 0)
{
DataHandler.GetPlayEventRaise().item += Instance.raiseEventItemCount;//이벤트템 획득
}
if (DataHandler.GetSysEventRoulette().id != 0)
{
DataHandler.GetPlayEventRoulette().item += Instance.rouletteEventItemCount;//이벤트템 획득
}
Instance.dropItemPoolCountNow = 0;//2256 번 줄도 수정
for (int i = 0; i < Instance.dropItemCount.Length; i++)
{
Instance.dropItemCount[i] = 0;
}
}
public static void NoReward()
{
for (int i = 0; i < Instance.dropItemPoolCountNow; i++)
{
Instance.dropItemPool[i].HideObject();
}
Instance.dropItemPoolCountNow = 0;
Instance.dropChestKey.Clear();
for (int i = 0; i < Instance.dropItemCount.Length; i++)
{
Instance.dropItemCount[i] = 0;
}
Instance.stageSuccessWindow.SetActive(false);
}
public static void NoRewardRepeatDungeon()
{
for (int i = 0; i < Instance.dropItemPoolCountNow; i++)
{
Instance.dropItemPool[i].HideObject();
}
Instance.dropItemPoolCountNow = 0;
Instance.dropChestKey.Clear();
for (int i = 0; i < Instance.dropItemCount.Length; i++)
{
Instance.dropItemCount[i] = 0;
}
}
#endregion
public void RushToEnemy(float fdt, int from=0)
{
if (from == 0)
ivChar.FrontToTarget(fdt);
else
ivCharEnemy.FrontToTarget(fdt);
}
public void RushToDir(int dir, float fdt, bool bfright)
{
ivChar.MoveToRush(dir, fdt, bfright);
}
#region Damage
/// <summary>
/// 특정 개체에게 데미지
/// </summary>
public void SendDamage(CreatureBase creature, BigInteger biatk, float fcrtdam, int icrtrate)
{
if (creature.IsBattleAvail())
{
creature.GetDamage(biatk, fcrtdam, icrtrate);
}
}
// 아군에게 데미지.
public void DamageToFriendly(BigInteger biatk, float fcrtdam, int icrtrate)
{
if (!ivChar.IsBattleAvail()) return;
ivChar.GetDamage(biatk, fcrtdam, icrtrate);
}
/// <summary>
/// Bonuds에 포함에 포함되면 데미지를 입는다.
/// </summary>
public void DamageToFriendly(Bounds bounds, BigInteger biatk, float fcrtdam, int icrtrate, int idamcnt = -1)
{
if (!ivChar.IsBattleAvail())
return;
if (!bounds.Contains(trfChar.position))
return;
if (ivChar.GetIsDamaged() == idamcnt)
return;
ivChar.GetDamage(biatk, fcrtdam, icrtrate);
}
/// <summary>
/// Bonuds에 포함되고 fdistance 거리 안에 있으면 데미지를 입는다.
/// </summary>
/// <param name="fdistance">player와 bounds 사이의 최대 거리</param>
public void DamageToFreiendlyDt(Bounds bounds, BigInteger biatk, float fcrtdam, int icrtrate, int idamcnt = -1, float fdistance = 0)
{
if (!ivChar.IsBattleAvail())
return;
if (!bounds.Contains(trfChar.position))
return;
if (ivChar.GetIsDamaged() == idamcnt)
return;
if (SCalcDistance(bounds.center, ivChar.transform.position) < fdistance)
return;
ivChar.GetDamage(biatk, fcrtdam, icrtrate);
}
// 전체 적에게 데미지.
public void DamageToEnemyAll(BigInteger biatk, float fcrtdam, int icrtrate)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (ivCharEnemy.IsBattleAvail())
ivCharEnemy.GetDamage(biatk, fcrtdam, icrtrate);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
ivMonsters[i].GetDamage(biatk, fcrtdam, icrtrate);
}
}
// 적에게 데미지.
public void DamageToEnemy(int index, BigInteger biatk, float fcrtdam, int icrtrate, float shake = 0f, int ivibrato = 10, int idnum = -1)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (ivCharEnemy.IsBattleAvail())
ivCharEnemy.GetDamage(biatk, fcrtdam, icrtrate);
return;
}
if (index < 0 || index >= I_ObjMonCnt)
return;
if (!ivMonsters[index].IsBattleAvail())
return;
ivMonsters[index].GetDamage(biatk, fcrtdam, icrtrate);
IVCameraController.SShakeCamera(0.1f, shake, ivibrato);
}
// 일정 범위 내 적에게 데미지.
public void DamageToEnemy(Bounds bounds, BigInteger biatk, float fcrtdam, int icrtrate,int idnum, int idamcnt = -1, float shake = 0, int ivibrato = 10, Action hitEffect=null)
{
int attackCnt = 0;
if (CurrentBattleType == BattleType.Pvp)
{
if (!ivCharEnemy.IsBattleAvail())
return;
if (!bounds.Contains(trfCharEnemy.position))
return;
if (ivCharEnemy.GetIsDamaged() == idamcnt)
return;
ivCharEnemy.GetDamage(biatk, fcrtdam, icrtrate);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
if (!bounds.Contains(trfMonsters[i].position))
continue;
if (ivMonsters[i].GetIsDamaged() == idamcnt)
continue;
ivMonsters[i].GetDamage(biatk, fcrtdam, icrtrate, idnum);
if (hitEffect != null)
hitEffect();
attackCnt++;
if (idamcnt > -1)
ivMonsters[i].SetIsDamaged(idamcnt);
}
if (attackCnt > 0)
IVCameraController.SShakeCamera(0.2f, shake, ivibrato);
}
// 일정 범위 내 가장 가까운 적에게 데미지
public void DamageToEnemyTarget(Bounds bounds, BigInteger biatk, float fcrtdam, int icrtrate, float shake = 0f, int ivibrato = 10)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (!ivCharEnemy.IsBattleAvail())
return;
if (!bounds.Contains(trfCharEnemy.position))
return;
ivCharEnemy.GetDamage(biatk, fcrtdam, icrtrate);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
if (!bounds.Contains(trfMonsters[i].position))
continue;
ivMonsters[i].GetDamage(biatk, fcrtdam, icrtrate);
IVCameraController.SShakeCamera(0.2f, shake, ivibrato);
return;
}
}
// 일정 범위 내 가장 가까운 적들에게 데미지
public void DamageToEnemyTargets(Bounds bounds, int baseTarget, int icount, BigInteger biatk, float fcrtdam, int icrtrate, float shake = 0f, int ivibrato = 10)
{
int icnt = 0;
if (CurrentBattleType == BattleType.Pvp)
{
if (!ivCharEnemy.IsBattleAvail())
return;
if (!bounds.Contains(trfCharEnemy.position))
return;
ivCharEnemy.GetDamage(biatk, fcrtdam, icrtrate);
return;
}
IVCameraController.SShakeCamera(0.2f, shake, ivibrato);
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (icnt == icount)
return;
if (!ivMonsters[i].IsBattleAvail())
continue;
if (bounds.Contains(trfMonsters[i].position))
{
ivMonsters[i].GetDamage(biatk, fcrtdam, icrtrate);
icnt++;
SSetNormalDamage(biatk);
}
}
if(icnt == 0)
{
if (!ivMonsters[baseTarget].IsBattleAvail())
return;
ivMonsters[baseTarget].GetDamage(biatk, fcrtdam, icrtrate);
}
}
public void DamageToEnemyDt(Bounds bounds, BigInteger biatk, float fcrtdam, int icrtrate, int idnum, int idamcnt = -1, float shake = 0, int ivibrato = 10, float fdistance=0, Action hitEffect = null)
{
int attackCnt = 0;
if (CurrentBattleType == BattleType.Pvp)
{
if (!ivCharEnemy.IsBattleAvail())
return;
if (!bounds.Contains(trfCharEnemy.position))
return;
if (ivCharEnemy.GetIsDamaged() == idamcnt)
return;
if (SCalcDistance(bounds.center, ivCharEnemy.transform.position) < fdistance)
return;
ivCharEnemy.GetDamage(biatk, fcrtdam, icrtrate);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
if (!bounds.Contains(trfMonsters[i].position))
continue;
if (ivMonsters[i].GetIsDamaged() == idamcnt)
continue;
if (SCalcDistance(bounds.center, ivMonsters[i].transform.position) < fdistance)
continue;
ivMonsters[i].GetDamage(biatk, fcrtdam, icrtrate);
if (hitEffect != null)
hitEffect();
attackCnt++;
//SSetTotalDamage(biatk, idnum);
if (idamcnt > -1)
ivMonsters[i].SetIsDamaged(idamcnt);
}
if (attackCnt > 0)
IVCameraController.SShakeCamera(0.2f, shake, ivibrato);
}
// 데미지 숫자 표시.
public void ShowDamage(CreatureBase.eCreatureClass cls, Vector2 v2pos, BigInteger biatkdam, bool bcrt)
{
if (!bOnDamageText)
return;
if (cls == CreatureBase.eCreatureClass.character)
{
// 플레이어 캐릭터.
for (int i = 0; i < I_ObjDamCnt; ++i)
{
if (goCharDmgTxts[i].activeSelf)
continue;
txtCharDmgTxts[i].color = CLR_CharDam;
txtCharDmgTxts[i].fontSize = F_DamNormal;
txtCharDmgTxts[i].text = FormatString.BigIntString1(biatkdam);
v2pos.y += F_AddYCharDam;
Vector2 screenPoint = camMain.WorldToScreenPoint(v2pos);
RectTransformUtility.ScreenPointToLocalPointInRectangle(trfCharDamages, screenPoint, camUI, out Vector2 canvasPos);
trfCharDmgTxts[i].localPosition = canvasPos;
goCharDmgTxts[i].SetActive(true);
dtaCharDmgTxts[i].DORestart(true);
return;
}
}
else
{
// 몬스터 & 적 캐릭터.
for (int i = 0; i < I_ObjDamCnt; i++)
{
if (goDmgTxts[i].activeSelf)
continue;
if (bcrt)
{
txtDmgTxts[i].color = CLR_DamCritical;
txtDmgTxts[i].fontSize = F_DamCritical;
}
else
{
txtDmgTxts[i].color = CLR_DamNormal;
txtDmgTxts[i].fontSize = F_DamNormal;
}
txtDmgTxts[i].text = FormatString.BigIntString1(biatkdam);
switch (cls)
{
case CreatureBase.eCreatureClass.charEnemy:
v2pos.y += F_AddYCharDam;
break;
case CreatureBase.eCreatureClass.elite:
v2pos.y += F_AddYEliteDam;
break;
case CreatureBase.eCreatureClass.boss:
v2pos.y += F_AddYBossDam;
break;
default:
v2pos.y += F_AddYNormalDam;
break;
}
Vector2 screenPoint = camMain.WorldToScreenPoint(v2pos);
RectTransformUtility.ScreenPointToLocalPointInRectangle(trfDamages, screenPoint, camUI, out Vector2 canvasPos);
trfDmgTxts[i].localPosition = canvasPos;
goDmgTxts[i].SetActive(true);
dtaDmgTxts[i].DORestart(true);
return;
}
}
}
#endregion Damage
#region Debuff To Friendly
// 전체 아군에게 둔화.
public void DecMovToFriendlyAll(float ftime, float fvalue)
{
ivChar.SetDecMove(ftime, fvalue);
}
// 아군에게 둔화.
public void DecMovToFriendly(float ftime, float fvalue, int idamCnt = -1)
{
if (ivChar.GetIsDamaged() == idamCnt)
return;
ivChar.SetDecMove(ftime, fvalue);
}
// 일정 범위 내 아군에게 둔화.
public void DecMovToFriendly(Bounds bounds, float ftime, float fvalue, int idamCnt = -1)
{
if (!bounds.Contains(trfChar.position))
return;
if (ivChar.GetIsDamaged() == idamCnt)
return;
//if (SoundMgr.EfcOn)
// asNormalAttack.Play();
ivChar.SetDecMove(ftime, fvalue);
}
// 전체 아군에게 출혈.
public void DamageSecToFriendlyAll(float ftime, BigInteger biatk, float fcrtdam, int icrtrate)
{
ivChar.SetDamageSec(ftime, biatk, fcrtdam, icrtrate);
}
// 아군에게 출혈.
public void DamageSecToFriendly(float ftime, BigInteger biatk, float fcrtdam, int icrtrate)
{
ivChar.SetDamageSec(ftime, biatk, fcrtdam, icrtrate);
}
// 일정 범위 내 아군에게 출혈.
public void DamageSecToFriendly(Bounds bounds, float ftime, BigInteger biatk, float fcrtdam, int icrtrate, int idamCnt)
{
if (!bounds.Contains(trfChar.position))
return;
if (ivChar.GetIsDamaged() == idamCnt)
return;
ivChar.SetDamageSec(ftime, biatk, fcrtdam, icrtrate);
}
// 전체 아군에게 기절.
public void StunToFriendlyAll(float ftime)
{
ivChar.SetStun(ftime);
}
// 아군에게 기절.
public void StunToFriendly(float ftime)
{
if (SoundMgr.EfcOn)
//asNormalAttack.Play();
ivChar.SetStun(ftime);
}
// 일정 범위 내 아군에게 기절.
public void StunToFriendly(Bounds bounds, float ftime)
{
if (!bounds.Contains(trfChar.position))
return;
ivChar.SetStun(ftime);
}
// 전체 아군에게 넉백.
public void PushToFriendlyAll(float fvalue)
{
ivChar.PushFrame(fvalue);
}
// 아군에게 넉백.
public void PushToFriendly(float fvalue, int iDamCnt = -1)
{
if (ivChar.GetIsDamaged() == iDamCnt)
return;
ivChar.PushFrame(fvalue);
}
// 일정 범위 내 아군에게 넉백.
public void PushToFriendly(Bounds bounds, float fvalue, int iDamCnt)
{
if (!bounds.Contains(trfChar.position))
return;
if (ivChar.GetIsDamaged() == iDamCnt)
return;
ivChar.PushFrame(fvalue);
}
// 일정 범위 내 아군 당기기.
public void PullToFriendly(Bounds bounds, BigInteger bivalue, Transform trfpos)
{
if (!bounds.Contains(trfChar.position))
return;
ivChar.SetPull(bivalue, trfpos);
}
#endregion Debuff To Friendly
#region Debuff To Enemy
// 전체 적에게 둔화.
public void DecMovToEnemyAll(float ftime, float fvalue)
{
if (CurrentBattleType == BattleType.Pvp)
{
ivCharEnemy.SetDecMove(ftime, fvalue);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
ivMonsters[i].SetDecMove(ftime, fvalue);
}
}
// 적에게 둔화.
public void DecMovToEnemy(int index, float ftime, float fvalue, int idamCnt = -1)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (ivCharEnemy.GetIsDamaged() == idamCnt)
return;
ivCharEnemy.SetDecMove(ftime, fvalue);
return;
}
if (index < 0 || index >= I_ObjMonCnt)
return;
if (!ivMonsters[index].IsBattleAvail())
return;
if (ivMonsters[index].GetIsDamaged() == idamCnt)
return;
ivMonsters[index].SetDecMove(ftime, fvalue);
}
// 일정 범위 내 적에게 둔화.
public void DecMovToEnemy(Bounds bounds, float ftime, float fvalue, int idamCnt = -1)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (!bounds.Contains(trfCharEnemy.position))
return;
if (ivCharEnemy.GetIsDamaged() == idamCnt)
return;
if (SoundMgr.EfcOn)
//asNormalAttack.Play();
ivCharEnemy.SetDecMove(ftime, fvalue);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
if (!bounds.Contains(trfMonsters[i].position))
continue;
if (ivMonsters[i].GetIsDamaged() == idamCnt)
continue;
if (SoundMgr.EfcOn)
//asNormalAttack.Play();
ivMonsters[i].SetDecMove(ftime, fvalue);
}
}
// 전체 적에게 출혈.
public void DamageSecToEnemyAll(float ftime, BigInteger biatk, float fcrtdam, int icrtrate, int idnum)
{
if (CurrentBattleType == BattleType.Pvp)
{
ivCharEnemy.SetDamageSec(ftime, biatk, fcrtdam, icrtrate, idnum);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
ivMonsters[i].SetDamageSec(ftime, biatk, fcrtdam, icrtrate, idnum);
}
}
// 적에게 출혈.
public void DamageSecToEnemy(int index, float ftime, BigInteger biatk, float fcrtdam, int icrtrate, int idnum)
{
if (CurrentBattleType == BattleType.Pvp)
{
ivCharEnemy.SetDamageSec(ftime, biatk, fcrtdam, icrtrate, idnum);
return;
}
if (index < 0 || index >= I_ObjMonCnt)
return;
if (!ivMonsters[index].IsBattleAvail())
return;
ivMonsters[index].SetDamageSec(ftime, biatk, fcrtdam, icrtrate, idnum);
}
// 일정 범위 내 적에게 출혈.
public void DamageSecToEnemy(Bounds bounds, float ftime, BigInteger biatk, float fcrtdam, int icrtrate, int idamCnt, int idnum)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (!bounds.Contains(trfCharEnemy.position))
return;
if (ivCharEnemy.GetIsDamaged() == idamCnt)
return;
ivCharEnemy.SetDamageSec(ftime, biatk, fcrtdam, icrtrate, idnum);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
if (!bounds.Contains(trfMonsters[i].position))
continue;
if (ivMonsters[i].GetIsDamaged() == idamCnt)
continue;
ivMonsters[i].SetDamageSec(ftime, biatk, fcrtdam, icrtrate, idnum);
}
}
// 전체 적에게 기절.
public void StunToEnemyAll(float ftime)
{
if (CurrentBattleType == BattleType.Pvp)
{
ivCharEnemy.SetStun(ftime);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
ivMonsters[i].SetStun(ftime);
}
}
// 적에게 기절.
public void StunToEnemy(int index, float ftime)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (SoundMgr.EfcOn)
//asNormalAttack.Play();
ivCharEnemy.SetStun(ftime);
return;
}
if (index < 0 || index >= I_ObjMonCnt)
return;
if (!ivMonsters[index].IsBattleAvail())
return;
if (SoundMgr.EfcOn)
//asNormalAttack.Play();
ivMonsters[index].SetStun(ftime);
}
// 일정 범위 내 적에게 기절.
public void StunToEnemy(Bounds bounds, float ftime)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (!bounds.Contains(trfCharEnemy.position))
return;
ivCharEnemy.SetStun(ftime);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
if (!bounds.Contains(trfMonsters[i].position))
continue;
ivMonsters[i].SetStun(ftime);
}
}
// 전체 적에게 넉백.
public void PushToEnemyAll(float fvalue)
{
if (CurrentBattleType == BattleType.GuardianDungeon)
{
return;
}
if (CurrentBattleType == BattleType.Pvp)
{
ivCharEnemy.PushFrame(fvalue);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
ivMonsters[i].PushFrame(fvalue);
}
}
// 적에게 넉백.
public void PushToEnemy(int index, float fvalue, int iDamCnt = -1)
{
if (CurrentBattleType == BattleType.GuardianDungeon)
{
return;
}
if (CurrentBattleType == BattleType.Pvp)
{
if (ivCharEnemy.GetIsDamaged() == iDamCnt)
return;
ivCharEnemy.PushFrame(fvalue);
return;
}
if (index < 0 || index >= I_ObjMonCnt)
return;
if (!ivMonsters[index].IsBattleAvail())
return;
if (ivMonsters[index].GetIsDamaged() == iDamCnt)
return;
ivMonsters[index].PushFrame(fvalue);
}
// 일정 범위 내 적에게 넉백.
public void PushToEnemy(Bounds bounds, float fvalue, int iDamCnt)
{
if (CurrentBattleType == BattleType.GuardianDungeon)
{
return;
}
if (CurrentBattleType == BattleType.Pvp)
{
if (!bounds.Contains(trfCharEnemy.position))
return;
if (ivCharEnemy.GetIsDamaged() == iDamCnt)
return;
ivCharEnemy.PushFrame(fvalue);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
if (!bounds.Contains(trfMonsters[i].position))
continue;
if (ivMonsters[i].GetIsDamaged() == iDamCnt)
continue;
ivMonsters[i].PushFrame(fvalue);
}
}
// 일정 범위 내 적 당기기.
public void PullToEnemy(Bounds bounds,BigInteger bivalue, Transform trfpos)
{
if (CurrentBattleType == BattleType.GuardianDungeon)
{
return;
}
if (CurrentBattleType == BattleType.Pvp)
{
if (!bounds.Contains(trfCharEnemy.position))
return;
ivCharEnemy.SetPull(bivalue, trfpos);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
if (!bounds.Contains(trfMonsters[i].position))
continue;
ivMonsters[i].SetPull(bivalue, trfpos);
}
}
#endregion Debuff To Enemy
#region Heal
public static void EnhanceHeal(int hpCalc)
{
float healPerHP = (hpCalc / (float)BuffMgr.Instance.GetCharHp()) * dConst.RateMaxFloat;
Instance.HealToFriendly(healPerHP);
}
public void HealToFriendly(float frate)
{
if (!ivChar.IsBattleAvail())
return;
ivChar.GetHeal(frate);
}
// 아군 회복.
public void HealToFriendly(Bounds bounds, float frate)
{
if (!ivChar.IsBattleAvail())
return;
if (!bounds.Contains(trfChar.position))
return;
ivChar.GetHeal(frate);
}
// 전체 적 회복.
public void HealToEnemyAll(float frate)
{
if (CurrentBattleType == BattleType.Pvp)
{
ivCharEnemy.GetHeal(frate);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
ivMonsters[i].GetHeal(frate);
}
}
// 적 회복.
public void HealToEnemy(int index, float frate)
{
if (CurrentBattleType == BattleType.Pvp)
{
ivCharEnemy.GetHeal(frate);
return;
}
if (index < 0 || index >= I_ObjMonCnt)
return;
if (!ivMonsters[index].IsBattleAvail())
return;
ivMonsters[index].GetHeal(frate);
}
// 일정 범위 내 적 회복.
public void HealToEnemy(Bounds bounds, float frate)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (!bounds.Contains(trfCharEnemy.position))
return;
ivCharEnemy.GetHeal(frate);
return;
}
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (!ivMonsters[i].IsBattleAvail())
continue;
if (!bounds.Contains(trfMonsters[i].position))
continue;
ivMonsters[i].GetHeal(frate);
}
}
#endregion Heal
#region Target & Position
/// <summary>
/// loop all creatures in battle. if func return false, stop loop.
/// </summary>
public static void LoopAllCreatures(Func<CreatureBase, bool> func)
{
if(Instance.ivChar.IsBattleAvail() && !func(Instance.ivChar)) return;
if (CurrentBattleType == BattleType.Pvp && Instance.ivCharEnemy.IsBattleAvail() && !func(Instance.ivCharEnemy)) return;
for (int i = 0; i < Instance.ivMonsters.Length; ++i)
{
if (Instance.ivMonsters[i].IsBattleAvail() && !func(Instance.ivMonsters[i])) return;
}
}
// 타겟 트랜스폼 인덱스로 가져오기.
public Transform GetTrfTarget(bool bfriend, int index)
{
if (bfriend)
{
if (CurrentBattleType == BattleType.Pvp)
{
return trfCharEnemy;
}
if (index < 0 || index >= I_ObjMonCnt)
return null;
return trfMonsters[index];
}
else
{
return trfChar;
}
}
// 타겟 인덱스로 가져오기.
public CreatureBase GetTarget(bool bfriend, int index)
{
if (bfriend)
{
if (CurrentBattleType == BattleType.Pvp)
{
return ivCharEnemy;
}
if (index < 0 || index >= I_ObjMonCnt)
return null;
return ivMonsters[index];
}
else
{
return ivChar;
}
}
public IVCharacter GetPlayer() => ivChar;
// 타겟 위치 가져오기.
public Vector3 GetTargetPos(bool bfriend, int index)
{
if (bfriend)
{
if (CurrentBattleType == BattleType.Pvp)
{
return trfCharEnemy.position;
}
if (index < 0 || index >= I_ObjMonCnt)
return Vector3.zero;
return trfMonsters[index].position;
}
else
{
return trfChar.position;
}
}
// 영역 내 타겟 하나.
public int GetTargetPosInBounds(bool bfriendly, Bounds bounds)
{
if (bfriendly)
{
if(CurrentBattleType == BattleType.Pvp)
{
int itarget = -1;
if (ivChar.IsBattleAvail())
{
if (bounds.Contains(trfChar.position))
{
itarget = 0;
}
}
return itarget;
}
else
{
int itarget = -1;
float fdist = 99999f;
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (ivMonsters[i].IsBattleAvail())
{
float fdtemp = SCalcDistance(trfChar.position, trfMonsters[i].position);
if (bounds.Contains(trfMonsters[i].position) && fdtemp < fdist)
{
fdist = fdtemp;
itarget = i;
}
}
}
return itarget;
}
}
else
{
if (CurrentBattleType == BattleType.Pvp)
{
if (!ivCharEnemy.IsBattleAvail())
return -1;
if (bounds.Contains(trfCharEnemy.position))
return 0;
}
int itarget = -1;
float fdist = 99999f;
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (ivMonsters[i].IsBattleAvail())
{
float fdtemp = SCalcDistance(trfChar.position, trfMonsters[i].position);
if (bounds.Contains(trfMonsters[i].position) && fdtemp < fdist)
{
fdist = fdtemp;
itarget = i;
}
}
}
return itarget;
}
}
// 타겟 위치 인덱스로 가져오기.
public Vector3[] GetFriendlyPoses()
{
return new Vector3[] { trfChar.position };
}
// 제일 가까운 타겟 인덱스.
public int GetTargetIndex(bool bfriendly, Transform trf = null)
{
if (bfriendly)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (ivCharEnemy.IsBattleAvail())
return 0;
return -1;
}
int itarget = -1;
float fdist = 99999f;
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (ivMonsters[i].IsBattleAvail())
{
if(trf == null)
{
float fdtemp = SCalcDistance(trfChar.position, trfMonsters[i].position);
if (fdtemp < fdist)
{
fdist = fdtemp;
itarget = i;
}
}
else
{
float fdtemp = SCalcDistance(trf.position, trfMonsters[i].position);
if (fdtemp < fdist)
{
fdist = fdtemp;
itarget = i;
}
}
}
}
return itarget;
}
else
{
if (ivChar.IsBattleAvail())
return 0;
return -1;
}
}
// 제일 가까운 타겟 인덱스(현재 타겟 제외).
public int GetTargetIndexExcept(bool bfriendly, int icurtarget)
{
if (bfriendly)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (icurtarget == 0)
return -1;
if (ivCharEnemy.IsBattleAvail())
return 0;
return -1;
}
int itarget = -1;
float fdist = 99999f;
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (i == icurtarget)
continue;
if (ivMonsters[i].IsBattleAvail())
{
float fdtemp = SCalcDistance(trfChar.position, trfMonsters[i].position);
if (fdtemp < fdist)
{
fdist = fdtemp;
itarget = i;
}
}
}
return itarget;
}
else
{
if (icurtarget == 0)
return -1;
if (ivChar.IsBattleAvail())
return 0;
return -1;
}
}
public int GetTargetIndexExceptObj(Vector3 objPos, bool bfriendly, int icurtarget)
{
if (bfriendly)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (icurtarget == 0)
return -1;
if (ivCharEnemy.IsBattleAvail())
return 0;
return -1;
}
int itarget = -1;
float fdist = 99999f;
for (int i = 0; i < I_ObjMonCnt; i++)
{
if (i == icurtarget)
continue;
if (ivMonsters[i].IsBattleAvail())
{
float fdtemp = SCalcDistance(objPos, trfMonsters[i].position);
if (fdtemp < fdist)
{
fdist = fdtemp;
itarget = i;
}
}
}
return itarget;
}
else
{
if (icurtarget == 0)
return -1;
if (ivChar.IsBattleAvail())
return 0;
return -1;
}
}
// 제일 가까운 아군들 인덱스.
public int[] GetFriendlyIndexes(int icount, int ibasetarget)
{
int[] itargets = new int[icount];
for (int i = 1; i < icount; i++)
{
itargets[i] = -1;
}
itargets[0] = ibasetarget;
if (ivChar.IsBattleAvail())
itargets[0] = 0;
return itargets;
}
// 타겟 위치 인덱스로 가져오기.
public Vector3[] GetEnemyPoses(int[] indexes)
{
if(indexes == null || indexes.Length == 0) return new Vector3[0];
Vector3[] results = new Vector3[indexes.Length];
if (CurrentBattleType == BattleType.Pvp)
{
results[0] = trfCharEnemy.position;
return results;
}
for (int i = 0; i < indexes.Length; i++)
{
if (indexes[i] >= 0 && indexes[i] < I_ObjMonCnt)
results[i] = trfMonsters[indexes[i]].position;
else
results[i] = Vector3.zero;
}
return results;
}
// 제일 가까운 적들 인덱스.
public int[] GetEnemyIndexes(int count, int pivotEnemyIdx)
{
if(count < 1 || pivotEnemyIdx < 0 || pivotEnemyIdx >= I_ObjMonCnt) return new int[0];
int[] targets = new int[count];
float[] dists = new float[count];
targets[0] = pivotEnemyIdx;
dists[0] = Vector2.SqrMagnitude(trfChar.position - trfMonsters[pivotEnemyIdx].position);
for (int i = 1; i < count; ++i)
{
targets[i] = -1;
dists[i] = float.MaxValue;
}
if (CurrentBattleType == BattleType.Pvp)
{
if (ivCharEnemy.IsBattleAvail()) targets[0] = 0;
}
else
{
for (int i = 0; i < I_ObjMonCnt; ++i)
{
if (!ivMonsters[i].IsBattleAvail()) continue;
float fdtemp = Vector2.SqrMagnitude(trfChar.position - trfMonsters[i].position); // 거리 저장
int indextemp = i; // 거리 저장한 id 저장
for (int j = 1; j < count; ++j)
{
if (fdtemp < dists[j] && fdtemp > dists[j - 1]) // 바뀌지 않았고, 측정한 거리가 설정된 거리보다 짧고 이전 거리보다 크면
{
targets[j] = indextemp;
dists[j] = fdtemp;
}
}
}
}
return targets;
}
#endregion Target & Position
#region Calc.
// 거리 계산. z축은 무시하고 x, y축만 사용.
public static float SCalcDistance(Vector3 v3pos1, Vector3 v3pos2)
{
v3pos1.z = 0f;
v3pos2.z = 0f;
return Vector3.Distance(v3pos1, v3pos2);
}
// 크리티컬인지 계산.
public static bool SIsCritical(int icrtrate)
{
if (icrtrate <= 0)
return false;
int irate = icrtrate % dConst.RateMax;
if (Random.Range(0, dConst.RateMax) < irate)
{
return true;
}
return false;
}
// 크리티컬 데미지 계산.
public static BigInteger SCalcCrtDam(BigInteger biatk, float fcrtdam, int icrtrate, bool bcrt)
{
#if true // 치명타 확률 오버한만큼 데미지 추가 ???
int icrtmul = icrtrate / dConst.RateMax;
icrtmul = icrtmul < 1 ? 1 : icrtmul;
#else
int icrtmul = 1;
#endif
if (bcrt)
icrtmul++;
BigInteger biLastAtk = biatk * icrtmul;
//@ fcrtdam 현재는 치명타 데미지 증가 스탯을 사용하지 않음. 추후 기획으로 추가되면 적용.
return biLastAtk;
}
#endregion Calc.
#region Effect
// 캐릭터 레벨업 이펙트.
private void PlayPtcLvUp(Vector3 v3worldpos)
{
trfLvUpChar.position = v3worldpos;
ptcLvUpChar.Play();
}
// 골드 드롭 연출.
private void PlayPtcGoldDrop(Vector3 v3worldpos)
{
for (int i = 0; i < ptcGoldDrops.Length; i++)
{
if (ptcGoldDrops[i].isPlaying)
continue;
trfGoldDrops[i].position = v3worldpos;
trfGoldDrops[i].localScale = Global.V3_1;
ptcGoldDrops[i].Play();
return;
}
}
public static bool SGetOnSkillEffect()
{
return Instance.bOnSkillEffect;
}
public static void SSetOnSkillEffect(bool bSkill)
{
Instance.bOnSkillEffect = bSkill;
}
public static bool SGetOnDamageText()
{
return Instance.bOnDamageText;
}
public static void SSetOnDamageText(bool bDamage)
{
Instance.bOnDamageText = bDamage;
}
public void SkillFade(bool bfade, bool bforce=false)
{
if (bfade)
{
iFadeCnt++;
srSkillFade.DOFade(0.6f, 0.5f);
}
else
{
iFadeCnt--;
if(iFadeCnt == 0 || bforce)
{
srSkillFade.DOFade(0f, 0.5f);
iFadeCnt = 0;
}
}
}
public void ResetFade()
{
iFadeCnt = 0;
srSkillFade.color = Color.clear;
}
#endregion Effect
#region Wave & Go/Retry
// 현재 스테이지 웨이브 수 랜덤으로 가져오기.
private int GetWaveTotal()
{
return DataHandler.GetArea(DataHandler.PlayData.curStage).wave;
}
int tradeEventMaxRate = 0;
int tradeEventRandomRate = 0;
int tradeEventItemCount = 0;
int raiseEventMaxRate = 0;
int raiseEventRandomRate = 0;
int raiseEventItemCount = 0;
int rouletteEventMaxRate = 0;
int rouletteEventRandomRate = 0;
int rouletteEventItemCount = 0;
private void GetStageItemAndGetPercent()
{
dArea curArea = DataHandler.GetArea(DataHandler.PlayData.curStage);
for(int i = 0; i < stageSuccessGoodsItem.Length; i++)
{
stageSuccessGoodsItem[i].gameObject.SetActive(false);
}
stageSuccessGoodsItem[0].SetGoods(cGoods.TCurrency, cGoods.CGold, curArea.gold);
stageSuccessGoodsItem[0].gameObject.SetActive(curArea.gold != 0);
stageSuccessGoodsItem[1].SetGoods(cGoods.TExp, 0, curArea.exp);
stageSuccessGoodsItem[1].gameObject.SetActive(curArea.exp != 0);
float fboxrate;
if (curArea.normalBoxCnt > 0 && curArea.normalBox != 0)
{
fboxrate = DataHandler.Const.normalBoxRate * (BuffMgr.Instance.GetChestDropRate() + dConst.RateMax) / dConst.RateMax;
stageSuccessGoodsItem[2].SetGoods(cGoods.TBox, curArea.normalBox, curArea.normalBoxCnt);
stageSuccessGoodsItem[2].gameObject.SetActive(curArea.exp != 0);
if(Random.Range(0, dConst.RateMax) < fboxrate)
{
dropItemCount[(int)DropItemKind.Box]++;
dropChestKey.Push(curArea.normalBox);
stageSuccessGoodsItem[2].gameObject.SetActive(true);
}
else
stageSuccessGoodsItem[2].gameObject.SetActive(false);
}
else
stageSuccessGoodsItem[2].gameObject.SetActive(false);
if (curArea.gearBoxCnt > 0 && curArea.gearBox != 0)
{
fboxrate = DataHandler.Const.gearBoxRate * (BuffMgr.Instance.GetChestDropRate() + dConst.RateMax) / dConst.RateMax;
stageSuccessGoodsItem[3].SetGoods(cGoods.TBox, curArea.gearBox, curArea.gearBoxCnt);
stageSuccessGoodsItem[3].gameObject.SetActive(curArea.exp != 0);
if (Random.Range(0, dConst.RateMax) < fboxrate)
{
dropItemCount[(int)DropItemKind.Box]++;
dropChestKey.Push(curArea.gearBox);
stageSuccessGoodsItem[3].gameObject.SetActive(true);
}
else
stageSuccessGoodsItem[3].gameObject.SetActive(false);
}
else
stageSuccessGoodsItem[3].gameObject.SetActive(false);
if (curArea.accBoxCnt > 0 && curArea.accBox != 0)
{
fboxrate = DataHandler.Const.gearBoxRate * (BuffMgr.Instance.GetChestDropRate() + dConst.RateMax) / dConst.RateMax;
stageSuccessGoodsItem[4].SetGoods(cGoods.TBox, curArea.accBox, curArea.accBoxCnt);
stageSuccessGoodsItem[4].gameObject.SetActive(curArea.exp != 0);
if (Random.Range(0, dConst.RateMax) < fboxrate)
{
dropItemCount[(int)DropItemKind.Box]++;
dropChestKey.Push(curArea.accBox);
stageSuccessGoodsItem[4].gameObject.SetActive(true);
}
else
stageSuccessGoodsItem[4].gameObject.SetActive(false);
}
else
stageSuccessGoodsItem[4].gameObject.SetActive(false);
if (curArea.petBoxCnt > 0 && curArea.petBox != 0)
{
fboxrate = DataHandler.Const.petBoxRate * (BuffMgr.Instance.GetChestDropRate() + dConst.RateMax) / dConst.RateMax;
stageSuccessGoodsItem[5].SetGoods(cGoods.TBox, curArea.petBox, curArea.petBoxCnt);
stageSuccessGoodsItem[5].gameObject.SetActive(curArea.exp != 0);
if (Random.Range(0, dConst.RateMax) < fboxrate)
{
dropItemCount[(int)DropItemKind.Box]++;
dropChestKey.Push(curArea.petBox);
stageSuccessGoodsItem[5].gameObject.SetActive(true);
}
else
stageSuccessGoodsItem[5].gameObject.SetActive(false);
}
else
stageSuccessGoodsItem[5].gameObject.SetActive(false);
if (DataHandler.GetSysEventTrade().id != 0)
{
tradeEventMaxRate = DataHandler.GetEvents()[(int)eEventMoveType.Exchange].scale1;
tradeEventRandomRate = Random.Range(0, IVDataFormat.dConst.RateMax);
if (tradeEventRandomRate < tradeEventMaxRate)//2476 번과 함께 수정 필요
{
tradeEventItemCount = Random.Range(DataHandler.GetEvents()[(int)eEventMoveType.Exchange].scale2, DataHandler.GetEvents()[(int)eEventMoveType.Exchange].scale3);
stageSuccessGoodsItem[6].SetGoods(cGoods.TEventTrade, 1, tradeEventItemCount);
stageSuccessGoodsItem[6].gameObject.SetActive(true);
dropItemCount[(int)DropItemKind.TradeEventCoin] += tradeEventItemCount / Mathf.Max((DataHandler.GetEvents()[(int)eEventMoveType.Exchange].scale3 / 3), 1) + 1;
}
else
{
stageSuccessGoodsItem[6].gameObject.SetActive(false);
}
}
if (DataHandler.GetSysEventRaise().id != 0)
{
raiseEventMaxRate = DataHandler.GetEvents()[(int)eEventMoveType.Raise].scale1;
raiseEventRandomRate = Random.Range(0, IVDataFormat.dConst.RateMax);
if (raiseEventRandomRate < raiseEventMaxRate)//2476 번과 함께 수정 필요
{
raiseEventItemCount = Random.Range(1, DataHandler.GetEvents()[(int)eEventMoveType.Raise].scale2);
stageSuccessGoodsItem[7].SetGoods(cGoods.TEventRaise, 1, raiseEventItemCount);
stageSuccessGoodsItem[7].gameObject.SetActive(true);
dropItemCount[(int)DropItemKind.RaiseEventCoin] = raiseEventItemCount / Mathf.Max((DataHandler.GetEvents()[(int)eEventMoveType.Raise].scale2 / 3), 1) + 1;
}
else
{
stageSuccessGoodsItem[7].gameObject.SetActive(false);
}
}
if (DataHandler.GetSysEventRoulette().id != 0)
{
rouletteEventMaxRate = DataHandler.GetEvents()[(int)eEventMoveType.Roulette].scale1;
rouletteEventRandomRate = Random.Range(0, IVDataFormat.dConst.RateMax);
if (rouletteEventRandomRate < rouletteEventMaxRate)//2476 번과 함께 수정 필요
{
rouletteEventItemCount = Random.Range(1, DataHandler.GetEvents()[(int)eEventMoveType.Roulette].scale2);
stageSuccessGoodsItem[8].SetGoods(cGoods.TEventRoulette, 1, rouletteEventItemCount);
stageSuccessGoodsItem[8].gameObject.SetActive(true);
dropItemCount[(int)DropItemKind.RouletteEventCoin] = rouletteEventItemCount / (Mathf.Max(DataHandler.GetEvents()[(int)eEventMoveType.Roulette].scale2 / 3, 1)) + 1;
}
else
{
stageSuccessGoodsItem[8].gameObject.SetActive(false);
}
}
for (int i = 6; i < stageSuccessGoodsItem.Length; i++)
{
if (stageSuccessGoodsItem[i] == null)
stageSuccessGoodsItem[i].gameObject.SetActive(false);
}
}
private void SetWaveCapsule(int wave)
{
goWaveBossArrow.SetActive(false);
for(int i = 0; i < imgWaveCapsule.Length; i++)
{
imgWaveCapsule[i].color = Color.white;
goWaveCapsuleArrow[i].SetActive(false);
if (i < wave - 1)
{
imgWaveCapsule[i].gameObject.SetActive(true);
}
else
{
imgWaveCapsule[i].gameObject.SetActive(false);
}
if (wave == 1)
{
imgWaveCapsule[0].gameObject.SetActive(true);
}
}
}
// 웨이브 진행시마다 UI 세팅.
private void SetStageAreaWave(int iareastage, int iwave)
{
int iarea = iareastage / 100;
int istage = iareastage % 100;
dArea areadata = DataHandler.GetArea(DataHandler.PlayData.curStage);
biMonAtk = areadata.atk;// + (areadata.atkInc * istage);
biMonHp = areadata.hp;//+ (areadata.hpInc * istage);
fMonSpeedN = new float[areadata.monsterNormal.Length];
fMonSpeedE = new float[areadata.monsterEpic.Length];
fMonSpeedB = new float[areadata.monsterBoss.Length];
iMonGroupN = new int[areadata.monsterNormal.Length];
iMonGroupE = new int[areadata.monsterEpic.Length];
iMonGroupB = new int[areadata.monsterBoss.Length];
for (int i = 0; i< areadata.monsterNormal.Length; i++)
{
fMonSpeedN[i] = DataHandler.GetMonsterSpeed(areadata.monsterNormal[i]);
iMonGroupN[i] = DataHandler.GetMonsterGroup(areadata.monsterNormal[i]);
}
for (int i = 0; i < areadata.monsterEpic.Length; i++)
{
fMonSpeedE[i] = DataHandler.GetMonsterSpeed(areadata.monsterEpic[i]);
iMonGroupE[i] = DataHandler.GetMonsterGroup(areadata.monsterEpic[i]);
}
for (int i = 0; i < areadata.monsterBoss.Length; i++)
{
fMonSpeedB[i] = DataHandler.GetMonsterSpeed(areadata.monsterBoss[i]);
iMonGroupB[i] = DataHandler.GetMonsterGroup(areadata.monsterBoss[i]);
}
txtBattleStage.text = FormatString.StringFormat(FormatString.AreaStageNoWave, iarea, istage.ToString());
imgBattleWave.fillAmount = (iwave - 1) / ((float)iTotalWave - 1);
if (iWave != 1)
{
goWaveCapsuleArrow[iWave - 2].SetActive(false);
}
if (imgBattleWave.fillAmount != 1)
{
SettingBossImage(istage);
imgWaveCapsule[iWave - 1].color = Global.CLR_WaveProgress;
goWaveCapsuleArrow[iWave - 1].SetActive(true);
}
else
{
goWaveBossArrow.SetActive(true);
}
}
private void SetDungeonWave(int level, int iwave)
{
switch (CurrentBattleType)
{
case BattleType.GoldDungeon:
SettingDungeonStat(level, DungeonMgr.DungeonKind.GoldDG);
SettingDungeonClearReward(DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.GoldDG).diffs[level - 1].rewards);
txtBattleStage.text = FormatString.StringFormat(LocalizationText.GetText("gold_dungeon_leftup"), level.ToString());
break;
case BattleType.EnhanceStoneDungeon:
SettingDungeonStat(level, DungeonMgr.DungeonKind.EnhanceStoneDG);
SettingDungeonClearReward(DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.EnhanceStoneDG).diffs[level - 1].rewards);
txtBattleStage.text = FormatString.StringFormat(LocalizationText.GetText("enhance_dungeon_leftup"), level.ToString());
break;
case BattleType.PetDungeon:
SettingDungeonStat(level, DungeonMgr.DungeonKind.PetDG);
SettingDungeonClearReward(DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.PetDG).diffs[level - 1].rewards);
txtBattleStage.text = FormatString.StringFormat(LocalizationText.GetText("pet_dungeon_leftup"), Mathf.Ceil((float)level / 10), (level - (Mathf.Ceil((float)level / 10) - 1) * 10));
break;
case BattleType.AwakenStoneDungeon:
SettingDungeonStat(level, DungeonMgr.DungeonKind.AwakenStoneDG);
SettingDungeonClearReward(DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.AwakenStoneDG).diffs[level - 1].rewards);
txtBattleStage.text = FormatString.StringFormat(LocalizationText.GetText("awaken_stone_dungeon_leftup"), level.ToString());
break;
case BattleType.AwakenDungeon:
SettingDungeonStat(level, DungeonMgr.DungeonKind.AwakenDG);
txtBattleStage.text = FormatString.StringFormat(LocalizationText.GetText("awaken_dungeon_leftup"), level.ToString());
break;
case BattleType.GuardianDungeon:
SettingDungeonStat(level, DungeonMgr.DungeonKind.GuardianDG);
txtBattleStage.text = FormatString.StringFormat(LocalizationText.GetText("guardian_dungeon_leftup"), level.ToString());
break;
case BattleType.RelicDungeon:
SettingDungeonStat(level, DungeonMgr.DungeonKind.relicDG);
SettingDungeonClearReward(DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.relicDG).diffs[level - 1].rewards);
txtBattleStage.text = FormatString.StringFormat(LocalizationText.GetText("relic_dungeon_leftup"), level.ToString());
break;
}
if (iTotalWave == 1)
{
imgBattleWave.fillAmount = 1;
imgWaveCapsule[iWave - 1].color = Global.CLR_WaveProgress;
}
else
{
imgBattleWave.fillAmount = (iwave - 1) / ((float)iTotalWave - 1);
}
if (iWave != 1)
{
goWaveCapsuleArrow[iWave - 2].SetActive(false);
}
if (imgBattleWave.fillAmount != 1)
{
SettingBossImage(0);
imgWaveCapsule[iWave - 1].color = Global.CLR_WaveProgress;
goWaveCapsuleArrow[iWave - 1].SetActive(true);
}
else
{
goWaveBossArrow.SetActive(true);
}
}
public void SettingDungeonStat(int level, DungeonMgr.DungeonKind type)
{
if (type != DungeonMgr.DungeonKind.EnhanceStoneDG)
{
biMonAtk = DataHandler.GetDungeonTypeInfo(type).diffs[level - 1].monAtk;
biMonHp = DataHandler.GetDungeonTypeInfo(type).diffs[level - 1].monHp;
}
else
{
biMonAtk = 0;
biMonHp = DataHandler.GetDungeonTypeInfo(type).diffs[level - 1].monHp + (DataHandler.GetDungeonTypeInfo(type).diffs[level - 1].hpInc * iWave);
}
switch (type)
{
case DungeonMgr.DungeonKind.GoldDG:
case DungeonMgr.DungeonKind.PetDG:
fMonSpeedE = new float[DataHandler.GetDungeonTypeInfo(type).monsterEpic.Length];
fMonSpeedB = new float[DataHandler.GetDungeonTypeInfo(type).monsterBoss.Length];
iMonGroupE = new int[DataHandler.GetDungeonTypeInfo(type).monsterEpic.Length];
iMonGroupB = new int[DataHandler.GetDungeonTypeInfo(type).monsterBoss.Length];
for (int i = 0; i < DataHandler.GetDungeonTypeInfo(type).monsterEpic.Length; i++)
{
fMonSpeedE[i] = DataHandler.GetMonsterSpeed(DataHandler.GetDungeonTypeInfo(type).monsterEpic[i]);
iMonGroupE[i] = DataHandler.GetMonsterGroup(DataHandler.GetDungeonTypeInfo(type).monsterEpic[i]);
}
for (int i = 0; i < DataHandler.GetDungeonTypeInfo(type).monsterBoss.Length; i++)
{
fMonSpeedB[i] = DataHandler.GetMonsterSpeed(DataHandler.GetDungeonTypeInfo(type).monsterBoss[i]);
iMonGroupB[i] = DataHandler.GetMonsterGroup(DataHandler.GetDungeonTypeInfo(type).monsterBoss[i]);
}
break;
case DungeonMgr.DungeonKind.GuardianDG:
fMonSpeedB[0] = DataHandler.GetMonsterSpeed(DataHandler.GetDungeonTypeInfo(type).monsterNormal[0]);
iMonGroupB[0] = DataHandler.GetMonsterGroup(DataHandler.GetDungeonTypeInfo(type).monsterNormal[0]);
break;
case DungeonMgr.DungeonKind.AwakenStoneDG:
fMonSpeedB[0] = DataHandler.GetMonsterSpeed(DataHandler.GetDungeonTypeInfo(type).monsterNormal[0]);
iMonGroupB[0] = DataHandler.GetMonsterGroup(DataHandler.GetDungeonTypeInfo(type).monsterNormal[0]);
break;
}
fMonSpeedN = new float[DataHandler.GetDungeonTypeInfo(type).monsterNormal.Length];
iMonGroupN = new int[DataHandler.GetDungeonTypeInfo(type).monsterNormal.Length];
for (int i = 0; i < DataHandler.GetDungeonTypeInfo(type).monsterNormal.Length; i++)
{
fMonSpeedN[i] = DataHandler.GetMonsterSpeed(DataHandler.GetDungeonTypeInfo(type).monsterNormal[i]);
iMonGroupN[i] = DataHandler.GetMonsterGroup(DataHandler.GetDungeonTypeInfo(type).monsterNormal[i]);
}
}
public void SettingBossImage(int stage)
{
if (stage == DataHandler.Const.stageMax)
{
imgWaveBoss.sprite = sprBoss;
}
else
{
imgWaveBoss.sprite = sprBossElite;
}
}
// 스테이지 돌파/반복.
public void BtnRetry()
{
bRetry = !bRetry;
SetRetry();
DataHandler.PlayData.stageRepeat = bRetry;
DataHandler.PlayData.Save();
if (bRetry)
{
GameUIMgr.SOpenToast(LocalizationText.GetText("btn_repeat_alarm"));
}
else
{
GameUIMgr.SOpenToast(LocalizationText.GetText("btn_progress_alarm"));
}
}
// 스테이지 돌파/반복 UI 세팅.
private void SetRetry()
{
if (bRetry)
{
imgBattleRetry.sprite = sprBattleRetry;
txtRetry.text = LocalizationText.GetText("all_repeat");
}
else
{
imgBattleRetry.sprite = sprBattleGo;
txtRetry.text = LocalizationText.GetText("all_break");
}
}
// 스테이지 이동.
public static bool SGoToStage(int iarea, int istage)
{
int icurarea = DataHandler.PlayData.curStage / 100;
Instance.bChangeArea = icurarea != iarea;
if (CurrentBattleType != BattleType.Stage)
{
CurrentBattleType = BattleType.Stage;
Instance.bChangeArea = true;
//return false;
}
Instance.BattlePause = true;
DataHandler.GoToStage(iarea, istage);
Instance.AStageMoveSave(false);
if (Instance.seqStartStage.IsPlaying())
Instance.seqStartStage.Pause();
if (Instance.seqDieStage.IsPlaying())
Instance.seqDieStage.Pause();
if (Instance.seqChangeStage.IsPlaying())
Instance.seqChangeStage.Pause();
if (Instance.seqChangeArea.IsPlaying())
Instance.seqChangeArea.Pause();
if (Instance.bChangeArea)
Instance.seqChangeArea.Restart();
else
Instance.seqChangeStage.Restart();
return true;
}
nStageRequest stageData = null;
//스테이지 서버 통신
public static void SStageMoveSave(bool isClear)
{
Instance.AStageMoveSave(isClear);
}
private void AStageMoveSave(bool isClear)
{
stageData = new nStageRequest();
stageData.curStage = DataHandler.PlayData.curStage;
stageData.clearStage = DataHandler.PlayData.clearStage;
stageData.isClear = isClear;
if (isClear)
{
stageData.curStage--;
SvConnectManager.Instance.RequestSvPost(false, 0, IVServerFormat.UrlApi.GetUrl(IVServerFormat.UrlApi.CurrentStageSave), typeof(nStageReturn), AStageMoveSaveSucc, AStageMoveSaveFail, stageData, true);
}
}
private void AStageMoveSaveFail(IVServerFormat.SvError error, object request)
{
stageData = null;
}
bool isUnlockCheck = false;
// 스테이지 갱신 교체 통신 성공.
private void AStageMoveSaveSucc(object result, object request)
{
nStageReturn data = result as nStageReturn;
if (data == null)
{
AStageMoveSaveFail(new IVServerFormat.SvError(IVServerFormat.eErrorCode.NULL_OR_EMPTY), request);
return;
}
isUnlockCheck = true;
stageData = null;
DataHandler.PlayData.Save();
//CoverCamera.Release();
}
#endregion Wave & Go/Retry
#region Pet
public static void SSetPet(int presetindex)
{
for(int i = 0; i < Instance.ivPets.Length; i++)
{
int key = DataHandler.PlayData.petPresets[presetindex][i];
Instance.ivPets[i].SetPet(key);
}
}
public static void SSetPetFront(bool bfriendly, bool bfrontright)
{
if (bfriendly)
{
for(int i = 0; i < Instance.ivPets.Length; i++)
{
Instance.ivPets[i].SetFront(bfrontright);
}
}
else
{
for(int i = 0; i < Instance.ivPetsEnemy.Length; i++)
{
Instance.ivPetsEnemy[i].SetFront(bfrontright);
}
}
}
public static void SChangePetFront(bool bfriendly, bool bfrontright)
{
if (bfriendly)
{
for (int i = 0; i < Instance.ivPets.Length; i++)
{
Instance.ivPets[i].ChangeFront(bfrontright);
}
}
else
{
for (int i = 0; i < Instance.ivPetsEnemy.Length; i++)
{
Instance.ivPetsEnemy[i].ChangeFront(bfrontright);
}
}
}
#endregion Pet
#region Guardian
public static void SinitIVGuardian()
{
Instance.ivGuardian.Init();
}
public static void SSetGuardian()
{
if(DataHandler.GetPlayGuardian(1) != null)
{
int key = DataHandler.GetPlayGuardian(1).lv;
Instance.ivGuardian.SetGuardian(key);
}
}
public static void SSetGuardianFront(bool bfriendly, bool bfrontright)
{
if (bfriendly)
{
Instance.ivGuardian.SetFront(bfrontright);
}
else
{
Instance.ivGuardianEnemy.SetFront(bfrontright);
}
}
public static void SChangeGuardianFront(bool bfriendly, bool bfrontright)
{
if (bfriendly)
{
Instance.ivGuardian.ChangeFront(bfrontright);
}
else
{
Instance.ivGuardianEnemy.ChangeFront(bfrontright);
}
}
#endregion
#region Costume
public static void SSetCharCostume()
{
if (Instance != null)
Instance.SetCharCostume();
}
public void TestCosLog()
{
string strbattle = FormatString.CombineAllString(iCosCloth.ToString(), "/", (tx2dCloth == null ? "null" : tx2dCloth.name));
string straddressable = AddressableMgr.GetCosInfo(iCosCloth);
string strchar = ivChar.GetCosInfo();
GameUIMgr.SOpenPopup1Button(FormatString.CombineAllString(strbattle, FormatString.S_BreakLine, straddressable, FormatString.S_BreakLine, strchar));
}
// 코스튬 세팅.
private void SetCharCostume()
{
int iwp = DataHandler.PlayEquipCostume.weaponId;
if (iwp != iCosWp)
{
I_InitCos++;
int iwpprev = iCosWp;
iCosWp = iwp;
AddressableMgr.LoadWeaponSpine(iCosWp, ALoadWeaponComp);
AddressableMgr.LoadWeaponAdd(iCosWp);
// 전투 화면 내 캐릭터는 2번씩 호출.
AddressableMgr.ReleaseWeaponSpine(iwpprev);
AddressableMgr.ReleaseWeaponSpine(iwpprev);
}
int icloth = DataHandler.PlayEquipCostume.outfitId;
if (icloth != iCosCloth)
{
I_InitCos++;
int iclothprev = iCosCloth;
iCosCloth = icloth;
AddressableMgr.LoadClothSpine(iCosCloth, ALoadClothComp);
AddressableMgr.LoadClothAdd(iCosCloth);
// 전투 화면 내 캐릭터는 2번씩 호출.
AddressableMgr.ReleaseClothSpine(iclothprev);
AddressableMgr.ReleaseClothSpine(iclothprev);
SRefreshCharCloth();
}
}
public static void SRefreshCharCloth()
{
Instance.RefreshCharCloth();
}
// 의상만 다시 세팅.
private void RefreshCharCloth()
{
if (tx2dCloth == null)
{
I_InitCos++;
AddressableMgr.LoadClothSpineSoon(iCosCloth, ALoadClothComp);
}
else
{
ivChar.SetCostume(tx2dCloth);
}
}
public static void SSetEnemyCostume(int iwp, int icloth, int ihair, int itop, int ieye)
{
if (Instance != null)
Instance.SetEnemyCostume(iwp, icloth, ihair, itop, ieye);
}
// 적 캐릭터 코스튬 세팅.
private void SetEnemyCostume(int iwp, int icloth, int ihair, int itop, int ieye)
{
iCosHairEnemy = ihair;
iCosTopEnemy = itop;
iCosEyeEnemy = ieye;
if (iwp != iCosWpEnemy)
{
I_InitCos++;
int iwpprev = iCosWpEnemy;
iCosWpEnemy = iwp;
AddressableMgr.LoadWeaponSpine(iCosWpEnemy, ALoadWeaponEnemyComp);
AddressableMgr.ReleaseWeaponSpine(iwpprev);
}
if (icloth != iCosClothEnemy)
{
I_InitCos++;
int iclothprev = iCosClothEnemy;
iCosClothEnemy = icloth;
AddressableMgr.LoadClothSpine(iCosClothEnemy, ALoadClothEnemyComp);
AddressableMgr.ReleaseClothSpine(iclothprev);
}
}
private void ResetEnemyCostume()
{
AddressableMgr.ReleaseWeaponSpine(iCosWpEnemy);
AddressableMgr.ReleaseClothSpine(iCosClothEnemy);
iCosHairEnemy = -1;
iCosTopEnemy = -1;
iCosEyeEnemy = -1;
iCosWpEnemy = -1;
iCosClothEnemy = -1;
}
private void ALoadClothComp(Texture2D obj)
{
if (obj != null)
{
tx2dCloth = obj;
ivChar.SetCostume(tx2dCloth);
}
I_InitCos--;
}
private void ALoadWeaponComp(Skin obj)
{
ivChar.SetWeapon(obj);
if (tx2dCloth != null)
ivChar.SetCostume(tx2dCloth);
I_InitCos--;
}
private void ALoadClothEnemyComp(Texture2D obj)
{
tx2dClothEnemy = obj;
ivCharEnemy.SetCostume(tx2dClothEnemy);
I_InitCos--;
}
private void ALoadWeaponEnemyComp(Skin obj)
{
ivCharEnemy.SetWeapon(obj);
if (tx2dClothEnemy != null)
ivCharEnemy.SetCostume(tx2dClothEnemy);
I_InitCos--;
}
#endregion Costume
#region Skill
// 모든 스킬 정지.
private void StopAllSkill()
{
foreach (var item in dicIvSkill.Values)
{
item.StopSkill();
}
foreach (var item in dicIvSkillEnemy.Values)
{
item.StopSkill();
}
}
public void UseButtonSkill(int key)
{
if (iSkillIds[key] == -1)
return;
ivChar.AddSkillAvail(iSkillIds[key]);
iUseSkillid = iSkillIds[key];
SoundMgr.PlaySfx(SoundName.BtnPress);
}
public static int GetUseSkillid()
{
return Instance.iUseSkillid;
}
/// <summary>
/// 스킬 사용.
/// </summary>
/// <param name="biatk">시전자의 공격력</param>
public int UseSkill(bool bfriendly, int key, Transform trfuse, int itarget, Transform trftarget, float icrtdam, int icrtrate, BigInteger biatk)
{
// 전투중이 아님.
if (BattlePause) return 0;
int index = GetSkillPresetIndex(bfriendly, key);
// 내가 사용한 스킬.
if (bfriendly)
{
// 사용할 수 없는 스킬.
if (index < 0 || index >= iSkillIds.Length || iSkillIds[index] < 0 || fSkillTicks[index] > 0f || !dicIvSkill.ContainsKey(key))
return -1;
IVSkill ivskill = dicIvSkill[key];
dSkillActive skilldata = DataHandler.GetSkillActive(key);
// NOTE : 플레이어 스킬 데미지 계산.
float fskilldmg = skilldata.atkValue + (skilldata.atkValueInc * (skilldata.level - 1));
fskilldmg *= BuffMgr.Instance.GetSkillDamage() / dConst.RateMaxFloat;
BigInteger biskilldmg = biatk.Multiply(fskilldmg);
if (skilldata.debuffType != eSkillDebuff.None)
{
BigInteger bidebuff = skilldata.debuffValue + (skilldata.debuffValueInc * (skilldata.level - 1));
if (skilldata.debuffType == eSkillDebuff.DamageSec)
bidebuff = biatk * bidebuff / dConst.RateMaxBi;
ivskill.SetDebuff(bidebuff, skilldata.debuffTime);
}
ivskill.StartSkill(bfriendly, icrtdam, icrtrate, biskilldmg / dConst.RateMax, trfuse, trftarget, itarget, ivChar.IsLookRight);
fSkillTicks[index] = fSkillTimes[index];
SetSkillUi(index);
if (Random.Range(0, 5) == 0)
{
iTalkChar = 2; // 스킬.
ShowTalkBox();
}
}
// 적이 사용한 스킬.
else
{
// 사용할 수 없는 스킬.
if (index < 0 || specEnemy.skillPreset[index] < 0 || fSkillEnemyTicks[index] > 0f || !dicIvSkillEnemy.ContainsKey(key))
return -1;
IVSkill ivskill = dicIvSkillEnemy[key];
dSkillActive skilldata = DataHandler.GetSkillActive(key);
// NOTE: 적 스킬 데미지 계산.
float fskilldmg = skilldata.atkValue + (skilldata.atkValueInc * (specEnemy.skillLv[index] - 1));
fskilldmg *= specEnemy.skillDamage / dConst.RateMaxFloat;
BigInteger biskilldmg = biatk.Multiply(fskilldmg);
if (skilldata.debuffType != eSkillDebuff.None)
{
BigInteger bidebuff = skilldata.debuffValue + (skilldata.debuffValueInc * (specEnemy.skillLv[index] - 1));
if (skilldata.debuffType == eSkillDebuff.DamageSec)
bidebuff = biatk * bidebuff / dConst.RateMaxBi;
ivskill.SetDebuff(bidebuff, skilldata.debuffTime);
}
ivskill.StartSkill(bfriendly, icrtdam, icrtrate, biskilldmg / dConst.RateMax, trfuse, trftarget, itarget, ivCharEnemy.IsLookRight);
fSkillEnemyTicks[index] = specEnemy.skillCool[index];
}
return 1;
}
public float GetSkillRange(int id)
{
float result = 0;
if (dicIvSkill.TryGetValue(id, out IVSkill targetSkill))
{
result = targetSkill.GetRange();
}
return result;
}
// 특정 스킬 UI 세팅.
private void SetSkillUi(int index)
{
if (fSkillTicks[index] > 0f)
{
if (!imgSkillCovers[index].gameObject.activeSelf)
{
btnSkills[index].interactable = false;
imgSkillCovers[index].gameObject.SetActive(true);
}
imgSkillCovers[index].fillAmount = fSkillTicks[index] / fSkillTimes[index];
txtSkills[index].text = Mathf.CeilToInt(fSkillTicks[index]).ToString();
}
else
{
if (imgSkillCovers[index].gameObject.activeSelf)
{
btnSkills[index].interactable = !bAutoSkill;
imgSkillCovers[index].gameObject.SetActive(false);
txtSkills[index].text = null;
}
}
}
// 스킬 프리셋 변경.
public void ChangeSkillPreset(int index)
{
if (CurrentBattleType == BattleType.Stage)
{
if (iLoading > 0)
return;
iLoading++;
ivChar.ClearSkillAvail();
if (index >= DataHandler.PlayData.skillPresets.Length)
index = 0;
DataHandler.ChangeSkillPreset(index);
DataHandler.PlayData.Save();
SetSkillPreset();
iLoading--;
}
SoundMgr.PlaySfx(SoundName.BtnPress);
}
// 스킬 프리셋 내용 변경 시 호출.
public static void SResetSkillPreset()
{
if (Instance is null) return;
Instance.ivChar.ClearSkillAvail();
Instance.SetSkillPreset();
}
// 스킬 프리셋 세팅.
private void SetSkillPreset()
{
//현재 선택한 프리셋 버튼만 비활성화
for (int i = 0; i < btnSkillPresets.Length; i++)
btnSkillPresets[i].interactable = DataHandler.PlayData.usePreset != i;
dicSkillIndex.Clear();
for (int i = 0; i < btnSkills.Length; i++)
{
int key = DataHandler.PlayData.skillPresets[DataHandler.PlayData.usePreset][i];
// 빈 스킬 슬롯.
if (key < 0)
{
iSkillIds[i] = -1;
fSkillTimes[i] = 1f;
fSkillTicks[i] = 0f;
goSkillEmptys[i].SetActive(true);
imgSkills[i].gameObject.SetActive(false);
imgSkillBg[i].gameObject.SetActive(false);
imgSkillCovers[i].gameObject.SetActive(false);
txtSkills[i].text = null;
}
// 스킬 있는 슬롯.
else
{
if (!dicSkillIndex.ContainsKey(key))
dicSkillIndex.Add(key, i);
iSkillIds[i] = key;
fSkillTimes[i] = DataHandler.GetSkillCool(key);
fSkillTicks[i] = fSkillTimes[i];
goSkillEmptys[i].SetActive(false);
imgSkills[i].gameObject.SetActive(true);
imgSkillBg[i].gameObject.SetActive(true);
imgSkillCovers[i].gameObject.SetActive(true);
imgSkills[i].sprite = AddressableMgr.GetSkillActiveIconS(key);
imgSkillBg[i].sprite = AddressableMgr.GetGradeIcon(DataHandler.GetSkillRarity(cGoods.TSkillActive, key) + 200);
}
btnSkills[i].interactable = false;
SetSkillUi(i);
}
}
// 적 캐릭터 스킬 프리셋 세팅.
private void SetSkillPresetEnemy()
{
dicSkillEnemyIndex.Clear();
for (int i = 0; i < specEnemy.skillPreset.Length; i++)
{
int key = specEnemy.skillPreset[i];
// 빈 스킬 슬롯.
if (key < 0)
{
fSkillEnemyTicks[i] = 0f;
}
// 스킬 있는 슬롯.
else
{
if (!dicSkillEnemyIndex.ContainsKey(key))
dicSkillEnemyIndex.Add(key, i);
fSkillEnemyTicks[i] = specEnemy.skillCool[i];
}
}
}
public void ResetSkillCooltime()
{
for(int i = 0; i < fSkillTicks.Length; i++)
{
fSkillTicks[i] = 0f;
SetSkillUi(i);
}
}
public void RecalcSkillCool(int skillKey)
{
if (dicSkillIndex.ContainsKey(skillKey))
{
int idx = dicSkillIndex[skillKey];
FValue coolTime = new FValue(DataHandler.GetSkillCool(skillKey));
foreach (var buff in GamePlayBuffMgr.Instance.BuffGroup.GetBuffs(eEffectType.PlayerSkillCoolFix))
{
coolTime.AddModifiers(buff.Value);
}
fSkillTimes[idx] = coolTime.ModifiedValue;
fSkillTicks[idx] = Mathf.Min(fSkillTicks[idx], fSkillTimes[idx]);
SetSkillUi(idx);
}
}
// 스킬 쿨타임 재계산.
public void RecalcAllSkillCool()
{
foreach (var skillKey in dicSkillIndex.Keys)
{
RecalcSkillCool(skillKey);
}
}
// 프리셋에서의 스킬 인덱스 가져오기.
private int GetSkillPresetIndex(bool bfriendly, int key)
{
if (bfriendly)
{
if (dicSkillIndex.ContainsKey(key))
return dicSkillIndex[key];
}
else
{
if (dicSkillEnemyIndex.ContainsKey(key))
return dicSkillEnemyIndex[key];
}
return -1;
}
// 스킬 사거리 가져오기.
public static int SGetSkillRange(int key)
{
if (Instance.dicIvSkill.ContainsKey(key))
return Instance.dicIvSkill[key].GetRange();
return 0;
}
// 스킬을 사용할 때 캐릭터 방향 가져오기
public bool GetIsFront(bool bfriendly) => bfriendly ? ivChar.IsLookRight : ivCharEnemy.IsLookRight;
public void OnOffAuto()
{
if (CurrentBattleType == BattleType.Pvp)
return;
bAutoSkill = !bAutoSkill;
if (bAutoSkill)
{
imgBtnAuto.sprite = sprAuto;
goAuto.SetActive(true);
}
else
{
imgBtnAuto.sprite = sprAutoOff;
goAuto.SetActive(false);
ivChar.ClearSkillAvail();
}
if (bAutoSkill)
{
for(int i = 0; i < iSkillIds.Length; i++)
{
ivChar.AddSkillAvail(iSkillIds[i]);
}
}
SoundMgr.PlaySfx(SoundName.BtnPress);
}
private void OnOffAutoTemp(bool bauto)
{
bAutoSkillPrev = bAutoSkill;
bAutoSkill = bauto;
if (bauto)
{
imgBtnAuto.sprite = sprAuto;
goAuto.SetActive(true);
}
else
{
imgBtnAuto.sprite = sprAutoOff;
goAuto.SetActive(false);
}
if (bauto)
{
for (int i = 0; i < iSkillIds.Length; i++)
{
ivChar.AddSkillAvail(iSkillIds[i]);
}
}
}
private void ResetAuto()
{
if (bAutoSkill != bAutoSkillPrev)
OnOffAuto();
}
public static bool GetAuto()
{
return Instance.bAutoSkill;
}
public static void allDisableSummons(bool bfriendly)
{
if (bfriendly)
{
for (int i = 0; i < Instance.ivsummons.Length; i++)
Instance.ivsummons[i].ForceUnSummon();
}
else
{
for (int i = 0; i < Instance.ivsummonsEnemy.Length; i++)
Instance.ivsummonsEnemy[i].ForceUnSummon();
}
}
#endregion Skill
#region Bg & Light & Talk
// 전투화면 배경 세팅.
private void SetBg(int idx)
{
if (idx == iBgId)
return;
iBgId = idx;
dBg data = DataHandler.GetBg(idx);
lightGlobal.color = new Color(data.globalLight[0] / 255f, data.globalLight[1] / 255f, data.globalLight[2] / 255f, 1f);
lightChar.color = new Color(data.charLight[0] / 255f, data.charLight[1] / 255f, data.charLight[2] / 255f, 1f);
SetBgCol();
Addressables.LoadAssetAsync<Sprite>(FormatString.StringFormat(AddressableMgr.PathBg, data.path)).Completed += ALoadBgComp;
}
private void SetBgCol()
{
if (CurrentBattleType == BattleType.EnhanceStoneDungeon)
{
colBg.size = new Vector3(20.48f * 6f, 6.6f, 1f);
colBg.center = new Vector3(40, -0.5f, 0);
}
else
{
colBg.size = new Vector3(19f, 13f, 1f);
colBg.center = new Vector3(0, -1f, 0);
}
return;
}
public static BoxCollider SGetBgSize()
{
return Instance.colBg;
}
// 전투화면 배경 로드 완료.
private void ALoadBgComp(AsyncOperationHandle<Sprite> obj)
{
srBg.sprite = obj.Result;
if (handleBg.IsValid())
Addressables.Release(handleBg);
srBg.size = new Vector2(20.48f * 11, 20.48f);
handleBg = obj;
}
// 조명 조절.
private IEnumerator LightCharOff()
{
while (lightChar.intensity > 0f)
{
lightChar.intensity -= Time.deltaTime * 2f;
yield return null;
}
lightChar.intensity = 0f;
}
// 조명 조절.
private IEnumerator LightCharOn()
{
while (lightChar.intensity < 1f)
{
lightChar.intensity += Time.deltaTime * 2f;
yield return null;
}
lightChar.intensity = 1f;
}
// 말풍선 표시.
private void ShowTalkBox()
{
if (iTalkChar < 0 || iTalkChar >= iTalkMax)
{
iTalkChar = -1;
return;
}
talkBox.ShowTalkBox(LocalizationText.GetText(FormatString.StringFormat("talkbox{0}", FormatString.TextInt2(iTalkChar))), 2f);
iTalkChar = -1;
}
#endregion Bg & Light & Talk
#region Pvp
public static void SPreparePvp(dPvpSpec specmy, dPvpSpec specenemy)
{
Instance.PreparePvp(specmy, specenemy);
}
private void PreparePvp(dPvpSpec specmy, dPvpSpec specenemy)
{
seqStartStage.Pause();
seqDieStage.Pause();
seqChangeStage.Pause();
seqChangeArea.Pause();
// 배틀 멈춤, 카메라 멈춤.
BattlePause = true;
IVCameraController.SSetTrace(false);
StopAllSkill();
UnsummonMon();
NoReward();
CurrentBattleType = BattleType.Pvp;
OnOffAutoTemp(true);
specEnemy = specenemy;
SetSkillPresetEnemy();
SetSkillPreset();
for (int i = 0; i < fSkillTicks.Length; i++)
{
fSkillTicks[i] = 0f;
fSkillEnemyTicks[i] = 0f;
}
sldPvpMyHp.value = 1f;
sldPvpEnemyHp.value = 1f;
iStageTimeLeft = DataHandler.sysPvp.timeout;
txtPvpTime.text = iStageTimeLeft.ToString();
SetBg(DataHandler.sysPvp.bgId);
IVCameraController.SMoveCamera(Vector3.zero);
///// PVP 펫은 나중에...
//ivPet.SetPet(specmy.petMain);
//ivPetEnemy.SetPet(specenemy.petMain);
//ivPet.Summon();
//ivPetEnemy.Summon();
ivChar.Summon(V3_CharPvp, true);
ivCharEnemy.Summon(V3_CharEnemyPvp, false);
ivChar.SetStatus(specmy.charAtk, specmy.charHp, specmy.criticalPower, specmy.criticalRate, specmy.move, specmy.speed, F_CharRangePvp);
ivCharEnemy.SetStatus(specenemy.charAtk, specenemy.charHp, specenemy.criticalPower, specenemy.criticalRate, specenemy.move, specenemy.speed, F_CharRangePvp);
imgBattleCover.color = Color.black;
imgBattleCover.gameObject.SetActive(true);
imgBattleCover.DOFade(0f, 1f);
SkillFade(false, true);
}
public static void SStartPvp()
{
Instance.StartPvp();
}
private void StartPvp()
{
biBattleDmg = 0L;
biBattleDmgEnemy = 0L;
ivChar.gameObject.SetActive(true);
ivCharEnemy.gameObject.SetActive(true);
imgBattleCover.gameObject.SetActive(false);
BattlePause = false;
}
private void EndPvp()
{
// 배틀 멈춤, 카메라 멈춤.
BattlePause = true;
IVCameraController.SSetTrace(false);
imgBattleCover.gameObject.SetActive(true);
CoverCamera.Hold();
// 결투장 나가기 팝업 닫기.
GameUIMgr.SClosePopup2Button(cGoods.TPvpTicket);
Invoke("EndPvp2", 1f);
SkillFade(false, true);
//ResetFade();
}
private void EndPvp2()
{
imgBattleCover.DOFade(1f, 0.3f);
Invoke("EndPvp3", 0.3f);
int imyhprate = Mathf.RoundToInt(sldPvpMyHp.value * 100f);
int ienemyhprate = Mathf.RoundToInt(sldPvpEnemyHp.value * 100f);
int iresult = imyhprate >= ienemyhprate ? 1 : 2;
PvpMgr.SResultPvp(iresult, imyhprate, ienemyhprate, biBattleDmg, biBattleDmgEnemy);
}
private void EndPvp3()
{
StopAllSkill();
UnsummonMon();
for(int i = 0; i < ivPets.Length; i++)
{
ivPets[i].OffPet();
}
CoverCamera.Release();
}
public static void SExitPvp()
{
Instance.ExitPvp();
}
// 결투장 종료시. 스테이지로 돌아가기.
private void ExitPvp()
{
// 배틀 멈춤, 카메라 멈춤.
BattlePause = true;
IVCameraController.SSetTrace(false);
StopAllSkill();
UnsummonMon();
imgBattleCover.gameObject.SetActive(true);
imgBattleCover.color = Color.black;
//ivPetEnemy.SetPet(-1);
//ivPet.OffPet();
//ivPetEnemy.OffPet();
ResetEnemyCostume();
ivChar.gameObject.SetActive(false);
ivCharEnemy.gameObject.SetActive(false);
specEnemy = null;
CurrentBattleType = BattleType.Stage;
GameUIMgr.SSetActiveHotTime(true);
ResetAuto();
Instance.seqStartStage.Restart();
}
// 결투장 데미지.
public void AddPvpDamage(bool bfirendly, BigInteger bidmg, float flefthp)
{
if (CurrentBattleType != BattleType.Pvp)
return;
// 아군이 데미지를 받았을 때.
if (bfirendly)
{
biBattleDmgEnemy += bidmg;
sldPvpMyHp.value = flefthp;
}
// 적이 데미지를 받았을 때.
else
{
biBattleDmg += bidmg;
sldPvpEnemyHp.value = flefthp;
}
}
#endregion Pvp
#region Test
public static void SSetTotalDamage(BigInteger dam, int id)
{
if (SettingMgr.SGetTest())
{
Instance.TestDps[id - 1] += dam;
activeDps();
if (Instance.timeSec != 0)
Instance.txtTestDpsDam[id - 1].text = FormatString.BigIntString1(Instance.TestDps[id - 1] / (BigInteger)Instance.timeSec);
}
}
public static void SSetNormalDamage(BigInteger dam)
{
if (SettingMgr.SGetTest())
{
Instance.txtNormalAttackDpsDam.transform.parent.gameObject.SetActive(true);
Instance.TestNormalAttackDps += dam;
if (Instance.timeSec != 0)
Instance.txtNormalAttackDpsDam.text = FormatString.BigIntString1(Instance.TestNormalAttackDps / (BigInteger)Instance.timeSec);
}
else
Instance.txtNormalAttackDpsDam.transform.parent.gameObject.SetActive(false);
}
public static void MoveToDir(Vector2 moveVec)
{
if (!doNotInterupt)
{
Instance.ivChar.MoveToDir(moveVec);
}
}
public static void UpdateDpsOneSec()
{
Instance.timeSec++;
}
public static void ResetDps()
{
Instance.timeSec = 0;
for(int i = 0; i< Instance.TestDps.Length; i++)
{
Instance.TestDps[i] = 0L;
}
Instance.TestNormalAttackDps = 0L;
}
public static void SetDpsSkill()
{
ResetDps();
for (int i = 0; i < Instance.TestDps.Length; i++)
{
Instance.txtTestDps[i].text = LocalizationText.GetText(FormatString.CombineAll("active", (i + 1)));
Instance.txtTestDps[i].gameObject.SetActive(false);
}
}
public static void activeDps()
{
for (int i = 0; i < Instance.TestDps.Length; i++)
{
if (Instance.TestDps[i] == 0L)
Instance.txtTestDps[i].gameObject.SetActive(false);
else
Instance.txtTestDps[i].gameObject.SetActive(true);
}
}
public static void SetBattleTypeDungeon(int num)
{
GameUIMgr.SSetActiveHotTime(false);
switch (num)
{
case 0:
CurrentBattleType = BattleType.GoldDungeon;
break;
case 1:
CurrentBattleType = BattleType.EnhanceStoneDungeon;
break;
case 2:
CurrentBattleType = BattleType.PetDungeon;
break;
case 3:
CurrentBattleType = BattleType.AwakenStoneDungeon;
break;
case 4:
CurrentBattleType = BattleType.AwakenDungeon;
break;
case 5:
CurrentBattleType = BattleType.GuardianDungeon;
break;
case 6:
CurrentBattleType = BattleType.RelicDungeon;
break;
}
}
public static void DungeonStart(int dungeonLevel)
{
Instance.BattlePause = true;
Instance.InitDungeonStage(dungeonLevel);
DungeonMgr.OnOffBtnDungeonOut(false);
Instance.seqChangeArea.Pause();
Instance.seqChangeStage.Pause();
Instance.seqDungeonArea.Restart();
}
public static void ChangeBattleTypeNormal()
{
MissionMgr.SRefreshMission();
GameUIMgr.SSetActiveHotTime(true);
CurrentBattleType = BattleType.Stage;
}
#endregion Test
#region Succ & Fail
public static void OpenFailScroll()
{
Instance.canvasStageFail.enabled = true;
Addressables.LoadAssetAsync<SkeletonDataAsset>("effect/game_off/game_off_SkeletonData.asset").Completed += Instance.ALoadExitComp;
}
private AsyncOperationHandle<SkeletonDataAsset> handleSkAnim;
public static void CloseFailScroll()
{
SkeletonAnimation skanim = Instance.canvasStageFail.transform.Find("skanim").GetComponent<SkeletonAnimation>();
// 애니메이션 언로드.
if (skanim.skeletonDataAsset != null)
{
CoverCamera.Hold();
skanim.transform.localScale = new Vector3(0.01f, 0.01f, 0.01f);
skanim.skeletonDataAsset.Clear();
skanim.ClearState();
skanim.skeletonDataAsset = null;
if (Instance.handleSkAnim.IsValid())
Addressables.Release(Instance.handleSkAnim);
AddressableMgr.SAddUnload();
CoverCamera.Release();
}
Instance.canvasStageFail.enabled = false;
}
private void ALoadExitComp(AsyncOperationHandle<SkeletonDataAsset> obj)
{
SkeletonAnimation skanim = canvasStageFail.transform.Find("skanim").GetComponent<SkeletonAnimation>();
MeshRenderer renderer = skanim.GetComponent<MeshRenderer>();
renderer.sortingLayerID = canvasStageFail.sortingLayerID;
renderer.sortingOrder = 16;
skanim.skeletonDataAsset = obj.Result;
skanim.Initialize(true);
skanim.AnimationState.SetAnimation(0, "idle", true);
skanim.transform.localScale = new Vector3(0.8f, 0.8f, 0.8f);
handleSkAnim = obj;
CoverCamera.Release();
}
public static void CloseSuccessWindow()
{
Instance.stageSuccessWindow.SetActive(false);
Instance.awakenSuccessWindow.SetActive(false);
}
#endregion Succ & Fail
#region Dungeon Reward
private void SetDungeonSetting(bool start)
{
if (start)
{
switch (CurrentBattleType)
{
case BattleType.GoldDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.GoldDG).timeOut;
iTotalWave = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.GoldDG).wave;
break;
case BattleType.EnhanceStoneDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.EnhanceStoneDG).timeOut;
iTotalWave = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.EnhanceStoneDG).wave;
break;
case BattleType.PetDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.PetDG).timeOut;
iTotalWave = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.PetDG).wave;
break;
case BattleType.AwakenStoneDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.AwakenStoneDG).timeOut;
iTotalWave = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.AwakenStoneDG).wave;
break;
case BattleType.AwakenDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.AwakenDG).timeOut;
iTotalWave = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.AwakenDG).wave;
break;
case BattleType.GuardianDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.GuardianDG).timeOut;
iTotalWave = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.GuardianDG).wave;
break;
case BattleType.RelicDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.relicDG).timeOut;
iTotalWave = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.relicDG).wave;
break;
}
}
else
{
switch (CurrentBattleType)
{
case BattleType.GoldDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.GoldDG).timeOut;
break;
case BattleType.EnhanceStoneDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.EnhanceStoneDG).timeOut;
break;
case BattleType.PetDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.PetDG).timeOut;
break;
case BattleType.AwakenStoneDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.AwakenStoneDG).timeOut;
break;
case BattleType.AwakenDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.AwakenDG).timeOut;
break;
case BattleType.GuardianDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.GuardianDG).timeOut;
break;
case BattleType.RelicDungeon:
iStageTimeLeft = DataHandler.GetDungeonTypeInfo(DungeonMgr.DungeonKind.relicDG).timeOut;
break;
}
}
}
public static void SettingDungeonClearReward(nReward[] data)
{
for (int i = 0; i < Instance.stageSuccessGoodsItem.Length; i++)
{
Instance.stageSuccessGoodsItem[i].gameObject.SetActive(false);
}
for (int i = 0; i < data.Length; i++)
{
Instance.stageSuccessGoodsItem[i].gameObject.SetActive(true);
Instance.stageSuccessGoodsItem[i].SetGoods(data[i].rewardType, data[i].rewardId, data[i].rewardCount);
if (data[i].rewardCount <= 0)
{
Instance.stageSuccessGoodsItem[i].gameObject.SetActive(false);
}
}
}
public static void GetClearDungeonReward(nReward[] data)
{
nGoods[] plusGoods = new nGoods[data.Length];
for (int i = 0; i < plusGoods.Length; i++)
{
plusGoods[i] = new nGoods();
plusGoods[i].propertyId = data[i].rewardId;
plusGoods[i].propertyType = data[i].rewardType;
plusGoods[i].propertyCount = data[i].rewardCount;
}
DataHandler.AddGoods(plusGoods, DataHandler.Goods, true);
Instance.stageSuccessWindow.SetActive(true);
SoundMgr.PlaySfx(SoundName.GetGoods);
}
public static void GetClearDungeonSkipReward(nReward[] data, int skipCount, float bonus = 1)
{
nGoods[] plusGoods = new nGoods[data.Length];
for (int i = 0; i < plusGoods.Length; i++)
{
plusGoods[i] = new nGoods();
plusGoods[i].propertyId = data[i].rewardId;
plusGoods[i].propertyType = data[i].rewardType;
plusGoods[i].propertyCount = data[i].rewardCount * (int)((bonus+1.0f) * dConst.RateMaxFloat) / dConst.RateMaxBi * skipCount;
}
DataHandler.AddGoods(plusGoods, DataHandler.Goods, true);
}
public static void AwakenSuccessWindowEnable()
{
Instance.awakenSuccessWindow.SetActive(true);
}
public static void SetAwakenRewardNumber(int i)
{
Instance.awakenNumber.text = i.ToString();
}
public void ResetBgScroll()
{
srBg.transform.position = new Vector3(0, 0, 0);
}
#endregion
}