public CombatRound Hit(Player player) { var round = new CombatRound(); // roll to hit, if success, then hit if (Server.Current.Random.Next(HitRoll) + 1 >= player.Armor) { // hit var damage = Server.Current.Random.Next(DamRoll) + 1; player.HitPoints -= damage; var damageAction = CombatHelper.GetDamageAction(player, damage); var playerText = string.Format("{0} {1} you for {2} damage!\n", Name, damageAction.Plural, damage); round.AddText(player, playerText, CombatTextType.Player); var groupText = string.Format("{0} {1} {2}!\n", Name, damageAction.Plural, player.Forename); round.AddText(player, groupText, CombatTextType.Group); } else { // miss var playerText = string.Format("{0} misses you!", Name); round.AddText(player, playerText, CombatTextType.Player); var groupText = string.Format("{0} misses {1}!\n", Name, player.Forename); round.AddText(player, groupText, CombatTextType.Group); } if (!_skillLoopStarted && Skills.Count > 0) { doSkillLoop(null, null); } return(round); }
public override void Execute(Session session, CommandContext context) { if (string.IsNullOrEmpty(context.ArgumentString)) { session.WriteLine("{0} what?", context.CommandName); return; } var arg1 = context.ArgumentString.ToLower(); // command lookup, should never be null or command lookup will handle // level check should already be done by command lookup var skill = Server.Current.Database.Get <CombatSkill>(realCommandName); // skill check i.e. does player have it? if (!session.Player.Skills.ContainsKey(skill.Key)) { session.WriteLine("You haven't practiced that yet."); return; } // status check, start combat if not already there if (session.Player.Status != GameStatus.Fighting && session.Player.Status != GameStatus.Standing) { session.WriteLine("You can't do that right now."); return; } // target check var room = RoomHelper.GetRoom(session.Player.Location); var target = room.GetNpcs().FirstOrDefault(n => n.Keywords.Contains(arg1)); if (target == null) { session.WriteLine("You can't find that here."); return; } // combat check var fight = Server.Current.CombatHandler.FindFight(session.Player); if (fight == null) { // start fight, since npc is found fight = new Game.Combat(); fight.AddFighter(session.Player); fight.AddMob(target); Server.Current.CombatHandler.StartFight(fight); } // do it if (Server.Current.Random.NextDouble() < session.Player.Skills[skill.Key]) { // get damage var damage = Server.Current.Random.Next(skill.MinDamage, skill.MaxDamage + 1); // hit target.HitPoints -= damage; // increase skill effectiveness if (session.Player.Skills[skill.Key] < skill.MaxEffectiveness) { session.Player.Skills[skill.Key] += skill.HitEffectivenessIncrease + target.HitPoints <= 0 ? skill.KillingBlowEffectivenessIncrease : 0; } var damageAction = CombatHelper.GetDamageAction(target, damage); // message session.WriteLine("Your {0} {1} {2} for {3} damage!", realCommandName, damageAction.Plural, target.Name, damage); // room message room.SendPlayers( string.Format("{0}{1} {2} {3} {4}!", session.Player.Forename, session.Player.Forename.ToLower().EndsWith("s") ? "'" : "s", skill.Key, damageAction.Plural, target.Name), session.Player, null, session.Player); // dead check // this feels hacky since it sort of duplicates some of the work of Combat.DoPlayerHits() if (target.HitPoints <= 0) { fight.RemoveFromCombat(target); target.Die(); var deadText = string.Format("`R{0} is DEAD!!!", target.Name); session.WriteLine(deadText); room.SendPlayers(deadText, session.Player, null, session.Player); } } else { // message session.WriteLine("Your {0} misses {1}!", realCommandName, target.Name); // room message room.SendPlayers(string.Format("{0}{1} {2} misses {3}!", session.Player.Forename, session.Player.Forename.ToLower().EndsWith("s") ? "'" : "s", skill.Key, target.Name), session.Player, null, session.Player); // increase skill effectiveness by less session.Player.Skills[skill.Key] += skill.MissEffectivenessIncrease; } }
private void doSkillLoop(object sender, ElapsedEventArgs e) { _skillLoopStarted = true; _skillReady = true; if (HitPoints > 0) // don't try to hit if dead { // get random skill and delay var keys = new List <string>(Skills.Keys); var size = Skills.Count; var skillKey = keys[Server.Current.Random.Next(size)]; var skill = Server.Current.CombatSkills.FirstOrDefault(s => s.Key == skillKey); var command = Server.Current.CommandLookup.FindCommand(skillKey, true); if (skill == null || command == null) { Server.Current.Log(string.Format("Can't find NPC skill: {0}", skillKey)); return; } var frequency = Skills[skillKey].Item1; var effectiveness = Skills[skillKey].Item2; // if frequency check hits if (Server.Current.Random.NextDouble() < frequency) { // find the fight var fight = Server.Current.CombatHandler.FindFight(this); if (fight == null) { return; } // get random player to hit var playerToHit = fight.GetFighters().OrderBy(x => Guid.NewGuid()).FirstOrDefault(); if (playerToHit == null) { return; } // get room var room = RoomHelper.GetPlayerRoom(playerToHit.Location); // if effectiveness hits if (Server.Current.Random.NextDouble() < effectiveness) { // do skill hit var damage = Server.Current.Random.Next(skill.MinDamage, skill.MaxDamage + 1); var damageAction = CombatHelper.GetDamageAction(playerToHit, damage); // message playerToHit.Send(string.Format("{0}{1} {2} {3} you for {4} damage!", Name, Name.EndsWith("s") ? "'" : "'s", skillKey.ToLower(), damageAction.Plural, damage), null); playerToHit.HitPoints -= damage; room.SendPlayers( string.Format("{0}{1} {2} {3} {4}", Name, Name.EndsWith("s") ? "'" : "'s", skillKey.ToLower(), damageAction.Plural, playerToHit.Forename), playerToHit, null, playerToHit); // check if player dead if (playerToHit.HitPoints <= 0) { // almost identical code used in combat handler when mob kills player in normal combat playerToHit.Die(); // changes status var statusText = Player.GetStatusText(playerToHit.Status).ToUpper(); var playerText = string.Format("You are {0}!!!", statusText); if (playerToHit.HitPoints < Server.DeadHitPoints) { playerText += " You have respawned, but you're in a different location.\n" + "Your corpse will remain for a short while, but you'll want to retrieve your\n" + "items in short order."; playerToHit.DieForReal(); } var groupText = string.Format("{0} is {1}!!!", playerToHit.Forename, statusText); playerToHit.Send(playerText, null); room.SendPlayers(groupText, playerToHit, null, playerToHit); fight.RemoveFromCombat(playerToHit); if (!fight.GetFighters().Any()) { fight.End(); return; // so timer doesn't start again } } } else { // miss message playerToHit.Send(string.Format("{0}{1} {2} misses you!", Name, Name.EndsWith("s") ? "'" : "'s", skillKey.ToLower()), null); room.SendPlayers( string.Format("{0}{1} {2} misses {3}", Name, skillKey.EndsWith("s") ? "'" : "'s", skillKey.ToLower(), playerToHit.Forename), playerToHit, null, playerToHit); } } _skillReady = false; // set delay and call this method again var t = new Timer() { AutoReset = false, Interval = (long)command.TickLength, }; t.Elapsed += doSkillLoop; t.Start(); } }