예제 #1
0
        public static void CounterAttack(Player human, Player bimboss)
        {
            // record that human attacked the boss
            AIProcedures.DealBossDamage(bimboss, human, true, 1);

            // if the bimboboss is inanimate, end this boss event
            if (bimboss.Mobility != PvPStatics.MobilityFull)
            {
                return;
            }

            // if the player doesn't currently have it, give them the infection kiss
            if (!EffectProcedures.PlayerHasEffect(human, KissEffectSourceId) && !EffectProcedures.PlayerHasEffect(human, CureEffectSourceId))
            {
                AttackProcedures.Attack(bimboss, human, KissSkillSourceId);
                AIProcedures.DealBossDamage(bimboss, human, false, 1);
            }

            // otherwise run the regular trasformation
            else if (human.FormSourceId != RegularBimboFormSourceId)
            {
                var rand        = new Random(Guid.NewGuid().GetHashCode());
                var attackCount = (int)Math.Floor(rand.NextDouble() * 2 + 1);
                for (var i = 0; i < attackCount; i++)
                {
                    AttackProcedures.Attack(bimboss, human, RegularTFSpellSourceId);
                }
                AIProcedures.DealBossDamage(bimboss, human, false, attackCount);
            }

            // otherwise make the human wander away to find more targets
            else
            {
                var targetLocation = GetLocationWithMostEligibleTargets();
                var newlocation    = AIProcedures.MoveTo(human, targetLocation, 9);

                IPlayerRepository playerRepo = new EFPlayerRepository();
                var dbHuman = playerRepo.Players.FirstOrDefault(p => p.Id == human.Id);
                dbHuman.TimesAttackingThisUpdate = PvPStatics.MaxAttacksPerUpdate;
                dbHuman.Health         = 0;
                dbHuman.Mana           = 0;
                dbHuman.XP            -= 25;
                dbHuman.dbLocationName = newlocation;
                dbHuman.ActionPoints  -= 10;

                if (dbHuman.XP < 0)
                {
                    dbHuman.XP = 0;
                }

                if (dbHuman.ActionPoints < 0)
                {
                    dbHuman.ActionPoints = 0;
                }

                playerRepo.SavePlayer(dbHuman);
                var message = "Lady Lovebringer is not pleased with you attacking her after she has so graciously given you that sexy body and carefree mind.  She whispers something into your ear that causes your body to grow limp in her arms, then injects you with a serum that makes your mind just a bit foggier and loyal to your bimbonic mother.  She orders you away to find new targets to spread the virus to.  The combination of lust and her command leaves you with no choice but to mindlessly obey...";
                PlayerLogProcedures.AddPlayerLog(human.Id, message, true);
            }
        }
예제 #2
0
        internal static int?PlaceBounty(Player player, Random rand = null)
        {
            // Only place bounties on PvP players
            if (player.GameMode != (int)GameModeStatics.GameModes.PvP)
            {
                return(null);
            }

            var numMappings = MAPPINGS.Count();

            if (numMappings == 0)
            {
                return(null);
            }

            rand = rand ?? new Random();
            var effect = MAPPINGS[rand.Next(numMappings)];

            if (EffectProcedures.PlayerHasEffect(player, effect.EffectSourceId))
            {
                return(null);
            }

            var possibleForms = JokeShopProcedures.Forms(e => e.Category == effect.Category).Select(e => e.FormSourceId).ToArray();
            var numForms      = possibleForms.Count();

            if (numForms == 0)
            {
                return(null);
            }

            EffectProcedures.GivePerkToPlayer(effect.EffectSourceId, player.Id, TURNS_OF_BOUNTY, TURNS_OF_BOUNTY + TURNS_OF_IMMUNITY);

            return(effect.EffectSourceId);
        }
        private static string RemoveEffect(Player victim, int effectSourceId, string message = null)
        {
            if (!EffectProcedures.PlayerHasEffect(victim, effectSourceId))
            {
                return(null);
            }

            EffectProcedures.RemovePerkFromPlayer(effectSourceId, victim);
            return(message);
        }
예제 #4
0
        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 string TeleportToOverworld(Player player, bool root, bool curse, Random rand = null)
        {
            rand = rand ?? new Random();
            var location = LocationsStatics.GetRandomLocationNotInDungeonOr(LocationsStatics.JOKE_SHOP);

            if (!Teleport(player, location, rand.Next(2) == 0))
            {
                return(null);
            }

            if (root)
            {
                CharacterPrankProcedures.GiveEffect(player, JokeShopProcedures.ROOT_EFFECT);
                root = EffectProcedures.PlayerHasActiveEffect(player.Id, JokeShopProcedures.ROOT_EFFECT);
            }

            if (curse && !root)
            {
                CharacterPrankProcedures.ApplyLocalCurse(player, location, rand);
            }

            return($"All of a sudden the Joke Shop spits you out and you find yourself in {LocationsStatics.GetConnectionName(location)}!");
        }
