using System;
using System.Collections.Generic;
using ActionGameFramework.Audio;
using ActionGameFramework.Health;
using Core.Health;
using TowerDefense.Agents;
using TowerDefense.Targetting;
using TowerDefense.Towers;
using TowerDefense.Towers.Projectiles;
using UnityEngine;
using KTGMGemClient;
namespace TowerDefense.Affectors
{
///
/// The common effect for handling firing projectiles to attack
///
/// Requires an ILauncher but it is not automatically added
/// Add an ILauncher implementation to this GameObject before you add this script
///
[RequireComponent(typeof(ILauncher))]
public class AttackAffector : Affector, ITowerRadiusProvider
{
///
/// The projectile used to attack
///
public GameObject projectile;
//
protected GameObject projectile1;
protected GameObject projectile2;
///
/// The list of points to launch the projectiles from
///
public Transform[] projectilePoints;
///
/// The reference to the center point where the tower will search from
///
public Transform epicenter;
///
/// Configuration for when the tower does splash damage
///
public bool isMultiAttack;
///
/// 如果是多目标攻击,最多攻击目标
///
public int maxAttackNum = 1;
///
/// The fire rate in fires-per-second
///
public float fireRate;
///
/// 是否木属性数据
///
public bool bWoodAffector = false;
///
/// The audio source to play when firing
///
public RandomAudioSource randomAudioSource;
///
/// Gets the targetter
///
public Targetter towerTargetter;
///
/// Color of effect radius visualization
///
public Color radiusEffectColor;
///
/// Search condition
///
public Filter searchCondition;
///
/// Fire condition
///
public Filter fireCondition;
///
/// The reference to the attached launcher
///
protected ILauncher m_Launcher;
///
/// The time before firing is possible
///
protected float m_FireTimer;
///
/// Reference to the current tracked enemy
///
protected Targetable m_TrackingEnemy;
///
/// 处理装弹时间.
///
protected float fillBulletTime = 0.0f;
///
/// 充能时间
///
protected float energyCalTime = 0;
protected float fInEnergy = 0;
protected float fBackupTimer = 0.0f;
///
/// Gets the search rate from the targetter
///
public float searchRate
{
get { return towerTargetter.searchRate; }
set { towerTargetter.searchRate = value; }
}
///
/// Gets the targetable
///
public Targetable trackingEnemy
{
get { return m_TrackingEnemy; }
}
///
/// Gets or sets the attack radius
///
public float effectRadius
{
get { return towerTargetter.effectRadius; }
}
public Color effectColor
{
get { return radiusEffectColor; }
}
public Targetter targetter
{
get { return towerTargetter; }
}
///
/// Initializes the attack affector
///
public override void Initialize(IAlignmentProvider affectorAlignment)
{
Initialize(affectorAlignment, -1);
}
///
/// 返回可能存在的Targetter.
///
///
public override TowerDefense.Targetting.Targetter GetTargetter()
{
return targetter;
}
///
/// Initialises the attack affector with a layer mask
///
public override void Initialize(IAlignmentProvider affectorAlignment, LayerMask mask)
{
base.Initialize(affectorAlignment, mask);
SetUpTimers();
towerTargetter.ResetTargetter();
towerTargetter.alignment = affectorAlignment;
towerTargetter.acquiredTarget += OnAcquiredTarget;
towerTargetter.lostTarget += OnLostTarget;
}
void OnDestroy()
{
towerTargetter.acquiredTarget -= OnAcquiredTarget;
towerTargetter.lostTarget -= OnLostTarget;
}
void OnLostTarget()
{
m_TrackingEnemy = null;
}
void OnAcquiredTarget(Targetable acquiredTarget)
{
m_TrackingEnemy = acquiredTarget;
}
public Damager damagerProjectile
{
get { return projectile == null ? null : projectile.GetComponent(); }
}
public Damager damagerProjectile1
{
get { return projectile == null ? null : projectile.GetComponent(); }
}
public Damager damagerProjectile2
{
get { return projectile == null ? null : projectile.GetComponent(); }
}
///
/// Returns the total projectile damage
///
public float GetProjectileDamage()
{
var splash = projectile.GetComponent();
float splashDamage = splash != null ? splash.damage : 0;
return damagerProjectile.finalDamage + splashDamage;
}
///
/// Initialise the RepeatingTimer
///
protected virtual void SetUpTimers()
{
m_FireTimer = 1 / fireRate;
m_Launcher = GetComponent();
}
protected void updateTowerSkillData()
{
//
// 预留出来装填子弹的时间.
if (fillBulletTime > 0)
{
fillBulletTime -= Time.deltaTime;
if (fillBulletTime <= 0.3f)
{
if (towerPtr && towerPtr.bulletCtl)
towerPtr.bulletCtl.resetToMaxBullet();
}
if (fillBulletTime <= 0)
{
fillBulletTime = 0;
}
}
//
// 充能时间的处理
if( towerPtr && towerPtr.energyCtl)
{
if( this.fInEnergy <= 0)
{
this.energyCalTime += Time.deltaTime;
float process = energyCalTime % 11.0f;
int proint = (int)Math.Floor(process);
proint += towerPtr.uiProOffset;
towerPtr.energyCtl.SetEnergyProcessFloat( process );
if (proint == 10)
{
fInEnergy = 5.0f;
// 设置多倍攻击速度
fBackupTimer = m_FireTimer;
m_FireTimer = m_FireTimer / 3.0f;
towerPtr.uiProOffset = 0;
towerPtr.PlayEnergyEffect(true);
}
}
else
{
fInEnergy -= Time.deltaTime;
if( fInEnergy <= 0)
{
EventCenter.Ins.BroadCast((int)KTGMGemClient.EventType.FireTowerChargeEnd);
fInEnergy = 0.0f;
this.energyCalTime = 0.0f;
towerPtr.energyCtl.SetEnergyProgress(0);
// 恢复正常攻击速度
m_FireTimer = fBackupTimer;
towerPtr.PlayEnergyEffect(false);
}
}
}
}
///
/// Update the timers
///
protected virtual void Update()
{
// 处理当前Affector所在Tower对应的技能
updateTowerSkillData();
m_FireTimer -= Time.deltaTime;
if( trackingEnemy == null )
m_TrackingEnemy = targetter.GetTarget(waveLineID, bWoodAffector);
if (trackingEnemy != null && m_FireTimer <= 0.0f)
{
OnFireTimer();
m_FireTimer = 1 / fireRate;
// 多倍攻速:
if (fInEnergy > 0.0f)
m_FireTimer = m_FireTimer / 3.0f;
}
}
///
/// Fired at every poll of the fire rate timer
///
protected virtual void OnFireTimer()
{
if (fireCondition != null)
{
if (!fireCondition())
{
return;
}
}
FireProjectile();
}
///
/// Common logic when attacking
/// 调用攻击的核心函数,由这个函数发起真正的攻击,多目标或者单目标
///
protected virtual void FireProjectile()
{
// 不再处理多子弹攻击,确保只有一个弹道
isMultiAttack = false;
m_TrackingEnemy = targetter.GetTarget( waveLineID, bWoodAffector );
if ( (m_TrackingEnemy == null) || (fillBulletTime>0) )
{
if (this.towerPtr)
towerPtr.setTowerState(false);
return;
}else
{
if (this.towerPtr)
towerPtr.setTowerState(true);
}
//
// 处理子弹充能相关的内容
if( towerPtr && (towerPtr.bulletCtl != null))
{
int bnum = towerPtr.bulletCtl.decBullet();
//
if (bnum == 0)
{
damagerProjectile.damageMulti = 2.0f;
fillBulletTime = 2.0f;
}
}
if (isMultiAttack)
{
List enemies = towerTargetter.GetAllTargets();
if( (enemies != null)&&(Targetter.bSearchTarget) )
m_Launcher.Launch(enemies, projectile, projectilePoints,this.maxAttackNum);
}
else
{
if(Targetter.bSearchTarget )
m_Launcher.Launch(m_TrackingEnemy, damagerProjectile.gameObject, projectilePoints);
}
if (randomAudioSource != null)
{
if( Targetter.bSearchTarget )
randomAudioSource.PlayRandomClip();
}
}
///
/// A delegate to compare distances of components
///
///
///
protected virtual int ByDistance(Targetable first, Targetable second)
{
float firstSqrMagnitude = Vector3.SqrMagnitude(first.position - epicenter.position);
float secondSqrMagnitude = Vector3.SqrMagnitude(second.position - epicenter.position);
return firstSqrMagnitude.CompareTo(secondSqrMagnitude);
}
#if UNITY_EDITOR
///
/// Draws the search area
///
void OnDrawGizmosSelected()
{
Gizmos.DrawWireSphere(epicenter.position, towerTargetter.effectRadius);
}
#endif
}
///
/// A delegate for boolean calculation logic
///
public delegate bool Filter();
}