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.
 
 
 
 
 
 

4011 lines
131 KiB

using DG.Tweening;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using IVDataFormat;
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 : MonoSingleton<BattleMgr>
{
public enum TalkType
{
Summon, Attack, Die,
}
#region Const & Values
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 int _talkBoxSummonMaxCount = 2;
private static readonly int _talkBoxAttackMaxCount = 4;
private static readonly int _talkBoxDieMaxCount = 2;
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 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_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;
#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 screenCoverImg;
private HpBar hpBarChar;
private HpBar hpBarCharEnemy;
private RectTransform trfHpBars;
[SerializeField]
private GameObject prfHpEnemy;
private HpBar[] hpBarEnemies;
private RectTransform trfDamages, trfCharDamages;
[SerializeField] DamageIndicatorText prfDmgIndicator;
private DamageIndicatorText[] dmgIndicatorsMon, dmgIndicatorsChar;
private RectTransform trfTxts;
private TalkBox talkBox;
#endregion Battle UI
#region UI Values
private LayerMask layerMask;
#endregion UI Values
#region Battle Scene
[Header("Battle Scene")]
[SerializeField] private SpriteRenderer srBg;
[SerializeField] StringList areaImgPathList;
[SerializeField] ExtendSpriteRenderer backGroundRenderer;
[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;
private HashSet<IBattleEntity> battleEntities = new();
#endregion Battle Scene
#region Battle Sound
[Header("Battle Sound")]
[SerializeField] private AudioSource asSummon;
[SerializeField] private AudioSource asUnsummon;
#endregion Battle Sound
public bool doNotInterupt { get; set; } = false;
#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
private bool battlePause = false;
public bool BattlePause
{
get => battlePause;
set
{
if(battlePause != value)
{
battlePause = value;
}
}
}
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 Texture2D tx2dCloth = null;
private Texture2D tx2dClothEnemy = null;
private int[] iSkillIds;
private float[] fSkillTimes = new float[0];
private float[] fSkillTicks = new float[0];
public bool IsOnAutoSkill { get; private set; }
private bool bAutoSkillPrev = true;
private Dictionary<int, int> dicSkillIndex;
private float[] fSkillEnemyTicks;
private Dictionary<int, int> dicSkillEnemyIndex;
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 seqDieStage = null;
private Sequence seqChangeStage = null;
private Sequence seqChangeArea = null;
private Sequence seqChangeGameMod = null;
private int iFadeCnt = 0;
private bool BgAndCameraChange = false;
private int useSkillid = -1;
public enum BattleType
{
Stage = 0,
Pvp = 9
}
public 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
#region Option Values
[HideInInspector] public bool bOnSkillEffect;
[HideInInspector] public bool bOnDamageText;
#endregion Option Values
[SerializeField] List<GameMod> gameMods;
GameMod currentGameMod;
#region Update
private void Update()
{
if (BattlePause) return;
if (currentGameMod is null)
{
UpdateModTime();
}
UpdateSkill();
}
// 현재 모드 타임 아웃 체크
private void UpdateModTime()
{
fTickSec += Time.deltaTime;
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)
{
ivChar.ChangeState(eState.die);
}
}
}
}
// 자동 스킬 쿨타임 감소 및 자동 사용 체크 시 시전 대기 스택에 넣기
private void UpdateSkill()
{
fTick += Time.deltaTime;
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 (IsOnAutoSkill)
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
#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 void Init(Camera camui)
{
IVCameraController.SSetTrace(false);
camMain = Camera.main;
camUI = camui;
InitObject();
CustomizeMgr.Instance.InitSkin();
iCosWp = DataHandler.PlayEquipCostume.weaponId;
iCosCloth = DataHandler.PlayEquipCostume.outfitId;
ivChar.SetSkin(iCosCloth, iCosWp);
SetEnemyCostume(DataHandler.PlayEquipCostume.weaponId, DataHandler.PlayEquipCostume.outfitId);
iCosClothEnemy = -1;
iCosWpEnemy = -1;
ivChar.gameObject.SetActive(false);
ivCharEnemy.gameObject.SetActive(false);
GamePlayBuffMgr.Instance.OnChanged -= OnChangedBuffList;
GamePlayBuffMgr.Instance.OnChanged += OnChangedBuffList;
}
private void OnChangedBuffList(BuffData buffData, bool added)
{
BuffMgr.Instance.CalcAllStat();
ivChar.RefreshStat();
RecalcAllSkillCool();
}
// 스테이지 초기화. 게임 시작시 전투 시작해도 되는 타이밍에 호출(다른 초기화 완료 후).
public void InitStage()
{
iStageTimeLeft = DataHandler.Const.stageTimeout;
txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft);
iWave = 1;
iTotalWave = GetWaveTotal();
SetWaveCapsule(iTotalWave);
GetStageItemAndGetPercent();
SetStageAreaWave(DataHandler.PlayData.curStage, iWave);
SetRetry();
var seqStartStage = DOTween.Sequence()
.SetUpdate(false)
.AppendCallback(() =>
{
screenCoverImg.color = Color.black;
screenCoverImg.gameObject.SetActive(true);
IVCameraController.SMoveCamera(V3_CharOrigin);
iStageTimeLeft = DataHandler.Const.stageTimeout;
txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft);
iWave = 1;
iTotalWave = GetWaveTotal();
SetWaveCapsule(iTotalWave);
SetBg();
InitMonArea();
SetStageAreaWave(DataHandler.PlayData.curStage, iWave);
})
.Append(screenCoverImg.DOFade(0f, 1f))
.AppendCallback(() =>
{
screenCoverImg.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;
SoundMgr.Instance.PlaySfx(asSummon.clip);
})
.AppendInterval(0.5f)
.AppendCallback(() =>
{
ShowTalkBox(TalkType.Summon);
SummonMonStage();
IVCameraController.SSetTrace(true);
BattlePause = false;
for (int i = 0; i < ivPets.Length; i++)
{
ivPets[i].Summon();
}
ivGuardian.Summon();
})
.Play();
}
// 전투 오브젝트 초기화. 클래스 초기화(SInit)에서 호출.
private void InitObject()
{
layerMask = LayerMask.GetMask("BG", "Character", "Effect");
#region Char
trfChar = ivChar.transform;
IVCameraController.SSetTarget(trfChar);
Transform trfbattleui = canvasUI.transform;
screenCoverImg = 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.SetHpbar(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.SetHpbar(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].SetHpbar(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 (IsOnAutoSkill)
{
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
dmgIndicatorsChar = new DamageIndicatorText[I_ObjDamCnt];
dmgIndicatorsMon = new DamageIndicatorText[I_ObjDamCnt];
for (int i = 0; i < I_ObjDamCnt; i++)
{
var charDmgIndicator = Instantiate(prfDmgIndicator, trfCharDamages);
var monDmgIndicator = Instantiate(prfDmgIndicator, trfDamages);
charDmgIndicator.name = FormatString.CombineAllString("txtdam", i.ToString());
monDmgIndicator.name = FormatString.CombineAllString("txtdam", i.ToString());
dmgIndicatorsChar[i] = charDmgIndicator;
dmgIndicatorsMon[i] = monDmgIndicator;
charDmgIndicator.Hide();
monDmgIndicator.Hide();
}
#endregion Txts
#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();
SoundMgr.Instance.PlaySfx(asUnsummon.clip);
ivChar.Unsummon();
allDisableSummons(true);
SetPetsSummonState(false);
SetGudiansSummonState(false);
MateMgr.Instance.ActiveMate?.Dispose();
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);
MateMgr.Instance.ActiveMate?.Spawn(ivChar, ivChar.LookDirection);
StartCoroutine(nameof(LightCharOn));
StageMgr.SRefreshStage();
SoundMgr.Instance.PlayBgm(BGM.stage);
SkillFade(false, true);
})
.AppendInterval(0.3f)
.AppendCallback(() =>
{
SoundMgr.Instance.PlaySfx(asSummon.clip);
})
.AppendInterval(0.5f)
.AppendCallback(() =>
{
ShowTalkBox(TalkType.Summon);
SummonMonStage();
IVCameraController.SSetTrace(true);
BattlePause = false;
SetCharCostume();
SetPetsSummonState(true);
SetGudiansSummonState(true);
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();
SoundMgr.Instance.PlaySfx(asUnsummon.clip);
ivChar.Unsummon();
allDisableSummons(true);
SetPetsSummonState(false);
SetGudiansSummonState(false);
MateMgr.Instance.ActiveMate?.Dispose();
StartCoroutine(nameof(LightCharOff));
})
.AppendInterval(1.2f)
.AppendCallback(() =>
{
screenCoverImg.gameObject.SetActive(true);
CloseSuccessWindow();
})
.Append(screenCoverImg.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();
InitMonArea();
SetStageAreaWave(DataHandler.PlayData.curStage, iWave);
StageMgr.SRefreshStage();
SoundMgr.Instance.PlayBgm(BGM.stage);
SkillFade(false, true);
})
.AppendInterval(0.2f)
.Append(screenCoverImg.DOFade(0f, 0.5f))
.AppendCallback(() =>
{
AddressableMgr.SForceUnload();
screenCoverImg.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();
MateMgr.Instance.ActiveMate?.Spawn(ivChar, ivChar.LookDirection);
StartCoroutine(nameof(LightCharOn));
})
.AppendInterval(0.3f)//캐릭터를 소환할때 애니메이션상으로 소환이 안 되는데, 이 타이밍에 옷을 갈아끼우고 애니메이션이 나오도록 함.
.AppendCallback(() =>
{
SoundMgr.Instance.PlaySfx(asSummon.clip);
})
.AppendInterval(0.5f)
.AppendCallback(() =>
{
ShowTalkBox(TalkType.Summon);
SummonMonStage();
SetPetsSummonState(true);
SetGudiansSummonState(true);
IVCameraController.SSetTrace(true);
BattlePause = false;
doNotInterupt = false;
})
.Pause();
#endregion On Area Change
#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(() =>
{
MateMgr.Instance.ActiveMate?.Dispose();
screenCoverImg.gameObject.SetActive(true);
})
.Append(screenCoverImg.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();
SetBg();
if (bChangeArea)
{
InitMonArea();
}
SetStageAreaWave(DataHandler.PlayData.curStage, iWave);
StageMgr.SRefreshStage();
SoundMgr.Instance.PlayBgm(BGM.stage);
SkillFade(false, true);
})
.Append(screenCoverImg.DOFade(0f, 0.5f))
.AppendInterval(2.5f)
.AppendCallback(() =>
{
CloseFailScroll();
if (bChangeArea)
{
AddressableMgr.SForceUnload();
}
screenCoverImg.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);
StartCoroutine(nameof(LightCharOn));
})
.AppendInterval(0.3f)//캐릭터를 소환할때 애니메이션상으로 소환이 안 되는데, 이 타이밍에 옷을 갈아끼우고 애니메이션이 나오도록 함.
.AppendCallback(() =>
{
ivChar.Summon();
MateMgr.Instance.ActiveMate?.Spawn(ivChar, ivChar.LookDirection);
SoundMgr.Instance.PlaySfx(asSummon.clip);
})
.AppendInterval(0.5f)
.AppendCallback(() =>
{
ShowTalkBox(TalkType.Die);
SummonMonStage();
IVCameraController.SSetTrace(true);
BattlePause = false;
SetCharCostume();
SetPetsSummonState(true);
SetGudiansSummonState(true);
doNotInterupt = false;
})
.Pause();
#endregion On Die Stage
#region On GameMod Start
seqChangeGameMod = DOTween.Sequence()//던전 진입시 실행
.SetAutoKill(false)
.SetUpdate(false)
.AppendCallback(() =>
{
doNotInterupt = true;
// 배틀 멈춤, 카메라 멈춤.
BattlePause = true;
IVCameraController.SSetTrace(false);
bClear = false;
})
.AppendInterval(0.8f)
.AppendCallback(() =>
{
// 소환 해제.
UnsummonMon();
SoundMgr.Instance.PlaySfx(asUnsummon.clip);
StopAllSkill();
ivChar.Unsummon();
MateMgr.Instance.ActiveMate?.Dispose();
allDisableSummons(true);
SetPetsSummonState(false);
SetGudiansSummonState(false);
})
.AppendInterval(0.8f)
.AppendCallback(() =>
{
screenCoverImg.gameObject.SetActive(true);
CloseSuccessWindow();
})
.Append(screenCoverImg.DOFade(1f, 0.5f))
.AppendCallback(() =>
{
if (currentGameMod != null)
{
currentGameMod.StartMod();
}
else
{
if (BgAndCameraChange)
{
ResetBgScroll();
IVCameraController.CameraXRangeChange(25);
BgAndCameraChange = false;
}
// 캐릭터 위치 랜덤.
var 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);
//현재 적과 제한시간과 배경 등등을 설정
txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft);
iWave = 1;
SkillFade(false, true);
}
})
.AppendInterval(0.2f)
.Append(screenCoverImg.DOFade(0f, 0.5f))
.AppendCallback(() =>
{
screenCoverImg.gameObject.SetActive(false);
if (currentGameMod is null)
{
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(() =>
{
if (currentGameMod is null)
{
SoundMgr.Instance.PlaySfx(asSummon.clip);
}
})
.AppendInterval(0.5f)
.AppendCallback(() =>
{
if (currentGameMod is null)
{
ShowTalkBox(TalkType.Summon);
SetPetsSummonState(true);
SetGudiansSummonState(true);
}
IVCameraController.SSetTrace(true);
BattlePause = false;
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 void SetCameraOn(bool bvalue)
{
if (bvalue)
camMain.cullingMask |= layerMask;
else
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;
}
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
public void SetPetsSummonState(bool summoned)
{
for (int i = 0; i < ivPets.Length; i++)
{
if(summoned)
ivPets[i].Summon();
else
ivPets[i].Unsummon();
}
}
public void SetGudiansSummonState(bool summoned)
{
if(summoned)
ivGuardian.Summon();
else
ivGuardian.Unsummon();
}
// 모든 적 소환 해제.
public 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();
}
}
UnregistBattleEntities(ivMonsters);
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;
}
// 일반 몬스터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;
}
// 각 웨이브 시작시에 몬스터 소환.
private void SummonMonStage()
{
// 소환할 몬스터 수.
int itotalcount = I_SummonMax;
int ielitecount = 0;
int ibosscount = 0;
if (iWave == iTotalWave)
{
if (DataHandler.PlayData.curStage % DataHandler.Const.stageMax == 0)
ibosscount = 1;
else
ielitecount = I_SummonEliteMin;
bossIncoming.gameObject.SetActive(true);
bossIncoming.AnimationState.SetAnimation(0, "animation", false);
//bossIncoming.DOPlay();
SoundMgr.Instance.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 (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;
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;
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;
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;
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;
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;
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.z = v3pos.y * 0.1f;
var monster = ivMonsters[index];
if (iWave == iTotalWave)
{
if(monster.GetCreatureClass() == eCreatureClass.elite)
{
monster.ResetDebuff();
monster.SetStatus(biatk, fhp, dConst.RateMaxFloat, 0, dConst.RateMaxFloat * 0.1f * fspeed, dConst.RateMax, frange, igroup: igroup);
hpBarEnemies[i].ReSetoffsetY(monster.GetMonType());
monster.Summon(v3pos, trfChar.position.x > v3pos.x);
iMonsterCount++;
}
if (monster.GetCreatureClass() == eCreatureClass.boss)
{
monster.ResetDebuff();
monster.SetStatus(biatk, fhp, dConst.RateMaxFloat, 0, dConst.RateMaxFloat * 0.1f * fspeed, dConst.RateMax, frange, igroup: igroup);
hpBarEnemies[i].ReSetoffsetY(monster.GetMonType());
monster.Summon(v3pos, trfChar.position.x > v3pos.x);
iMonsterCount++;
}
}
else
{
monster.ResetDebuff();
monster.SetStatus(biatk, fhp, dConst.RateMaxFloat, 0, dConst.RateMaxFloat * 0.1f * fspeed, dConst.RateMax, frange, igroup: igroup);
hpBarEnemies[i].ReSetoffsetY(monster.GetMonType());
monster.Summon(v3pos, trfChar.position.x > v3pos.x);
iMonsterCount++;
}
RegistBattleEntities(monster);
if (indexlist.Count == 0)
break;
}
}
// 몬스터 종류별로 소환 가능한 인덱스 가져오기.
private int GetAvailMonsterIndex(eCreatureClass cls, int itype)
{
switch (cls)
{
case 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 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 eCreatureClass.boss:
return (I_MonTypeNormal * I_SummonMax) + (I_MonTypeElite * I_SummonEliteMax);
}
return -1;
}
#endregion Summon
#region Die & Fail
// 아군 사망시 처리.
public void DieFriendly()
{
if (currentGameMod != null) return;
ShowTalkBox(TalkType.Die);
int area = DataHandler.PlayData.curStage / 100;
int stage = DataHandler.PlayData.curStage % 100;
if (CurrentBattleType != BattleType.Stage)
bChangeArea = true;
else
bChangeArea = stage == 1 && area > 1;
GameUIMgr.ClosePopupSet();
switch (CurrentBattleType)
{
case BattleType.Stage:
DataHandler.FailStage();
bRetry = true;
DataHandler.PlayData.stageRepeat = bRetry;
DataHandler.PlayData.Save();
SetRetry();
break;
case BattleType.Pvp:
EndPvp();
return;
}
ClearRewardItemObjects();
stageSuccessWindow.SetActive(false);
seqDieStage.Restart();
}
int waveMonCount = 0;
// 적 사망시 처리.
public void DieEnemy(eCreatureClass cls, int index)
{
iMonsterCount--;
UnregistBattleEntities(ivMonsters[index]);
if (CurrentBattleType == BattleType.Pvp)
{
ShowTalkBox(TalkType.Attack);
EndPvp();
return;
}
if (CurrentBattleType == BattleType.Stage)
{
DataHandler.AddPassProgress(eCondition.MonsterCnt, 1);
DataHandler.AddRecord(eCondition.MonsterCnt);
if (cls == 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 == 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(eState.idle);
switch (CurrentBattleType)
{
case BattleType.Stage:
bChangeArea = !bRetry && DataHandler.PlayData.curStage >= DataHandler.Const.stageMax;
DataHandler.ClearStage(!bRetry);
if (bChangeArea)
{
seqChangeArea.Restart(); //?-1 교체
ClearReward();
}
else
{
seqChangeStage.Restart();//1-? 교체
ClearReward();
}
break;
}
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;
}
}
}
}
void UnlockCheck()
{
PetMgr.IsUnlock();
TreasureMgr.IsUnlock();
DungeonMgr.Instance.IsUnlock();
}
#endregion Die & Fail
#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.Instance.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 void ClearRewardItemObjects()
{
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
#region Damage
/// <summary>
/// 특정 개체에게 데미지
/// </summary>
public void SendDamage(IBattleEntity battleEntity, BigInteger biatk, float fcrtdam, int icrtrate)
{
if (battleEntity.IsBattleAvail())
{
battleEntity.GetDamage(biatk, fcrtdam, icrtrate);
}
}
public DamageIndicatorText GetDamageIndicatorText(bool isForCharacter)
{
var damageIndicatorTexts = isForCharacter ? dmgIndicatorsChar : dmgIndicatorsMon;
for(int i = 0; i < I_ObjDamCnt; i++)
{
if (!damageIndicatorTexts[i].IsShowing)
return damageIndicatorTexts[i];
}
return null;
}
#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;
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)
{
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(IBattleEntity target, float ftime, float fvalue, int idamCnt = -1)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (ivCharEnemy.GetIsDamaged() == idamCnt) return;
ivCharEnemy.SetDecMove(ftime, fvalue);
return;
}
if (!target.IsBattleAvail()) return;
var enemy = target as CreatureBase;
if (enemy.GetIsDamaged() == idamCnt) return;
enemy.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;
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;
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(IBattleEntity target, float ftime, BigInteger biatk, float fcrtdam, int icrtrate, int idnum)
{
if (CurrentBattleType == BattleType.Pvp)
{
ivCharEnemy.SetDamageSec(ftime, biatk, fcrtdam, icrtrate, idnum);
return;
}
if (!target.IsBattleAvail()) return;
var enemy = target as CreatureBase;
enemy.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(IBattleEntity target, float ftime)
{
if (CurrentBattleType == BattleType.Pvp)
{
ivCharEnemy.SetStun(ftime);
return;
}
if (!target.IsBattleAvail()) return;
var enemy = target as CreatureBase;
enemy.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.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(IBattleEntity target, float fvalue, int iDamCnt = -1)
{
if (CurrentBattleType == BattleType.Pvp)
{
if (ivCharEnemy.GetIsDamaged() == iDamCnt) return;
ivCharEnemy.PushFrame(fvalue);
return;
}
if (!target.IsBattleAvail()) return;
var enemy = target as CreatureBase;
if (enemy.GetIsDamaged() == iDamCnt) return;
enemy.PushFrame(fvalue);
}
// 일정 범위 내 적에게 넉백.
public void PushToEnemy(Bounds bounds, float fvalue, int iDamCnt)
{
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.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(IBattleEntity target, float frate)
{
if (CurrentBattleType == BattleType.Pvp)
{
ivCharEnemy.GetHeal(frate);
return;
}
if (!target.IsBattleAvail()) return;
var enemy = target as CreatureBase;
enemy.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 BattleEntities
private HashSet<IBattleEntity> addRegisterSet = new();
private HashSet<IBattleEntity> removeRegisterSet = new();
public void RegistBattleEntities(params IBattleEntity[] entities)
{
for(int i = 0; i < entities.Length; i++)
{
removeRegisterSet.Remove(entities[i]);
addRegisterSet.Add(entities[i]);
}
}
public void UnregistBattleEntities(params IBattleEntity[] entities)
{
for(int i = 0; i < entities.Length; i++)
{
addRegisterSet.Remove(entities[i]);
removeRegisterSet.Add(entities[i]);
}
}
/// <summary>
/// loop all creatures in battle. if func return false, stop loop.
/// </summary>
public void LoopAllBattleEntities(Func<IBattleEntity, bool> func)
{
if (ivChar.IsBattleAvail() && !func(ivChar)) return;
if (CurrentBattleType == BattleType.Pvp && ivCharEnemy.IsBattleAvail() && !func(ivCharEnemy)) return;
foreach (var entity in addRegisterSet)
{
battleEntities.Add(entity);
}
addRegisterSet.Clear();
foreach (var entity in removeRegisterSet)
{
battleEntities.Remove(entity);
}
removeRegisterSet.Clear();
foreach (var bEntity in battleEntities)
{
if(bEntity.IsBattleAvail() && !func(bEntity)) return;
}
}
public IVCharacter GetPlayer() => ivChar;
#endregion
#region Calc.
// 거리 계산. z축은 무시하고 x, y축만 사용.
public static float SCalcDistance(Vector3 v3pos1, Vector3 v3pos2)
{
v3pos1.z = 0f;
v3pos2.z = 0f;
return Vector3.Distance(v3pos1, v3pos2);
}
#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)
{
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)
{
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)
{
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++)
{
goWaveCapsuleArrow[i].SetActive(false);
imgWaveCapsule[i].color = Color.white;
imgWaveCapsule[i].gameObject.SetActive(i < wave - 1);
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);
}
}
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 bool GoToStage(int area, int stage, bool forceSetChangeArea = false)
{
int curarea = DataHandler.PlayData.curStage / 100;
if (forceSetChangeArea)
bChangeArea = true;
else
bChangeArea = curarea != area;
DataHandler.GoToStage(area, stage);
AStageMoveSave(false);
seqDieStage.Pause();
seqChangeStage.Pause();
seqChangeArea.Pause();
if (bChangeArea)
seqChangeArea.Restart();
else
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 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);
}
}
#endregion
#region Costume
// 코스튬 세팅.
public void SetCharCostume()
{
ivChar.SetSkin(DataHandler.PlayEquipCostume.outfitId, DataHandler.PlayEquipCostume.weaponId);
}
public void SetEnemyCostume(int wp, int cloth)
{
iCosWpEnemy = wp;
iCosClothEnemy = cloth;
ivCharEnemy.SetSkin(iCosClothEnemy, iCosWpEnemy);
}
private void ResetEnemyCostume()
{
iCosWpEnemy = -1;
iCosClothEnemy = -1;
}
#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]);
useSkillid = iSkillIds[key];
SoundMgr.Instance.PlaySfx(SoundName.BtnPress);
}
public int GetUseSkillid() => useSkillid;
/// <summary>
/// 스킬 사용.
/// </summary>
/// <param name="biatk">시전자의 공격력</param>
public int UseSkill(bool bfriendly, int key, IBattleEntity caster, IBattleEntity target, 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, caster, target, ivChar.IsLookRight);
fSkillTicks[index] = fSkillTimes[index];
SetSkillUi(index);
ShowTalkBox(TalkType.Attack);
}
// 적이 사용한 스킬.
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, caster, target, 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 = !IsOnAutoSkill;
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.Instance.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 value in GamePlayBuffMgr.Instance.GetValues(eEffectType.PlayerSkillCoolFix))
{
coolTime.AddModifiers(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;
IsOnAutoSkill = !IsOnAutoSkill;
if (IsOnAutoSkill)
{
imgBtnAuto.sprite = sprAuto;
goAuto.SetActive(true);
}
else
{
imgBtnAuto.sprite = sprAutoOff;
goAuto.SetActive(false);
ivChar.ClearSkillAvail();
}
if (IsOnAutoSkill)
{
for(int i = 0; i < iSkillIds.Length; i++)
{
ivChar.AddSkillAvail(iSkillIds[i]);
}
}
SoundMgr.Instance.PlaySfx(SoundName.BtnPress);
}
private void OnOffAutoTemp(bool bauto)
{
bAutoSkillPrev = IsOnAutoSkill;
IsOnAutoSkill = 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 (IsOnAutoSkill != bAutoSkillPrev)
OnOffAuto();
}
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 bgIdx = Math.Clamp(DataHandler.GetAreaNumber(), 1, areaImgPathList.Length) - 1;
SetBackGround(areaImgPathList[bgIdx]);
}
public void SetBackGround(string path)
{
lightGlobal.color = new Color(1f, 1f, 1f, 1f);
lightChar.color = new Color(0f, 0f, 0f, 1f);
colBg.size = new Vector3(19f, 13f, 1f);
colBg.center = new Vector3(0, -1f, 0);
backGroundRenderer?.SetImageAsync(path);
}
public BoxCollider GetBgSize() => Instance.colBg;
// 조명 조절.
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;
}
// 말풍선 표시.
public void ShowTalkBox(TalkType talkType, int talkIndex = -1, bool force = false)
{
if(!force && talkBox.IsShow()) return;
int talkMaxCount = 0;
switch (talkType)
{
case TalkType.Summon: talkMaxCount = _talkBoxSummonMaxCount; break;
case TalkType.Attack: talkMaxCount = _talkBoxAttackMaxCount; break;
case TalkType.Die: talkMaxCount = _talkBoxDieMaxCount; break;
}
if (talkIndex == -1)
talkIndex = Random.Range(0, talkMaxCount);
if (talkIndex >= talkMaxCount)
talkIndex = talkMaxCount - 1;
talkBox.ShowTalkBox(LocalizationText.GetText(FormatString.StringFormat("talkbox_{0}_{1}", talkType, talkIndex)), 2f);
}
#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)
{
seqDieStage.Pause();
seqChangeStage.Pause();
seqChangeArea.Pause();
// 배틀 멈춤, 카메라 멈춤.
BattlePause = true;
IVCameraController.SSetTrace(false);
StopAllSkill();
UnsummonMon();
ClearRewardItemObjects();
stageSuccessWindow.SetActive(false);
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();
// set pvp background
dBg data = DataHandler.GetBg(DataHandler.sysPvp.bgId);
SetBackGround(FormatString.StringFormat(AddressableMgr.PathBg, data.path));
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);
screenCoverImg.color = Color.black;
screenCoverImg.gameObject.SetActive(true);
screenCoverImg.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);
screenCoverImg.gameObject.SetActive(false);
BattlePause = false;
}
private void EndPvp()
{
// 배틀 멈춤, 카메라 멈춤.
BattlePause = true;
IVCameraController.SSetTrace(false);
screenCoverImg.gameObject.SetActive(true);
CoverCamera.Hold();
// 결투장 나가기 팝업 닫기.
GameUIMgr.SClosePopup2Button(cGoods.TPvpTicket);
Invoke(nameof(EndPvp2), 1f);
SkillFade(false, true);
//ResetFade();
}
private void EndPvp2()
{
screenCoverImg.DOFade(1f, 0.3f);
Invoke(nameof(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();
screenCoverImg.gameObject.SetActive(true);
screenCoverImg.color = Color.black;
ResetEnemyCostume();
ivChar.gameObject.SetActive(false);
ivCharEnemy.gameObject.SetActive(false);
specEnemy = null;
CurrentBattleType = BattleType.Stage;
ResetAuto();
Instance.seqChangeArea.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 void MoveToDir(Vector2 moveVec)
{
if (!doNotInterupt)
{
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 bool TryGetGameMod(uint modId, out GameMod gameMod)
{
gameMod = gameMods.Find(x => x.ModID == modId);
return gameMod != null;
}
public void ChangeGameMod(GameModData gMod)
{
if(TryGetGameMod(gMod.ModID, out currentGameMod))
{
currentGameMod.OnDone -= OnGameModDone;
currentGameMod.OnDone += OnGameModDone;
SetSkillPreset();
ResetSkillCooltime();
seqChangeArea.Pause();
seqChangeStage.Pause();
seqChangeGameMod.Restart();
}
else
{
Logger.LogError("can't found game mod");
}
}
public void OnGameModDone(GameMod.Result result)
{
currentGameMod.EndMod();
if(result == GameMod.Result.Success && currentGameMod.Data is IAutoProgressable autoProgressable && autoProgressable.AutoProgress)
{
SetSkillPreset();
ResetSkillCooltime();
seqChangeArea.Pause();
seqChangeStage.Pause();
seqChangeGameMod.Restart();
}
else
{
currentGameMod = null;
CurrentBattleType = BattleType.Stage;
bChangeArea = true;
GameUIMgr.ClosePopupSet();
MissionMgr.SRefreshMission();
MissionMgr.SOpenMission();
GameUIMgr.SReturnToPreservePreset();
GameUIMgr.SOnOffDungeonButton(true);
if (result == GameMod.Result.Dead)
{
seqDieStage.Restart();
}
else if (result == GameMod.Result.Quit)
{
GoToStage(DataHandler.PlayData.curStage / 100, DataHandler.PlayData.curStage % 100, true);
}
else
{
seqChangeArea.Restart();
}
}
}
#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 void CloseSuccessWindow()
{
stageSuccessWindow.SetActive(false);
awakenSuccessWindow.SetActive(false);
}
#endregion Succ & Fail
#region Dungeon Reward
public void ShowTrainDgSuccWindow()
{
awakenSuccessWindow.SetActive(true);
}
public void ResetBgScroll()
{
srBg.transform.position = new Vector3(0, 0, 0);
}
#endregion
void ContentUnlockCheck(int stage)
{
UnlockCheck();
GameModDataGroup.Instance.TryGetModData(DeepCaveDungeonProperty.CodeName, out DeepCaveDungeonData deepCaveDungeonData);
GameModDataGroup.Instance.TryGetModData(AtlantisDungeonProperty.CodeName, out AtlantisDungeonData atlantisDungeonData);
GameModDataGroup.Instance.TryGetModData(ProtectTheMerchantDgProp.CodeName, out ProtectTheMerchantDgData protectTheMerchantDgData);
GameModDataGroup.Instance.TryGetModData(DevelopTheJungleDgProp.CodeName, out DevelopTheJungleDgData developTheJungleDgData);
GameModDataGroup.Instance.TryGetModData(TrainDgProp.CodeName, out TrainDgData trainDgData);
int goToContent = 0;
if (stage == deepCaveDungeonData.OpenStage) goToContent = 0;
else if (stage == atlantisDungeonData.OpenStage) goToContent = 1;
else if (stage == protectTheMerchantDgData.OpenStage) goToContent = 2;
else if (stage == developTheJungleDgData.OpenStage) goToContent = 3;
else if (stage == trainDgData.OpenStage) goToContent = 4;
else if (stage == DataHandler.Const.gearAccOpenStage) goToContent = 5;
else if (stage == DataHandler.Const.gearTreasureOpenStage) goToContent = 6;
else if (stage > deepCaveDungeonData.OpenStage &&
stage > atlantisDungeonData.OpenStage &&
stage > protectTheMerchantDgData.OpenStage &&
stage > developTheJungleDgData.OpenStage &&
stage > trainDgData.OpenStage &&
stage > DataHandler.Const.gearAccOpenStage &&
stage > DataHandler.Const.gearTreasureOpenStage)
{
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);
}
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);
}
}