예제 #6
0
        public virtual ActionResult RemoveCurseSend(int curseEffectSourceId, int id)
        {
            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 this item
            var itemToUse = ItemProcedures.GetItemViewModel(id);

            if (itemToUse == null || itemToUse.dbItem.OwnerId != me.Id)
            {
                TempData["Error"] = "You do not own the item needed to do this.";
                return(RedirectToAction(MVC.PvP.Play()));
            }

            // assert that the item can remove curses and is not any old item
            if (itemToUse.dbItem.ItemSourceId != ItemStatics.CurseLifterItemSourceId && itemToUse.dbItem.ItemSourceId != ItemStatics.ButtPlugItemSourceId)
            {
                TempData["Error"] = "This item cannot remove curses.";
                return(RedirectToAction(MVC.PvP.Play()));
            }

            var curseToRemove = EffectStatics.GetDbStaticEffect(curseEffectSourceId);

            // assert this curse is removable
            if (!curseToRemove.IsRemovable)
            {
                TempData["Error"] = "This curse is too strong to be lifted.";
                return(RedirectToAction(MVC.PvP.Play()));
            }

            // back on your feet curse/buff -- just delete outright
            if (curseToRemove.Id == PvPStatics.Effect_BackOnYourFeetSourceId)
            {
                EffectProcedures.RemovePerkFromPlayer(curseToRemove.Id, me);
            }

            // regular curse; set duration to 0 but keep cooldown
            else
            {
                EffectProcedures.SetPerkDurationToZero(curseToRemove.Id, me);
            }

            // if the item is a consumable type, delete it.  Otherwise reset its cooldown
            if (itemToUse.Item.ItemType == PvPStatics.ItemType_Consumable)
            {
                ItemProcedures.DeleteItem(itemToUse.dbItem.Id);
            }
            // else if (itemToUse.Item.ItemType == PvPStatics.ItemType_Consumable_Reuseable)
            else
            {
                ItemProcedures.ResetUseCooldown(itemToUse);
            }

            PlayerProcedures.AddItemUses(me.Id, 1);

            var result = $"You have successfully removed the curse <b>{curseToRemove.FriendlyName}</b> from your body!";

            TempData["Result"] = result;

            var playerMessage = itemToUse.Item.UsageMessage_Player;

            if (string.IsNullOrEmpty(playerMessage))
            {
                PlayerLogProcedures.AddPlayerLog(me.Id, result, false);
            }
            else
            {
                PlayerLogProcedures.AddPlayerLog(me.Id, $"{playerMessage}<br />{result}", itemToUse.dbItem.FormerPlayerId != null);
            }

            if (itemToUse.dbItem.ItemSourceId == ItemStatics.ButtPlugItemSourceId && itemToUse.dbItem.FormerPlayerId != null)
            {
                var itemMessage = itemToUse.Item.UsageMessage_Item;
                var context     = $"Your owner just used you to remove the curse <b>{curseToRemove.FriendlyName}</b>! Doesn't that make you feel all warm and tingly?";
                itemMessage = string.IsNullOrEmpty(itemMessage) ? context : $"{itemMessage}<br />{context}";
                PlayerLogProcedures.AddPlayerLog((int)itemToUse.dbItem.FormerPlayerId, itemMessage, true);
            }

            return(RedirectToAction(MVC.PvP.Play()));
        }
예제 #7
0
        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
            });
        }
예제 #8
0
        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;
                }
            }
        }
예제 #9
0
        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..");
        }
예제 #10
0
        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!");
        }
