#region Arthea License /*********************************************************************** * Arthea MUD by R. Jennings (2007) http://arthea.googlecode.com/ * * By using this code you comply with the Artistic and GPLv2 Licenses. * ***********************************************************************/ #endregion using System.Collections.Generic; using Arthea.Abilities; using Arthea.Connections.Players; using Arthea.Continents.Areas.Characters; using Arthea.Continents.Areas.Characters.Enums; using Arthea.Environment; namespace Arthea.Collections { /// <summary> /// Implementation of combat. /// </summary> public class Combat : List<Character> { #region [rgn] Constructors (2) /// <summary> /// Initializes a new instance of the <see cref="Combat"/> class. /// </summary> /// <param name="collection">The collection whose elements are copied to the new list.</param> /// <exception cref="T:System.ArgumentNullException">collection is null.</exception> public Combat(IEnumerable<Character> collection) : base(collection) { } /// <summary> /// Initializes a new instance of the <see cref="Combat"/> class. /// </summary> public Combat() { } #endregion [rgn] #region [rgn] Methods (6) // [rgn] Public Methods (5) /// <summary> /// Damages the specified skill. /// </summary> /// <param name="skill">The skill.</param> /// <param name="killer">The killer.</param> /// <param name="victim">The victim.</param> /// <param name="dam">The dam.</param> public static void Damage(Ability skill, Character killer, Character victim, int dam) { if (victim.Position == Position.Dead) return; if (victim.Fighting == null) victim.Fighting = killer; if (killer.Fighting == null) killer.Fighting = victim; DamMessage(skill, killer, victim, dam); victim.Hit -= dam; if (victim.Hit <= 0) { killer.Act(null, victim, Act.ToPlayer, "$N is dead!"); killer.Act(null, victim, Act.ToVictim, "$n has killed you!"); killer.Act(null, victim, Act.ToRoom, "$n has killed $N!"); killer.Fighting = null; victim.Fighting = null; if (victim is Player) { victim.Room = Lists.Rooms[Globals.Limbo]; } else { victim.Release(); } if (killer is Player) { Player p = killer as Player; int xp = CalcExp(p, victim); p.Experience += xp; p.WriteLine("You gain {0} experience points!", xp); if (p.CanGainLevel()) { p.WriteLine("You can gain another level."); } } } } /// <summary> /// The damage message. /// </summary> /// <param name="skill">The skill.</param> /// <param name="killer">The killer.</param> /// <param name="victim">The victim.</param> /// <param name="dam">The dam.</param> public static void DamMessage(Ability skill, Character killer, Character victim, int dam) { int damp = (dam*100)/victim.MaxHit; string vs, vp, punc; if (damp <= 0) { vs = "miss"; vp = "misses"; } else if (damp <= 2) { vs = "bruise"; vp = "bruises"; } else if (damp <= 5) { vs = "scratch"; vp = "scratches"; } else if (damp <= 9) { vs = "hit"; vp = "hits"; } else if (damp <= 13) { vs = "scar"; vp = "scars"; } else if (damp <= 18) { vs = "injure"; vp = "injures"; } else if (damp <= 23) { vs = "wound"; vp = "wounds"; } else if (damp <= 28) { vs = "maul"; vp = "mauls"; } else if (damp <= 34) { vs = "DECIMATE"; vp = "DECIMATES"; } else if (damp <= 40) { vs = "DEVASTATE"; vp = "DEVASTATES"; } else if (damp <= 46) { vs = "OBLITERATE"; vp = "OBLITERATES"; } else if (damp <= 53) { vs = "MUTILATE"; vp = "MUTILATES"; } else if (damp <= 60) { vs = "DISEMBOWEL"; vp = "DISEMBOWELS"; } else if (damp <= 67) { vs = "*** DEMOLISH ***"; vp = "*** DEMOLISHES ***"; } else if (damp <= 75) { vs = "-=- PULVERIZE -=-"; vp = "-=- PULVERIZES -=-"; } else if (damp <= 83) { vs = "<-&-> WASTE <-&->"; vp = "<-&-> WASTES <-&->"; } else if (damp <= 91) { vs = "<::><::> DISFIGURE <::><::>"; vp = "<::><::> DISFIGURES <::><::>"; } else { vs = "inflict UNIMAGINABLE PAIN on"; vp = "inflicts UNIMAGINABLE PAIN on"; } punc = damp < 10 ? "." : damp < 30 ? "!" : damp < 45 ? "!!" : damp < 60 ? "!!!" : damp < 75 ? "!!!!" : damp < 90 ? "!!!!!!" : "!!!!!!!!"; if (skill == null) { if (killer == victim) { killer.Act(null, null, Act.ToRoom, "$n {0} $m{1}", vp, punc); killer.Act(null, null, Act.ToPlayer, "You {0} yourself{1}", vs, punc); } else { killer.Act(null, victim, Act.ToPlayer, "You {0} $N{1}", vs, punc); killer.Act(null, victim, Act.ToVictim, "$n {0} you{1}", vp, punc); killer.Act(null, victim, Act.ToRoom, "$n {0} $N{1}", vp, punc); } } else { if (killer == victim) { killer.Act(null, null, Act.ToRoom, "$n's {0} {1} $m{2}", skill.DamageNoun, vp, punc); killer.Act(null, null, Act.ToPlayer, "Your {0} {1} yourself{2}", skill.DamageNoun, vp, punc); } else { killer.Act(null, victim, Act.ToPlayer, "Your {0} {1} $N{2}", skill.DamageNoun, vp, punc); killer.Act(null, victim, Act.ToVictim, "$n's {0} {1} you{2}", skill.DamageNoun, vp, punc); killer.Act(null, victim, Act.ToRoom, "$n's {0} {1} $N{2}", skill.DamageNoun, vp, punc); } } } /// <summary> /// Multis the hit. /// </summary> /// <param name="killer">The killer.</param> /// <param name="victim">The victim.</param> public static void MultiHit(Character killer, Character victim) { OneHit(killer, victim); } /// <summary> /// Ones the hit. /// </summary> /// <param name="killer">The killer.</param> /// <param name="victim">The victim.</param> public static void OneHit(Character killer, Character victim) { int ac = 10 + victim.Armor; int roll = Randomizer.Next(20); if (killer is Player) { roll *= (killer as Player).Class.BaseAttackMod; roll /= 100; } if (roll < ac) { killer.Act(null, victim, Act.ToPlayer, "You miss $N."); killer.Act(null, victim, Act.ToVictim, "$n misses you."); killer.Act(null, victim, Act.ToRoom, "$n misses $N."); return; } int dam = Randomizer.Next(killer.Level/3, killer.Level); Damage(null, killer, victim, dam); } /// <summary> /// Updates this instance. /// </summary> public void Update() { if (Count == 0) { return; } // leading line foreach (Character ch in this) { if (ch is Player) ch.WriteLine(); } for (int i = 0; i < Count;) { if (this[i].Fighting == null) { RemoveAt(i); continue; } if (this[i].Room != this[i].Fighting.Room) { this[i].Fighting = null; continue; } MultiHit(this[i], this[i].Fighting); i++; } } // [rgn] Private Methods (1) private static int CalcExp(Character killer, Character victim) { int levelRange = victim.Level - killer.Level; int xp; switch (levelRange) { default: xp = 0; break; case -9: xp = 1; break; case -8: xp = 2; break; case -7: xp = 5; break; case -6: xp = 9; break; case -5: xp = 11; break; case -4: xp = 22; break; case -3: xp = 33; break; case -2: xp = 50; break; case -1: xp = 66; break; case 0: xp = 83; break; case 1: xp = 99; break; case 2: xp = 121; break; case 3: xp = 143; break; case 4: xp = 165; break; } if (levelRange > 4) xp = 160 + 20*(levelRange - 4); return Randomizer.Next(xp*3/4, xp*5/4); } #endregion [rgn] } }