private List <TDEntity> GetTowersInRange(TDLocation loc, int Radius, bool IncludeTowers, bool IncludeAttackers) { List <TDEntity> towersInRange = new List <TDEntity>(); if (IncludeAttackers) { foreach (TDAttacker a in TDSession.thisSession.CurrentLevel.Attackers) { if (TDMath.PointInRange(loc, a.Location, Radius)) { towersInRange.Add(a); } } } if (IncludeTowers) { foreach (TDTower t in TDSession.thisSession.CurrentLevel.Towers) { if (TDMath.PointInRange(loc, t.Location, Radius)) { towersInRange.Add(t); } } } return(towersInRange); }
private AttackerTypes GetWeightedAttackerType(bool AllowBoss) { int d = TDMath.D(100); if (d < 25) { return(AttackerTypes.Goblin); } else if (d < 50) { return(AttackerTypes.GoblinArcher); } else if (d < 75) { return(AttackerTypes.Orc); } else if (d < 95 || (AllowBoss == false)) // boss number will default to troll { return(AttackerTypes.Troll); } else // d >= 95 { return(AttackerTypes.Boss); } }
public bool isTowerOnPath(TDTower t) { // first check if intersting any corner TDPathPoint lastPoint = null; foreach (TDPath p in this.Paths) { foreach (TDPathPoint pp in p.PathPoints) { if (TDMath.Intersects(t.Location, t.Size, pp.Location, GridSize)) { return(true); } else { // check intersecting any line if (lastPoint != null) { if (TDMath.Intersects(t, pp, lastPoint)) { return(true); } } lastPoint = pp; } } } return(false); }
private TDEntity GetTowerAtPoint(Point point) { if (TDSession.thisSession == null || TDSession.thisSession.CurrentLevel == null) { return(null); } TDLocation p = new TDLocation(point.X, point.Y); foreach (TDAttacker a in TDSession.thisSession.CurrentLevel.Attackers) { if (TDMath.PointOnPoint(a.Location, p, a.Size)) { return(a); } } foreach (TDTower t in TDSession.thisSession.CurrentLevel.Towers) { if (TDMath.PointOnPoint(t.Location, p, t.Size)) { return(t); } } // if not a tower or attacker, then nothing return(null); }
internal bool isTowerOnTowers(TDTower target) { foreach (TDTower t in this.Towers) { if (TDMath.Intersects(target.Location, target.Size, t.Location, t.Size)) { return(true); } } return(false); }
public void Update() { // if on target if (this.Seeking && TDMath.PointOnPoint(this.CurrentLocation, target.Location, (int)(this.speed * TDSession.SpeedFactor))) { HitTarget(target as TDEntity); } else { // if on any target type if (target is TDAttacker) { // hit any target for (int i = 0; i < TDSession.thisSession.CurrentLevel.Attackers.Count; i++) { if (TDSession.thisSession.CurrentLevel.Attackers[i] != this.source && TDMath.PointOnPoint(this.CurrentLocation, TDSession.thisSession.CurrentLevel.Attackers[i].Location, TDSession.thisSession.CurrentLevel.Attackers[i].Size)) { HitTarget(TDSession.thisSession.CurrentLevel.Attackers[i] as TDEntity); break; } } } else // if target is TDTower { // hit any tower for (int i = 0; i < TDSession.thisSession.CurrentLevel.Towers.Count; i++) { if (TDMath.PointOnPoint(this.CurrentLocation, TDSession.thisSession.CurrentLevel.Towers[i].Location, TDSession.thisSession.CurrentLevel.Towers[i].Size)) { HitTarget(TDSession.thisSession.CurrentLevel.Towers[i] as TDEntity); break; } } } // move toward target MoveToward(target.Location); } }
private TDAttacker GetFarAttacker(List <TDAttacker> atts) { TDAttacker result = atts[0]; double farthestRange = 0; double rangeToThis = 0; foreach (TDAttacker a in atts) { rangeToThis = TDMath.RangeToTarget(this.Location, a.Location); if (rangeToThis > farthestRange) { farthestRange = rangeToThis; result = a; } } return(result); }
private TDAttacker GetCloseAttacker(List <TDAttacker> atts) { TDAttacker result = atts[0]; double closestRange = 0; double rangeToThis = 0; foreach (TDAttacker a in atts) { rangeToThis = TDMath.RangeToTarget(this.Location, a.Location); if (closestRange == 0 || rangeToThis < closestRange) { closestRange = rangeToThis; result = a; } } return(result); }
private void HitTarget(TDEntity entity) { #region splash if (this.SplashRadius > 0) { DamageRadius(target.Location, this.SplashRadius); // spawn a new explosion TDSession.thisSession.CurrentLevel.Explosions.Add(new TDExplosion(entity.Location, this.SplashRadius)); } #endregion else // not splash { entity.HPCurrent -= this.damage; // apply any effects if (this.Effects != null && this.Effects.Count > 0) { foreach (TDEffect e in this.Effects) { entity.Effects.Add(new TDEffect(e.Effect, e.Power, e.Duration, true)); } } } #region Chaining if (this.ChainCount > 0) { // find the next closest attacker, not the source List <TDEntity> newTargets = GetTowersInRange(entity.Location, this.ChainDist, false, true); // don't hit this source. if (newTargets.Contains(this.source)) { newTargets.Remove(this.source); } // and don't hit this new target itself if (newTargets.Contains(entity)) { newTargets.Remove(entity); } if (newTargets.Count > 0) { // get a random target within this range TDEntity newTarget = newTargets[TDMath.D(newTargets.Count) - 1]; // make a new ammo from this one, TDAmmo newAmmo = new TDAmmo(entity, newTarget); // start from this target hit // reduce the chain count newAmmo.ChainDist = this.ChainDist; newAmmo.ChainCount = this.ChainCount - 1; newAmmo.damage = Math.Max(1, this.damage - 1); // override the damage with the chain decline TDSession.thisSession.CurrentLevel.Ammo.Add(newAmmo); } } #endregion // since ammo dies automatically this.DeleteMe = true; }
private void GenerateAttackersForLevel(int lvl, List <TDPath> Paths) { // waves this._WaveCount = 9 + (lvl); if (testing) { _WaveCount = 0; } // wave attacker type bool mixed = (TDMath.D(100) > 70); // 30% mixed // attackers per wave int attPerWave = 5 + TDMath.D(10 * lvl); if (testing) { attPerWave = 0; } // if 80, then betwen 41 and 80; int ThisWaveDelay = (WaveDelay / 2) + TDMath.D(WaveDelay / 2); if (testing) { ThisWaveDelay = WaveDelay; } int MaxDelay = 0; // for each wave for (int i = 0; i < this._WaveCount; i++) { // set the type and path for this wave AttackerTypes t = GetWeightedAttackerType(false); TDPath p = Paths[TDMath.D(Paths.Count) - 1]; // vary the attacker separation for this wave (between 1/2 and full value) int AttackerDelayWithinThisWave = (AttackerDelayWithinWave / 2) + TDMath.D((AttackerDelayWithinWave / 2)); if (testing) { AttackerDelayWithinThisWave = AttackerDelayWithinWave; } for (int j = 0; j < attPerWave; j++) { // check for mixed attacker type if (mixed && lvl > 3) // don't mix until lvl 4+ { // randomized the type for the next attacker t = GetWeightedAttackerType(true); p = Paths[TDMath.D(Paths.Count) - 1]; } // generate the new attacker TDAttacker a = new TDAttacker(t, lvl); a.WaveIndex = i + 1; int delayMS = Math.Max(1, (i * ThisWaveDelay) + (j * AttackerDelayWithinThisWave)); // slightly stagger each attacker within the wave (j) a.Effects.Add(new TDEffect(TDEffectTypes.WaveDelay, 0, new TimeSpan(0, 0, 0, 0, delayMS), false)); a.SetPath(p); this.Attackers.Add(a); // remember the MaxDelay for the Boss MaxDelay = Math.Max(MaxDelay, delayMS); } } // and finally, add the level boss TDAttacker boss = new TDAttacker(AttackerTypes.Boss, lvl + 10); boss.Size += 4; boss.HPMax = boss.HPMax * 6; boss.HPCurrent = boss.HPMax; int AdditionalBossDelay = 500; if (testing) { AdditionalBossDelay = 10000; } boss.Effects.Add(new TDEffect(TDEffectTypes.WaveDelay, 0, new TimeSpan(0, 0, 0, 0, MaxDelay + AdditionalBossDelay), false)); // 1/2 second after last attacker TDPath pBoss = Paths[TDMath.D(Paths.Count) - 1]; boss.SetPath(pBoss); this.Attackers.Add(boss); }
private bool AttackerrWithinRange(TDAttacker a) { return(TDMath.PointInRange(this.Location, a.Location, this.Range)); }
private bool TowerWithinRange(TDTower tower) { return(TDMath.PointInRange(this.Location, tower.Location, this.Range)); }
private bool OnPoint(TDLocation L1, TDLocation L2) { return(TDMath.PointOnPoint(L1, L2, (int)Math.Max(1, this.SpeedCurrent * TDSession.SpeedFactor))); }
public double DistanceToNextPoint() { return(TDMath.RangeToTarget(this.Location, this.Path.PathPoints[NextPoint].Location)); }
public override void Update() { if (this.CanStart && this.Immune) { this.Immune = false; // update the next wave to be at least this index. TDSession.thisSession.CurrentLevel.WaveStarted = Math.Max(this.WaveIndex, TDSession.thisSession.CurrentLevel.WaveStarted); } // apply any effects if (this.Effects != null && this.Effects.Count > 0) { foreach (TDEffect e in this.Effects) { if (e.Effect == TDEffectTypes.WaveDelay) { if (e.State == TDEffect.TDTimerState.Finished) { e.HasBeenApplied = true; this.CanStart = true; } else if (e.State == TDEffect.TDTimerState.Running && e.DurationRemaining.TotalMilliseconds < 0) { e.State = TDEffect.TDTimerState.Finished; return; } else { // if we have not finished this effect, then we can't start yet. (or do anything else). return; } } #region Slow if (e.Effect == TDEffectTypes.Slow) { if (e.State == TDEffect.TDTimerState.Running) { // slow only applies once if (!e.HasBeenApplied) { // change current speed to effect. this.SpeedCurrent = (this.SpeedMax * (100 - (double)e.Power) / 100); e.HasBeenApplied = true; } } else if (e.State == TDEffect.TDTimerState.Finished) { // only edit if the effect is still applied if (e.HasBeenApplied) { // set the speed back to normal this.SpeedCurrent = this.SpeedMax; // tell the system we have undid the speed change e.HasBeenApplied = false; } } } // end slow #endregion } } // next point if (OnPoint(this.Location, this.Path.PathPoints[NextPoint].Location)) { // change destination to the next point on the path. NextPoint++; // if on last point, then damage lvl HP if (NextPoint >= Path.PathPoints.Count) { TDSession.thisSession.CurrentLevel.HPRemaining -= this.HPCurrent; this.Cost = 0; // no loot for an enemy crashing into your base! DeleteMe = true; return; } } // move toward point MoveToward(this.Path.PathPoints[NextPoint].Location); // check cooldown to see if can fire if (DateTime.Now > this.LastFire + new TimeSpan(0, 0, 0, 0, (int)(this.Cooldown.TotalMilliseconds / TDSession.SpeedFactor))) { // we can, so see if any towers in range List <TDTower> towersInRange = GetTowersInRange(); // check towers in range to fire at if (towersInRange.Count == 0) { // do nothing - no towers } else { // only have a chance to shoot this update (makes the firing more random) if (TDMath.D(100) > 97) { if (towersInRange.Count == 1) { // if one is the destination tower, hit it ShootAtTower(towersInRange[0]); } else if (towersInRange.Count > 1) { // if multiples // future: pick a tower (weakest, strongest, first?) // for now, just shoot the first one ShootAtTower(towersInRange[0]); } LastFire = DateTime.Now; } } // end else - are towers in range } }