예제 #11
0
        public void SendAs(string message, PlayerFormViewModel me)
        {
            string room = Clients.Caller.toRoom;

            me.Player.UpdateOnlineActivityTimestamp();

            if (me.Player.BotId == AIStatics.ActivePlayerBotId && DomainRegistry.Repository.FindSingle(new IsAccountLockedOut {
                userId = me.Player.MembershipId
            }))
            {
                return;
            }

            // Assert player is not banned
            if (me.Player.IsBannedFromGlobalChat && room == "global")
            {
                return;
            }

            if (!message.TrimStart().StartsWith("/") && EffectProcedures.PlayerHasActiveEffect(me.Player.ToDbPlayer(), CharacterPrankProcedures.HUSHED_EFFECT))
            {
                String[] denied = { "/me tries to speak but cannot!",
                                    "/me puffs profusely but doesn't make a sound!",
                                    "/me is unable to utter a single word!",
                                    "/me gesticulates wildly in the hope of communicating!",
                                    "/me is afflicted by a magical field, leaving them completely mute!",
                                    "/me has been hushed!",
                                    "/me tries to mouth some words in the hope you can understand!",
                                    "/me has lost their voice!",
                                    "/me has their lips sealed!",
                                    "/me will be unable to speak until the enchantment cast on them has lapsed!",
                                    "/me is counting down the minutes until they are able to speak again!",
                                    "/me tries to communicate through telepathy!" };
                message = denied[new Random().Next(denied.Count())];
            }

            // Get player picture and name
            var pic        = HtmlHelpers.GetImageURL(me, true).ToString();
            var descriptor = me.Player.GetDescriptor();

            var name = descriptor.Item1;

            pic = string.IsNullOrWhiteSpace(descriptor.Item2) ? pic : descriptor.Item2;

            if (me.Player.BotId == AIStatics.ActivePlayerBotId)
            {
                if (Context.User.IsInRole(PvPStatics.Permissions_Developer))
                {
                    name = name + " (Dev)";
                }
                else if (Context.User.IsInRole(PvPStatics.Permissions_Admin))
                {
                    name = name + " (Admin)";
                }
                else if (Context.User.IsInRole(PvPStatics.Permissions_Moderator))
                {
                    switch (me.Player.MembershipId)
                    {
                    case "d465db1c-ba4f-4347-b666-4dfd1c9a5e33":     //Because Martha wants to be a filthy casual.
                        break;

                    case "08b476c3-d262-45b6-9e6a-7d94b472fefe":
                        break;     //So is this one.

                    default:
                        name = name + " (Mod)";
                        break;
                    }
                }
            }

            // Performs message processing to correctly format any special text
            var output = ChatMessageProcessor.ProcessMessage(new MessageData(name, message));

            if (!string.IsNullOrWhiteSpace(output.Text))
            {
                var colorOut = output.SendPlayerChatColor ? me.Player.ChatColor : "";

                if (me.Player.BotId == AIStatics.ActivePlayerBotId)
                {
                    _chatPersistenceService.TrackMessageSend(me.Player.MembershipId, Context.ConnectionId);
                }

                var model = new
                {
                    User        = name,
                    IsStaff     = me.Player.BotId == AIStatics.ActivePlayerBotId ? ChatStatics.Staff.ContainsKey(me.Player.MembershipId) : false,
                    Color       = colorOut,
                    Pic         = pic,
                    Message     = WebUtility.HtmlEncode(output.Text),
                    MessageType = Enum.GetName(output.MessageType.GetType(), output.MessageType),
                    Timestamp   = DateTime.UtcNow.ToUnixTime(),
                };

                if (me.Player.BotId == AIStatics.ActivePlayerBotId && _chatPersistenceService.HasNameChanged(me.Player.MembershipId, name))
                {
                    _chatPersistenceService.TrackPlayerNameChange(me.Player.MembershipId, name);
                    Clients.Caller.nameChanged(name);
                }

                Clients.Group(room).addNewMessageToPage(model);

                DomainRegistry.Repository.Execute(new CreateChatLog
                {
                    Message     = output.Text,
                    Room        = room,
                    Name        = name,
                    UserId      = me.Player.MembershipId,
                    Color       = me.Player.ChatColor,
                    PortraitUrl = pic
                });
            }

            UpdateUserList(room);

            // NPC dice prank
            if (room == "global" && me.Player.BotId == AIStatics.ActivePlayerBotId &&
                message.StartsWith("/roll") && message.Contains("4d20") &&
                JokeShopProcedures.IsJokeShopActive())
            {
                var rand = new Random();

                if (rand.Next(10) == 0)
                {
                    IPlayerRepository playerRepo = new EFPlayerRepository();
                    var npcIds = playerRepo.Players.Where(p => p.BotId <= AIStatics.PsychopathBotId &&
                                                          p.Mobility == PvPStatics.MobilityFull)
                                 .Select(p => p.Id).ToArray();

                    if (npcIds.Any())
                    {
                        var npcId = npcIds[rand.Next(npcIds.Count())];
                        SendAs(message, PlayerProcedures.GetPlayerFormViewModel(npcId));
                    }
                }
            }
        }
