Example #1
0
        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);
            }
        }
Example #2
0
        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;
        }
Example #3
0
        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);
        }
Example #4
0
        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
            }
        }