예제 #1
0
        public IEnumerable <T> Create(int level)
        {
            // modify the level randomly
            int walkedLevel = Rng.WalkLevel(level).Clamp(1, 100);

            // choose up to it (best of two tries)
            int choiceValue = Math.Max(Rng.IntInclusive(walkedLevel),
                                       Rng.IntInclusive(walkedLevel));

            IDrop <T> dropped = null;

            // count through to find the last one at least the random level
            foreach (DropChoice choice in Choices)
            {
                if (choiceValue >= choice.Odds)
                {
                    dropped = choice.Drop;
                }
            }

            // drop it if we have one
            if (dropped != null)
            {
                // if the choice was less than the max, then bump up the subsequent level a bit to compensate
                int bonus = (walkedLevel - choiceValue) / 4;

                level = Math.Max(Game.MaxDepth, level + bonus);

                foreach (var item in dropped.Create(level))
                {
                    yield return(item);
                }
            }
        }
예제 #2
0
        private void InitBuildings(Content content, List <Rect> maxSizes)
        {
            if (maxSizes.Count != 6)
            {
                throw new ArgumentException("Should have the max sizes for 6 buildings.");
            }

            List <TileType> buildings = new List <TileType>()
            {
                TileType.DoorStore1, TileType.DoorStore2, TileType.DoorStore3,
                TileType.DoorStore4, TileType.DoorStore5, TileType.DoorStore6
            };

            // make each building
            foreach (Rect maxSize in maxSizes)
            {
                // pick an actual rect within it
                Vec size = new Vec(Rng.Int(6, maxSize.Width), Rng.Int(4, maxSize.Height));
                Vec pos  = maxSize.Position + Rng.Vec(maxSize.Size - size);

                Rect bounds = new Rect(pos, size);

                // pick the type
                int index = Rng.Int(buildings.Count);
                while (buildings[index] == TileType.Floor)
                {
                    index = (index + 1) % 6;
                }

                TileType type = buildings[index];
                // don't use this store again
                buildings[index] = TileType.Floor;

                Store store = new Store(content.Stores[index]);

                Vec doorPos = new Vec(Rng.IntInclusive(bounds.Left + 1, bounds.Right - 1), bounds.Bottom - 1);
                mBuildings.Add(new Building(store, type, bounds, doorPos));
            }
        }
예제 #3
0
 public static Roller Range(int min, int max)
 {
     return(new Roller(
                () => Rng.IntInclusive(min, max),
                (min + max) / 2.0f, min.ToString() + "-" + max.ToString()));
 }