예제 #12
0
        public virtual ActionResult SendMessage(MessageSubmitViewModel input)
        {
            var myMembershipId = User.Identity.GetUserId();
            var me             = PlayerProcedures.GetPlayerFromMembership(myMembershipId);
            var receiver       = PlayerProcedures.GetPlayer(input.ReceiverId);

            // assert player is not banned from chat
            if (me.IsBannedFromGlobalChat)
            {
                TempData["Error"]    = "You have been banned and cannot send any messages.";
                TempData["SubError"] = "If you feel this is in error or wish to make an appeal you may do so on the forums.";
                return(RedirectToAction(MVC.PvP.Play()));
            }

            // assert no blacklist exists
            if (BlacklistProcedures.PlayersHaveBlacklistedEachOther(me, receiver, "message"))
            {
                TempData["Error"]    = "This player has blacklisted you or is on your own blacklist.";
                TempData["SubError"] = "You cannot send messages to players who have blacklisted you.  Remove them from your blacklist or ask them to remove you from theirs.";
                return(RedirectToAction(MVC.PvP.Play()));
            }

            if (EffectProcedures.PlayerHasActiveEffect(me, CharacterPrankProcedures.HUSHED_EFFECT))
            {
                TempData["ErrorMessage"] = "You have been hushed and cannot currently send a message.  Try again once the effect has worn off.";
                TempData["MessageText"]  = input.MessageText;
                return(RedirectToAction(MVC.Messages.Write(input.ReceiverId, input.responseToId)));
            }

            if (input.MessageText.IsNullOrEmpty())
            {
                TempData["ErrorMessage"] = "You need to write something to send to this person.";
                TempData["MessageText"]  = input.MessageText;
                return(RedirectToAction(MVC.Messages.Write(input.ReceiverId, input.responseToId)));
            }

            if (input.MessageText.Length > 1000)
            {
                TempData["ErrorMessage"] = "Your message is too long.";
                TempData["MessageText"]  = input.MessageText;
                return(RedirectToAction(MVC.Messages.Write(input.ReceiverId, input.responseToId)));
            }

            MessageDetail repliedMsg = null;

            if (input.responseToId > 0)
            {
                repliedMsg = DomainRegistry.Repository.FindSingle(new GetMessage {
                    MessageId = input.responseToId, OwnerId = me.Id
                });
            }


            DomainRegistry.Repository.Execute(new CreateMessage
            {
                ReceiverId            = receiver.Id,
                SenderId              = me.Id,
                Text                  = input.MessageText,
                ReplyingToThisMessage = repliedMsg
            });

            NoticeService.PushNotice(receiver, "<b>" + me.GetFullName() + " has sent you a new message.</b>", NoticeService.PushType__PlayerMessage);

            TempData["Result"] = "Your message has been sent.";

            if (me.Mobility != PvPStatics.MobilityFull)
            {
                ItemProcedures.UpdateSouledItem(me);
            }

            return(RedirectToAction(MVC.Messages.Index()));
        }
        public static void RunValentineActions()
        {
            IPlayerRepository playerRepo = new EFPlayerRepository();
            var valentine = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.ValentineBotId);

            // if valentine is not in the right place have him move to the other location
            var locationToBe = GetStanceLocation();

            if (valentine.dbLocationName != locationToBe)
            {
                AIProcedures.MoveTo(valentine, locationToBe, 100000);
                valentine.dbLocationName = locationToBe;
                playerRepo.SavePlayer(valentine);
            }

            // get all of the players in the room
            var playersHere = PlayerProcedures.GetPlayersAtLocation(valentine.dbLocationName).ToList();

            playersHere = playersHere.Where(p => p.Mobility == PvPStatics.MobilityFull &&
                                            !PlayerProcedures.PlayerIsOffline(p) &&
                                            p.Level >= 3 &&
                                            p.BotId == AIStatics.ActivePlayerBotId &&
                                            p.Id != valentine.Id &&
                                            p.InDuel <= 0 &&
                                            p.InQuest <= 0).ToList();

            var turnNo = PvPWorldStatProcedures.GetWorldTurnNumber();

            if (valentine.Mana < valentine.MaxMana / 3)
            {
                var valentineBuffs = ItemProcedures.GetPlayerBuffs(valentine);
                DomainRegistry.Repository.Execute(new Meditate {
                    PlayerId = valentine.Id, Buffs = valentineBuffs, NoValidate = true
                });
                DomainRegistry.Repository.Execute(new Meditate {
                    PlayerId = valentine.Id, Buffs = valentineBuffs, NoValidate = true
                });
            }

            foreach (var p in playersHere)
            {
                // give this player the vampire curse if they do not yet have it
                if (!EffectProcedures.PlayerHasEffect(p, BloodyKissEffectSourceId))
                {
                    AttackProcedures.Attack(valentine, p, BloodyCurseSpellSourceId);
                    AIProcedures.DealBossDamage(valentine, p, false, 1);
                }

                // give this player the immobility curse if they do not yet have it
                if (!EffectProcedures.PlayerHasEffect(p, ValentinesPresenceEffectSourceId))
                {
                    AttackProcedures.Attack(valentine, p, ValentinesPresenceSpellSourceId);
                    AIProcedures.DealBossDamage(valentine, p, false, 1);
                }
            }

            // have Valentine equip his two strongest swords
            IItemRepository    itemRepo        = new EFItemRepository();
            IEnumerable <Item> valentineSwords = itemRepo.Items.Where(i => i.OwnerId == valentine.Id && i.ItemSourceId != QueensPantiesItemSourceId).OrderByDescending(i => i.Level);
            var swordsToSave = new List <Item>();

            var counter = 1;

            foreach (var sword in valentineSwords)
            {
                if (!sword.IsEquipped && counter < 3)
                {
                    sword.IsEquipped = true;
                    swordsToSave.Add(sword);
                }
                else if (sword.IsEquipped && counter >= 3)
                {
                    sword.IsEquipped = false;
                    swordsToSave.Add(sword);
                }
                counter++;
            }

            foreach (var sword in swordsToSave)
            {
                itemRepo.SaveItem(sword);
            }
        }
        public static void CounterAttack(Player human, Player valentine)
        {
            AIProcedures.DealBossDamage(valentine, human, true, 1);

            // if Valentine's willpower is down to zero, have him hand over the panties and vanish.
            if (valentine.Health <= 0)
            {
                var victoryMessage = "'Fa-la-la-la-la la la la-la!' you recite again, pushing Lady Krampus closer to her limits. The Krampus, worn and weary from your incessant singing, frowns and shakes her head as you continue with your attack upon her. 'I grow tired of this entire charade! This isn't any fun!' she scowls and puts hands over her ears, stepping aside as if to escape your jingling. 'You win! I can't stand this! I didn't even want to stay in this accursed town, anyways!' You can feel a smile creep across your lips, happy in your attempts to erode their will. Still holding her hands upon the sides of her head, she moves to the back of the cabin and reaches into a corner. 'All I wanted to do was punish naughty boys and girls and make the holiday better, but my efforts are clearly out-classed! I feel you would do better in my place!' She continued to mutter to herself as she digs through the rubble, only relenting once they have fetched a lock-box from the debris. 'You seem to be a particularly greedy type, so I have a gift for you. Take it and do as you like with it. I'm done with this place.' She places it into your hands and in an instant, she disappears in a cloud of snow. In their parting, the ringing of caroling in your own brain seems to finally cease to free you from its curse. Shaking your head to come back to your senses, you look down at the item left for you. You cautiously open the unlocked box, finding a simple crystalline item. Much like a snowflake, its form looks rather delicate and fragile.";

                PlayerLogProcedures.AddPlayerLog(human.Id, victoryMessage, true);

                EndEvent(human.Id);
            }

            // Valentine is fine, do counterattack
            else
            {
                // regular counterattacks, not berserk
                if (valentine.Health > valentine.MaxHealth / 4)
                {
                    //Gingerbread Boys and Candy Cane Girls
                    if (human.Gender == PvPStatics.GenderMale)
                    {
                        AttackProcedures.Attack(valentine, human, PvPStatics.Spell_WeakenId);
                        AttackProcedures.Attack(valentine, human, BoySpellSourceID);
                        AttackProcedures.Attack(valentine, human, BoySpellSourceID);
                        AIProcedures.DealBossDamage(valentine, human, false, 3);
                    }
                    else
                    {
                        AttackProcedures.Attack(valentine, human, PvPStatics.Spell_WeakenId);
                        AttackProcedures.Attack(valentine, human, GirlSpellSourceID);
                        AttackProcedures.Attack(valentine, human, GirlSpellSourceID);
                        AIProcedures.DealBossDamage(valentine, human, false, 3);
                    }

                    // give this player the vampire curse if they do not yet have it
                    if (!EffectProcedures.PlayerHasEffect(human, BloodyKissEffectSourceId))
                    {
                        AttackProcedures.Attack(valentine, human, BloodyCurseSpellSourceId);
                        AIProcedures.DealBossDamage(valentine, human, false, 1);
                    }

                    // give this player the immobility curse if they do not yet have it
                    if (!EffectProcedures.PlayerHasEffect(human, ValentinesPresenceEffectSourceId))
                    {
                        AttackProcedures.Attack(valentine, human, ValentinesPresenceSpellSourceId);
                        AIProcedures.DealBossDamage(valentine, human, false, 1);
                    }
                }

                // berserk mode counterattack
                else
                {
                    // counterattack three against original attacker, and don't bother trying to turn them into a tree.
                    if (human.Gender == PvPStatics.GenderMale)
                    {
                        AttackProcedures.Attack(valentine, human, PvPStatics.Spell_WeakenId);
                        AttackProcedures.Attack(valentine, human, BoySpellSourceID);
                        AttackProcedures.Attack(valentine, human, BoySpellSourceID);
                        AttackProcedures.Attack(valentine, human, BoySpellSourceID);
                        AIProcedures.DealBossDamage(valentine, human, false, 4);
                    }
                    else
                    {
                        AttackProcedures.Attack(valentine, human, PvPStatics.Spell_WeakenId);
                        AttackProcedures.Attack(valentine, human, GirlSpellSourceID);
                        AttackProcedures.Attack(valentine, human, GirlSpellSourceID);
                        AttackProcedures.Attack(valentine, human, GirlSpellSourceID);
                        AIProcedures.DealBossDamage(valentine, human, false, 4);
                    }

                    // give this player the vampire curse if they do not yet have it
                    if (!EffectProcedures.PlayerHasEffect(human, BloodyKissEffectSourceId))
                    {
                        AttackProcedures.Attack(valentine, human, BloodyCurseSpellSourceId);
                        AIProcedures.DealBossDamage(valentine, human, false, 1);
                    }

                    // give this player the immobility curse if they do not yet have it
                    if (!EffectProcedures.PlayerHasEffect(human, ValentinesPresenceEffectSourceId))
                    {
                        AttackProcedures.Attack(valentine, human, ValentinesPresenceSpellSourceId);
                        AIProcedures.DealBossDamage(valentine, human, false, 1);
                    }

                    // attack everyone else with 1 cast for Holiday cheer.
                    var playersHere = PlayerProcedures.GetPlayersAtLocation(valentine.dbLocationName).ToList();

                    playersHere = playersHere.Where(p => p.Mobility == PvPStatics.MobilityFull &&
                                                    !PlayerProcedures.PlayerIsOffline(p) &&
                                                    p.Level >= 3 &&
                                                    p.BotId == AIStatics.ActivePlayerBotId &&
                                                    p.Id != valentine.Id &&
                                                    p.Id != human.Id &&
                                                    p.InDuel <= 0 &&
                                                    p.InQuest <= 0).ToList();

                    //People need to be more festive!
                    foreach (var p in playersHere)
                    {
                        AttackProcedures.Attack(valentine, p, TreeSpellSourceID);
                        AIProcedures.DealBossDamage(valentine, p, false, 1);
                    }
                }
            }
        }
