using ActionGameFramework.Health;
using Core.Utilities;
using DG.Tweening;
using System;
using System.Net.Http.Headers;
using TowerDefense.Agents;
using TowerDefense.UI.HUD;
using UnityEngine;
using System.Collections;
namespace TowerDefense.Towers.Projectiles
{
///
/// Implementation of hitscan projectile
/// The principle behind this weapon is that it instantly attacks enemies
///
[RequireComponent(typeof(Damager))]
public class HitscanAttack : MonoBehaviour
{
///
/// The amount of time to delay
///
public float delay;
///
/// 攻击敌人后,重设敌人到开始位置的概率,默认为零,不需要重设。
///
public float resetStartPosRate = 0;
///
/// 链式攻击的概率,目前只有一个链式攻击的模式,暂时不需要处理细节,先测试起来
///
public float chainAttackRate = 0;
///
/// 当前攻击塔位对应的属性ID
///
public int attributeId = 0;
///
/// The delay timer
///
protected Timer m_Timer;
///
/// The enemy this projectile will attack
///
protected Targetable m_Enemy;
///
/// The Damager attached to the object
///
protected Damager m_Damager;
///
/// The towers projectile position
///
protected Vector3 m_Origin;
///
/// Configuration for pausing the timer delay timer
/// without setting Time.timeScale to 0
///
protected bool m_PauseTimer;
protected int mLiveID = 0;
///
/// 随机数数据
///
protected System.Random mRand;
///
/// 攻击增加.
///
public float attackRise { get; set; }
///
/// The delay configuration for the attacking
///
///
/// The point the attack will be fired from
///
///
/// The enemy to attack
///
public void AttackEnemy(Vector3 origin, Targetable enemy, float delayTime = 0)
{
m_Enemy = enemy;
m_Origin = origin;
// 更快的击中目标:
if (delayTime > 0)
m_Timer.SetTime(delayTime / 4.0f);
m_Timer.Reset();
m_PauseTimer = false;
mLiveID = enemy.liveID;
}
///
/// 处理塔位的属性攻击
///
///
///
protected void ProcessTowerAttributeAttack(Targetable enemy, float damage, int attid)
{
int id = (int)Math.Floor(attid / 10000.0f);
switch (id)
{
case 2: // 减速.
enemy.addSpeedSlowRate(0.25f);
enemy.SetTargetableMatColor(Color.blue);
break;
case 3: // 中毒
enemy.poisonAgent(damage, attid);
enemy.SetTargetableMatColor(Color.green);
break;
case 5: // 破甲
enemy.bShieldBreak = true;
break;
}
return;
}
///
/// The actual attack of the hitscan attack.
/// Early returns from the method if the there is no enemy to attack.
///
protected void DealDamage()
{
Poolable.TryPool(gameObject);
if (m_Enemy == null)
{
return;
}
// 攻击目标已经经历过了Pool了,不能再攻击了。
if (mLiveID != m_Enemy.liveID) return;
// effects
// ParticleSystem pfxPrefab = m_Damager.collisionParticles;
// var attackEffect = Poolable.TryGetPoolable(pfxPrefab.gameObject);
// attackEffect.transform.position = m_Enemy.position;
// attackEffect.Play();
// GameObject hitObj = Poolable.TryGetPoolable(m_Damager.collisionObj);
// ParticleSystem ps = hitObj.GetComponent();
// if (ps == null)
// ps = hitObj.transform.GetChild(0).GetComponent();
// ps.Play();
// // StartCoroutine(RecycleParticle(hitObj, ps.main.duration));
// var hitVFX = Instantiate(m_Damager.collisionObj, m_Enemy.position, Quaternion.identity);
// var ps = hitVFX.GetComponent();
// if (ps == null)
// {
// var psChild = hitVFX.transform.GetChild(0).GetComponent();
// psChild.Play();
// Destroy(hitVFX, psChild.main.duration);
// }
// else
// {
// ps.Play();
// Destroy(hitVFX, ps.main.duration);
// }
float finalDamage = m_Damager.finalDamage;
bool crit = m_Damager.isCrit;
if (crit)
{
finalDamage += finalDamage;
// 暂时去掉这个ShakePosition的功能:
//m_Enemy.transform.DOShakePosition(0.5f);
}
// 精英怪和Boss双倍攻击.
bool doubleHit = m_Damager.doubleHit && m_Enemy.bElit;
if (doubleHit)
{
finalDamage *= 2;
}
//
// 处理光塔对应的攻击增加:
if (attackRise > 0)
finalDamage += (finalDamage * attackRise);
// 破甲状态
if (m_Enemy.bShieldBreak)
finalDamage += (finalDamage * 0.1f);
//
// 提前处理非当前Enemy的爆炸攻击:
if (chainAttackRate > 0)
AgentInsManager.instance.StartExplodeAttack(m_Enemy as Agent, finalDamage);
int tid = m_Enemy.liveID;
Vector3 backPos = m_Enemy.position;
m_Enemy.TakeDamage(finalDamage, m_Enemy.position, m_Damager.alignmentProvider, attributeId);
// 处理塔位的技能攻击:
ProcessTowerAttributeAttack(m_Enemy, finalDamage, attributeId);
if (!m_Enemy.opponentAgent)
GameUI.instance.generateBloodText(backPos, finalDamage, crit, doubleHit);
// 播放受击动画:
if ((!m_Enemy.isDead) && (m_Enemy.liveID == tid))
(m_Enemy as Agent).PlayOnHit();
// 重设到开始位置的处理. liveID必须要等于tid.
/*if( (resetStartPosRate > 0)&&(!m_Enemy.isDead)&& (m_Enemy.liveID == tid))
{
if (mRand.NextDouble() < resetStartPosRate)
{
Agent ag = m_Enemy as Agent;
if( ag.bBoss)
{
// 如果是Boss,更低的概率重设位置.
if (mRand.NextDouble() < resetStartPosRate / 20.0f)
ag.execAgentPosResetAction();
}
else
ag.execAgentPosResetAction();
}
}*/
/*// 链式攻击的测试处理: 需要确保是同一个敌人,ID相同.
if( (chainAttackRate > 0)&& (!m_Enemy.isDead) && (m_Enemy.liveID == tid) )
{
if (mRand.NextDouble() < chainAttackRate)
AgentInsManager.instance.StartChainAttack(m_Enemy as Agent,m_Damager.alignmentProvider,(float)Math.Floor(finalDamage/2.0f ));
}*/
m_PauseTimer = true;
}
///
/// Cache the damager component attached to this object
///
protected virtual void Awake()
{
m_Damager = GetComponent();
float fdelay = delay - 0.05f;
if (fdelay < 0) fdelay = 0.0f;
m_Timer = new Timer(fdelay, DealDamage);
if ((resetStartPosRate > 0) || (chainAttackRate > 0))
mRand = new System.Random();
attackRise = 0.0f;
}
///
/// Update the m_Timer if it is available
///
protected virtual void Update()
{
if (!m_PauseTimer)
{
m_Timer.Tick(Time.deltaTime);
}
}
}
}