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); } } }
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)); } }
public static Roller Range(int min, int max) { return(new Roller( () => Rng.IntInclusive(min, max), (min + max) / 2.0f, min.ToString() + "-" + max.ToString())); }
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); } }
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); } }