예제 #15
0
        public static void RunTurnLogic()
        {
            IPlayerRepository playerRepo = new EFPlayerRepository();
            var boss = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.MotorcycleGangLeaderBotId);

            // motorcycle gang boss is no longer animate; end the event
            if (boss.Mobility != PvPStatics.MobilityFull)
            {
                EndEvent();
                return;
            }

            // Step 1:  Find the most online characters (psychos and players) on the streets and move there.  Move anyone in the biker follower form to her.

            var targetLocation = GetLocationWithMostEligibleTargets();

            targetLocation = String.IsNullOrEmpty(targetLocation) ? boss.dbLocationName : targetLocation;

            var newlocation = AIProcedures.MoveTo(boss, targetLocation, 9);

            boss.dbLocationName = newlocation;
            boss.Mana           = boss.MaxMana;
            playerRepo.SavePlayer(boss);

            var followers = GetFollowers();

            // move all followers to the new location
            foreach (var follower in followers)
            {
                Player followerEF          = playerRepo.Players.First(p => p.Id == follower.Id);
                var    followerNewLocation = AIProcedures.MoveTo(follower, newlocation, 100000);

                // leave location log and penalize some 5 AP
                if (followerEF.dbLocationName != followerNewLocation)
                {
                    var newlocationFriendlyName = LocationsStatics.LocationList.GetLocation
                                                  .First(l => l.dbName == followerNewLocation).Name;

                    LocationLogProcedures.AddLocationLog(followerNewLocation, $"{followerEF.GetFullName()} rode off to <b>{newlocationFriendlyName}</b> to help protect {boss.GetFullName()}.");
                    followerEF.ActionPoints = Math.Max(0, followerEF.ActionPoints - SummonToBossAPPenalty);
                }

                followerEF.dbLocationName = followerNewLocation;

                if (follower.BotId == AIStatics.ActivePlayerBotId)
                {
                    PlayerLogProcedures.AddPlayerLog(follower.Id, $"<b>The leader of your gang, {boss.GetFullName()}, beckons for you to follow!  You have no choice but to comply.</b>", true);
                }
                else if (follower.BotId == AIStatics.PsychopathBotId)
                {
                    followerEF.Health += 25;
                    followerEF.Health  = followerEF.Health > followerEF.MaxHealth ? followerEF.MaxHealth : followerEF.Health;
                    followerEF.LastActionTimestamp = DateTime.UtcNow;
                }
                playerRepo.SavePlayer(followerEF);
            }

            // Step 2:  Give the boss the appropriate effect, determined by how many followers she has.
            EffectProcedures.GivePerkToPlayer(GetPerkSourceIdToGive(followers.Count), boss);

            // Step 3:  Attack everyone in the region 2-3 times with the biker follower spell if they are not already that form.
            var victims = GetEligibleTargetsAtLocation(newlocation);

            // try and turn everyone there into biker gang followers
            foreach (var victim in victims)
            {
                AttackProcedures.Attack(boss, victim, BikerFollowerSpellSourceId);
                AttackProcedures.Attack(boss, victim, BikerFollowerSpellSourceId);
                AttackProcedures.Attack(boss, victim, BikerFollowerSpellSourceId);
            }
        }
