/// <summary> /// Attack an attacking player back. There is a random chance to draw Narcissa's aggro from doing this if she has a target. If she has no active target, /// the attacker instantly becomes her new target. /// </summary> /// <param name="attacker"></param> public static void CounterAttack(Player attacker) { IPlayerRepository playerRepo = new EFPlayerRepository(); var faeboss = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.FaebossBotId); AIProcedures.DealBossDamage(faeboss, attacker, true, 1); // log attack for human on boss var spell = ChooseSpell(PvPWorldStatProcedures.GetWorldTurnNumber(), PvPStatics.MobilityInanimate); for (var i = 0; i < 3; i++) { AttackProcedures.Attack(faeboss, attacker, spell); AIProcedures.DealBossDamage(faeboss, attacker, false, 1); // log attack for boss on human } var directive = AIDirectiveProcedures.GetAIDirective(faeboss.Id); // random chance to aggro faeboss var rand = new Random(Guid.NewGuid().GetHashCode()); var num = rand.NextDouble(); if (num < AggroChance || directive.Var1 == 0) { IAIDirectiveRepository aiRepo = new EFAIDirectiveRepository(); var dbDirective = aiRepo.AIDirectives.FirstOrDefault(a => a.Id == directive.Id); dbDirective.Var1 = attacker.Id; aiRepo.SaveAIDirective(dbDirective); } }
public static void SpawnLindella() { var merchant = DomainRegistry.Repository.FindSingle(new GetPlayerByBotId { BotId = AIStatics.LindellaBotId }); if (merchant == null) { var cmd = new CreatePlayer { BotId = AIStatics.LindellaBotId, Level = 5, FirstName = "Lindella", LastName = "the Soul Vendor", Health = 100000, Mana = 100000, MaxHealth = 100000, MaxMana = 100000, Mobility = PvPStatics.MobilityFull, Money = 1000, FormSourceId = LindellaFormId, Location = "270_west_9th_ave", // Lindella starts her rounds here Gender = PvPStatics.GenderFemale, }; var id = DomainRegistry.Repository.Execute(cmd); IPlayerRepository playerRepo = new EFPlayerRepository(); var newMerchant = playerRepo.Players.FirstOrDefault(p => p.Id == id); newMerchant.ReadjustMaxes(ItemProcedures.GetPlayerBuffs(newMerchant)); playerRepo.SavePlayer(newMerchant); AIDirectiveProcedures.GetAIDirective(id); AIDirectiveProcedures.SetAIDirective_MoveTo(id, "street_15th_south"); } }
public static string OpenPsychoNip(Player player) { IAIDirectiveRepository directiveRepo = new EFAIDirectiveRepository(); var idleBots = directiveRepo.AIDirectives.Where(d => d.State == "idle") .Select(d => d.OwnerId) .ToArray(); // Set three lowest level psychos without targets on the player IPlayerRepository playerRepo = new EFPlayerRepository(); var botsToAttract = playerRepo.Players.Where(p => idleBots.Contains(p.Id) && p.BotId == AIStatics.PsychopathBotId && p.Mobility == PvPStatics.MobilityFull) .OrderBy(p => p.Level) .Select(p => p.Id) .Take(3) .ToArray(); foreach (var botId in botsToAttract) { AIDirectiveProcedures.SetAIDirective_Attack(botId, player.Id); } PlayerLogProcedures.AddPlayerLog(player.Id, $"You open a tin pf PsychoNip", false); LocationLogProcedures.AddLocationLog(player.dbLocationName, $"{player.GetFullName()} opened a tin of PsychoNip!"); return("You spot a tin with a colorful insignia on a shelf. You move over to take a closer look, but accidentally knock the tin to the floor and spill its contents! You gather up the fallen leaves and place them back in the tin. \"PsychoNip,\" it reads. Perhaps you should stay alert for the next few turns in case the scent has caught anyone's attention..."); }
public static void DonnaCounterattack(Player personAttacking, Player donna) { AIProcedures.DealBossDamage(donna, personAttacking, true, 1); var rand = new Random(); var roll = rand.NextDouble() * 3; for (var i = 0; i < roll; i++) { AttackProcedures.Attack(donna, personAttacking, ChooseSpell(PvPStatics.LastGameTurn)); } AIProcedures.DealBossDamage(donna, personAttacking, false, (int)roll); // if Donna is weak enough start having her mega-attack anyone in the room if (donna.Health < donna.MaxHealth / 5) { var PlayersHere = PlayerProcedures.GetPlayersAtLocation(donna.dbLocationName).ToList(); foreach (var p in PlayersHere) { if (p.BotId == AIStatics.ActivePlayerBotId && p.Level > 3 && p.Mobility == PvPStatics.MobilityFull && !PlayerProcedures.PlayerIsOffline(p) && p.Id != personAttacking.Id && p.InDuel <= 0 && p.InQuest <= 0) { AttackProcedures.Attack(donna, p, ChooseSpell(PvPStatics.LastGameTurn)); AIProcedures.DealBossDamage(donna, p, false, 1); } } } //AIDirective directive = AIDirectiveProcedures.GetAIDirective(bot.Id); var directive = AIDirectiveProcedures.GetAIDirective(donna.Id); // if Donna has no target or by a random chance, make her target this attacker if (directive.TargetPlayerId == -1 || directive.State == "idle" || roll < 1) { AIDirectiveProcedures.SetAIDirective_Attack(donna.Id, personAttacking.Id); } }
/// <summary> /// Spawns Narcissa into the world and sets her initial blank AI Directive /// </summary> public static void SpawnFaeBoss() { var faeboss = DomainRegistry.Repository.FindSingle(new GetPlayerByBotId { BotId = AIStatics.FaebossBotId }); if (faeboss == null) { var cmd = new CreatePlayer { FirstName = FirstName, LastName = LastName, Location = SpawnLocation, Gender = PvPStatics.GenderFemale, Health = 100000, Mana = 100000, MaxHealth = 100000, MaxMana = 100000, FormSourceId = FaeBossFormId, Money = 1000, Mobility = PvPStatics.MobilityFull, Level = 25, BotId = AIStatics.FaebossBotId, }; var id = DomainRegistry.Repository.Execute(cmd); var playerRepo = new EFPlayerRepository(); var faebossEF = playerRepo.Players.FirstOrDefault(p => p.Id == id); faebossEF.ReadjustMaxes(ItemProcedures.GetPlayerBuffs(faebossEF)); playerRepo.SavePlayer(faebossEF); AIDirectiveProcedures.GetAIDirective(id); for (var i = 0; i < 2; i++) { DomainRegistry.Repository.Execute(new GiveRune { ItemSourceId = RuneStatics.NARCISSA_RUNE, PlayerId = faebossEF.Id }); } } }
public static void RunActions(int turnNumber) { IPlayerRepository playerRepo = new EFPlayerRepository(); var merchant = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.LindellaBotId && f.Mobility == PvPStatics.MobilityFull); if (merchant != null && merchant.Mobility == PvPStatics.MobilityFull) { var directive = AIDirectiveProcedures.GetAIDirective(merchant.Id); if (directive.TargetLocation.IsEmpty()) { AIDirectiveProcedures.SetAIDirective_MoveTo(merchant.Id, "270_west_9th_ave"); } if (directive.TargetLocation != merchant.dbLocationName) { var newplace = AIProcedures.MoveTo(merchant, directive.TargetLocation, 6); merchant.dbLocationName = newplace; } // if the merchant has arrived, set a new target for next time. // Does this count as turning Lindella into a snail? if (directive.TargetLocation == merchant.dbLocationName && turnNumber % 2 == 0) { if (merchant.dbLocationName == "270_west_9th_ave") { AIDirectiveProcedures.SetAIDirective_MoveTo(merchant.Id, "street_15th_south"); } else if (merchant.dbLocationName == "street_15th_south") { AIDirectiveProcedures.SetAIDirective_MoveTo(merchant.Id, "street_220_sunnyglade_drive"); } else if (merchant.dbLocationName == "street_220_sunnyglade_drive") { AIDirectiveProcedures.SetAIDirective_MoveTo(merchant.Id, "street_70e9th"); } else if (merchant.dbLocationName == "street_70e9th") { AIDirectiveProcedures.SetAIDirective_MoveTo(merchant.Id, "street_130_main"); } else if (merchant.dbLocationName == "street_130_main") { AIDirectiveProcedures.SetAIDirective_MoveTo(merchant.Id, "270_west_9th_ave"); } } playerRepo.SavePlayer(merchant); var box = ItemProcedures.GetPlayerBuffs(merchant); if ((merchant.Health / merchant.MaxHealth) < .75M) { if (merchant.Health < merchant.MaxHealth) { DomainRegistry.Repository.Execute(new Cleanse { PlayerId = merchant.Id, Buffs = box, NoValidate = true }); DomainRegistry.Repository.Execute(new Cleanse { PlayerId = merchant.Id, Buffs = box, NoValidate = true }); DomainRegistry.Repository.Execute(new Meditate { PlayerId = merchant.Id, Buffs = box, NoValidate = true }); } } else { if (merchant.Mana < merchant.MaxMana) { DomainRegistry.Repository.Execute(new Meditate { PlayerId = merchant.Id, Buffs = box, NoValidate = true }); DomainRegistry.Repository.Execute(new Meditate { PlayerId = merchant.Id, Buffs = box, NoValidate = true }); DomainRegistry.Repository.Execute(new Cleanse { PlayerId = merchant.Id, Buffs = box, NoValidate = true }); } } if (turnNumber % 16 == 1) { DomainRegistry.Repository.Execute(new RestockNPC { BotId = AIStatics.LindellaBotId }); DomainRegistry.Repository.Execute(new RestockNPC { BotId = AIStatics.LoremasterBotId }); } } }
public static string RunAction(Player victim, JokeShopActionViewModel input) { switch (input.Action) { case JokeShopActions.None: break; case JokeShopActions.WarnPlayer: return(JokeShopProcedures.EnsurePlayerIsWarned(victim, duration: input.EffectDuration, cooldown: input.EffectCooldown)); case JokeShopActions.RemindPlayer: return(JokeShopProcedures.EnsurePlayerIsWarnedTwice(victim, duration: input.EffectDuration, cooldown: input.EffectCooldown)); case JokeShopActions.BanPlayer: return(JokeShopProcedures.BanCharacter(victim, duration: input.EffectDuration, cooldown: input.EffectCooldown)); case JokeShopActions.UnbanPlayer: return(RemoveEffect(victim, JokeShopProcedures.BANNED_FROM_JOKE_SHOP_EFFECT, "Lifted Joke Shop ban on player")); case JokeShopActions.EjectPlayer: return(JokeShopProcedures.EjectCharacter(victim)); case JokeShopActions.EjectOfflinePlayers: JokeShopProcedures.EjectOfflineCharacters(); return("Ejected offline players"); case JokeShopActions.EjectAllPlayers: return(JokeShopProcedures.EmptyJokeShopOnto(LocationsStatics.GetRandomLocationNotInDungeonOr(LocationsStatics.JOKE_SHOP))); case JokeShopActions.MildPrank: return(JokeShopProcedures.MildPrank(victim)); case JokeShopActions.MischievousPrank: return(JokeShopProcedures.MischievousPrank(victim)); case JokeShopActions.MeanPrank: return(JokeShopProcedures.MeanPrank(victim)); case JokeShopActions.Search: return(JokeShopProcedures.Search(victim)); case JokeShopActions.Cleanse: return(JokeShopProcedures.Cleanse(victim)); case JokeShopActions.Meditate: return(JokeShopProcedures.Meditate(victim)); case JokeShopActions.SelfRestore: return(JokeShopProcedures.SelfRestore(victim)); case JokeShopActions.Activate: JokeShopProcedures.SetJokeShopActive(true); return("Joke shop activated"); case JokeShopActions.Deactivate: JokeShopProcedures.SetJokeShopActive(false); return("Joke shop deactivated"); case JokeShopActions.Relocate: LocationsStatics.MoveJokeShop(); return("Joke Shop moved"); case JokeShopActions.AnimateSafetyNet: return(JokeShopProcedures.Restore(victim)); case JokeShopActions.BlowWhistle: AIDirectiveProcedures.DeaggroPsychopathsOnPlayer(victim); return("Whistle blown"); case JokeShopActions.DiceGame: return(NovelPrankProcedures.DiceGame(victim)); case JokeShopActions.RandomShout: return(NovelPrankProcedures.RandomShout(victim)); case JokeShopActions.CombatRadar: return(NovelPrankProcedures.LocatePlayerInCombat(victim)); case JokeShopActions.RareFind: return(EnvironmentPrankProcedures.RareFind(victim)); case JokeShopActions.SummonPsychopath: return(NovelPrankProcedures.SummonPsychopath(victim, aggro: input.PsychoAggro)); case JokeShopActions.SummonEvilTwin: return(NovelPrankProcedures.SummonDoppelganger(victim, aggro: input.PsychoAggro)); case JokeShopActions.OpenPsychoNip: return(NovelPrankProcedures.OpenPsychoNip(victim)); case JokeShopActions.SummonLvl1Psychopath: return(NovelPrankProcedures.SummonPsychopath(victim, strengthOverride: 0, aggro: input.PsychoAggro)); case JokeShopActions.SummonLvl3Psychopath: return(NovelPrankProcedures.SummonPsychopath(victim, strengthOverride: 1, aggro: input.PsychoAggro)); case JokeShopActions.SummonLvl5Psychopath: return(NovelPrankProcedures.SummonPsychopath(victim, strengthOverride: 2, aggro: input.PsychoAggro)); case JokeShopActions.SummonLvl7Psychopath: return(NovelPrankProcedures.SummonPsychopath(victim, strengthOverride: 3, aggro: input.PsychoAggro)); case JokeShopActions.SummonLvl9Psychopath: return(NovelPrankProcedures.SummonPsychopath(victim, strengthOverride: 4, aggro: input.PsychoAggro)); case JokeShopActions.SummonLvl11Psychopath: return(NovelPrankProcedures.SummonPsychopath(victim, strengthOverride: 5, aggro: input.PsychoAggro)); case JokeShopActions.SummonLvl13Psychopath: return(NovelPrankProcedures.SummonPsychopath(victim, strengthOverride: 6, aggro: input.PsychoAggro)); case JokeShopActions.PlaceBounty: return(NovelPrankProcedures.PlaceBountyOnPlayersHead(victim)); case JokeShopActions.AwardChallenge: { var minDuration = input.MinChallengeDuration ?? 1; var maxDuration = input.MaxChallengeDuration ?? 480; var penalties = (bool?)null; return(NovelPrankProcedures.AwardChallenge(victim, minDuration, maxDuration, penalties)); } case JokeShopActions.ClearChallenge: foreach (var challengeType in ChallengeProcedures.CHALLENGE_TYPES) { RemoveEffect(victim, challengeType.EffectSourceId); } return("Challenge cleared"); case JokeShopActions.CurrentChallenge: return(NovelPrankProcedures.DescribeChallenge(victim, ChallengeProcedures.CurrentChallenge(victim))); case JokeShopActions.ChallengeProgress: return(ChallengeProgress(victim)); case JokeShopActions.CheckChallenge: ChallengeProcedures.CheckChallenge(victim, false); return("Challenge checked"); case JokeShopActions.ForceAttack: return(NovelPrankProcedures.ForceAttack(victim)); case JokeShopActions.Incite: return(NovelPrankProcedures.Incite(victim)); case JokeShopActions.FillInventory: return(EnvironmentPrankProcedures.FillInventory(victim, overflow: false)); case JokeShopActions.LearnSpell: return(EnvironmentPrankProcedures.LearnSpell(victim)); case JokeShopActions.UnlearnSpell: return(EnvironmentPrankProcedures.UnlearnSpell(victim)); case JokeShopActions.BlockAttacks: return(EnvironmentPrankProcedures.BlockAttacks(victim)); case JokeShopActions.BlockCleanses: return(EnvironmentPrankProcedures.BlockCleanseMeditates(victim)); case JokeShopActions.BlockItemUses: return(EnvironmentPrankProcedures.BlockItemUses(victim)); case JokeShopActions.ResetCombatTimer: return(EnvironmentPrankProcedures.ResetCombatTimer(victim)); case JokeShopActions.ResetActivityTimer: EnvironmentPrankProcedures.ResetActivityTimer(victim); return("Activity timer reset"); case JokeShopActions.LiftRandomCurse: return(CharacterPrankProcedures.LiftRandomCurse(victim)); case JokeShopActions.Boost: return(CharacterPrankProcedures.GiveRandomEffect(victim, CharacterPrankProcedures.BOOST_EFFECTS, duration: input.EffectDuration, cooldown: input.EffectCooldown)); case JokeShopActions.DisciplineBoost: return(GiveEffect(victim, input, CharacterPrankProcedures.DISCIPLINE_BOOST)); case JokeShopActions.PerceptionBoost: return(GiveEffect(victim, input, CharacterPrankProcedures.PERCEPTION_BOOST)); case JokeShopActions.CharismaBoost: return(GiveEffect(victim, input, CharacterPrankProcedures.CHARISMA_BOOST)); case JokeShopActions.FortitudeBoost: return(GiveEffect(victim, input, CharacterPrankProcedures.FORTITUDE_BOOST)); case JokeShopActions.AgilityBoost: return(GiveEffect(victim, input, CharacterPrankProcedures.AGILITY_BOOST)); case JokeShopActions.RestorationBoost: return(GiveEffect(victim, input, CharacterPrankProcedures.RESTORATION_BOOST)); case JokeShopActions.MagickaBoost: return(GiveEffect(victim, input, CharacterPrankProcedures.MAGICKA_BOOST)); case JokeShopActions.RegenerationBoost: return(GiveEffect(victim, input, CharacterPrankProcedures.REGENERATION_BOOST)); case JokeShopActions.LuckBoost: return(GiveEffect(victim, input, CharacterPrankProcedures.LUCK_BOOST)); case JokeShopActions.InventoryBoost: return(GiveEffect(victim, input, CharacterPrankProcedures.INVENTORY_BOOST)); case JokeShopActions.MobilityBoost: return(GiveEffect(victim, input, CharacterPrankProcedures.MOBILITY_BOOST)); case JokeShopActions.Penalty: return(CharacterPrankProcedures.GiveRandomEffect(victim, CharacterPrankProcedures.PENALTY_EFFECTS, duration: input.EffectDuration, cooldown: input.EffectCooldown)); case JokeShopActions.DisciplinePenalty: return(GiveEffect(victim, input, CharacterPrankProcedures.DISCIPLINE_PENALTY)); case JokeShopActions.PerceptionPenalty: return(GiveEffect(victim, input, CharacterPrankProcedures.PERCEPTION_PENALTY)); case JokeShopActions.CharismaPenalty: return(GiveEffect(victim, input, CharacterPrankProcedures.CHARISMA_PENALTY)); case JokeShopActions.FortitudePenalty: return(GiveEffect(victim, input, CharacterPrankProcedures.FORTITUDE_PENALTY)); case JokeShopActions.AgilityPenalty: return(GiveEffect(victim, input, CharacterPrankProcedures.AGILITY_PENALTY)); case JokeShopActions.RestorationPenalty: return(GiveEffect(victim, input, CharacterPrankProcedures.RESTORATION_PENALTY)); case JokeShopActions.MagickaPenalty: return(GiveEffect(victim, input, CharacterPrankProcedures.MAGICKA_PENALTY)); case JokeShopActions.RegenerationPenalty: return(GiveEffect(victim, input, CharacterPrankProcedures.REGENERATION_PENALTY)); case JokeShopActions.LuckPenalty: return(GiveEffect(victim, input, CharacterPrankProcedures.LUCK_PENALTY)); case JokeShopActions.InventoryPenalty: return(GiveEffect(victim, input, CharacterPrankProcedures.INVENTORY_PENALTY)); case JokeShopActions.MobilityPenalty: return(GiveEffect(victim, input, CharacterPrankProcedures.MOBILITY_PENALTY)); case JokeShopActions.Blind: return(GiveEffect(victim, input, CharacterPrankProcedures.BLINDED_EFFECT)); case JokeShopActions.Dizzy: return(GiveEffect(victim, input, CharacterPrankProcedures.DIZZY_EFFECT)); case JokeShopActions.Hush: return(GiveEffect(victim, input, CharacterPrankProcedures.HUSHED_EFFECT)); case JokeShopActions.SneakLow: return(GiveEffect(victim, input, CharacterPrankProcedures.SNEAK_REVEAL_1)); case JokeShopActions.SneakMedium: return(GiveEffect(victim, input, CharacterPrankProcedures.SNEAK_REVEAL_2)); case JokeShopActions.SneakHigh: return(GiveEffect(victim, input, CharacterPrankProcedures.SNEAK_REVEAL_3)); case JokeShopActions.MakeInvisible: return(CharacterPrankProcedures.MakeInvisible(victim, duration: input.EffectDuration, cooldown: input.EffectCooldown)); case JokeShopActions.UndoInvisible: RemoveEffect(victim, JokeShopProcedures.INVISIBILITY_EFFECT); CharacterPrankProcedures.UndoInvisible(victim); return("Triggered undo invisible"); case JokeShopActions.UndoInvisibleItems: CharacterPrankProcedures.EnsureItemsAreVisible(); return("Invisible items fixed"); case JokeShopActions.MakePsychotic: return(CharacterPrankProcedures.MakePsychotic(victim, duration: input.EffectDuration, cooldown: input.EffectCooldown)); case JokeShopActions.UndoPsychotic: RemoveEffect(victim, JokeShopProcedures.PSYCHOTIC_EFFECT); return(CharacterPrankProcedures.UndoPsychotic(victim.Id)); case JokeShopActions.Instinctive: return(GiveEffect(victim, input, JokeShopProcedures.INSTINCT_EFFECT)); case JokeShopActions.UndoInstinctive: return(RemoveEffect(victim, JokeShopProcedures.INSTINCT_EFFECT, "Instinctive removed")); case JokeShopActions.AutoRestore: return(GiveEffect(victim, input, JokeShopProcedures.AUTO_RESTORE_EFFECT)); case JokeShopActions.ClearAutoRestore: return(RemoveEffect(victim, JokeShopProcedures.AUTO_RESTORE_EFFECT, "Player will no longer autorestore.<br><b>Important:</b> If they are a lost item they will be trapped in limbo and require you to give them a form change in order to escape!")); case JokeShopActions.TeleportToOverworld: return(EnvironmentPrankProcedures.TeleportToOverworld(victim, root: false, curse: false)); case JokeShopActions.TeleportToDungeon: return(EnvironmentPrankProcedures.TeleportToDungeon(victim, meanness: 0)); case JokeShopActions.TeleportToFriendlyNPC: return(EnvironmentPrankProcedures.TeleportToFriendlyNPC(victim)); case JokeShopActions.TeleportToHostileNPC: return(EnvironmentPrankProcedures.TeleportToHostileNPC(victim, attack: false)); case JokeShopActions.TeleportToBar: return(EnvironmentPrankProcedures.TeleportToBar(victim, root: false)); case JokeShopActions.TeleportToQuest: return(EnvironmentPrankProcedures.TeleportToQuest(victim)); case JokeShopActions.RunAway: return(EnvironmentPrankProcedures.RunAway(victim)); case JokeShopActions.WanderAimlessly: return(EnvironmentPrankProcedures.WanderAimlessly(victim)); case JokeShopActions.AnimateTransform: return(CharacterPrankProcedures.AnimateTransform(victim)); case JokeShopActions.ImmobileTransform: return(CharacterPrankProcedures.ImmobileTransform(victim, temporary: false)); case JokeShopActions.InanimateTransform: return(CharacterPrankProcedures.InanimateTransform(victim, temporary: false)); case JokeShopActions.LostItemTransform: return(CharacterPrankProcedures.InanimateTransform(victim, temporary: true)); case JokeShopActions.MobileInanimateTransform: return(CharacterPrankProcedures.MobileInanimateTransform(victim)); case JokeShopActions.TGTransform: return(CharacterPrankProcedures.TGTransform(victim)); case JokeShopActions.BodySwap: return(CharacterPrankProcedures.BodySwap(victim, clone: false)); case JokeShopActions.Clone: return(CharacterPrankProcedures.BodySwap(victim, clone: true)); case JokeShopActions.UndoTemporaryForm: CharacterPrankProcedures.UndoTemporaryForm(victim.Id); return(RemoveEffect(victim, JokeShopProcedures.AUTO_RESTORE_EFFECT, "Triggered undo of temporary form")); case JokeShopActions.RestoreBaseForm: return(CharacterPrankProcedures.RestoreBaseForm(victim)); case JokeShopActions.RestoreName: return(CharacterPrankProcedures.RestoreName(victim)); case JokeShopActions.IdentityChange: return(CharacterPrankProcedures.IdentityChange(victim)); case JokeShopActions.TransformToMindControlledForm: return(CharacterPrankProcedures.TransformToMindControlledForm(victim)); case JokeShopActions.ChangeBaseForm: return(CharacterPrankProcedures.ChangeBaseForm(victim)); case JokeShopActions.SetBaseFormToRegular: return(CharacterPrankProcedures.SetBaseFormToRegular(victim)); case JokeShopActions.SetBaseFormToCurrent: return(CharacterPrankProcedures.SetBaseFormToCurrent(victim)); case JokeShopActions.BossPrank: return(CharacterPrankProcedures.BossPrank(victim)); case JokeShopActions.Update: // Unreachable = case should have been handled by earlier code break; } return(null); }
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.."); }
public static string SummonPsychopath(Player player, Random rand = null, int?strengthOverride = null, bool?aggro = null) { rand = rand ?? new Random(); var baseStrength = Math.Min(Math.Max(0, (player.Level - 1) / 3), 3); var strength = strengthOverride ?? (baseStrength + Math.Max(0, rand.Next(6) - 1)); var prefix = ""; int level; int perk; int?extraPerk = null; var gender = rand.Next(2); int form; var turnNumber = PvPWorldStatProcedures.GetWorldTurnNumber(); if (strength <= 0 || (turnNumber < 300 && !strengthOverride.HasValue)) { strength = 0; level = 1; perk = AIProcedures.PsychopathicForLevelOneEffectSourceId; form = gender == 0 ? AIProcedures.Psycho1MId : AIProcedures.Psycho1FId; } else if (strength == 1 || (turnNumber < 600 && !strengthOverride.HasValue)) { strength = 1; level = 3; prefix = "Fierce"; perk = AIProcedures.PsychopathicForLevelThreeEffectSourceId; form = gender == 0 ? AIProcedures.Psycho3MId : AIProcedures.Psycho3FId; } else if (strength == 2 || (turnNumber < 900 && !strengthOverride.HasValue)) { strength = 2; level = 5; prefix = "Wrathful"; perk = AIProcedures.PsychopathicForLevelFiveEffectSourceId; form = gender == 0 ? AIProcedures.Psycho5MId : AIProcedures.Psycho5FId; } else if (strength == 3 || (turnNumber < 1500 && !strengthOverride.HasValue)) { strength = 3; level = 7; prefix = "Loathful"; perk = AIProcedures.PsychopathicForLevelSevenEffectSourceId; form = gender == 0 ? AIProcedures.Psycho7MId : AIProcedures.Psycho7FId; } else if (strength == 4 || (turnNumber < 2400 && !strengthOverride.HasValue)) { strength = 4; level = 9; prefix = "Soulless"; perk = AIProcedures.PsychopathicForLevelNineEffectSourceId; form = gender == 0 ? AIProcedures.Psycho9MId : AIProcedures.Psycho9FId; } else if (strength == 5 || (turnNumber < 3600 && !strengthOverride.HasValue)) { strength = 5; level = 11; prefix = "Ruthless"; perk = AIProcedures.PsychopathicForLevelNineEffectSourceId; extraPerk = AIProcedures.PsychopathicForLevelThreeEffectSourceId; form = gender == 0 ? AIProcedures.Psycho9MId : AIProcedures.Psycho9FId; } else { strength = 6; level = 13; prefix = "Eternal"; perk = AIProcedures.PsychopathicForLevelNineEffectSourceId; extraPerk = AIProcedures.PsychopathicForLevelFiveEffectSourceId; form = gender == 0 ? AIProcedures.Psycho9MId : AIProcedures.Psycho9FId; } var firstName = "Psychopath"; var lastName = NameService.GetRandomLastName(); if (!prefix.IsEmpty()) { firstName = $"{prefix} {firstName}"; } IPlayerRepository playerRepo = new EFPlayerRepository(); var cmd = new CreatePlayer { FirstName = firstName, LastName = lastName, Location = player.dbLocationName, FormSourceId = form, Level = level, Health = 100000, MaxHealth = 100000, Mana = 100000, MaxMana = 100000, BotId = AIStatics.PsychopathBotId, UnusedLevelUpPerks = 0, XP = 0, Money = (strength + 1) * 50, Gender = gender == 0 ? PvPStatics.GenderMale : PvPStatics.GenderFemale, }; var botId = DomainRegistry.Repository.Execute(cmd); // Give spells var eligibleSkills = SkillStatics.GetLearnablePsychopathSkills().ToList(); SkillProcedures.GiveSkillToPlayer(botId, eligibleSkills[rand.Next(eligibleSkills.Count())].Id); if (strength >= 5) { SkillProcedures.GiveSkillToPlayer(botId, PvPStatics.Spell_WeakenId); } if (strength >= 6) { var limitedMobilityForms = JokeShopProcedures.AnimateForms().Where(f => f.Category == JokeShopProcedures.LIMITED_MOBILITY).ToArray(); if (limitedMobilityForms.Any()) { IDbStaticSkillRepository skillsRepo = new EFDbStaticSkillRepository(); var formId = limitedMobilityForms[rand.Next(limitedMobilityForms.Count())].FormSourceId; var immobileSkill = skillsRepo.DbStaticSkills.FirstOrDefault(spell => spell.FormSourceId == formId); if (immobileSkill != null) { SkillProcedures.GiveSkillToPlayer(botId, immobileSkill.Id); } } } // Give bonuses EffectProcedures.GivePerkToPlayer(perk, botId); if (extraPerk.HasValue) { EffectProcedures.GivePerkToPlayer(extraPerk.Value, botId); } // Give runes var quantity = rand.Next(1, 3); for (var c = 0; c < quantity; c++) { var runeId = DomainRegistry.Repository.FindSingle(new GetRandomRuneAtLevel { RuneLevel = strength * 2 + 1, 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 {firstName} {lastName}!</b> Beware! They are not friendly!!", true); LocationLogProcedures.AddLocationLog(player.dbLocationName, $"{player.GetFullName()} has summoned <b>{firstName} {lastName}</b>!"); return("Near the counter is an altar with a leather-bound book resting open upon it. You take a look and try to read one of the jokes aloud. It seems to be some consonant-heavy tongue twister that soon leaves you faltering. You're not quite sure what the set up means, but hope the punchline will be worth it. As you spurt out the last syllable a puff of red smoke explodes out from the book with an audible bang. You're not laughing, and that remains the case when you close the book to see a large pentagram seared into the cover. As the smoke subsides there seems to be a strange neon flicker to the light and a crackling to the air. You turn sharply to see the psychopath you just summoned readying their attack against you!"); }
public static void RunDonnaActions() { IPlayerRepository playerRepo = new EFPlayerRepository(); var worldTurnNumber = PvPWorldStatProcedures.GetWorldTurnNumber() - 1; var donna = playerRepo.Players.FirstOrDefault(p => p.BotId == AIStatics.DonnaBotId); if (donna.Mobility != PvPStatics.MobilityFull) { EndEvent(donna); } else if (donna.Mobility == PvPStatics.MobilityFull) { var donnasBuffs = ItemProcedures.GetPlayerBuffs(donna); // have donna meditate if (donna.Mana < donna.MaxMana) { DomainRegistry.Repository.Execute(new Meditate { PlayerId = donna.Id, Buffs = donnasBuffs, NoValidate = true }); DomainRegistry.Repository.Execute(new Meditate { PlayerId = donna.Id, Buffs = donnasBuffs, NoValidate = true }); } var directive = AIDirectiveProcedures.GetAIDirective(donna.Id); if (directive.State == "attack" || directive.State == "idle") { var target = playerRepo.Players.FirstOrDefault(p => p.Id == directive.TargetPlayerId); // if Donna's target goes offline, is inanimate, or in the dungeon, have her teleport back to the ranch if (target == null || target.Mobility != PvPStatics.MobilityFull || PlayerProcedures.PlayerIsOffline(target) || target.IsInDungeon() || target.InDuel > 0 || target.InQuest > 0) { if (donna.dbLocationName != "ranch_bedroom") { LocationLogProcedures.AddLocationLog(donna.dbLocationName, donna.FirstName + " " + donna.LastName + " vanished from here in a flash of smoke."); donna.dbLocationName = "ranch_bedroom"; LocationLogProcedures.AddLocationLog(donna.dbLocationName, donna.FirstName + " " + donna.LastName + " appeared here in a flash of smoke."); playerRepo.SavePlayer(donna); } AIDirectiveProcedures.SetAIDirective_Idle(donna.Id); } // Donna has a valid target; go chase it down and attack. Donna does not look for new targets. else { var newplace = AIProcedures.MoveTo(donna, target.dbLocationName, 10); donna.dbLocationName = newplace; playerRepo.SavePlayer(donna); if (target.dbLocationName == newplace) { var rand = new Random(); var roll = rand.NextDouble() * 3 + 2; for (var i = 0; i < roll; i++) { AttackProcedures.Attack(donna, target, ChooseSpell(PvPStatics.LastGameTurn)); } AIProcedures.DealBossDamage(donna, target, false, (int)roll); } else { } } } else { } // have Donna equip all the pets she owns IItemRepository itemRepo = new EFItemRepository(); IEnumerable <Item> donnasItems = itemRepo.Items.Where(i => i.OwnerId == donna.Id && !i.IsEquipped && i.Level > 3); var itemsToEquip = new List <Item>(); foreach (var i in donnasItems) { itemsToEquip.Add(i); } foreach (var i in itemsToEquip) { i.IsEquipped = true; i.dbLocationName = donna.dbLocationName; itemRepo.SaveItem(i); } //The list should only look at pets. var donnasPlayerPets = DomainRegistry.Repository.Find(new GetItemsOwnedByPlayer { OwnerId = donna.Id }).Where(i => i.ItemSource.ItemType == PvPStatics.ItemType_Pet).OrderBy(i => i.Level).ToList(); // have Donna release her weakest pet every so often if (worldTurnNumber % 6 == 0 && donnasPlayerPets.Any()) { var weakestItem = donnasPlayerPets.First(); ItemProcedures.DropItem(weakestItem.Id, donna.dbLocationName); LocationLogProcedures.AddLocationLog(donna.dbLocationName, "Donna released one of her weaker pets, " + weakestItem.FormerPlayer.FullName + ", here."); var luckyVictim = PlayerProcedures.GetPlayerWithExactName(weakestItem.FormerPlayer.FullName); PlayerLogProcedures.AddPlayerLog(luckyVictim.Id, "Donna has released you, allowing you to wander about or be tamed by a new owner.", true); } } }
/// <summary> /// Perform Narcissa's regular actions when a new turn has started. If Narcissa has no aggroed target, she seeks to transform random people into /// certain animate forms. If she has aggro, she will attempt to chase them and cast a pet spell on them. If she can't catch up, she'll cast the animate /// spells in the area instead and resume pursuit next turn. /// </summary> public static void RunTurnLogic() { IPlayerRepository playerRepo = new EFPlayerRepository(); var faeboss = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.FaebossBotId); // fae boss is no longer animate; end the event if (faeboss.Mobility != PvPStatics.MobilityFull) { EndEvent(); return; } // have Narcissa periodically drop all of her pets/belongings so she doesn't get OP with them if (PvPWorldStatProcedures.GetWorldTurnNumber() % 12 == 0) { DomainRegistry.Repository.Execute(new DropAllItems { PlayerId = faeboss.Id, IgnoreRunes = true }); } // have Narcissa meditate to get her mana back up faeboss.Mana = faeboss.MaxMana; var directive = AIDirectiveProcedures.GetAIDirective(faeboss.Id); // no target, go out and hit some random people with animate spells if (!HasValidTarget(directive)) { ResetTarget(directive); var newTargetLocation = GetLocationWithMostEligibleTargets(); var newActualLocation = AIProcedures.MoveTo(faeboss, newTargetLocation, GetRandomChaseDistance()); faeboss.dbLocationName = newActualLocation; playerRepo.SavePlayer(faeboss); CastAnimateSpellsAtLocation(faeboss); } // Narcissa has a valid target, go for them else { var target = PlayerProcedures.GetPlayer((int)directive.Var1); var newTargetLocation = target.dbLocationName; var newActualLocation = AIProcedures.MoveTo(faeboss, newTargetLocation, GetRandomChaseDistance()); faeboss.dbLocationName = newActualLocation; playerRepo.SavePlayer(faeboss); if (faeboss.dbLocationName == target.dbLocationName) { var spell = ChooseSpell(PvPWorldStatProcedures.GetWorldTurnNumber(), PvPStatics.MobilityPet); for (var i = 0; i < 4; i++) { AttackProcedures.Attack(faeboss, target, spell); } } else { CastAnimateSpellsAtLocation(faeboss); } } }
private static void EndEvent() { PvPWorldStatProcedures.Boss_EndThieves(); IPlayerRepository playerRepo = new EFPlayerRepository(); var malethief = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.MaleRatBotId); var femalethief = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.FemaleRatBotId); AIDirectiveProcedures.DeleteAIDirectiveByPlayerId(malethief.Id); AIDirectiveProcedures.DeleteAIDirectiveByPlayerId(femalethief.Id); // find the players who dealt the most damage and award them with money var damages_male = AIProcedures.GetTopAttackers(malethief.BotId, 10); var damages_female = AIProcedures.GetTopAttackers(femalethief.BotId, 10); // top player gets 500 XP, each player down the line receives 25 fewer var maxReward_Female = 1000 + Math.Floor(femalethief.Money); var maxReward_Male = 300 + Math.Floor(malethief.Money); for (var i = 0; i < damages_male.Count; i++) { var damage = damages_male.ElementAt(i); var victor = playerRepo.Players.FirstOrDefault(p => p.Id == damage.PlayerId); if (victor == null) { continue; } var reward = Math.Floor(maxReward_Male); victor.Money += maxReward_Male; PlayerLogProcedures.AddPlayerLog(victor.Id, "<b>For your contribution in defeating " + MaleBossFirstName + " you have been given " + (int)reward + " Arpeyjis from an old bounty placed on him.</b>", true); playerRepo.SavePlayer(victor); maxReward_Male *= .75M; // top two get runes if (i <= 1 && victor.Mobility == PvPStatics.MobilityFull) { DomainRegistry.Repository.Execute(new GiveRune { ItemSourceId = RuneStatics.RAT_THIEF_RUNE, PlayerId = victor.Id }); } } for (var i = 0; i < damages_female.Count; i++) { var damage = damages_female.ElementAt(i); var victor = playerRepo.Players.FirstOrDefault(p => p.Id == damage.PlayerId); var reward = Math.Floor(maxReward_Female); victor.Money += maxReward_Female; PlayerLogProcedures.AddPlayerLog(victor.Id, "<b>For your contribution in defeating " + FemaleBossFirstName + " you have been given " + (int)reward + " Arpeyjis from an old bounty placed on her.</b>", true); playerRepo.SavePlayer(victor); maxReward_Female *= .75M; // top two get runes if (i <= 1 && victor.Mobility == PvPStatics.MobilityFull) { DomainRegistry.Repository.Execute(new GiveRune { ItemSourceId = RuneStatics.RAT_THIEF_RUNE, PlayerId = victor.Id }); } } }