public virtual ActionResult RemoveCurse(int itemId) { var myMembershipId = User.Identity.GetUserId(); var me = PlayerProcedures.GetPlayerFromMembership(myMembershipId); // assert player is animate if (me.Mobility != PvPStatics.MobilityFull) { TempData["Error"] = "You must be animate in order to use this."; return(RedirectToAction(MVC.PvP.Play())); } // assert player has not already used an item this turn if (me.ItemsUsedThisTurn >= PvPStatics.MaxItemUsesPerUpdate) { TempData["Error"] = "You've already used an item this turn."; TempData["SubError"] = "You will be able to use another consumable next turn."; return(RedirectToAction(MVC.Item.MyInventory())); } // assert player owns at least one of the type of item needed var itemToUse = ItemProcedures.GetAllPlayerItems(me.Id).FirstOrDefault(i => i.dbItem.Id == itemId); if (itemToUse == null) { TempData["Error"] = "You do not own the item needed to do this."; return(RedirectToAction(MVC.PvP.Play())); } if (itemToUse.dbItem.ItemSourceId != ItemStatics.CurseLifterItemSourceId && itemToUse.dbItem.ItemSourceId != ItemStatics.ButtPlugItemSourceId) { TempData["Error"] = "This type of item cannot lift curses."; return(RedirectToAction(MVC.PvP.Play())); } IEnumerable <EffectViewModel2> effects = EffectProcedures.GetPlayerEffects2(me.Id).Where(e => e.Effect.IsRemovable && e.dbEffect.Duration > 0).ToList(); RemoveCurseViewModel output = new RemoveCurseViewModel { Effects = effects, Item = itemToUse }; return(View(MVC.Item.Views.RemoveCurse, output)); }
public static void ClaimReward(Player attacker, Player victim, DbStaticForm victimNewForm) { if (attacker == null || victim == null || victimNewForm == null) { return; } // Ensure victim is still in PvP, or not a player (in case we want to support bounties on NPCs) if (victim.BotId == AIStatics.ActivePlayerBotId && victim.GameMode != (int)GameModeStatics.GameModes.PvP) { return; } // NPCs are not eligible to claim bounties if (attacker.BotId != AIStatics.ActivePlayerBotId) { return; } // Only reward PvP players to avoid friend list/alt abuse if (attacker.GameMode != (int)GameModeStatics.GameModes.PvP) { return; } var bountyStaticEffectIds = MAPPINGS.Select(se => se.EffectSourceId); var victimEffects = EffectProcedures.GetPlayerEffects2(victim.Id).Where(e => bountyStaticEffectIds.Contains(e.dbEffect.EffectSourceId)); var award = 0; foreach (var victimEffect in victimEffects) { var bounty = BountyDetails(victim, victimEffect.dbEffect.EffectSourceId); if (bounty == null) { continue; } if (victimNewForm.Id == bounty.Form?.Id) { // Victim has been turned into the requested form - full reward award = bounty.CurrentReward; } else if (victimNewForm.ItemSourceId.HasValue) { // Award half bounty for a different inanimate form of the same type IDbStaticItemRepository itemsRepo = new EFDbStaticItemRepository(); var itemForm = itemsRepo.DbStaticItems.FirstOrDefault(i => i.Id == victimNewForm.ItemSourceId.Value); if (itemForm?.ItemType == bounty.Category) { award = bounty.CurrentReward / 2; } } if (award > 0) { // Release the victim from the claimed bounty EffectProcedures.SetPerkDurationToZero(victimEffect.dbEffect.EffectSourceId, victim); // Award bounty funds to attacker PlayerLogProcedures.AddPlayerLog(attacker.Id, $"For turning {victim.GetFullName()} into a {victimNewForm.FriendlyName} you claim a bounty of {award} arpeyjis.", true); PlayerProcedures.GiveMoneyToPlayer(attacker, award); StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__BountiesClaimed, award); break; } } }
internal static BountyInfo BountyDetails(Player player, int effectId) { var effect = MAPPINGS.FirstOrDefault(e => e.EffectSourceId == effectId); if (effect == null || !EffectProcedures.PlayerHasEffect(player, effect.EffectSourceId)) { return(null); } var possibleFormSourceIds = JokeShopProcedures.Forms(e => e.Category == effect.Category).Select(e => e.FormSourceId).ToArray(); var numFormSourceIds = possibleFormSourceIds.Count(); if (numFormSourceIds == 0) { return(null); } var playerEffect = EffectProcedures.GetPlayerEffects2(player.Id).FirstOrDefault(e => e.dbEffect.EffectSourceId == effect.EffectSourceId); if (playerEffect == null || playerEffect.dbEffect.Duration == 0) { return(null); } var duration = playerEffect.dbEffect.Duration; if (duration <= 0) { return(null); } var turn = PvPStatics.LastGameTurn; if (turn == 0) { // Check server hasn't been restarted mid-game (in which case PvPStatics.LastGameTurn is not accurate) var worldStats = DomainRegistry.Repository.FindSingle(new GetWorld()); turn = worldStats.TurnNumber; } var expiresTurn = turn + duration; var formIndex = player.Id + expiresTurn; var formSourceId = possibleFormSourceIds[formIndex % possibleFormSourceIds.Count()]; // Locate the desired form IDbStaticFormRepository formsRepo = new EFDbStaticFormRepository(); var form = formsRepo.DbStaticForms.FirstOrDefault(f => f.Id == formSourceId); if (form == null) { return(null); } // Calculate the reward that could be claimed right now var reward = Math.Min(MAXIMUM_REWARD, BASE_REWARD + (MAXIMUM_REWARD - BASE_REWARD) * duration / TURNS_OF_BOUNTY); if (form.MobilityType == PvPStatics.MobilityFull) { reward /= 2; } var category = MAPPINGS.Where(m => m.EffectSourceId == effect.EffectSourceId).Select(m => m.Category).FirstOrDefault(); return(new BountyInfo { PlayerName = player.GetFullName(), Form = form, ExpiresTurn = expiresTurn, CurrentReward = reward, Category = category }); }
public static string SummonDoppelganger(Player player, Random rand = null, bool?aggro = null) { rand = rand ?? new Random(); IPlayerRepository playerRepo = new EFPlayerRepository(); var cmd = new CreatePlayer { FirstName = $"Evil {player.FirstName}", LastName = player.LastName, Location = player.dbLocationName, FormSourceId = player.FormSourceId, Level = Math.Min(9, player.Level), Health = player.Health, MaxHealth = player.MaxHealth, Mana = player.Mana, MaxMana = player.MaxMana, BotId = AIStatics.PsychopathBotId, UnusedLevelUpPerks = 0, XP = 0, Money = 100 + player.Money / 10, Gender = player.Gender, }; var botId = DomainRegistry.Repository.Execute(cmd); // Give spells var eligibleSkills = SkillStatics.GetLearnablePsychopathSkills().ToList(); SkillProcedures.GiveSkillToPlayer(botId, eligibleSkills[rand.Next(eligibleSkills.Count())].Id); SkillProcedures.GiveSkillToPlayer(botId, PvPStatics.Spell_WeakenId); // Give bonuses - we exclude some with no stats, with side effects, or that serve no purpose on psychos var sourcePerks = EffectProcedures.GetPlayerEffects2(player.Id); int[] effectsToExclude = { JokeShopProcedures.FIRST_WARNING_EFFECT, JokeShopProcedures.SECOND_WARNING_EFFECT, JokeShopProcedures.BANNED_FROM_JOKE_SHOP_EFFECT, JokeShopProcedures.INVISIBILITY_EFFECT, // Ensure twin is visible, even if player can't yet attack JokeShopProcedures.PSYCHOTIC_EFFECT, // Prevent psycho twin leaving rehab (Sorry, Pinocchio) JokeShopProcedures.INSTINCT_EFFECT, // Should be safe, but just to be on the safe side JokeShopProcedures.AUTO_RESTORE_EFFECT, // No free second chances for twins, bad ends are forever }; foreach (var sourcePerk in sourcePerks) { var effect = sourcePerk.dbEffect; if (!effectsToExclude.Contains(effect.EffectSourceId) && effect.Duration > 0) { EffectProcedures.GivePerkToPlayer(effect.EffectSourceId, botId, effect.Duration, effect.Cooldown); } } // Approximately mirror the buffs the player gets from their items. // (Actually equipping equivalent items and runes could easily be abused so use perks) var itemBuffs = ItemProcedures.GetPlayerBuffs(player).ItemBuffs(); itemBuffs += 30; // level 1 psycho effect gives -30 stats if (itemBuffs >= 315) { itemBuffs -= 315; EffectProcedures.GivePerkToPlayer(AIProcedures.PsychopathicForLevelNineEffectSourceId, botId); } if (itemBuffs >= 225) { itemBuffs -= 225; EffectProcedures.GivePerkToPlayer(AIProcedures.PsychopathicForLevelSevenEffectSourceId, botId); } if (itemBuffs >= 135) { itemBuffs -= 135; EffectProcedures.GivePerkToPlayer(AIProcedures.PsychopathicForLevelFiveEffectSourceId, botId); } if (itemBuffs >= 70) { itemBuffs -= 70; EffectProcedures.GivePerkToPlayer(AIProcedures.PsychopathicForLevelThreeEffectSourceId, botId); } if (itemBuffs < 30) { itemBuffs += 30; EffectProcedures.GivePerkToPlayer(AIProcedures.PsychopathicForLevelOneEffectSourceId, botId); } // Give runes (round level down to odd) var runeLevel = cmd.Level - 1; runeLevel = runeLevel - (runeLevel % 2) + 1; var quantity = rand.Next(1, 3); for (var c = 0; c < quantity; c++) { var runeId = DomainRegistry.Repository.FindSingle(new GetRandomRuneAtLevel { RuneLevel = runeLevel, Random = rand }); DomainRegistry.Repository.Execute(new GiveRune { ItemSourceId = runeId, PlayerId = botId }); } // Balance stats var psychoEF = playerRepo.Players.FirstOrDefault(p => p.Id == botId); psychoEF.ReadjustMaxes(ItemProcedures.GetPlayerBuffs(psychoEF)); playerRepo.SavePlayer(psychoEF); // Tell the bot to attack the player if (!aggro.HasValue || aggro.Value) { AIDirectiveProcedures.SetAIDirective_Attack(botId, player.Id); } PlayerLogProcedures.AddPlayerLog(player.Id, $"<b>You have summoned your evil twin!</b> Beware! They are not friendly!", true); LocationLogProcedures.AddLocationLog(player.dbLocationName, $"{player.GetFullName()} has summoned their evil twin!"); return("In the corner of the room is a freestanding mirror with a silver gilt frame. You smear some of the dust off the glass to see your reflection staring back at you through the clearing in the misty haze. As you look into it you catch sight of yourself twitching slightly, but you don't actually feel anything. Then your reflection narrows their gaze into a scowl and steps through the rippling glazed portal, bringing you face-to-face with your mirror self! You should be careful. Meeting your doppelganger never ends well.."); }