예제 #4
0
        public override void Hit(Action action, Hit hit)
        {
            bool madeContact = true;

            // give the entity a chance to dodge
            if (hit.CanDodge)
            {
                // ask the defender how hard it is to hit
                int strike = GetDodge();

                // modify it by how good this entity is at hitting
                // subtract so that a positive bonus is good for the attacker
                strike -= hit.Attack.StrikeBonus;

                // keep it in bounds
                strike = strike.Clamp(5, 95);

                int strikeRoll = Rng.IntInclusive(1, 100);

                madeContact = (strikeRoll >= strike);
            }

            // see if we hit
            if (madeContact)
            {
                // damage the defender
                hit.SetDamage(ReceiveDamage(hit.Attack));

                // if damage was actually done
                if (hit.Damage > 0)
                {
                    // only need to add the effect here if it's conditional on dodging. otherwise it's already been addded
                    if (hit.CanDodge)
                    {
                        action.AddEffect(hit.CreateEffect(Position));
                    }

                    Hero actingHero     = Dungeon.Game.ActingEntity as Hero;
                    bool attackerIsHero = (actingHero != null);

                    if (Health.Current <= 0)
                    {
                        action.Log(LogType.Good, hit.Attacker, "{subject} kill[s] {object}.", this);

                        // if a monster was killed by the hero, tell the hero so he can gain experience
                        Monster killed = this as Monster;
                        if ((killed != null) && (actingHero != null))
                        {
                            actingHero.Killed(action, killed);
                        }

                        Die(action);
                    }
                    else
                    {
                        action.Log(LogType.Good, hit.Attacker, "{subject} " + hit.Attack.Verb + " {object} for " + hit.Damage + " damage.", this);

                        // tell the user about the resists
                        float  resist  = OnGetResistance(hit.Attack.Element);
                        string element = hit.Attack.Element.ToString().ToLower();

                        if (resist < 1.0f)
                        {
                            action.Log(LogType.Resist, this, "{subject} resist[s] " + element + ".");
                        }
                        else if (resist > 1.0f)
                        {
                            action.Log(LogType.Resist, this, "{subject} [are|is] weak against " + element + ".");
                        }

                        // tell the user about the slays
                        float slays = OnGetSlays(hit.Attack.Flags);
                        if (slays < 1.0f)
                        {
                            action.Log(LogType.Resist, "The attack is ineffective on {object}.", this);
                        }
                        else if (slays > 4.0f)
                        {
                            action.Log(LogType.Resist, "The attack is deadly against {object}.", this);
                        }
                        else if (slays > 2.0f)
                        {
                            action.Log(LogType.Resist, "The attack is especially effective against {object}.", this);
                        }
                        else if (slays > 1.0f)
                        {
                            action.Log(LogType.Resist, "The attack is effective against {object}.", this);
                        }

                        AfterDamage(action, hit);
                    }
                }
                else
                {
                    // tell why no damage was done
                    float  resist  = OnGetResistance(hit.Attack.Element);
                    string element = hit.Attack.Element.ToString().ToLower();
                    float  slays   = OnGetSlays(hit.Attack.Flags);

                    if (resist == 0)
                    {
                        action.Log(LogType.Message, this, "{subject} [are|is] immune to " + element + ".");
                    }
                    else if (slays == 0)
                    {
                        action.Log(LogType.Message, this, "{subject} [are|is] impervious to the attack.");
                    }
                    else
                    {
                        // armor absorbed all of the damage
                        action.Log(LogType.Message, this, "{subject} [are|is] unhurt by {object}.", hit.Attacker);
                    }
                }
            }
            else
            {
                // miss
                action.Log(LogType.Message, hit.Attacker, "{subject} miss[es] {object}.", this);
            }
        }
예제 #5
0
        public IEnumerable <T> Create(int level)
        {
            // find the drops before and after the level
            int before = -1;
            int after  = -1;

            for (int i = 0; i < Choices.Count; i++)
            {
                if (Choices[i].Odds <= level)
                {
                    before = i;
                }
                else if (Choices[i].Odds >= level)
                {
                    after = i;
                    break;
                }
            }

            if (before == -1)
            {
                before = after;
            }
            if (after == -1)
            {
                after = before;
            }

            // choose between the two drops, weighted by the level's distance to each one
            int index = before;

            if (before != after)
            {
                if (Rng.IntInclusive((int)Choices[before].Odds, (int)Choices[after].Odds) <= level)
                {
                    index = after;
                }
                else
                {
                    index = before;
                }
            }

            const int ChanceOfDecrement = 40; // out of 100
            const int ChanceOfIncrement = 10;

            // randomly walk through the drops
            if (Rng.Int(100) < ChanceOfDecrement)
            {
                // walk down
                while (index > 0)
                {
                    index--;

                    if (Rng.Int(100) >= ChanceOfDecrement)
                    {
                        break;
                    }
                }
            }
            else if (Rng.Int(100) < ChanceOfIncrement)
            {
                // walk up
                while (index < Choices.Count - 1)
                {
                    index++;

                    if (Rng.Int(100) >= ChanceOfIncrement)
                    {
                        break;
                    }
                }
            }

            // drop it
            foreach (var item in Choices[index].Drop.Create(level))
            {
                yield return(item);
            }
        }