public static string AcceptFriendRequest(int id, string membershipId) { IFriendRepository friendRepo = new EFFriendRepository(); var friend = friendRepo.Friends.FirstOrDefault(f => f.Id == id); // assert exists if (friend == null) { return("Error"); } // assert this was sent to you else if (friend.FriendMembershipId == membershipId) { friend.IsAccepted = true; friendRepo.SaveFriend(friend); var me = PlayerProcedures.GetPlayerFromMembership(membershipId); var newFriend = PlayerProcedures.GetPlayerFromMembership(friend.OwnerMembershipId); if (me != null && newFriend != null) { PlayerLogProcedures.AddPlayerLog(me.Id, $"You have accepted {newFriend.GetFullName()}'s friend request.", false); PlayerLogProcedures.AddPlayerLog(newFriend.Id, $"{me.GetFullName()} has accepted your friend request!", true); } return("Success"); } else { return(""); } }
public static void BeginDuel(int duelId) { IDuelRepository duelRepo = new EFDuelRepository(); var duel = duelRepo.Duels.FirstOrDefault(d => d.Id == duelId); duel.StartTurn = PvPWorldStatProcedures.GetWorldTurnNumber(); duel.Status = ACTIVE; var members = GetPlayerViewModelsInDuel(duelId); var memberNames = ""; foreach (var p in members) { memberNames += p.Player.GetFullName() + ", "; } foreach (var p in members) { duel.Combatants.FirstOrDefault(f => f.PlayerId == p.Player.Id).StartFormSourceId = p.Player.FormSourceId; PlayerProcedures.EnterDuel(p.Player.Id, duel.Id); var playerMessage = "<b>Your duel between " + memberNames + " has begun!</b>"; PlayerLogProcedures.AddPlayerLog(p.Player.Id, playerMessage, true); } LocationLogProcedures.AddLocationLog(members.First().Player.dbLocationName, "<b class='playerAttackNotification'>A duel started here.</b>"); duelRepo.SaveDuel(duel); }
public static void EndDuel(int duelId, string endStatus) { IDuelRepository duelRepo = new EFDuelRepository(); var duel = duelRepo.Duels.FirstOrDefault(d => d.Id == duelId); duel.CompletionTurn = PvPWorldStatProcedures.GetWorldTurnNumber(); duel.Status = endStatus; duelRepo.SaveDuel(duel); foreach (var d in duel.Combatants) { PlayerProcedures.EnterDuel(d.PlayerId, 0); var message = ""; if (endStatus == TIMEOUT) { message = "<b class='bad'>Your duel has timed out, ending in a disappointing draw. You feel as if some frustrated spirits have left you weakened by a curse...</b>"; EffectProcedures.GivePerkToPlayer(TimeoutCurseEffectSourceId, d.PlayerId); } else { message = "<b>Your duel has ended.</b>"; } PlayerLogProcedures.AddPlayerLog(d.PlayerId, message, true); } }
public static void AddCovenantApplication(Player applicant, Covenant covenant) { ICovenantApplicationRepository covAppRepo = new EFCovenantApplicationRepository(); var saveMe = new CovenantApplication { CovenantId = covenant.Id, OwnerId = applicant.Id, Timestamp = DateTime.UtcNow, Message = "", }; covAppRepo.SaveCovenantApplication(saveMe); var message = "<b><span style='color: #003300;'>" + applicant.FirstName + " " + applicant.LastName + " has applied to your covenant, " + covenant.Name + ".</span></b>"; PlayerLogProcedures.AddPlayerLog(covenant.LeaderId, message, true); }
public static void SendDuelChallenge(Player challenger, Player target) { IPlayerRepository playerRepo = new EFPlayerRepository(); IDuelRepository duelRepo = new EFDuelRepository(); var dbChallenger = playerRepo.Players.FirstOrDefault(p => p.Id == challenger.Id); var dbTarget = playerRepo.Players.FirstOrDefault(p => p.Id == target.Id); var newDuel = new Duel { StartTurn = -1, ProposalTurn = PvPWorldStatProcedures.GetWorldTurnNumber(), CompletionTurn = -1, Status = PENDING, LastResetTimestamp = DateTime.UtcNow, Combatants = new List <DuelCombatant> { new DuelCombatant { PlayerId = challenger.Id, Team = 1, }, new DuelCombatant { PlayerId = target.Id, Team = 2, } }, }; duelRepo.SaveDuel(newDuel); // TODO: make it so target has to accept first // dbChallenger.InDuel = newDuel.Id; // dbTarget.InDuel = newDuel.Id; var messageToTarget = "You have been challenge to a duel by <b>" + challenger.GetFullName() + "</b>! Will you accept the challenge or show your cowardice? " + "<b><u><a href='/Duel/AcceptChallenge/" + newDuel.Id + "'>Click here to Accept</a></b></u>." ; PlayerLogProcedures.AddPlayerLog(dbTarget.Id, messageToTarget, true); playerRepo.SavePlayer(dbChallenger); playerRepo.SavePlayer(dbTarget); }
public static string CancelFriendRequest(int id, string membershipId) { IFriendRepository friendRepo = new EFFriendRepository(); var friend = friendRepo.Friends.FirstOrDefault(f => f.Id == id); // assert exists if (friend == null) { return("Error"); } // assert you've sent this, or else it was sent to you else if (friend.OwnerMembershipId == membershipId || friend.FriendMembershipId == membershipId) { friendRepo.DeleteFriend(friend.Id); var me = PlayerProcedures.GetPlayerFromMembership(membershipId); var otherMembership = (friend.OwnerMembershipId == membershipId) ? friend.FriendMembershipId : friend.OwnerMembershipId; var nonFriend = PlayerProcedures.GetPlayerFromMembership(otherMembership); if (friend.IsAccepted) { PlayerLogProcedures.AddPlayerLog(me.Id, $"You are no longer friends with {nonFriend?.GetFullName()}.", false); } else { PlayerLogProcedures.AddPlayerLog(me.Id, $"You have declined {nonFriend?.GetFullName()}'s friend request.", false); } return(""); } else { return(""); } }
public static string AttackLocation(Player player, BuffBox buffs) { ILocationInfoRepository repo = new EFLocationInfoRepository(); ICovenantRepository covRepo = new EFCovenantRepository(); var location = LocationsStatics.LocationList.GetLocation.FirstOrDefault(l => l.dbName == player.dbLocationName); var output = ""; if (location == null) { output = "You cast an enchantment here, but you aren't actually anywhere!"; return(output); } var info = repo.LocationInfos.FirstOrDefault(l => l.dbName == player.dbLocationName) ?? new LocationInfo { TakeoverAmount = 75, CovenantId = -1, dbName = player.dbLocationName, }; if (player.Covenant == null) { output = "You cast an enchantment here, but it did no effect as you aren't part of a covenant"; return(output); } if (info.TakeoverAmount >= 100 && info.CovenantId == player.Covenant) { output = "You cast an enchantment here, but it did no effect as this location's enchantment is already at its highest possible level, 100."; return(output); } var takeoverAmount = (float)player.Level / 2.0F; takeoverAmount += buffs.EnchantmentBoost; decimal XPGain = 0; try { XPGain = 40 / Math.Round(Convert.ToDecimal(101 - Math.Abs(info.TakeoverAmount)), 1); } catch (Exception) { XPGain = 0; } if (XPGain > PvPStatics.XP__EnchantmentMaxXP) { XPGain = PvPStatics.XP__EnchantmentMaxXP; } var XPGainText = String.Format("{0:0.#}", XPGain); // location is not controlled; give it to whichever covenant is attacking it if (info.TakeoverAmount <= 0) { info.CovenantId = (int)player.Covenant; info.TakeoverAmount = takeoverAmount; if (info.TakeoverAmount > 100) { info.TakeoverAmount = 100; } info.LastTakeoverTurn = PvPWorldStatProcedures.GetWorldTurnNumber(); output = "<b>Your enchantment settles in this location, converting its energies from the previous controlling covenant to your own! (+" + XPGainText + " XP)</b>"; location.CovenantController = (int)player.Covenant; location.TakeoverAmount = info.TakeoverAmount; var myCov = covRepo.Covenants.First(c => c.Id == player.Covenant); var locationLogMessage = "<b class='playerAttackNotification'>" + player.GetFullName() + " enchanted this location and claimed it for " + myCov.Name + "!</b>"; LocationLogProcedures.AddLocationLog(player.dbLocationName, locationLogMessage); var covLogWinner = player.GetFullName() + " enchanted " + location.Name + " and has claimed it for this covenant."; CovenantProcedures.WriteCovenantLog(covLogWinner, myCov.Id, true); } // otherwise the location is controlled by someone else { // add points toward the attacker's covenant or take them away if it belongs to another if (info.CovenantId == player.Covenant) { info.TakeoverAmount += takeoverAmount; location.TakeoverAmount = info.TakeoverAmount; var cov = covRepo.Covenants.FirstOrDefault(c => c.Id == player.Covenant); output = $"Your enchantment reinforces this location by {takeoverAmount}. New influence level is {info.TakeoverAmount} for your covenant, {cov?.Name ?? "unknown"}. (+{XPGainText} XP)</b>"; } else { info.TakeoverAmount -= takeoverAmount; location.TakeoverAmount = info.TakeoverAmount; var cov = info.CovenantId == null ? null : covRepo.Covenants.FirstOrDefault(c => c.Id == info.CovenantId); if (info.TakeoverAmount <= 0) { // notify old covenant who stole the location and their covenant if (info.CovenantId != null && info.CovenantId > 0) { var attackingCov = CovenantProcedures.GetCovenantViewModel((int)player.Covenant); var covLogLoser = player.GetFullName() + " of " + attackingCov.dbCovenant.Name + " enchanted " + location.Name + ", removing it from this covenant's influence!"; CovenantProcedures.WriteCovenantLog(covLogLoser, (int)info.CovenantId, true); } info.CovenantId = -1; info.LastTakeoverTurn = PvPWorldStatProcedures.GetWorldTurnNumber(); } if (cov != null) { output = "You dispel the enchantment at this location by " + takeoverAmount + ". New influence level is " + info.TakeoverAmount + " for the location's existing controller, " + cov.Name + ". (+" + XPGainText + " XP)</b>"; } else { output = "You dispel the enchantment at this location by " + takeoverAmount + ". New influence level is " + info.TakeoverAmount + ". (+" + XPGainText + " XP)</b>"; } } var locationLogMessage = "<span class='playerAttackNotification'>" + player.GetFullName() + " cast an enchantment on this location.</span>"; LocationLogProcedures.AddLocationLog(player.dbLocationName, locationLogMessage); } if (info.TakeoverAmount > 100) { info.TakeoverAmount = 100; } // cap at 0 to 100 points else if (info.TakeoverAmount <= 0) { info.CovenantId = -1; info.TakeoverAmount = 0; } repo.SaveLocationInfo(info); PlayerProcedures.GiveXP(player, XPGain); PlayerLogProcedures.AddPlayerLog(player.Id, output, false); return(output); }
public static (bool, string) Attack(Player attackingPlayer, Player attackedPlayer, SkillViewModel skillBeingUsed, bool timestamp = true) { var result = ""; var attacker = PlayerProcedures.GetPlayer(attackingPlayer.Id); var victim = PlayerProcedures.GetPlayer(attackedPlayer.Id); if (victim.Mobility != PvPStatics.MobilityFull || attacker.Mobility != PvPStatics.MobilityFull || victim.GameMode == (int)GameModeStatics.GameModes.Invisible || attacker.GameMode == (int)GameModeStatics.GameModes.Invisible) { return(false, ""); } var complete = false; var logs = new LogBox(); // all of our checks seem to be okay. So let's lower the player's mana and action points PlayerProcedures.ChangePlayerActionMana(-PvPStatics.AttackCost, 0, -PvPStatics.AttackManaCost, attacker.Id, timestamp); PlayerProcedures.LogCombatTimestampsAndAddAttackCount(victim, attacker); var attackerFullName = attacker.GetFullName(); var victimFullName = victim.GetFullName(); // if the spell is a curse, give the effect and that's all if (skillBeingUsed.StaticSkill.GivesEffectSourceId != null) { var effectBeingGiven = EffectStatics.GetDbStaticEffect(skillBeingUsed.StaticSkill.GivesEffectSourceId.Value); EffectProcedures.GivePerkToPlayer(skillBeingUsed.StaticSkill.GivesEffectSourceId.Value, victim); if (attacker.Gender == PvPStatics.GenderMale && !effectBeingGiven.AttackerWhenHit_M.IsNullOrEmpty()) { logs.AttackerLog += effectBeingGiven.AttackerWhenHit_M; } else if (attacker.Gender == PvPStatics.GenderFemale && !effectBeingGiven.AttackerWhenHit_F.IsNullOrEmpty()) { logs.AttackerLog += effectBeingGiven.AttackerWhenHit_F; } else { logs.AttackerLog += effectBeingGiven.AttackerWhenHit; } if (!String.IsNullOrEmpty(logs.AttackerLog)) { logs.AttackerLog += "<br><br>"; } logs.LocationLog = "<span class='playerAttackNotification'>" + attackerFullName + " cursed " + victimFullName + " with " + skillBeingUsed.StaticSkill.FriendlyName + ".</span>"; logs.AttackerLog += "You cursed " + victimFullName + " with " + skillBeingUsed.StaticSkill.FriendlyName + "."; logs.AttackerLog += " (+1 XP) "; logs.AttackerLog += PlayerProcedures.GiveXP(attacker, 1); logs.VictimLog = effectBeingGiven.MessageWhenHit; logs.VictimLog += " <span class='playerAttackNotification'>" + attackerFullName + " cursed you with <b>" + skillBeingUsed.StaticSkill.FriendlyName + "</b>.</b></span> "; result = logs.AttackerLog; } // the spell is a regular attack else { logs.LocationLog = "<span class='playerAttackNotification'>" + attackerFullName + " cast " + skillBeingUsed.StaticSkill.FriendlyName + " against " + victimFullName + ".</span>"; logs.AttackerLog = "You cast " + skillBeingUsed.StaticSkill.FriendlyName + " against " + victimFullName + ". "; logs.VictimLog = "<span class='playerAttackNotification'>" + attackerFullName + " cast " + skillBeingUsed.StaticSkill.FriendlyName + " against you.</span> "; var meBuffs = ItemProcedures.GetPlayerBuffs(attacker); var targetedBuffs = ItemProcedures.GetPlayerBuffs(victim); var rand = new Random(Guid.NewGuid().GetHashCode()); var basehitChance = rand.NextDouble() * 100; var meDmgExtra = meBuffs.SpellExtraHealthDamagePercent(); var criticalMissPercentChance = PvPStatics.CriticalMissPercentChance - meBuffs.SpellMisfireChanceReduction(); var criticalPercentChance = meBuffs.ExtraSkillCriticalPercent() + PvPStatics.CriticalHitPercentChance; var evasionPercentChance = targetedBuffs.EvasionPercent() - meBuffs.EvasionNegationPercent(); var evasionUpgrade = false; var failedAttack = false; // clamp modifiedEvasion at 50% max if (evasionPercentChance > 50) { evasionPercentChance = 50; } // critical miss! damage caster instead if (basehitChance < (double)criticalMissPercentChance) { // check if there is a health damage aspect to this spell if (skillBeingUsed.StaticSkill.HealthDamageAmount > 0) { var amountToDamage = skillBeingUsed.StaticSkill.HealthDamageAmount * (1 + meDmgExtra / 100); PlayerProcedures.DamagePlayerHealth(attacker.Id, amountToDamage); logs.AttackerLog += $"Misfire! Your spell accidentally lowered your own willpower by {amountToDamage:N2}. "; logs.VictimLog += $"Misfire! {GetPronoun_HisHer(attacker.Gender)} spell accidentally lowered {GetPronoun_hisher(attacker.Gender)} own willpower by {amountToDamage:N2}."; result += logs.AttackerLog; } failedAttack = true; } // spell is evaded else if (basehitChance < (double)criticalMissPercentChance + (double)evasionPercentChance) { // Check for a crit to upgrade the miss to a hit var criticalHitChance = rand.NextDouble() * 100; if (criticalHitChance < (double)criticalPercentChance) { evasionUpgrade = true; } else { logs.AttackerLog += victimFullName + " managed to leap out of the way of your spell."; logs.VictimLog += "You managed to leap out of the way " + attackerFullName + "'s spell."; result = logs.AttackerLog; failedAttack = true; } } // not a miss, so let's deal some damage, possibly if (!failedAttack) { decimal criticalModifier = 1; if (evasionUpgrade) { logs.AttackerLog += "<b>Piercing hit!</b> "; logs.VictimLog += "<b>Piercing hit!</b> "; } else if (rand.NextDouble() * 100 < (double)criticalPercentChance) { criticalModifier = 2; logs.AttackerLog += "<b>Critical hit!</b> "; logs.VictimLog += "<b>Critical hit!</b> "; } var initialVictimHealth = victim.Health; // check if there is a health damage aspect to this spell if (skillBeingUsed.StaticSkill.HealthDamageAmount > 0) { var targetProt = targetedBuffs.SpellHealthDamageResistance(); // calculator the modifier as extra attack - defense. 15 - 20 = -5 modifier var willpowerDamageModifierFromBonuses = 1 + ((meDmgExtra - targetProt) / 100.0M); // cap the modifier at at 50 % IF the target is a human if (willpowerDamageModifierFromBonuses < .5M) { willpowerDamageModifierFromBonuses = .5M; } // cap the modifier at 200 % IF the target is a human if (willpowerDamageModifierFromBonuses > 2 && victim.BotId == AIStatics.ActivePlayerBotId) { willpowerDamageModifierFromBonuses = 2; } var totalHealthDamage = skillBeingUsed.StaticSkill.HealthDamageAmount * willpowerDamageModifierFromBonuses * criticalModifier; // make sure damage is never in the negatives (which would heal instead) if (totalHealthDamage < 0) { totalHealthDamage = 0; } PlayerProcedures.DamagePlayerHealth(victim.Id, totalHealthDamage); // even though it's been done in the db, change the player health here as well victim.Health -= totalHealthDamage; logs.AttackerLog += $"Your spell lowered {GetPronoun_hisher(victim.Gender)} willpower by {Math.Round(totalHealthDamage, 2)}. "; logs.VictimLog += $"{GetPronoun_HisHer(attacker.Gender)} spell lowered your willpower by {Math.Round(totalHealthDamage, 2)}. "; result += logs.AttackerLog; } // if this skill has any TF power, add energy and check for form change if (skillBeingUsed.StaticSkill.TFPointsAmount > 0) { var TFEnergyDmg = meBuffs.SpellExtraTFEnergyPercent(); var TFEnergyArmor = targetedBuffs.SpellTFEnergyDamageResistance(); // calculator the modifier as extra attack - defense. var tfEnergyDamageModifierFromBonuses = 1 + ((TFEnergyDmg - TFEnergyArmor) / 100.0M); // cap the modifier at at 50 % IF the target is a human if (tfEnergyDamageModifierFromBonuses < .5M) { tfEnergyDamageModifierFromBonuses = .5M; } // cap the modifier at at 200 % IF the target is a human if (tfEnergyDamageModifierFromBonuses > 2 && victim.BotId == AIStatics.ActivePlayerBotId) { tfEnergyDamageModifierFromBonuses = 2; } var totalTFEnergyModifier = criticalModifier * tfEnergyDamageModifierFromBonuses; LogBox tfEnergyResult; (complete, tfEnergyResult) = TFEnergyProcedures.AddTFEnergyToPlayer(victim, attacker, skillBeingUsed, totalTFEnergyModifier, initialVictimHealth); logs.Add(tfEnergyResult); result = logs.AttackerLog; } } } LocationLogProcedures.AddLocationLog(attacker.dbLocationName, logs.LocationLog); PlayerLogProcedures.AddPlayerLog(attacker.Id, logs.AttackerLog, false); PlayerLogProcedures.AddPlayerLog(victim.Id, logs.VictimLog, true); DomainRegistry.AttackNotificationBroker.Notify(victim.Id, logs.VictimLog); // if this is a psycho-on-psycho battle, have a chance for the victim bot to switch targets to the attacker bot if (attacker.BotId == AIStatics.PsychopathBotId && victim.BotId == AIStatics.PsychopathBotId) { var rand = new Random(Guid.NewGuid().GetHashCode()); var botAggroRoll = rand.NextDouble(); if (botAggroRoll < .08) { AIDirectiveProcedures.SetAIDirective_Attack(victim.Id, attacker.Id); } } return(complete, result); }
public static string DoAnimalAction(string actionName, int animalPlayerId, int victimId) { IPlayerRepository playerRepo = new EFPlayerRepository(); var animalPlayer = playerRepo.Players.FirstOrDefault(p => p.Id == animalPlayerId); var animalItem = DomainRegistry.Repository.FindSingle(new GetItemByFormerPlayer { PlayerId = animalPlayerId }); var victim = playerRepo.Players.FirstOrDefault(p => p.Id == victimId); Player attackerOwner = null; if (animalItem.Owner != null) { attackerOwner = playerRepo.Players.FirstOrDefault(p => p.Id == animalItem.Owner.Id); } var here = LocationsStatics.LocationList.GetLocation.FirstOrDefault(l => l.dbName == animalPlayer.dbLocationName); var attackerPlus = PlayerProcedures.GetPlayerFormViewModel(animalPlayerId); if (attackerPlus == null) { return(""); } var victimMessage = ""; var attackerMessage = ""; var locationMessage = ""; string victimPronoun; if (victim.Gender == PvPStatics.GenderMale) { victimPronoun = "his"; } else { victimPronoun = "her"; } if (actionName == "snarl") { victim.Mana -= 1; if (victim.Mana < 0) { victim.Mana = 0; } if (attackerOwner != null) { victimMessage = "<span class='petActionBad'>" + animalPlayer.GetFullName() + ", a " + attackerPlus.Form.FriendlyName + " kept as a pet by " + attackerOwner.GetFullName() + ", snarls at you, slightly lowering your mana.</span>"; } else { victimMessage = "<span class='petActionBad'>" + animalPlayer.GetFullName() + ", a feral " + attackerPlus.Form.FriendlyName + " snarls at you, slightly lowering your mana.</span>"; } attackerMessage = "You snarl at " + victim.GetFullName() + ", lowering " + victimPronoun + " mana slightly."; locationMessage = animalPlayer.GetFullName() + ", a " + attackerPlus.Form.FriendlyName + ", snarled at " + victim.GetFullName() + "."; } else if (actionName == "lick") { victim.Health += 1; if (victim.Health > victim.MaxHealth) { victim.Health = victim.MaxHealth; } if (attackerOwner != null) { victimMessage = "<span class='petActionGood'>" + animalPlayer.GetFullName() + ", a " + attackerPlus.Form.FriendlyName + " kept as a pet by " + attackerOwner.FirstName + " " + attackerOwner.LastName + ", gently licks you, slightly raising your willpower.</span>"; } else { victimMessage = "<span class='petActionGood'>" + animalPlayer.GetFullName() + ", a feral " + attackerPlus.Form.FriendlyName + " gently licks you, slightly raising your willpower.</span>"; } attackerMessage = "You gently lick " + victim.GetFullName() + ", raising " + victimPronoun + " willpower slightly."; locationMessage = animalPlayer.GetFullName() + ", a " + attackerPlus.Form.FriendlyName + ", licked " + victim.FirstName + " " + victim.LastName + "."; } else if (actionName == "nuzzle") { victim.Mana += 1; if (victim.Mana > victim.MaxMana) { victim.Mana = victim.MaxMana; } if (attackerOwner != null) { victimMessage = "<span class='petActionGood'>" + animalPlayer.GetFullName() + ", a " + attackerPlus.Form.FriendlyName + " kept as a pet by " + attackerOwner.FirstName + " " + attackerOwner.LastName + ", gently nuzzles you, slightly raising your mana.</span>"; } else { victimMessage = "<span class='petActionGood'>" + animalPlayer.GetFullName() + ", a feral " + attackerPlus.Form.FriendlyName + " gently nuzzles you, slightly raising your mana.</span>"; } attackerMessage = "You gently nuzzle " + victim.GetFullName() + ", raising " + victimPronoun + " mana slightly."; locationMessage = animalPlayer.GetFullName() + ", a " + attackerPlus.Form.FriendlyName + ", nuzzles " + victim.FirstName + " " + victim.LastName + "."; } if (actionName == "headbutt") { victim.Health -= 1; if (victim.Health < 0) { victim.Health = 0; } if (attackerOwner != null) { victimMessage = "<span class='petActionBad'>" + animalPlayer.GetFullName() + ", a " + attackerPlus.Form.FriendlyName + " kept as a pet by " + attackerOwner.GetFullName() + ", lightly headbutts you, slightly lowering your willpower.</span>"; } else { victimMessage = "<span class='petActionBad'>" + animalPlayer.GetFullName() + ", a feral " + attackerPlus.Form.FriendlyName + " lightly headbutts you, slightly lowering your willpower.</span>"; } attackerMessage = "You headbutt " + victim.FirstName + " " + victim.LastName + ", lowering " + victimPronoun + " willpower slightly."; locationMessage = animalPlayer.GetFullName() + ", a " + attackerPlus.Form.FriendlyName + ", headbutted " + victim.FirstName + " " + victim.LastName + "."; } PlayerLogProcedures.AddPlayerLog(victim.Id, victimMessage, true); PlayerLogProcedures.AddPlayerLog(animalPlayer.Id, attackerMessage, false); LocationLogProcedures.AddLocationLog(here.dbName, locationMessage); animalPlayer.TimesAttackingThisUpdate++; playerRepo.SavePlayer(victim); playerRepo.SavePlayer(animalPlayer); return(attackerMessage); }
public static string ThrowGrenade(Player attacker, decimal damage, string orbStrengthName) { IPlayerRepository playerREpo = new EFPlayerRepository(); var attackerLocation = attacker.dbLocationName; var here = LocationsStatics.LocationList.GetLocation.First(l => l.dbName == attackerLocation); var playersHere = new List <Player>(); var playersHereOnline = new List <Player>(); if (attacker.GameMode == (int)GameModeStatics.GameModes.PvP) { playersHere = playerREpo.Players.Where(p => p.dbLocationName == attackerLocation && (p.GameMode == (int)GameModeStatics.GameModes.PvP || p.BotId < AIStatics.RerolledPlayerBotId) && p.Mobility == PvPStatics.MobilityFull && p.InDuel <= 0 && p.InQuest <= 0).ToList(); } else if (attacker.GameMode == (int)GameModeStatics.GameModes.Protection || attacker.GameMode == (int)GameModeStatics.GameModes.Superprotection) { playersHere = playerREpo.Players.Where(p => p.dbLocationName == attackerLocation && p.BotId < AIStatics.RerolledPlayerBotId && p.Mobility == PvPStatics.MobilityFull && p.InDuel <= 0 && p.InQuest <= 0).ToList(); } // filter out offline players as well as the attacker foreach (var p in playersHere) { if (!PlayerProcedures.PlayerIsOffline(p) && p.Id != attacker.Id) { playersHereOnline.Add(p); } } foreach (var p in playersHereOnline) { p.Health -= damage; if (p.Health < 0) { p.Health = 0; } playerREpo.SavePlayer(p); var message = "<span class='playerAttackNotification'>" + attacker.GetFullName() + " threw a " + orbStrengthName + " Submissiveness Splash Orb at " + here.Name + ", lowering your willpower by " + damage + " along with " + (playersHereOnline.Count - 1) + " others.</span>"; PlayerLogProcedures.AddPlayerLog(p.Id, message, true); } var logMessage = attacker.FirstName + " " + attacker.LastName + " threw a Submissiveness Splash Orb here."; LocationLogProcedures.AddLocationLog(attackerLocation, logMessage); var attackerMessage = "You threw a " + orbStrengthName + " Submissiveness Splash Orb at " + here.Name + ", lowering " + playersHereOnline.Count + " people's willpower by " + damage + " each."; PlayerLogProcedures.AddPlayerLog(attacker.Id, attackerMessage, false); // set the player's last action flag, combat time var dbAttacker = playerREpo.Players.First(p => p.Id == attacker.Id); dbAttacker.LastActionTimestamp = DateTime.UtcNow; dbAttacker.LastCombatTimestamp = DateTime.UtcNow; dbAttacker.TimesAttackingThisUpdate++; playerREpo.SavePlayer(dbAttacker); return(attackerMessage); }
public static string SuddenDeathExplosion(Player attacker, Player victim, decimal damage) { IPlayerRepository playerREpo = new EFPlayerRepository(); var attackerLocation = attacker.dbLocationName; var here = LocationsStatics.LocationList.GetLocation.First(l => l.dbName == attackerLocation); var playersHere = new List <Player>(); var playersHereOnline = new List <Player>(); if (attacker.GameMode == (int)GameModeStatics.GameModes.PvP) { playersHere = playerREpo.Players.Where(p => p.dbLocationName == attackerLocation && (p.GameMode == (int)GameModeStatics.GameModes.PvP || p.BotId < AIStatics.RerolledPlayerBotId) && p.Mobility == PvPStatics.MobilityFull && p.InDuel <= 0 && p.InQuest <= 0).ToList(); } else if (attacker.GameMode == (int)GameModeStatics.GameModes.Protection || attacker.GameMode == (int)GameModeStatics.GameModes.Superprotection) { playersHere = playerREpo.Players.Where(p => p.dbLocationName == attackerLocation && p.BotId < AIStatics.RerolledPlayerBotId && p.Mobility == PvPStatics.MobilityFull && p.InDuel <= 0 && p.InQuest <= 0).ToList(); } // filter out offline players as well as the attacker foreach (var p in playersHere) { if (!PlayerProcedures.PlayerIsOffline(p) && p.Id != attacker.Id) { playersHereOnline.Add(p); } } foreach (var p in playersHereOnline) { p.Health -= damage; if (p.Health < 0) { p.Health = 0; } playerREpo.SavePlayer(p); var message = "<span class='playerAttackNotification'>" + victim.GetFullName() + " convulses and shakes before exploding into a roiling tide of chaotic energies damaging you for " + damage + " along with " + (playersHereOnline.Count - 1) + " others.</span>"; PlayerLogProcedures.AddPlayerLog(p.Id, message, true); } var logMessage = victim.FirstName + " " + victim.LastName + " exploded into a violent shower of chaotic energies."; LocationLogProcedures.AddLocationLog(attackerLocation, logMessage); var attackerMessage = "The explosion caused by " + victim.FirstName + " " + victim.LastName + " scattered violent energies throughout " + here + ", lowering " + playersHereOnline.Count + " people's willpower by " + damage + " each."; PlayerLogProcedures.AddPlayerLog(attacker.Id, attackerMessage, false); // set the player's last action flag var dbAttacker = playerREpo.Players.First(p => p.Id == attacker.Id); dbAttacker.LastActionTimestamp = DateTime.UtcNow; playerREpo.SavePlayer(dbAttacker); return(attackerMessage); }
public static string CurseTransformOwner(Player player, Player owner, ItemDetail playerItem, bool isWhitelist) { var rand = new Random(); var roll = rand.NextDouble() * 100; IInanimateXPRepository inanimateXpRepo = new EFInanimateXPRepository(); var xp = inanimateXpRepo.InanimateXPs.FirstOrDefault(x => x.OwnerId == player.Id); var gameTurn = PvPWorldStatProcedures.GetWorldTurnNumber(); // assign the player inanimate XP based on turn building if (xp == null) { xp = new InanimateXP { OwnerId = player.Id, Amount = 0, TimesStruggled = -6 * player.Level, LastActionTimestamp = DateTime.UtcNow, LastActionTurnstamp = gameTurn - 1, }; } double chanceOfSuccess = (gameTurn - xp.LastActionTurnstamp); ITFMessageRepository tfMessageRepo = new EFTFMessageRepository(); var tf = tfMessageRepo.TFMessages.FirstOrDefault(t => t.FormSourceId == playerItem.ItemSource.CurseTFFormSourceId); var ownerSuccessMessage = ""; var ownerFailureMessage = ""; var playerMessage = ""; var newFormSourceId = -1; if (playerItem.ItemSource.CurseTFFormSourceId == null) { // No item-provided TF curse - reduce chance of transforming to a preset form chanceOfSuccess /= 4.0; newFormSourceId = PvPStatics.DefaultTFCurseForms[rand.Next(PvPStatics.DefaultTFCurseForms.Length)]; } else { // Regular TF curse - load its details newFormSourceId = playerItem.ItemSource.CurseTFFormSourceId.Value; if (playerItem.Owner.Gender == PvPStatics.GenderMale && !tf.CursedTF_Succeed_M.IsNullOrEmpty()) { ownerSuccessMessage = tf.CursedTF_Succeed_M; } else if (playerItem.Owner.Gender == PvPStatics.GenderFemale && !tf.CursedTF_Succeed_F.IsNullOrEmpty()) { ownerSuccessMessage = tf.CursedTF_Succeed_F; } else if (!tf.CursedTF_Succeed.IsNullOrEmpty()) { ownerSuccessMessage = tf.CursedTF_Succeed; } if (playerItem.Owner.Gender == PvPStatics.GenderMale && !tf.CursedTF_Fail_M.IsNullOrEmpty()) { ownerFailureMessage = tf.CursedTF_Fail_M; } else if (playerItem.Owner.Gender == PvPStatics.GenderFemale && !tf.CursedTF_Fail_F.IsNullOrEmpty()) { ownerFailureMessage = tf.CursedTF_Fail_F; } else if (!tf.CursedTF_Fail.IsNullOrEmpty()) { ownerFailureMessage = tf.CursedTF_Fail; } } // success; owner is transformed! if (roll < chanceOfSuccess) { IPlayerRepository playerRepo = new EFPlayerRepository(); var newForm = FormStatics.GetForm(newFormSourceId); if (newForm.MobilityType == PvPStatics.MobilityFull) { DomainRegistry.Repository.Execute(new ChangeForm { PlayerId = playerItem.Owner.Id, FormSourceId = newFormSourceId }); var dbOwner = playerRepo.Players.FirstOrDefault(p => p.Id == playerItem.Owner.Id); dbOwner.ReadjustMaxes(ItemProcedures.GetPlayerBuffs(dbOwner)); dbOwner.Mana -= dbOwner.MaxMana * .5M; dbOwner.NormalizeHealthMana(); playerRepo.SavePlayer(dbOwner); if (ownerSuccessMessage.IsNullOrEmpty()) { ownerSuccessMessage = $"One of your items, {playerItem.FormerPlayer.FullName}, attempts to trigger a curse placed upon it. Suddenly you are overwhelmed as you find yourself transformed into a {newForm.FriendlyName}!"; } playerMessage = "Your subtle transformation curse overwhelms your owner, transforming them into a " + newForm.FriendlyName + "!"; PlayerLogProcedures.AddPlayerLog(playerItem.Owner.Id, ownerSuccessMessage, true); LocationLogProcedures.AddLocationLog(owner.dbLocationName, "<b> " + owner.GetFullName() + " is suddenly transformed by " + playerItem.FormerPlayer.FullName + " the " + playerItem.ItemSource.FriendlyName + ", one of their belongings!</b>"); } } // fail; owner is not transformed else { if (ownerFailureMessage.IsNullOrEmpty()) { ownerFailureMessage = "One of your items attempts to trigger a curse placed upon it, but it fails to transform you."; } playerMessage = "Unfortunately your subtle transformation curse fails to transform your owner."; PlayerLogProcedures.AddPlayerLog(owner.Id, ownerFailureMessage, true); } PlayerProcedures.AddAttackCount(player); return(playerMessage + GiveInanimateXP(player.MembershipId, isWhitelist)); }
public static string ReturnToAnimate(Player player, bool dungeonPenalty) { IInanimateXPRepository inanimXpRepo = new EFInanimateXPRepository(); IItemRepository itemRepo = new EFItemRepository(); var inanimXP = inanimXpRepo.InanimateXPs.FirstOrDefault(i => i.OwnerId == player.Id); var currentGameTurn = PvPWorldStatProcedures.GetWorldTurnNumber(); if (inanimXP == null) { inanimXP = new InanimateXP { OwnerId = player.Id, Amount = 0, // set the initial times struggled proportional to how high of a level the player is TimesStruggled = -6 * player.Level, LastActionTimestamp = DateTime.UtcNow, LastActionTurnstamp = currentGameTurn - 1, }; } double strugglebonus = currentGameTurn - inanimXP.LastActionTurnstamp; if (strugglebonus > TurnTimesStatics.GetItemMaxTurnsBuildup()) { strugglebonus = TurnTimesStatics.GetItemMaxTurnsBuildup(); } if (strugglebonus < 0) { strugglebonus = 0; } if (PvPStatics.ChaosMode) { strugglebonus = 100; } // increment the player's attack count. Also decrease their player XP some. IPlayerRepository playerRepo = new EFPlayerRepository(); var dbPlayer = playerRepo.Players.FirstOrDefault(p => p.Id == player.Id); dbPlayer.TimesAttackingThisUpdate++; var strugglesMade = Convert.ToDouble(GetStruggleChance(player, dungeonPenalty)); var rand = new Random(); var roll = rand.NextDouble() * 100; var dbPlayerItem = DomainRegistry.Repository.FindSingle(new GetItemByFormerPlayer { PlayerId = player.Id }); if (dbPlayerItem == null) { return("Cannot struggle - no player item"); } if (dbPlayerItem.Owner != null) { var owner = PlayerProcedures.GetPlayer(dbPlayerItem.Owner.Id); dbPlayer.dbLocationName = owner.dbLocationName; } var itemPlus = ItemStatics.GetStaticItem(dbPlayerItem.ItemSource.Id); if (roll < strugglesMade) { // assert that the covenant the victim is in is not too full to accept them back in if (dbPlayer.Covenant > 0) { var victimCov = CovenantProcedures.GetCovenantViewModel((int)dbPlayer.Covenant).dbCovenant; if (victimCov != null && CovenantProcedures.GetPlayerCountInCovenant(victimCov, true) >= PvPStatics.Covenant_MaximumAnimatePlayerCount) { return("Although you had enough energy to break free from your body as a " + itemPlus.FriendlyName + " and restore your regular body, you were unfortunately not able to break free because there is no more room in your covenant for any more animate mages."); } } // if the item has an owner, notify them via a message. if (dbPlayerItem.Owner != null) { var message = player.FirstName + " " + player.LastName + ", your " + itemPlus.FriendlyName + ", successfully struggles against your magic and reverses their transformation. You can no longer claim them as your property, not unless you manage to turn them back again..."; PlayerLogProcedures.AddPlayerLog(dbPlayerItem.Owner.Id, message, true); } // change the player's form and mobility DomainRegistry.Repository.Execute(new ChangeForm { PlayerId = dbPlayer.Id, FormSourceId = dbPlayer.OriginalFormSourceId }); dbPlayer.ActionPoints = TurnTimesStatics.GetActionPointLimit(); dbPlayer.ActionPoints_Refill = TurnTimesStatics.GetActionPointReserveLimit(); dbPlayer.CleansesMeditatesThisRound = PvPStatics.MaxCleansesMeditatesPerUpdate; dbPlayer.TimesAttackingThisUpdate = PvPStatics.MaxAttacksPerUpdate; // don't let the player spawn in the dungeon as they will have Back On Your Feet // and may not be meet the level and game mode requirements if (dbPlayer.IsInDungeon()) { dbPlayer.dbLocationName = LocationsStatics.GetRandomLocationNotInDungeon(); } dbPlayer = PlayerProcedures.ReadjustMaxes(dbPlayer, ItemProcedures.GetPlayerBuffs(dbPlayer)); dbPlayer.Health = dbPlayer.MaxHealth / 3; dbPlayer.Mana = dbPlayer.MaxHealth / 3; playerRepo.SavePlayer(dbPlayer); // drop any runes embedded on the player-item, or return them to the former owner's inventory DomainRegistry.Repository.Execute(new UnbembedRunesOnItem { ItemId = dbPlayerItem.Id }); // delete the item or animal that this player had turned into itemRepo.DeleteItem(dbPlayerItem.Id); // delete the inanimate XP item inanimXpRepo.DeleteInanimateXP(inanimXP.Id); // give the player the recovery buff EffectProcedures.GivePerkToPlayer(PvPStatics.Effect_BackOnYourFeetSourceId, dbPlayer); var msg = "You have managed to break free from your form as " + itemPlus.FriendlyName + " and occupy an animate body once again!"; if (PvPStatics.ChaosMode) { msg += $" [CHAOS MODE: Struggle value overriden to {strugglebonus:0}% per struggle.]"; } PlayerLogProcedures.AddPlayerLog(dbPlayer.Id, msg, false); StatsProcedures.AddStat(dbPlayer.MembershipId, StatsProcedures.Stat__SuccessfulStruggles, 1); return(msg); } // failure to break free; increase time struggles else { // raise the probability of success for next time somewhat proportion to how many turns they missed inanimXP.TimesStruggled += Convert.ToInt32(strugglebonus); inanimXP.LastActionTimestamp = DateTime.UtcNow; inanimXP.LastActionTurnstamp = currentGameTurn; inanimXpRepo.SaveInanimateXP(inanimXP); playerRepo.SavePlayer(dbPlayer); if (dbPlayerItem.Owner != null) { var message = $"{player.FirstName} {player.LastName}, your {itemPlus.FriendlyName}, struggles but fails to return to an animate form. [Recovery chance next struggle: {(int)GetStruggleChance(player, dungeonPenalty)}%]"; PlayerLogProcedures.AddPlayerLog(dbPlayerItem.Owner.Id, message, true); } PlayerLogProcedures.AddPlayerLog(dbPlayer.Id, "You struggled to return to a human form.", false); return($"Unfortunately you are not able to struggle free from your form as {itemPlus.FriendlyName}. Keep trying and you might succeed later... [Recovery chance next struggle: {(int)GetStruggleChance(player, dungeonPenalty)}%]"); } }
public static string GiveInanimateXP(string membershipId, bool isWhitelist) { IInanimateXPRepository inanimXpRepo = new EFInanimateXPRepository(); IItemRepository itemRep = new EFItemRepository(); // get the current level of this player based on what item they are var me = PlayerProcedures.GetPlayerFromMembership(membershipId); var inanimateMeHack = DomainRegistry.Repository.FindSingle(new GetItemByFormerPlayer { PlayerId = me.Id }); var inanimateMe = itemRep.Items.FirstOrDefault(i => i.Id == inanimateMeHack.Id); // TODO: Replace with proper Command var currentGameTurn = PvPWorldStatProcedures.GetWorldTurnNumber(); decimal xpGain = 0; // get the number of inanimate accounts under this IP IPlayerRepository playerRepo = new EFPlayerRepository(); decimal playerCount = playerRepo.Players.Count(p => p.IpAddress == me.IpAddress && (p.Mobility == PvPStatics.MobilityInanimate || p.Mobility == PvPStatics.MobilityPet) && p.BotId == AIStatics.ActivePlayerBotId); if (playerCount == 0 || isWhitelist) { playerCount = 1; } var xp = inanimXpRepo.InanimateXPs.FirstOrDefault(i => i.OwnerId == me.Id); if (xp == null) { xp = new InanimateXP { OwnerId = me.Id, Amount = xpGain / playerCount, TimesStruggled = -6 * me.Level, LastActionTimestamp = DateTime.UtcNow, LastActionTurnstamp = currentGameTurn - 1, }; if (me.Mobility == PvPStatics.MobilityInanimate) { StatsProcedures.AddStat(me.MembershipId, StatsProcedures.Stat__InanimateXPEarned, (float)xpGain); } else if (me.Mobility == PvPStatics.MobilityPet) { StatsProcedures.AddStat(me.MembershipId, StatsProcedures.Stat__PetXPEarned, (float)xpGain); } } else { double turnsSinceLastAction = currentGameTurn - xp.LastActionTurnstamp; if (turnsSinceLastAction > TurnTimesStatics.GetItemMaxTurnsBuildup()) { turnsSinceLastAction = TurnTimesStatics.GetItemMaxTurnsBuildup(); } if (turnsSinceLastAction < 0) { turnsSinceLastAction = 0; } xpGain += Convert.ToDecimal(turnsSinceLastAction) * InanimateXPStatics.XPGainPerInanimateAction; xpGain = xpGain / playerCount; if (me.Mobility == PvPStatics.MobilityInanimate) { StatsProcedures.AddStat(me.MembershipId, StatsProcedures.Stat__InanimateXPEarned, (float)xpGain); } else if (me.Mobility == PvPStatics.MobilityPet) { StatsProcedures.AddStat(me.MembershipId, StatsProcedures.Stat__PetXPEarned, (float)xpGain); } xp.Amount += xpGain; xp.TimesStruggled -= 2 * Convert.ToInt32(turnsSinceLastAction); xp.LastActionTimestamp = DateTime.UtcNow; xp.LastActionTurnstamp = currentGameTurn; } var resultMessage = " "; if (xp.Amount >= Convert.ToDecimal(ItemProcedures.GetXPRequiredForItemPetLevelup(inanimateMe.Level))) { xp.Amount -= Convert.ToDecimal(ItemProcedures.GetXPRequiredForItemPetLevelup(inanimateMe.Level)); inanimateMe.Level++; itemRep.SaveItem(inanimateMe); resultMessage += $" You have gained {xpGain:0.#} xp. <b>Congratulations, you have gained a level! Your owner will be so proud...</b>"; var wearerMessage = "<span style='color: darkgreen'>" + me.FirstName + " " + me.LastName + ", currently your " + ItemStatics.GetStaticItem(inanimateMe.ItemSourceId).FriendlyName + ", has gained a level! Treat them kindly and they might keep helping you out...</span>"; // now we need to change the owner's max health or mana based on this leveling if (inanimateMe.OwnerId > 0) { PlayerLogProcedures.AddPlayerLog((int)inanimateMe.OwnerId, wearerMessage, true); var inanimateMePlus = ItemProcedures.GetItemViewModel(inanimateMe.Id); if (inanimateMePlus.Item.HealthBonusPercent != 0.0M || inanimateMePlus.Item.ManaBonusPercent != 0.0M) { var myowner = playerRepo.Players.FirstOrDefault(p => p.Id == inanimateMe.OwnerId); var healthChange = PvPStatics.Item_LevelBonusModifier * inanimateMePlus.Item.HealthBonusPercent; var manaChange = PvPStatics.Item_LevelBonusModifier * inanimateMePlus.Item.ManaBonusPercent; myowner.MaxHealth += healthChange; myowner.MaxMana += manaChange; if (myowner.MaxHealth < 1) { myowner.MaxHealth = 1; } if (myowner.MaxMana < 1) { myowner.MaxMana = 1; } if (myowner.Health > myowner.MaxHealth) { myowner.Health = myowner.MaxHealth; } if (myowner.Mana > myowner.MaxMana) { myowner.Mana = myowner.MaxMana; } playerRepo.SavePlayer(myowner); } } } else { resultMessage = $" You have gained {xpGain:0.#} xp. ({xp.Amount:0.#}/{ItemProcedures.GetXPRequiredForItemPetLevelup(inanimateMe.Level):0.#} to next level)."; } inanimXpRepo.SaveInanimateXP(xp); // lock the player into their fate if their inanimate XP gets too high if (xp.TimesStruggled <= TurnTimesStatics.GetStruggleXPBeforeItemPermanentLock() * .5 && xp.TimesStruggled > TurnTimesStatics.GetStruggleXPBeforeItemPermanentLock() && !inanimateMe.IsPermanent) { resultMessage += " Careful, if you keep doing this you may find yourself stuck in your current form forever..."; } if (xp.TimesStruggled <= TurnTimesStatics.GetStruggleXPBeforeItemPermanentLock() && !inanimateMe.IsPermanent) { inanimateMe.IsPermanent = true; itemRep.SaveItem(inanimateMe); DomainRegistry.Repository.Execute(new RemoveSoulbindingOnPlayerItems { PlayerId = me.Id }); DomainRegistry.Repository.Execute(new DropAllItems { PlayerId = me.Id, IgnoreRunes = false }); var formRepo = new EFDbStaticFormRepository(); var form = formRepo.DbStaticForms.FirstOrDefault(f => f.Id == me.FormSourceId); if (inanimateMe.OwnerId != null && form != null) { PlayerLogProcedures.AddPlayerLog(inanimateMe.OwnerId.Value, $"{me.GetFullName()} has locked and is now unable to escape their form as your {form.FriendlyName}!", true); } PlayerLogProcedures.AddPlayerLog(me.Id, $"You have locked in your current form as a {form.FriendlyName}!", false); resultMessage += " <b>You find the last of your old human self slip away as you permanently embrace your new form.</b>"; } return(resultMessage); }
private static void PerformInanimateTransformation(Player victim, Player attacker, int skillSourceId, DbStaticForm targetForm, LogBox output) { SkillProcedures.UpdateFormSpecificSkillsToPlayer(victim, targetForm.Id); DomainRegistry.Repository.Execute(new ChangeForm { PlayerId = victim.Id, FormSourceId = targetForm.Id }); if (targetForm.MobilityType == PvPStatics.MobilityInanimate && victim.BotId != AIStatics.MinibossPlushAngelId) //No reward for monsters that hurt an innocent little plush friend. :( { StatsProcedures.AddStat(victim.MembershipId, StatsProcedures.Stat__TimesInanimateTFed, 1); StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__TimesInanimateTFing, 1); } else if (targetForm.MobilityType == PvPStatics.MobilityPet && victim.BotId != AIStatics.MinibossPlushAngelId) //No reward for monsters that hurt an innocent little plush friend. :( { StatsProcedures.AddStat(victim.MembershipId, StatsProcedures.Stat__TimesAnimalTFed, 1); StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__TimesAnimalTFing, 1); } if (targetForm.MobilityType == PvPStatics.MobilityPet || targetForm.MobilityType == PvPStatics.MobilityInanimate) { if (victim.BotId == AIStatics.PsychopathBotId) { StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__PsychopathsDefeated, 1); } if (victim.BotId == AIStatics.ActivePlayerBotId && attacker.GameMode == (int)GameModeStatics.GameModes.PvP && victim.GameMode == (int)GameModeStatics.GameModes.PvP) { StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__PvPPlayerNumberTakedowns, 1); StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__PvPPlayerLevelTakedowns, victim.Level); } } // extra log stuff for turning into item var extra = ItemProcedures.PlayerBecomesItem(victim, targetForm, attacker); output.AttackerLog += extra.AttackerLog; output.VictimLog += extra.VictimLog; output.LocationLog += extra.LocationLog; // give some of the victim's money to the attacker, the amount depending on what mode the victim is in var moneygain = victim.Money * .35M; PlayerProcedures.GiveMoneyToPlayer(attacker, moneygain); PlayerProcedures.GiveMoneyToPlayer(victim, -moneygain / 2); var levelDifference = attacker.Level - victim.Level; // only give the lump sum XP if the victim is not in the same covenant if (attacker.Covenant == null || attacker.Covenant != victim.Covenant) { var xpGain = 100 - (PvPStatics.XP__EndgameTFCompletionLevelBase * levelDifference); if (xpGain < 50) { xpGain = 50; } else if (xpGain > 200) { xpGain = 200; } // give the attacker a nice lump sum for having completed the transformation output.AttackerLog += $" <br>For having sealed your opponent into their new form, you gain an extra <b>{xpGain}</b> XP."; output.AttackerLog += PlayerProcedures.GiveXP(attacker, xpGain); } // exclude PvP score for bots if (victim.BotId == AIStatics.ActivePlayerBotId) { var score = PlayerProcedures.GetPvPScoreFromWin(attacker, victim); if (score > 0) { output.AttackerLog += PlayerProcedures.GivePlayerPvPScore(attacker, victim, score); output.VictimLog += PlayerProcedures.RemovePlayerPvPScore(victim, attacker, score); StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__DungeonPointsStolen, (float)score); } else { output.AttackerLog += $" {victim.GetFullName()} unfortunately did not have any dungeon points for you to steal for yourself."; } } // Call out a player for being the monster they are when they defeat the plush angel. if (victim.BotId == AIStatics.MinibossPlushAngelId) { output.AttackerLog += "<br><br>Why did you do that to the poor plush? They just wanted to be a friend!<br>"; output.LocationLog += $"<br><b>{attacker.GetFullName()}</b> went and bullied <b>{victim.GetFullName()}</b>, like some <b>monster</b>. The angelic plush left some flowers to the 'victor', in hope they would forgive it despite doing no wrong."; // Give the dummy a bit of madness for being a bully. EffectProcedures.GivePerkToPlayer(198, attacker); } // Heals the victorious player provided that the target was eligible if (attacker.BotId == AIStatics.ActivePlayerBotId) { // Provide no healing if the victim shared a coven with the attacker if (attacker.Covenant != null && attacker.Covenant == victim.Covenant) { output.AttackerLog += " <br>There is no glory to be had in this victory, your willpower & mana are not restored."; } else { // Figure out the modifier to be used double modifier = (levelDifference * 5) / 100; // Cap the modifier to prevent too much / too little healing. if (modifier > 0.3) { modifier = 0.3; } if (modifier < -0.55) { modifier = -0.55; } decimal healingPercent = (decimal)(0.6 + modifier); if (victim.BotId != AIStatics.ActivePlayerBotId) { // The victim is not a player, provide half of the healing. healingPercent /= 2; } // Heal the attacker and restore their Mana var healingTotal = attacker.MaxHealth * healingPercent; var manaRestoredTotal = attacker.MaxMana * healingPercent; PlayerProcedures.ChangePlayerActionMana(0, healingTotal, manaRestoredTotal, attacker.Id, false); // Remove any Self Restore entires. RemoveSelfRestore(victim); output.AttackerLog += $"<br />Invigorated by your victory and fuelled by the scattered essence that was once your foe, you are healed for {healingTotal:#} willpower and {manaRestoredTotal:#} mana."; } } output.AttackerLog += $" You collect {Math.Round(moneygain, 0)} Arpeyjis your victim dropped during the transformation."; // create inanimate XP for the victim InanimateXPProcedures.GetStruggleChance(victim, false); // if this victim is a bot, clear out some old stuff that is not needed anymore if (victim.BotId < AIStatics.ActivePlayerBotId) { AIDirectiveProcedures.DeleteAIDirectiveByPlayerId(victim.Id); PlayerLogProcedures.ClearPlayerLog(victim.Id); } TFEnergyProcedures.DeleteAllPlayerTFEnergiesOfFormSourceId(victim.Id, targetForm.Id); // if the attacker is a psycho, have them change to a new spell and equip whatever they just earned if (attacker.BotId == AIStatics.PsychopathBotId) { SkillProcedures.DeletePlayerSkill(attacker, skillSourceId); if (targetForm.MobilityType == PvPStatics.MobilityInanimate || targetForm.MobilityType == PvPStatics.MobilityPet) { if (attacker.MembershipId.IsNullOrEmpty()) { // give this bot a random replacement inanimate/pet skill var eligibleSkills = SkillStatics.GetLearnablePsychopathSkills().ToList(); var rand = new Random(); var skillToLearn = eligibleSkills.ElementAt(rand.Next(eligibleSkills.Count)); SkillProcedures.GiveSkillToPlayer(attacker.Id, skillToLearn.Id); } else { // Bot is being controlled by a player - re-add the original skill so only the ordering of skills changes SkillProcedures.GiveSkillToPlayer(attacker.Id, skillSourceId); } } } }
public static string GivePerkToPlayer(int effectSourceId, Player player, int?Duration = null, int?Cooldown = null) { IEffectRepository effectRepo = new EFEffectRepository(); // see if this player already has this perk. If so, reject it var possibleSamePerk = effectRepo.Effects.FirstOrDefault(e => e.EffectSourceId == effectSourceId && e.OwnerId == player.Id); if (possibleSamePerk != null) { return("You already have this perk. Choose another."); } // grab the static part of this effect var effectPlus = EffectStatics.GetDbStaticEffect(effectSourceId); if (effectPlus.isLevelUpPerk) { // assert that the perk doesn't require a level higher than the player if (effectPlus.AvailableAtLevel > player.Level) { return("You are not at a high enough level to earn this perk."); } // assert that the perk doesn't require a prerequisite that the player does not yet have if (effectPlus.PreRequisiteEffectSourceId != null) { var requiredPrerequisite = effectRepo.Effects.FirstOrDefault(e => e.OwnerId == player.Id && e.EffectSourceId == effectPlus.PreRequisiteEffectSourceId); if (requiredPrerequisite == null) { return("This perk requires the <b>" + EffectStatics.GetDbStaticEffect(effectPlus.PreRequisiteEffectSourceId.Value).FriendlyName + "</b> prerequisite perk which you do not have."); } } } var cmd = new CreateEffect(); cmd.EffectSourceId = EffectStatics.GetDbStaticEffect(effectSourceId).Id; cmd.OwnerId = player.Id; // this effect is a permanent levelup perk if (effectPlus.AvailableAtLevel > 0) { cmd.Duration = 99999; cmd.Cooldown = 99999; cmd.IsPermanent = true; cmd.Level = 1; } // this effect is temporary, grab some of its stats from the effect static if (effectPlus.AvailableAtLevel == 0) { var duration = Duration ?? effectPlus.Duration; var cooldown = Cooldown.HasValue ? Math.Max(duration, Cooldown.Value) : effectPlus.Cooldown; cmd.Duration = duration; cmd.Cooldown = cooldown; cmd.IsPermanent = false; } // okay to proceed--give this player this perk. DomainRegistry.Repository.Execute(cmd); IPlayerRepository playerRepo = new EFPlayerRepository(); var person = playerRepo.Players.FirstOrDefault(p => p.Id == player.Id); var logMessage = $"You have gained the perk {effectPlus.FriendlyName}."; if (cmd.IsPermanent) { // this is a level up perk so just return a simple message PlayerLogProcedures.AddPlayerLog(player.Id, logMessage, false); //remove an unused perk from the player person.UnusedLevelUpPerks--; } else { // this is a temporary perk so return the flavor text if (player.Gender == PvPStatics.GenderMale && !effectPlus.MessageWhenHit_M.IsNullOrEmpty()) { logMessage = effectPlus.MessageWhenHit_M; } else if (player.Gender == PvPStatics.GenderFemale && !effectPlus.MessageWhenHit_F.IsNullOrEmpty()) { logMessage = effectPlus.MessageWhenHit_F; } else { logMessage = effectPlus.MessageWhenHit; } PlayerLogProcedures.AddPlayerLog(player.Id, logMessage, false); } person.ReadjustMaxes(ItemProcedures.GetPlayerBuffs(person)); playerRepo.SavePlayer(person); return(logMessage); }