/// <summary> /// Get the next move to use /// </summary> /// <param name="lastAttack">Was there an attack last go</param> /// <returns>The next art to use</returns> public IFightingArt GetNext(IFightingArt lastAttack) { var nextAttack = Arts.FirstOrDefault(); try { if (lastAttack != null) { if (string.IsNullOrWhiteSpace(lastAttack.RekkaKey) || lastAttack.RekkaPosition < 0) { var myIndex = Arts.ToList().IndexOf(lastAttack); nextAttack = Arts.Skip(myIndex + 1).FirstOrDefault(); } else { nextAttack = Arts.FirstOrDefault(art => !string.IsNullOrWhiteSpace(art.RekkaKey) && art.RekkaKey.Equals(lastAttack.RekkaKey) && art.RekkaPosition == lastAttack.RekkaPosition + 1); } if (nextAttack == null) { //just throwing to redefault throw new Exception(); } } } catch (Exception ex) { LoggingUtility.LogError(ex); nextAttack = Arts.FirstOrDefault(); } return(nextAttack); }
/// <summary> /// Is this art valid to be used at the moment /// </summary> /// <param name="actor">who's doing the hitting</param> /// <param name="victim">who's being hit</param> /// <returns>yea or nay</returns> public bool IsValid(IMobile actor, IMobile victim, ulong distance, IFightingArt lastAttack = null) { return(distance.IsBetweenOrEqual(DistanceRange.Low, DistanceRange.High) && actor.CurrentHealth >= Health.Actor && actor.CurrentStamina >= Stamina.Actor && (lastAttack == null || (lastAttack.RekkaKey.Equals(RekkaKey) && lastAttack.RekkaPosition == RekkaPosition - 1))); }
/// <summary> /// Make the output messaging /// </summary> /// <returns>actor, target, room</returns> private static Tuple <string, string, string> GetOutputStrings(IFightingArt attack, IMobile target, bool blocked, ReadinessState avoidanceType) { var targetGlyph = target == null ? "a shadow" : "$T$"; var actorTargetGlyph = target == null ? "your shadow" : "$T$"; var verb = !string.IsNullOrWhiteSpace(attack.ActionVerb) ? attack.ActionVerb : attack.Name; var subject = !string.IsNullOrWhiteSpace(attack.ActionSubject) ? attack.ActionSubject + " " : string.Empty; var obj = !string.IsNullOrWhiteSpace(attack.ActionPredicate) ? "and " + attack.ActionPredicate + " " : string.Empty; string toOrigin = string.Format("$A$ {0}s {3}{2}{1}.", verb, targetGlyph, obj, subject); string toActor = string.Format("You {0} {3}{2}{1}.", verb, actorTargetGlyph, obj, subject); string toTarget = ""; if (target != null) { toTarget = string.Format("$A$ {0}s {1}you.", verb, obj); if (blocked) { switch (avoidanceType) { case ReadinessState.Circle: //circle is dodge essentially toActor = string.Format("{0} dodges your attack!", actorTargetGlyph); toTarget = string.Format("You dodge $A$'s {0}.", verb); toOrigin = string.Format("$A$ {0}s {2}{1} but they dodge.", verb, targetGlyph, subject); break; case ReadinessState.Block: toActor = string.Format("You {0} {2}{1} but they block!", verb, actorTargetGlyph, subject); toTarget = string.Format("$A$ {0}s {1}you but you block it.", verb, subject); toOrigin = string.Format("$A$ {0}s {2}{1} but they block.", verb, targetGlyph, subject); break; case ReadinessState.Deflect: toActor = string.Format("You {0} {2}{1} but they deflect it!", verb, actorTargetGlyph, subject); toTarget = string.Format("$A$ {0}s {1}you but you deflect it.", verb, subject); toOrigin = string.Format("$A$ {0}s {2}{1} but they deflect the blow.", verb, targetGlyph, subject); break; case ReadinessState.Redirect: toActor = string.Format("{0} redirects your attack back to you!", actorTargetGlyph); toTarget = string.Format("You redirect $A$s {0} back at them.", verb); toOrigin = string.Format("$A$ {0}s {2}{1} but they redirect the attack back at them.", verb, targetGlyph, subject); break; case ReadinessState.Offensive: //successful clash toActor = string.Format("{0}'s attack clashes with yours!", actorTargetGlyph); toTarget = string.Format("Your attack clashes with $A$'s.", verb); toOrigin = string.Format("$A$'s {0} clashes with {1}'s attack.", verb, targetGlyph); break; } } } return(new Tuple <string, string, string>(toActor, toTarget, toOrigin)); }
public ActionResult FightingArtEdit(int id, AddEditFightingArtViewModel vModel) { ApplicationUser authedUser = UserManager.FindById(User.Identity.GetUserId()); IFightingArt obj = TemplateCache.Get <IFightingArt>(id); if (obj == null) { string message = "That does not exist"; return(RedirectToRoute("Index", new { StatusMessage = message })); } if (vModel.DataObject.CalculateCostRatio() > 0) { ViewData.Add("Message", "The Calculated Cost must be equal to or below zero."); return(View("~/Views/Manage/FightingArtEdit.cshtml", vModel)); } obj.Name = vModel.DataObject.Name; obj.ActorCriteria = vModel.DataObject.ActorCriteria; obj.Aim = vModel.DataObject.Aim; obj.Armor = vModel.DataObject.Armor; obj.DistanceChange = vModel.DataObject.DistanceChange; obj.DistanceRange = vModel.DataObject.DistanceRange; obj.Health = vModel.DataObject.Health; obj.HelpText = vModel.DataObject.HelpText; obj.Impact = vModel.DataObject.Impact; obj.PositionResult = vModel.DataObject.PositionResult; obj.Recovery = vModel.DataObject.Recovery; obj.RekkaKey = vModel.DataObject.RekkaKey; obj.RekkaPosition = vModel.DataObject.RekkaPosition; obj.Setup = vModel.DataObject.Setup; obj.Stamina = vModel.DataObject.Stamina; obj.VictimCriteria = vModel.DataObject.VictimCriteria; obj.ResultQuality = vModel.DataObject.ResultQuality; obj.AdditiveQuality = vModel.DataObject.AdditiveQuality; obj.QualityValue = vModel.DataObject.QualityValue; obj.Readiness = vModel.DataObject.Readiness; obj.ActionVerb = vModel.DataObject.ActionVerb; obj.ActionPredicate = vModel.DataObject.ActionPredicate; if (obj.Save(authedUser.GameAccount, authedUser.GetStaffRank(User))) { LoggingUtility.LogAdminCommandUsage("*WEB* - EditFightingArt[" + obj.Id.ToString() + "]", authedUser.GameAccount.GlobalIdentityHandle); } else { } return(RedirectToAction("Index")); }
public ActionResult FightingArtRemove(long removeId = -1, string authorizeRemove = "", long unapproveId = -1, string authorizeUnapprove = "") { string message; if (!string.IsNullOrWhiteSpace(authorizeRemove) && removeId.ToString().Equals(authorizeRemove)) { ApplicationUser authedUser = UserManager.FindById(User.Identity.GetUserId()); IFightingArt obj = TemplateCache.Get <IFightingArt>(removeId); if (obj == null) { message = "That does not exist"; } else if (obj.Remove(authedUser.GameAccount, authedUser.GetStaffRank(User))) { LoggingUtility.LogAdminCommandUsage("*WEB* - RemoveRoom[" + removeId.ToString() + "]", authedUser.GameAccount.GlobalIdentityHandle); message = "Delete Successful."; } else { message = "Error; Removal failed."; } } else if (!string.IsNullOrWhiteSpace(authorizeUnapprove) && unapproveId.ToString().Equals(authorizeUnapprove)) { ApplicationUser authedUser = UserManager.FindById(User.Identity.GetUserId()); IFightingArt obj = TemplateCache.Get <IFightingArt>(unapproveId); if (obj == null) { message = "That does not exist"; } else if (obj.ChangeApprovalStatus(authedUser.GameAccount, authedUser.GetStaffRank(User), ApprovalState.Returned)) { LoggingUtility.LogAdminCommandUsage("*WEB* - UnapproveRoom[" + unapproveId.ToString() + "]", authedUser.GameAccount.GlobalIdentityHandle); message = "Unapproval Successful."; } else { message = "Error; Unapproval failed."; } } else { message = "You must check the proper remove or unapprove authorization radio button first."; } return(RedirectToAction("Index", new { Message = message })); }
public ActionResult Add(AddEditFightingArtViewModel vModel) { string message = string.Empty; ApplicationUser authedUser = UserManager.FindById(User.Identity.GetUserId()); IFightingArt newObj = vModel.DataObject; if (newObj.Create(authedUser.GameAccount, authedUser.GetStaffRank(User)) == null) { message = "Error; Creation failed."; } else { LoggingUtility.LogAdminCommandUsage("*WEB* - AddFightingArt[" + newObj.Id.ToString() + "]", authedUser.GameAccount.GlobalIdentityHandle); } return(RedirectToAction("Index", new { Message = message })); }
public ActionResult FightingArtEdit(int id) { string message = string.Empty; IFightingArt obj = TemplateCache.Get <IFightingArt>(id); if (obj == null) { message = "That does not exist"; return(RedirectToRoute("ErrorOrClose", new { Message = message })); } AddEditFightingArtViewModel vModel = new AddEditFightingArtViewModel { AuthedUser = UserManager.FindById(User.Identity.GetUserId()), DataObject = obj, }; return(View("~/Views/Manage/FightingArtEdit.cshtml", vModel)); }
public ActionResult FightingArtAdd(AddEditFightingArtViewModel vModel) { string message = string.Empty; ApplicationUser authedUser = UserManager.FindById(User.Identity.GetUserId()); IFightingArt newObj = vModel.DataObject; if (newObj.CalculateCostRatio() > 0) { ViewData.Add("Message", "The Calculated Cost must be equal to or below zero."); return(View("~/Views/Manage/FightingArtAdd.cshtml", vModel)); } if (newObj.Create(authedUser.GameAccount, authedUser.GetStaffRank(User)) == null) { message = "Error; Creation failed."; } else { LoggingUtility.LogAdminCommandUsage("*WEB* - AddFightingArt[" + newObj.Id.ToString() + "]", authedUser.GameAccount.GlobalIdentityHandle); } return(RedirectToAction("FightingArts", new { Message = message })); }
/// <summary> /// Execute an attack round /// </summary> /// <param name="actor">the person attacking</param> /// <param name="target">the person defending</param> public static bool ExecuteRound(IMobile actor, IMobile target) { //Stagger clearance comes before ending a fight if (actor.Stagger > 0) { actor.Stagger -= 1; //Send a ui update actor.WriteTo(null); return(true); } if (!actor.IsFighting()) { return(false); } if (actor == target) { target = null; } IFightingArt attack = actor.LastAttack; var rand = new Random(); //If we lack an attack or we're on the tail end of the attack just find a new one and start it if (attack == null || !actor.Executing) { IFightingArtCombination myCombo = actor.LastCombo; if (myCombo == null) { var weights = GetUsageWeights(actor, target); ulong distance = 0; if (target != null) { distance = 1; } var validCombos = actor.Combos.Where(combo => combo.IsValid(actor, target, distance)); if (validCombos.Count() == 0) { myCombo = actor.Combos.OrderByDescending(combo => weights[combo.SituationalUsage] * rand.NextDouble()).FirstOrDefault(); } else { myCombo = validCombos.OrderByDescending(combo => weights[combo.SituationalUsage] * rand.NextDouble()).FirstOrDefault(); } } //uhh k we need to use a fake combo logic to get a random attack if (myCombo == null) { var attacks = TemplateCache.GetAll <IFightingArt>(true); attack = attacks.Where(atk => atk.IsValid(actor, target, (ulong)Math.Abs(actor.Balance))).OrderBy(atk => Guid.NewGuid()).FirstOrDefault(); } else { attack = myCombo.GetNext(actor.LastAttack); } if (attack == null) { //we have no valid attacks, so we're tired actor.Stagger += 10; actor.Sleep(1); //recover stamina actor.WriteTo(null); return(true); } actor.Stagger = attack.Setup; actor.Sturdy = attack.Armor; actor.LastCombo = myCombo; actor.LastAttack = attack; actor.Executing = true; if (actor.Stagger > 0) { actor.Stagger -= 1; //Send a ui update actor.WriteTo(null); return(true); } //else we just run right into the combo if there's no setup } //execute the attack actor.Executing = false; //basics actor.Stagger = attack.Recovery; actor.LastAttack = attack; actor.LastCombo = null; actor.Balance = attack.DistanceChange; //numbers damage if (attack.Health.Actor > 0) { actor.Harm(attack.Health.Actor); } if (attack.Stamina.Actor > 0) { actor.Exhaust(attack.Stamina.Actor); } Tuple <string, string, string> messaging = null; if (target != null) { target.Balance = -1 * attack.DistanceChange; var targetReadiness = ReadinessState.Offensive; //attacking is default var targetDirection = AnatomyAim.Mid; //mid is default if (target.LastAttack != null) { targetReadiness = target.LastAttack.Readiness; targetDirection = target.LastAttack.Aim; } //TODO: for now we're just doing flat chances for avoidance states since we have no stats to base anything on var avoided = false; var blocked = false; double impact = attack.Impact; double damage = attack.Health.Victim; double staminaDrain = attack.Stamina.Victim; var aimDifferential = Math.Abs(attack.Aim - targetDirection); //no blocking if it's not an attack if (attack.Readiness != ReadinessState.Offensive || attack.Health.Victim > 0) { switch (targetReadiness) { case ReadinessState.Circle: //circle is dodge essentially avoided = rand.Next(0, 100) <= Math.Max(1, Math.Abs(target.Balance)) / (Math.Max(1, aimDifferential + target.Stagger) * 4) * 100; break; case ReadinessState.Block: blocked = rand.Next(0, 100) <= Math.Max(1, Math.Abs(target.Balance)) / (Math.Max(1, aimDifferential + target.Stagger) * 2) * 100; if (blocked) { impact *= .25; damage *= .50; staminaDrain *= .50; } ; break; case ReadinessState.Deflect: blocked = rand.Next(0, 100) <= Math.Max(1, Math.Abs(target.Balance)) / (Math.Max(1, aimDifferential + target.Stagger) * 2) * 100; if (blocked) { impact *= .50; damage *= .25; staminaDrain *= .25; } break; case ReadinessState.Redirect: avoided = rand.Next(0, 100) <= Math.Max(1, Math.Abs(target.Balance)) / (Math.Max(1, aimDifferential + target.Stagger) * 20) * 100; break; case ReadinessState.Offensive: //Clash mechanics, only works if the target is mid-execution if (target.LastAttack != null && aimDifferential == 0 && target.Executing) { var impactDifference = target.LastAttack.Impact + target.LastAttack.Armor - attack.Impact; if (impactDifference > 0) { blocked = true; impact = 0; damage /= impactDifference; staminaDrain *= .75; } } break; } } messaging = GetOutputStrings(attack, target, avoided || blocked, targetReadiness); if (!avoided) { var victStagger = target.Sturdy - (int)Math.Truncate(impact); //Affect the victim, sturdy/armor absorbs stagger impact and the remainder gets added to victim stagger target.Sturdy = Math.Max(0, victStagger); target.Stagger += Math.Abs(Math.Min(0, victStagger)); if (damage > 0) { target.Harm((int)Math.Truncate(damage)); } if (staminaDrain > 0) { target.Exhaust((int)Math.Truncate(staminaDrain)); } //affect qualities if (attack.QualityValue != 0 && !string.IsNullOrWhiteSpace(attack.ResultQuality)) { target.SetQuality(attack.QualityValue, attack.ResultQuality, attack.AdditiveQuality); } } } else { messaging = GetOutputStrings(attack, target, false, ReadinessState.Offensive); } var msg = new Message(new LexicalParagraph(messaging.Item1)) { ToTarget = new LexicalParagraph[] { new LexicalParagraph(messaging.Item2) }, ToOrigin = new LexicalParagraph[] { new LexicalParagraph(messaging.Item3) } }; msg.ExecuteMessaging(actor, null, target, actor.CurrentLocation.CurrentContainer, null, true); return(true); }