Project_WL/Assets/Script/Character/Projectile/ProjectileBase.cs

451 lines
18 KiB
C#
Raw Normal View History

2024-12-15 01:39:39 +00:00
using CodeStage.AntiCheat.ObscuredTypes;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum eProjectileStartPos { None, Shooter, ShooterCenter, Target, TargetCenter, Custom }
public enum eProjectileStrait { Forward, Down }
public class ProjectileData
{
public ProjectileBase m_ProjectileBase;
public Actor shooter, target;
public SkillListTableData m_SkillListTableData;
public OptionConfigTableData m_OptionConfigTableData;
public SkillTypeConfigTableData m_skillTypeConfigTable;
public eEffect m_Skill = eEffect.None;
public eSkillExtraType e_SkillExtraType = eSkillExtraType.None;
2025-02-19 04:14:09 +00:00
public float Speed = 5f, LifeTime = 4f, DamageArea;
2024-12-15 01:39:39 +00:00
public eProjectileStartPos eStartPos = eProjectileStartPos.None;
public Vector3 v3_StartPos;
public bool SetSkillExtraType = true, IsRandomPos, LookTarget = true, CheckOptionWhenStart = true;
public double Amount;
public Action<Actor> Action_OnHit;
ObscuredDouble _BaseDmg;
2025-02-19 04:14:09 +00:00
ObscuredFloat _AddDmgPercent = 1f, _CC_AddTime, _CC_AddDmg, _CC_AddVal1, _CC_AddVal2;
public double BaseDmg { get { return _BaseDmg; } set { _BaseDmg = value; _BaseDmg.RandomizeCryptoKey(); } }
public float AddDmgPercent { get { return _AddDmgPercent; }
set
{
_AddDmgPercent = value;
_AddDmgPercent.RandomizeCryptoKey();
}
}
public float CC_AddTime { get { return _CC_AddTime; } set { _CC_AddTime = value; _CC_AddTime.RandomizeCryptoKey(); } }
public float CC_AddDmg { get { return _CC_AddDmg; } set { _CC_AddDmg = value; _CC_AddDmg.RandomizeCryptoKey(); } }
public float CC_AddVal1 { get { return _CC_AddVal1; } set { _CC_AddVal1 = value; _CC_AddVal1.RandomizeCryptoKey(); } }
public float CC_AddVal2 { get { return _CC_AddVal2; } set { _CC_AddVal2 = value; _CC_AddVal2.RandomizeCryptoKey(); } }
2024-12-15 01:39:39 +00:00
2025-02-09 06:50:27 +00:00
public void Reset()
{
shooter = null;
target = null;
2025-02-19 04:14:09 +00:00
AddDmgPercent = 1f;
2025-02-09 06:50:27 +00:00
eStartPos = eProjectileStartPos.ShooterCenter;
v3_StartPos = Vector3.zero;
LifeTime = 4f;
SetSkillExtraType = true;
LookTarget = true;
IsRandomPos = false;
CheckOptionWhenStart = true;
m_Skill = eEffect.None;
e_SkillExtraType = eSkillExtraType.None;
}
2024-12-15 01:39:39 +00:00
public bool IsSkill() { return !DSUtil.CheckNull(m_SkillListTableData); }
public bool IsSkill(eEffect skill) { return IsSkill() && m_SkillListTableData.e_Skill == skill; }
public Vector3 Get_EffectPos(Actor target)
{
var stcData = m_skillTypeConfigTable;
if (!DSUtil.CheckNull(stcData))
{
Vector3 effectPos;
switch (stcData.e_EffectLocation)
{
case eEffectLocation.Top: effectPos = target.Get_Top_postion(); break;
default: effectPos = target.Get_Center_position(); break;
case eEffectLocation.Bottom: effectPos = target.Get_position(); break;
}
return new Vector3(effectPos.x + stcData.n_EffectPosition_X, effectPos.y + stcData.n_EffectPosition_Y, effectPos.z);
}
return Vector3.right * 1000000f;
}
public float Get_SkillDamagePercent()
{
var lv = shooter.Get_ServerData().Get_SkillLv(shooter.m_Role, m_SkillListTableData.n_SkillID);
var tabledmg = m_SkillListTableData.Get_SkillDamage(shooter.Get_StatInfo(), lv);
2024-12-15 01:39:39 +00:00
return tabledmg + (float)shooter.Get_StatInfo().Get_Stat(eStat.SKILL_Multiplier) + AddDmgPercent;
}
public ProjectileData Copy()
{
ProjectileData pd = new ProjectileData();
Copy(pd);
return pd;
}
public void Copy(ProjectileData pd)
{
pd.m_ProjectileBase = m_ProjectileBase;
pd.shooter = shooter;
pd.Action_OnHit = Action_OnHit;
pd.target = target;
pd.m_skillTypeConfigTable = m_skillTypeConfigTable;
pd.IsRandomPos = IsRandomPos;
pd.LifeTime = LifeTime;
pd.m_SkillListTableData = m_SkillListTableData;
pd.m_Skill = m_Skill;
pd.Speed = Speed;
pd.v3_StartPos = v3_StartPos;
pd.eStartPos = eStartPos;
2025-02-19 04:14:09 +00:00
pd.AddDmgPercent = AddDmgPercent;
2024-12-15 01:39:39 +00:00
pd.BaseDmg = BaseDmg;
pd.CC_AddTime = CC_AddTime;
pd.CC_AddDmg = CC_AddDmg;
pd.CC_AddVal1 = CC_AddVal1;
pd.CC_AddVal2 = CC_AddVal2;
pd.DamageArea = DamageArea;
}
2025-02-20 01:00:59 +00:00
public void Set_SkillExtra_MakeSkillListTableData(eSkillExtraType skillExtraType, float val1, float val2 = 0f, float ccRate = 1f)
2025-02-20 01:00:59 +00:00
{
e_SkillExtraType = skillExtraType;
m_skillTypeConfigTable = table_skilltypeconfig.Ins.Get_Data_orNull(skillExtraType);
m_SkillListTableData = new SkillListTableData
{
e_SkillExtraType = skillExtraType,
f_ExtraValue1 = val1,
f_ExtraValue2 = val2,
2025-02-20 01:00:59 +00:00
f_ExtraValue4 = ccRate
};
}
2024-12-15 01:39:39 +00:00
}
public class ProjectileBase : MonoBehaviour
{
[Header("관통 여부")]
2024-12-15 01:39:39 +00:00
public bool m_Pierce;
[Header("투사체 타격 시 나올 이펙트")]
2024-12-15 01:39:39 +00:00
public string str_HitEffect;
[Header("시간이 0이 됐을 때 이펙트 표시 여부")]
public bool m_ShowTimeOverEffect = true;
2025-02-09 06:50:27 +00:00
protected bool bFirstLoad = true, isProjectiledata = false;
ProjectileData _projectileData;
protected ProjectileData m_ProjecTileData
{
get { return _projectileData; }
set { _projectileData = value; isProjectiledata = !DSUtil.CheckNull(value); }
}
2024-12-15 01:39:39 +00:00
protected float m_LifeTime;
protected Vector3 v3_scale;
protected Action<double> act_returnDmg;
protected Action<Actor> act_afterFreezing;
DamageInfo m_DamageInfo;
private void Awake() { v3_scale = transform.localScale; }
private void OnEnable()
{
if (bFirstLoad)
{
2025-02-09 06:50:27 +00:00
m_ProjecTileData = new ProjectileData();
2024-12-15 01:39:39 +00:00
Off_FisrLoad();
transform.position = Vector3.one * 100000f;
Off(true);
}
}
public void Off_FisrLoad() { bFirstLoad = false; }
public virtual void Set(ProjectileData _data)
{
2025-02-19 04:14:09 +00:00
_data.CC_AddTime = _data.CC_AddDmg = _data.CC_AddVal1 = _data.CC_AddVal2 = 0f;
2025-02-09 06:50:27 +00:00
_data.Copy(m_ProjecTileData);
m_ProjecTileData.m_ProjectileBase = this;
m_DamageInfo = Get_NewDamageInfo();
2024-12-15 01:39:39 +00:00
var isNullTarget = DSUtil.CheckNull(m_ProjecTileData.target);
2024-12-28 00:20:09 +00:00
if (m_ProjecTileData.IsSkill())
2024-12-15 01:39:39 +00:00
{
var skillData = m_ProjecTileData.m_SkillListTableData;
if (m_ProjecTileData.SetSkillExtraType)
m_ProjecTileData.e_SkillExtraType = skillData.e_SkillExtraType;
2024-12-15 01:39:39 +00:00
}
else
{
transform.localScale = v3_scale;
var statinfo = m_ProjecTileData.shooter.Get_StatInfo();
2024-12-15 01:39:39 +00:00
if (!DSUtil.CheckNull(statinfo))
{
m_ProjecTileData.Speed += (float)statinfo.Get_Stat(eStat.ProjectileSpeed_Up);
2024-12-15 01:39:39 +00:00
transform.localScale += v3_scale * (float)statinfo.Get_Stat(eStat.ProjectileSize_Up);
}
}
m_ProjecTileData.m_skillTypeConfigTable = table_skilltypeconfig.Ins.Get_Data_orNull(m_ProjecTileData.e_SkillExtraType);
if (!isNullTarget && !DSUtil.CheckNull(m_ProjecTileData.m_skillTypeConfigTable) &&
m_ProjecTileData.m_skillTypeConfigTable.e_SkillExtraTiming == eSkillExtraTiming.Start)
m_ProjecTileData.target.Check_Extra(m_DamageInfo);
2024-12-15 01:39:39 +00:00
if (m_ProjecTileData.CheckOptionWhenStart)
2024-12-15 01:39:39 +00:00
{
m_ProjecTileData.CheckOptionWhenStart = false;
m_ProjecTileData.shooter.Check_EnchantOption(m_DamageInfo, false);
2024-12-15 01:39:39 +00:00
}
Set_Checkers();
m_LifeTime = _data.LifeTime;
gameObject.SetActive(true);
switch (_data.eStartPos)
{
case eProjectileStartPos.Shooter: transform.position = _data.shooter.Get_CenterPositionFoward(); break;
case eProjectileStartPos.ShooterCenter: transform.position = _data.shooter.Get_CenterPositionFoward(); break;
default: transform.position = _data.target.Get_CenterPositionFoward(); break;
case eProjectileStartPos.TargetCenter: transform.position = _data.target.Get_CenterPositionFoward(); break;
2024-12-15 01:39:39 +00:00
case eProjectileStartPos.Custom: transform.position = _data.v3_StartPos; break;
}
2024-12-28 00:20:09 +00:00
if (!isNullTarget)
2024-12-15 01:39:39 +00:00
{
if (_data.LookTarget)
{
switch (_data.eStartPos)
{
case eProjectileStartPos.Shooter:
case eProjectileStartPos.Target:
transform.LookAt(_data.target.Get_position());
break;
default:
Vector3 targetPosition = _data.target.Get_Center_position();
targetPosition.y = _data.shooter.Get_Center_position().y;
transform.LookAt(targetPosition);
break;
}
}
}
2025-02-21 03:21:31 +00:00
else if (_data.LookTarget && !DSUtil.CheckNull(_data.shooter))
2024-12-15 01:39:39 +00:00
transform.eulerAngles = _data.shooter.transform.eulerAngles;
}
2025-01-18 04:56:33 +00:00
public virtual void Launch(Vector3 start, Vector3 end, float wavePhase, float waveAmplitude, float waveFrequency) { }
2024-12-15 01:39:39 +00:00
protected void LookAt_ShooterFoward()
{
transform.rotation = m_ProjecTileData.shooter.transform.rotation;
transform.eulerAngles = new Vector3(0f, transform.eulerAngles.y);
}
2024-12-15 01:39:39 +00:00
/// <summary>
/// 쿨타임을 감소시킨다. f_ExtraValue1 값을 사용한다.
/// </summary>
protected void Set_ReduceCoolTime_byStep(int step)
{
if (IsStep(step))
m_ProjecTileData.shooter.Set_SkillCoolTime(false, m_ProjecTileData.m_SkillListTableData.n_SkillID,
2024-12-15 01:39:39 +00:00
Get_AwakenData(step, 1));
}
/// <summary>
/// active 스킬 실행 여부
/// </summary>
public void Show_Effect(Actor target, float effectLifeTime = 5f, Action<TurnOff_GO> cceffect = null)
2024-12-15 01:39:39 +00:00
{
InGameInfo.Ins.Show_SkillTypeEffect(m_ProjecTileData, target, effectLifeTime, cceffect);
2024-12-15 01:39:39 +00:00
}
2025-02-09 06:50:27 +00:00
public virtual void Set_Shooter(Actor _shoter) { if (isProjectiledata) m_ProjecTileData.shooter = _shoter; }
2024-12-15 01:39:39 +00:00
protected void Check_TargetBoss()
{
2025-02-09 06:50:27 +00:00
if (isProjectiledata)
2024-12-15 01:39:39 +00:00
{
if (!m_ProjecTileData.target.IsSubRole(eSubRol.Boss) || m_ProjecTileData.target.transform.localScale.x <= 2f)
2024-12-15 01:39:39 +00:00
{
var enemies = Get_Enemies(transform, 8f);
var boss = enemies.Find(f => f.IsSubRole(eSubRol.Boss) || f.transform.localScale.x > 2f);
2024-12-15 01:39:39 +00:00
if (boss != null)
m_ProjecTileData.target = boss;
2024-12-15 01:39:39 +00:00
}
}
}
public ProjectileData Get_ProjectTileData() { return m_ProjecTileData; }
2024-12-15 01:39:39 +00:00
DamageInfo Get_SkillDamage()
{
2025-02-19 04:14:09 +00:00
m_ProjecTileData.AddDmgPercent = m_ProjecTileData.Get_SkillDamagePercent();
var dinfo = m_ProjecTileData.shooter.Get_DamageInfo(m_ProjecTileData,
m_ProjecTileData.CC_AddVal2 > 0 && m_ProjecTileData.m_SkillListTableData.e_Skill == eEffect.Skill_IceBolt &&
m_ProjecTileData.target.IsSkillExtraStatus(eSkillExtraType.Frost));
2024-12-15 01:39:39 +00:00
dinfo.act_returnLastDmg = act_returnDmg;
dinfo.act_AfterFreezing = act_afterFreezing;
return dinfo;
}
protected DamageInfo Get_NewDamageInfo()
{
return m_ProjecTileData.IsSkill() ? Get_SkillDamage() : m_ProjecTileData.shooter.Get_DamageInfo(m_ProjecTileData);
}
2024-12-17 01:48:30 +00:00
protected DamageInfo Get_DamageInfo(bool extradmg = false, bool calcri = true)
{
m_DamageInfo.Damage = m_DamageInfo.NoCriDmg;
2024-12-17 01:48:30 +00:00
m_DamageInfo.bExtraDmg = extradmg;
if (calcri) m_DamageInfo.Cal_Cri(m_ProjecTileData.shooter.m_AttackType, m_ProjecTileData.shooter.Get_StatInfo());
2024-12-17 01:48:30 +00:00
return m_DamageInfo;
}
2024-12-15 01:39:39 +00:00
protected bool IsStep(int _step)
{
var sdata = m_ProjecTileData.shooter.Get_ServerData();
2024-12-15 01:39:39 +00:00
if (!DSUtil.CheckNull(sdata))
{
if (m_ProjecTileData.shooter.IsRole(eRole.PC))
return sdata.Get_SkillAwakenLv(m_ProjecTileData.m_SkillListTableData.n_SkillID) >= _step;
2024-12-15 01:39:39 +00:00
else
return sdata.Get_PetSkillAwakenLv(m_ProjecTileData.shooter.Get_ID()) >= _step;
2024-12-15 01:39:39 +00:00
}
return false;
}
protected Actor Get_NearstEnemy(float dist = 20f)
{ return ActorInfo.Ins.Get_Nearest_EnemyActor_orNull(m_ProjecTileData.shooter.IsEnemy(), transform.position, dist); }
2024-12-15 01:39:39 +00:00
protected List<Actor> Get_Enemies()
{ return ActorInfo.Ins.Get_EnemyActors(m_ProjecTileData.shooter.IsEnemy(), transform.position); }
2024-12-15 01:39:39 +00:00
protected List<Actor> Get_Enemies(Transform tf, float dist)
2024-12-28 00:20:09 +00:00
{
#if UNITY_EDITOR
if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name == "StatTest")
return new List<Actor> { MainToStatTest.Ins.actors[1] };
#endif
return ActorInfo.Ins.Get_EnemyActors(m_ProjecTileData.shooter.IsEnemy(), tf.position, dist);
2024-12-28 00:20:09 +00:00
}
2024-12-15 01:39:39 +00:00
protected void Show_HitEffect(bool effectbyHit, Actor target)
{
2025-02-09 06:50:27 +00:00
if (isProjectiledata && !string.IsNullOrEmpty(str_HitEffect))
2024-12-15 22:56:30 +00:00
InGameInfo.Ins.Show_Effect(str_HitEffect, Get_HitEffectPos(effectbyHit, target));
2024-12-15 01:39:39 +00:00
}
Vector3 Get_HitEffectPos(bool effectbyHit, Actor target)
{
if (DSUtil.CheckNull(target)) effectbyHit = false;
return effectbyHit ? target.Get_Center_position() : transform.position;
}
protected virtual void Off(bool forceoff = false, bool showtimeovereffect = true)
2024-12-15 01:39:39 +00:00
{
if (forceoff || !m_Pierce) gameObject.SetActive(false);
if (!bFirstLoad && showtimeovereffect) Show_HitEffect(false, null);
2024-12-15 01:39:39 +00:00
}
2025-01-02 07:38:57 +00:00
protected IEnumerator Co_Off(float delay)
{
yield return new WaitForSeconds(delay);
Off(true, m_ShowTimeOverEffect);
2025-01-02 07:38:57 +00:00
}
2024-12-15 01:39:39 +00:00
/// <summary>
/// 포물선 움직임
/// </summary>
/// <param name="journeyTime">시작위치에서 종료위치까지 도달하는 시간, 값이 높을수록 느리게 간다.</param>
/// <param name="reduceHeight">Center값을 줄이기, 해당 값이 높을수록 포물선의 높이는 낮아진다.</param>
/// <returns></returns>
protected IEnumerator Co_Move_Split(Action _actreach, Vector3 startpos, Vector3 targetpos, float journeyTime = 1.0f, float reduceHeight = 0.25f)
{
float startTime = Time.time;
while (true)
{
Vector3 center = (startpos + targetpos) * 0.5f; //Center 값만큼 위로 올라간다.
center -= new Vector3(0, 1f * reduceHeight, 0); //y값을 높이면 높이가 낮아진다.
Vector3 riseRelCenter = startpos - center;
Vector3 setRelCenter = targetpos - center;
float fracComplete = (Time.time - startTime) / journeyTime;
transform.position = Vector3.Slerp(riseRelCenter, setRelCenter, fracComplete);
transform.position += center;
if (fracComplete >= 1f)
{
_actreach?.Invoke();
break;
}
yield return null;
}
}
protected IEnumerator Co_Move_Strait(eProjectileStrait direction)
{
while (m_ProjecTileData.LifeTime > 0f)
2024-12-15 01:39:39 +00:00
{
if (DSUtil.CheckNull(m_ProjecTileData.shooter)) break;
2024-12-15 01:39:39 +00:00
if (direction == eProjectileStrait.Forward)
transform.Translate(m_ProjecTileData.Speed * Time.deltaTime * Vector3.forward);
2024-12-15 01:39:39 +00:00
else
transform.Translate(m_ProjecTileData.Speed * Time.deltaTime * Vector3.down);
2024-12-15 01:39:39 +00:00
m_ProjecTileData.LifeTime -= Time.deltaTime;
2024-12-15 01:39:39 +00:00
yield return null;
}
Off(true);
}
protected virtual void OnTriggerEnter(Collider other) { ProcessCollider(other); }
protected virtual void OnCollisionEnter(Collision collision) { ProcessCollider(collision.collider); }
2025-01-18 23:21:18 +00:00
public virtual bool ProcessCollider(Collider other, bool Off_byHit = true, bool noDmg = false)
2024-12-15 01:39:39 +00:00
{
2025-02-09 06:50:27 +00:00
int targetLayer = other.gameObject.layer;
if (isProjectiledata && targetLayer == LayerMask.NameToLayer("Actor"))
2024-12-15 01:39:39 +00:00
{
2025-02-09 06:50:27 +00:00
// 캐싱된 GetComponent 호출
if (!other.TryGetComponent<Actor>(out var hitter)) return false;
if (m_ProjecTileData.shooter.IsEnemy() != hitter.IsEnemy())
{
if (!noDmg) hitter.Get_Damage(Get_DamageInfo());
m_ProjecTileData.Action_OnHit?.Invoke(hitter);
if (Off_byHit) Off(false, false);
Show_HitEffect(true, hitter);
return true;
}
2024-12-15 01:39:39 +00:00
}
return false;
}
public void Set_Checkers()
{
var chekers = GetComponentsInChildren<ProjectileHitChecker>(true);
for (int i = 0; i < chekers.Length; i++)
chekers[i].Set(this);
}
public void Set_CheckersSize(float addsize)
{
var chekers = GetComponentsInChildren<ProjectileHitChecker>(true);
for (int i = 0; i < chekers.Length; i++)
chekers[i].Set_Size(addsize);
}
protected float Get_AwakenData(int step, int index)
{
var data = table_skillawakenconfig.Ins.Get_Data_orNull(m_ProjecTileData.m_SkillListTableData.n_SkillID, step);
2024-12-15 01:39:39 +00:00
if (DSUtil.CheckNull(data))
return 0f;
switch (index)
{
case 1: return data.f_ExtraValue1;
case 2: return data.f_ExtraValue2;
case 3: return data.f_ExtraValue3;
default: return 0f;
}
}
protected int Get_FairyCount(eEffect _effect)
{
return m_ProjecTileData.shooter.Get_SelectSkill(_effect) ? 4 : 1;
2024-12-15 01:39:39 +00:00
}
#if UNITY_EDITOR
protected void Add_AwakendLv(int lv)
{
if (m_ProjecTileData.shooter.IsRole(eRole.PC))
2024-12-15 01:39:39 +00:00
for (int i = 0; i < lv; i++)
m_ProjecTileData.shooter.Get_ServerData().Add_SkillAwakenLv(m_ProjecTileData.m_SkillListTableData.n_SkillID);
else if (m_ProjecTileData.shooter.IsRole(eRole.Pet))
m_ProjecTileData.shooter.Get_ServerData().Add_PetLv(m_ProjecTileData.shooter.Get_ID(), lv * 15);
2024-12-15 01:39:39 +00:00
}
#endif
}