package game.towers
{
import com.cheezeworld.utils.Input;
import com.cheezeworld.utils.KeyCode;
import com.experion.utils.GetClass;
import events.ModelEvent;
import factories.IProjectileFactory;
import factories.PathGridObjectFactory;
import factories.ProjectileFactory;
import game.build.BuildManager;
import game.enemies.Enemy;
import game.models.Model;
import game.projectiles.Projectile;
import game.projectiles.SpecialProjectile;
import game.UpgradeManager;
import grid.path.PathFollowUnit;
import grid.path.PathGridObject;
import utils.ModelUtilities;
/**
* ...
* @author
*/
public class Tower extends Model {
static public const TOWER_FIRE:String = "towerFire";
static public const TOWER_UPGRADE:String = "towerUpgrade";
protected var _location:PathGridObject;
protected var _target:Enemy;
protected var _range:Number;
protected var _fireDelay:Number;
protected var _damage:int;
protected var _projectileFactory:IProjectileFactory;
protected var _upgradeCost:int;
protected var _level:int;
private var _currentDelay:int;
private var _readyToFire:Boolean;
private var _enemies:Vector.;
public function Tower(location:PathGridObject/*, upgrade:UpgradeManager*/) {
super();
_location = location;
position.x = _location.position.x;
position.y = _location.position.y;
_readyToFire = false;
_range = 100;
_fireDelay = 4;
_damage = 10;
_upgradeCost = BuildManager.COST_TOWER_BASIC * 2;
_level = 1;
_projectileFactory = new ProjectileFactory();
/*if (upgrade.register(this)) {
}*/
}
public function updateTarget(enemies:Vector.):void {
/*if (_enemies == null)*/ _enemies = enemies;
checkFireDelay();
if (_target != null && _target.position) {
if ( !checkRangeWith(_target) ) {
getNewTarget(enemies);
} else {
if (_readyToFire) {
shootProjectile();
_readyToFire = false;
}
}
} else {
getNewTarget(enemies);
}
}
/**
* Checks if the Tower is ready to fire.
*/
private function checkFireDelay():void {
if (!_readyToFire) {
_currentDelay++;
if (_currentDelay > _fireDelay) {
_readyToFire = true;
_currentDelay = 0;
}
}
}
/** Shoots the projectile. */
private function shootProjectile():void {
if (_projectileFactory.usesSpecialProjectiles) {
var projectile:SpecialProjectile = _projectileFactory.createProjectile(this, _target) as SpecialProjectile;
projectile.setUpAdditionalValues(_enemies);
dispatchEvent( new ModelEvent(TOWER_FIRE, projectile ) );
} else {
dispatchEvent( new ModelEvent(TOWER_FIRE, _projectileFactory.createProjectile(this, _target) ) );
}
}
/**
* Gets a new target to shoot at. It'll take the closest Enemy.
* @param enemies - The list with Enemies
*/
protected function getNewTarget(enemies:Vector.):void {
var closestEnemy:Enemy;
var closestDistance:Number;
//Go through every existing enemy
for (var i:int = 0; i < enemies.length; i++) {
var currEnemy:Enemy = enemies[i];
//Check if the current enemy we're checking for is in range
if ( checkRangeWith(currEnemy) ) {
var enemyDistance:Number = ModelUtilities.getRadiusDistance(this, currEnemy);
//If the distance of this enemy is closer than the other enemies we've checked, this will become the closest.
if ( closestEnemy == null || enemyDistance < closestDistance ) {
closestEnemy = currEnemy;
closestDistance = enemyDistance;
}
}
}
_target = closestEnemy;
}
public function checkRangeWith(enemy:Enemy):Boolean {
return ModelUtilities.getRadiusCollision(this, enemy, _range);
}
public function upgrade():void {
//upgrade ze stats here
_upgradeCost *= 1.3;
_level++;
upgradeStats();
}
public function get level():int {
return _level;
}
protected function upgradeStats():void {
_range += 15;
//_damage += 2;
_damage += 3 + (level/2);
if (level % 10 == 0) {
if (_fireDelay > 2) {
_fireDelay--;
}
}
}
public function get upgradeCost():int {
return _upgradeCost;
}
public function get range():Number {
return _range;
}
public function get location():PathGridObject {
return _location;
}
public function get target():Enemy {
return _target;
}
public function get damage():int {
return _damage;
}
public function get fireDelay():Number {
return _fireDelay;
}
}
}