예제 #16
0
        public static void RunActions(int turnNumber)
        {
            IPlayerRepository playerRepo = new EFPlayerRepository();
            var bimboBoss = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.BimboBossBotId);

            // move her toward the location with the most eligible targets
            if (bimboBoss == null || bimboBoss.Mobility != PvPStatics.MobilityFull)
            {
                EndEvent();
                return;
            }

            var targetLocation = GetLocationWithMostEligibleTargets();
            var newlocation    = AIProcedures.MoveTo(bimboBoss, targetLocation, 13);

            bimboBoss.dbLocationName = newlocation;

            playerRepo.SavePlayer(bimboBoss);
            bimboBoss = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.BimboBossBotId);
            var bimboBossBuffs = ItemProcedures.GetPlayerBuffs(bimboBoss);

            // Get mana back up
            if (bimboBoss.Mana < bimboBoss.MaxMana / 4)
            {
                DomainRegistry.Repository.Execute(new Meditate {
                    PlayerId = bimboBoss.Id, Buffs = bimboBossBuffs, NoValidate = true
                });
                DomainRegistry.Repository.Execute(new Meditate {
                    PlayerId = bimboBoss.Id, Buffs = bimboBossBuffs, NoValidate = true
                });
                DomainRegistry.Repository.Execute(new Meditate {
                    PlayerId = bimboBoss.Id, Buffs = bimboBossBuffs, NoValidate = true
                });
            }
            else if (bimboBoss.Mana < bimboBoss.MaxMana / 3)
            {
                DomainRegistry.Repository.Execute(new Meditate {
                    PlayerId = bimboBoss.Id, Buffs = bimboBossBuffs, NoValidate = true
                });
                DomainRegistry.Repository.Execute(new Meditate {
                    PlayerId = bimboBoss.Id, Buffs = bimboBossBuffs, NoValidate = true
                });
            }
            else if (bimboBoss.Mana < bimboBoss.MaxMana / 2)
            {
                DomainRegistry.Repository.Execute(new Meditate {
                    PlayerId = bimboBoss.Id, Buffs = bimboBossBuffs, NoValidate = true
                });
            }

            var rand = new Random(Guid.NewGuid().GetHashCode());

            // attack all eligible targets here, even if it's not her final destination
            var playersHere = GetEligibleTargetsInLocation(newlocation, bimboBoss);

            foreach (var p in playersHere)
            {
                // if the player doesn't currently have it, give them the infection kiss
                if (!EffectProcedures.PlayerHasEffect(p, KissEffectSourceId) && !EffectProcedures.PlayerHasEffect(p, CureEffectSourceId))
                {
                    AttackProcedures.Attack(bimboBoss, p, KissSkillSourceId);
                    AIProcedures.DealBossDamage(bimboBoss, p, false, 1);
                }


                // otherwise run the regular trasformation
                else if (p.FormSourceId != RegularBimboFormSourceId)
                {
                    AttackProcedures.Attack(bimboBoss, p, RegularTFSpellSourceId);
                    AIProcedures.DealBossDamage(bimboBoss, p, false, 1);
                }
            }

            // have a random chance that infected players spontaneously transform
            IEffectRepository effectRepo = new EFEffectRepository();
            var ownerIds = effectRepo.Effects.Where(e => e.EffectSourceId == KissEffectSourceId).Select(e => e.OwnerId).ToList();

            foreach (var effectId in ownerIds)
            {
                var infectee = playerRepo.Players.FirstOrDefault(p => p.Id == effectId);

                // if the infectee is no longer animate or is another boss, skip them
                if (infectee.Mobility != PvPStatics.MobilityFull || infectee.BotId < AIStatics.PsychopathBotId)
                {
                    continue;
                }

                var roll = rand.NextDouble();

                // random chance of spontaneously transforming
                if (infectee.FormSourceId != RegularBimboFormSourceId && !PlayerProcedures.PlayerIsOffline(infectee))
                {
                    if (roll < .16 && infectee.InDuel <= 0 && infectee.InQuest <= 0)
                    {
                        DomainRegistry.Repository.Execute(new ChangeForm
                        {
                            PlayerId     = infectee.Id,
                            FormSourceId = RegularBimboFormSourceId
                        });

                        DomainRegistry.Repository.Execute(new ReadjustMaxes
                        {
                            playerId = infectee.Id,
                            buffs    = ItemProcedures.GetPlayerBuffs(infectee)
                        });

                        infectee = playerRepo.Players.FirstOrDefault(p => p.Id == effectId);

                        var message       = "You gasp, your body shifting as the virus infecting you overwhelms your biological and arcane defenses.  Before long you find that your body has been transformed into that of one of the many bimbonic plague victims and you can't help but succumb to the urges to spread your infection--no, your gift!--on to the rest of mankind.";
                        var loclogMessage = "<b style='color: red'>" + infectee.GetFullName() + " succumbed to the bimbonic virus, spontaneously transforming into one of Lady Lovebringer's bimbos.</b>";

                        PlayerLogProcedures.AddPlayerLog(infectee.Id, message, true);
                        LocationLogProcedures.AddLocationLog(infectee.dbLocationName, loclogMessage);
                    }
                }

                // spread the kiss so long as the player is not offline
                if (infectee.FormSourceId == RegularBimboFormSourceId && !PlayerProcedures.PlayerIsOffline(infectee))
                {
                    // back up the last action timestamp since we don't want these attacks to count against their offline timer
                    var lastActionBackup = infectee.LastActionTimestamp;

                    var eligibleTargets  = GetEligibleTargetsInLocation(infectee.dbLocationName, infectee);
                    var attacksMadeCount = 0;

                    foreach (var p in eligibleTargets)
                    {
                        if (!EffectProcedures.PlayerHasEffect(p, KissEffectSourceId) && !EffectProcedures.PlayerHasEffect(p, CureEffectSourceId) && attacksMadeCount < 3)
                        {
                            attacksMadeCount++;
                            AttackProcedures.Attack(infectee, p, KissSkillSourceId);
                        }
                        else if (attacksMadeCount < 3)
                        {
                            AttackProcedures.Attack(infectee, p, RegularTFSpellSourceId);
                            attacksMadeCount++;
                        }
                    }

                    // if there were any attacked players, restore the old last action timestamp and make sure AP and mana has not gone into negative
                    if (attacksMadeCount > 0)
                    {
                        infectee = playerRepo.Players.FirstOrDefault(p => p.Id == effectId);
                        infectee.LastActionTimestamp = lastActionBackup;

                        if (infectee.ActionPoints < 0)
                        {
                            infectee.ActionPoints = 0;
                        }

                        if (infectee.Mana < 0)
                        {
                            infectee.Mana = 0;
                        }

                        playerRepo.SavePlayer(infectee);
                    }
                }
            }


            // every 5 turns heal the boss based on how many infected bots there are
            if (ShouldHeal(bimboBoss, turnNumber))
            {
                var activeCurses = effectRepo.Effects.Count(eff => eff.EffectSourceId == KissEffectSourceId) * 5;
                activeCurses      = activeCurses > 130 ? 130 : activeCurses;
                bimboBoss.Health += activeCurses;
                playerRepo.SavePlayer(bimboBoss);
                var message = "<b>" + bimboBoss.GetFullName() + " draws energy from her bimbo horde, regenerating her own willpower by " + activeCurses + ".</b>";
                LocationLogProcedures.AddLocationLog(newlocation, message);
            }

            // drop a cure
            DropCure(turnNumber);
        }