Пример #1
0
        private static void DropCure(int turnNumber)
        {
            for (var i = 0; i < 2; i++)
            {
                var cmd = new CreateItem
                {
                    dbLocationName   = LocationsStatics.GetRandomLocationNotInDungeon(),
                    IsEquipped       = false,
                    IsPermanent      = false,
                    Level            = 0,
                    PvPEnabled       = 2,
                    OwnerId          = null,
                    TurnsUntilUse    = 0,
                    EquippedThisTurn = false,
                    ItemSourceId     = ItemStatics.GetStaticItem(CureItemSourceId).Id
                };

                if (turnNumber % 3 == 0)
                {
                    cmd.PvPEnabled = 1;
                }

                DomainRegistry.Repository.Execute(cmd);
            }
        }
        public static string TeleportToDungeon(Player player, int meanness, Random rand = null)
        {
            if (!PlayerProcedures.CheckAllowedInDungeon(player, out _))
            {
                return(null);
            }

            var lastAttackTimeAgo = Math.Abs(DateTime.UtcNow.Subtract(player.GetLastCombatTimestamp()).TotalMinutes);

            if (lastAttackTimeAgo < TurnTimesStatics.GetMinutesSinceLastCombatBeforeQuestingOrDuelling())
            {
                return(null);
            }

            var location = LocationsStatics.GetRandomLocation_InDungeon();

            rand = rand ?? new Random();

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

            if (meanness % 2 == 1)
            {
                ResetCombatTimer(player);
            }

            if (meanness >= 2)
            {
                CharacterPrankProcedures.GiveEffect(player, JokeShopProcedures.ROOT_EFFECT);
            }

            return("You feel the room start to shake and shimmer, parts of the shop fading away as it is pulled between realms.  The shelves rattle ever more violently and you try and take shelter under the counter.  But the shop has other ideas and the floor gives way, leaving you tumbling through the air just as the store flickers out of this plane.  That's the last thing you remember.  Nursing a headache, with a bleary blink of your eyes your surroundings slowly come into focus.  You've landed in the deepest depths of the dungeon!");
        }
        public static string RunAway(Player player)
        {
            var destination = LocationsStatics.GetRandomLocationNotInDungeonOr(LocationsStatics.JOKE_SHOP);

            if (MovePlayer(player, destination, 15) == null)
            {
                return(null);
            }

            return("You stroll around the shop, but stub your toe on an ornate box that is just lying in one of the aisles.  As you bend down to inspect it the lid springs open and a Jack-in-the-Box launches out, straight towards you.  Coming nose-to-nose with that mindless painted face is utterly terrifying and without a moment's hesitation you turn and run out of the shop screaming!");
        }
Пример #4
0
        private static IEnumerable <InstinctData> MaidActions(IPlayerRepository playerRepo, IEnumerable <InstinctData> mcPlayers, Random rand)
        {
            // Maids - find places to clean
            var mcMaids = mcPlayers.Where(p => JokeShopProcedures.MAIDS.Any(maidForm => p.FormSourceId == maidForm)).ToList();

            foreach (var maid in mcMaids)
            {
                var maidPlayer = playerRepo.Players.FirstOrDefault(p => p.Id == maid.Id);
                var maidLoc    = LocationsStatics.LocationList.GetLocation.FirstOrDefault(l => l.dbName == maidPlayer.dbLocationName);

                if (maidLoc != null)
                {
                    string nextLoc;
                    string newContract = "";

                    string[] cleaningContracts = { "coffee_shop", "tavern", "oldoak_apartments", "mansion", "ranch_inside", "castle", "salon" };
                    if (cleaningContracts.Contains(maidLoc.Region))
                    {
                        nextLoc = LocationsStatics.GetRandomLocation_InRegion(maidLoc.Region);
                    }
                    else
                    {
                        newContract = "One of the local facilities has just signed a new contract with you!  ";
                        nextLoc     = LocationsStatics.GetRandomLocation_InRegion(cleaningContracts[rand.Next(cleaningContracts.Count())]);
                    }

                    var stoppedAt = EnvironmentPrankProcedures.MovePlayer(maidPlayer, nextLoc, 20, timestamp: false);

                    if (stoppedAt == nextLoc || maidPlayer.dbLocationName == nextLoc)
                    {
                        var      here       = LocationsStatics.GetConnectionName(nextLoc);
                        string[] activities = { "dusting away the cobwebs", "vaccuuming the floor", "washing up the dishes", "doing the laundry", "serving refreshments", "sweeping the trash", "handing out freshly baked cupcakes" };
                        var      activity   = activities[rand.Next(activities.Count())];

                        PlayerLogProcedures.AddPlayerLog(maidPlayer.Id, $"{newContract}You arrive at <b>{here}</b> and start {activity}!", true);
                        LocationLogProcedures.AddLocationLog(nextLoc, $"{maidPlayer.GetFullName()} arrives here and starts <b>{activity}</b>.");
                    }
                    else if (stoppedAt != null)
                    {
                        var here = LocationsStatics.GetConnectionName(stoppedAt);
                        PlayerLogProcedures.AddPlayerLog(maidPlayer.Id, $"{newContract}You quickly head to your new job but only get as far as <b>{here}</b>.", true);
                    }
                }

                mcPlayers = mcPlayers.Where(p => p.Id != maid.Id);
            }

            return(mcPlayers);
        }
Пример #5
0
        public override IEnumerable <BusStop> Execute(IDataContext context)
        {
            var stops = new List <BusStop>();

            foreach (var stop in LocationsStatics.BusStops)
            {
                var loc = LocationsStatics.LocationList.GetLocation.FirstOrDefault(l => l.dbName == stop);

                var busStop = new BusStop
                {
                    Name   = loc.Name,
                    dbName = loc.dbName
                };

                busStop.Cost = LocationsStatics.GetTicketPriceBetweenLocations(currentLocation, loc.dbName);

                stops.Add(busStop);
            }


            return(stops);
        }
        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)}!");
        }
Пример #7
0
        public void ChangeForm(FormSource form)
        {
            if (this.Item != null)
            {
                if (this.Item.Owner != null && !this.Item.Owner.Location.IsNullOrEmpty())
                {
                    this.Location = this.Item.Owner.Location;
                }
                else if (!this.Item.dbLocationName.IsNullOrEmpty())
                {
                    this.Location = this.Item.dbLocationName;
                }
            }

            if (this.Location.IsNullOrEmpty())
            {
                this.Location = LocationsStatics.GetRandomLocationNotInDungeonOr(LocationsStatics.JOKE_SHOP);
            }

            FormSource = form;
            Gender     = form.Gender;
            Mobility   = form.MobilityType;
            ForceWithinBounds();
        }
Пример #8
0
        public static string LocatePlayerInCombat(Player player, Random rand = null)
        {
            rand = rand ?? new Random();
            var cutoff = DateTime.UtcNow.AddMinutes(-TurnTimesStatics.GetMinutesSinceLastCombatBeforeQuestingOrDuelling());

            var playerRepo      = new EFPlayerRepository();
            var playersInCombat = playerRepo.Players
                                  .Where(p => p.LastCombatTimestamp >= cutoff &&
                                         p.Id != player.Id &&
                                         p.Mobility == PvPStatics.MobilityFull &&
                                         p.InDuel <= 0 &&
                                         p.InQuest <= 0 &&
                                         p.BotId == AIStatics.ActivePlayerBotId).ToList();

            if (playersInCombat.IsEmpty())
            {
                return(null);
            }

            var detected = playersInCombat[rand.Next(playersInCombat.Count())];
            var location = LocationsStatics.GetConnectionName(detected.dbLocationName);

            return($"You hear a beep from a machine.  It has a radar-like display and shows that <b>{detected.GetFullName()}</b> has recently been in combat and is currently in <b>{location}</b>!");
        }
Пример #9
0
        public static void SpawnAIPsychopaths(int count)
        {
            var rand = new Random();
            IPlayerRepository playerRepo = new EFPlayerRepository();
            var turnNumber = PvPWorldStatProcedures.GetWorldTurnNumber();
            var botCount   = playerRepo.Players.Count(b => b.BotId == AIStatics.PsychopathBotId);

            for (var i = (0 + botCount); i < (count + botCount); i++)
            {
                var cmd = new CreatePlayer
                {
                    FirstName          = "Psychopath",
                    Location           = LocationsStatics.GetRandomLocationNotInDungeon(),
                    Health             = 100000,
                    MaxHealth          = 100000,
                    Mana               = 100000,
                    MaxMana            = 100000,
                    BotId              = AIStatics.PsychopathBotId,
                    UnusedLevelUpPerks = 0,
                    XP       = 0,
                    Money    = 100,
                    LastName = NameService.GetRandomLastName(),
                    Gender   = i % 2 == 1 ? PvPStatics.GenderMale : PvPStatics.GenderFemale,
                };


                var strength = GetPsychopathLevel(turnNumber);

                if (strength == 1)
                {
                    cmd.Level = 1;
                }
                else if (strength == 3)
                {
                    cmd.FirstName = "Fierce " + cmd.FirstName;
                    cmd.Level     = 3;
                }
                else if (strength == 5)
                {
                    cmd.FirstName = "Wrathful " + cmd.FirstName;
                    cmd.Level     = 5;
                }
                else if (strength == 7)
                {
                    cmd.FirstName = "Loathful " + cmd.FirstName;
                    cmd.Level     = 7;
                }
                else if (strength == 9)
                {
                    cmd.FirstName = "Soulless " + cmd.FirstName;
                    cmd.Level     = 9;
                }

                var idAndFormName = GetPsychoFormFromLevelAndSex(cmd.Level, cmd.Gender);
                cmd.FormSourceId = idAndFormName.Item1;

                // assert this name isn't already taken
                var ghost = playerRepo.Players.FirstOrDefault(p => p.FirstName == cmd.FirstName && p.LastName == cmd.LastName);
                if (ghost != null)
                {
                    continue;
                }

                var id = DomainRegistry.Repository.Execute(cmd);

                // give this bot a random skill
                var eligibleSkills = SkillStatics.GetLearnablePsychopathSkills().ToList();

                double max       = eligibleSkills.Count;
                var    randIndex = Convert.ToInt32(Math.Floor(rand.NextDouble() * max));

                var skillToLearn = eligibleSkills.ElementAt(randIndex);
                SkillProcedures.GiveSkillToPlayer(id, skillToLearn.Id);

                // give this bot the Psychpathic perk
                if (strength == 1)
                {
                    EffectProcedures.GivePerkToPlayer(PsychopathicForLevelOneEffectSourceId, id);
                }
                else if (strength == 3)
                {
                    EffectProcedures.GivePerkToPlayer(PsychopathicForLevelThreeEffectSourceId, id);
                }
                else if (strength == 5)
                {
                    EffectProcedures.GivePerkToPlayer(PsychopathicForLevelFiveEffectSourceId, id);
                }
                else if (strength == 7)
                {
                    EffectProcedures.GivePerkToPlayer(PsychopathicForLevelSevenEffectSourceId, id);
                }
                else if (strength == 9)
                {
                    EffectProcedures.GivePerkToPlayer(PsychopathicForLevelNineEffectSourceId, id);
                }

                // give this psycho a new rune with some random chance it is a higher level than they are, to a max of level 13
                var random = new Random(Guid.NewGuid().GetHashCode());
                var roll   = random.NextDouble();

                if (roll < .1)
                {
                    strength += 4;
                }
                else if (roll < .3)
                {
                    strength += 2;
                }

                var quantity = Math.Floor(random.NextDouble() * 2) + 1; // 1 or 2

                for (var c = 0; c < quantity; c++)
                {
                    var runeId = DomainRegistry.Repository.FindSingle(new GetRandomRuneAtLevel {
                        RuneLevel = strength, Random = random
                    });
                    DomainRegistry.Repository.Execute(new GiveRune {
                        ItemSourceId = runeId, PlayerId = id
                    });
                }

                var psychoEF = playerRepo.Players.FirstOrDefault(p => p.Id == id);
                psychoEF.ReadjustMaxes(ItemProcedures.GetPlayerBuffs(psychoEF));
                playerRepo.SavePlayer(psychoEF);
            }
        }
Пример #10
0
        private static (IEnumerable <InstinctData> mcPlayers, IEnumerable <InstinctData> freePlayers) SheepActions(IPlayerRepository playerRepo, IEnumerable <InstinctData> mcPlayers, IEnumerable <InstinctData> freePlayers, Random rand)
        {
            // Sheep - find another sheep and follow it
            var mcSheep = mcPlayers.Where(p => JokeShopProcedures.SHEEP.Any(sheepForm => p.FormSourceId == sheepForm)).ToList();

            if (!mcSheep.IsEmpty())
            {
                var freeSheep       = freePlayers.Where(p => JokeShopProcedures.SHEEP.Any(sheepForm => p.FormSourceId == sheepForm)).ToList();
                var flockToPlayer   = -1;
                var flockToLocation = "";

                if (!freeSheep.IsEmpty())
                {
                    var target = freeSheep[rand.Next(freeSheep.Count())];
                    flockToPlayer   = target.Id;
                    flockToLocation = target.dbLocationName;
                }
                else
                {
                    flockToLocation = LocationsStatics.GetRandomLocationNotInDungeonOr(LocationsStatics.JOKE_SHOP);
                }

                foreach (var sheep in mcSheep)
                {
                    var sheepPlayer = playerRepo.Players.FirstOrDefault(p => p.Id == sheep.Id);
                    var stoppedAt   = EnvironmentPrankProcedures.MovePlayer(sheepPlayer, flockToLocation, 15, timestamp: false, callback: (p, loc) =>
                    {
                        if (rand.Next(3) == 0)
                        {
                            LocationLogProcedures.AddLocationLog(loc, $"{p.GetFullName()} bleated here:  <b>Baaaaa!</b>");
                        }
                    });

                    if (stoppedAt == flockToLocation)
                    {
                        if (flockToPlayer >= 0)
                        {
                            PlayerLogProcedures.AddPlayerLog(flockToPlayer, $"{sheepPlayer.GetFullName()} bleated at you:  <b>Baaaaa!</b>", true);
                        }

                        LocationLogProcedures.AddLocationLog(stoppedAt, $"{sheepPlayer.GetFullName()} bleated here:  <b>Baaaaa!</b>");
                    }

                    if (stoppedAt != null)
                    {
                        var here = LocationsStatics.GetConnectionName(stoppedAt);
                        PlayerLogProcedures.AddPlayerLog(sheepPlayer.Id, $"You followed your flock to <b>{here}</b>.", true);
                    }
                }

                // Don't consider affected players for any more actions this turn
                mcPlayers = mcPlayers.Where(p => mcSheep.All(s => p.Id != s.Id));

                if (flockToPlayer >= 0)
                {
                    freePlayers = freePlayers.Where(p => p.Id != flockToPlayer);
                }
            }

            return(mcPlayers, freePlayers);
        }
Пример #11
0
        private static IEnumerable <InstinctData> GhostActions(IPlayerRepository playerRepo, IEnumerable <InstinctData> mcPlayers, Random rand)
        {
            // Ghosts - haunt old buildings
            var mcGhosts = mcPlayers.Where(p => JokeShopProcedures.GHOSTS.Any(ghostForm => p.FormSourceId == ghostForm)).ToList();

            foreach (var ghost in mcGhosts)
            {
                var ghostPlayer = playerRepo.Players.FirstOrDefault(p => p.Id == ghost.Id);
                var ghostLoc    = LocationsStatics.LocationList.GetLocation.FirstOrDefault(l => l.dbName == ghostPlayer.dbLocationName);

                if (ghostLoc != null)
                {
                    string nextLoc;

                    string[] haunts = { "mansion", "castle" };
                    if (haunts.Contains(ghostLoc.Region))
                    {
                        nextLoc = LocationsStatics.GetRandomLocation_InRegion(ghostLoc.Region);
                    }
                    else
                    {
                        nextLoc = LocationsStatics.GetRandomLocation_InRegion(haunts[rand.Next(haunts.Count())]);
                    }

                    // Check whether we can haunt the current tile
                    // An enhancement would be to allow ghosts to move through walls
                    var stoppedAt = EnvironmentPrankProcedures.MovePlayer(ghostPlayer, nextLoc, 20, timestamp: false);

                    var canHaunt = stoppedAt == nextLoc || ghostPlayer.dbLocationName == nextLoc;

                    if (!canHaunt && stoppedAt != null)
                    {
                        var stoppedAtTile = LocationsStatics.LocationList.GetLocation.FirstOrDefault(l => l.dbName == stoppedAt);
                        canHaunt = haunts.Contains(stoppedAtTile.Region);
                    }

                    if (canHaunt)
                    {
                        var here   = LocationsStatics.GetConnectionName(nextLoc);
                        var cutoff = DateTime.UtcNow.AddMinutes(-TurnTimesStatics.GetOfflineAfterXMinutes());

                        var candidates = playerRepo.Players
                                         .Where(p => p.dbLocationName == nextLoc &&
                                                p.LastActionTimestamp >= cutoff &&
                                                p.Id != ghostPlayer.Id &&
                                                p.Mobility == PvPStatics.MobilityFull &&
                                                p.InDuel <= 0 &&
                                                p.InQuest <= 0 &&
                                                p.BotId == AIStatics.ActivePlayerBotId)
                                         .ToList();

                        if (candidates.Any())
                        {
                            var      victim = candidates[rand.Next(candidates.Count())];
                            string[] calls  = { "Boo!", "Whooo!" };
                            var      call   = calls[rand.Next(calls.Count())];

                            PlayerLogProcedures.AddPlayerLog(ghostPlayer.Id, $"After entering {here} you tap {victim.GetFullName()} on the shoulder and shout <b>\"{call}\"</b>!", true);
                            PlayerLogProcedures.AddPlayerLog(victim.Id, $"{ghostPlayer.GetFullName()} taps you on the shoulder and shouts <b>\"{call}\"</b>!", true);
                            LocationLogProcedures.AddLocationLog(nextLoc, $"{ghostPlayer.GetFullName()} shouts <b>\"{call}\"</b> at {victim.GetFullName()}.");
                        }
                        else
                        {
                            string[] activities = { "rattles some chains", "wails like a banshee", "floats through a wall", "lights a candle", "makes the lights flicker", "fades into the background", "knocks a book off a shelf", "melts into a pool of ectoplasm", "sends a a chill through the air" };
                            var      activity   = activities[rand.Next(activities.Count())];

                            PlayerLogProcedures.AddPlayerLog(ghostPlayer.Id, $"You begin haunting {here}!", true);
                            LocationLogProcedures.AddLocationLog(nextLoc, $"<b>{ghostPlayer.GetFullName()} {activity}</b>.");
                        }
                    }
                    else if (stoppedAt != null)
                    {
                        var here = LocationsStatics.GetConnectionName(stoppedAt);
                        PlayerLogProcedures.AddPlayerLog(ghostPlayer.Id, $"The spirits call you to <b>{here}</b>.", true);
                    }
                }

                mcPlayers = mcPlayers.Where(p => p.Id != ghost.Id);
            }

            return(mcPlayers);
        }
Пример #12
0
        public static string ReturnToAnimate(Player player, bool dungeonPenalty)
        {
            IInanimateXPRepository inanimXpRepo = new EFInanimateXPRepository();
            IItemRepository        itemRepo     = new EFItemRepository();

            var inanimXP = inanimXpRepo.InanimateXPs.FirstOrDefault(i => i.OwnerId == player.Id);

            var currentGameTurn = PvPWorldStatProcedures.GetWorldTurnNumber();

            if (inanimXP == null)
            {
                inanimXP = new InanimateXP
                {
                    OwnerId = player.Id,
                    Amount  = 0,

                    // set the initial times struggled proportional to how high of a level the player is
                    TimesStruggled      = -6 * player.Level,
                    LastActionTimestamp = DateTime.UtcNow,
                    LastActionTurnstamp = currentGameTurn - 1,
                };
            }

            double strugglebonus = currentGameTurn - inanimXP.LastActionTurnstamp;

            if (strugglebonus > TurnTimesStatics.GetItemMaxTurnsBuildup())
            {
                strugglebonus = TurnTimesStatics.GetItemMaxTurnsBuildup();
            }

            if (strugglebonus < 0)
            {
                strugglebonus = 0;
            }

            if (PvPStatics.ChaosMode)
            {
                strugglebonus = 100;
            }

            // increment the player's attack count.  Also decrease their player XP some.
            IPlayerRepository playerRepo = new EFPlayerRepository();
            var dbPlayer = playerRepo.Players.FirstOrDefault(p => p.Id == player.Id);

            dbPlayer.TimesAttackingThisUpdate++;

            var strugglesMade = Convert.ToDouble(GetStruggleChance(player, dungeonPenalty));

            var rand = new Random();
            var roll = rand.NextDouble() * 100;

            var dbPlayerItem = DomainRegistry.Repository.FindSingle(new GetItemByFormerPlayer {
                PlayerId = player.Id
            });

            if (dbPlayerItem == null)
            {
                return("Cannot struggle - no player item");
            }

            if (dbPlayerItem.Owner != null)
            {
                var owner = PlayerProcedures.GetPlayer(dbPlayerItem.Owner.Id);
                dbPlayer.dbLocationName = owner.dbLocationName;
            }

            var itemPlus = ItemStatics.GetStaticItem(dbPlayerItem.ItemSource.Id);

            if (roll < strugglesMade)
            {
                // assert that the covenant the victim is in is not too full to accept them back in
                if (dbPlayer.Covenant > 0)
                {
                    var victimCov = CovenantProcedures.GetCovenantViewModel((int)dbPlayer.Covenant).dbCovenant;
                    if (victimCov != null && CovenantProcedures.GetPlayerCountInCovenant(victimCov, true) >= PvPStatics.Covenant_MaximumAnimatePlayerCount)
                    {
                        return("Although you had enough energy to break free from your body as a " + itemPlus.FriendlyName + " and restore your regular body, you were unfortunately not able to break free because there is no more room in your covenant for any more animate mages.");
                    }
                }


                // if the item has an owner, notify them via a message.
                if (dbPlayerItem.Owner != null)
                {
                    var message = player.FirstName + " " + player.LastName + ", your " + itemPlus.FriendlyName + ", successfully struggles against your magic and reverses their transformation.  You can no longer claim them as your property, not unless you manage to turn them back again...";
                    PlayerLogProcedures.AddPlayerLog(dbPlayerItem.Owner.Id, message, true);
                }

                // change the player's form and mobility
                DomainRegistry.Repository.Execute(new ChangeForm
                {
                    PlayerId     = dbPlayer.Id,
                    FormSourceId = dbPlayer.OriginalFormSourceId
                });

                dbPlayer.ActionPoints               = TurnTimesStatics.GetActionPointLimit();
                dbPlayer.ActionPoints_Refill        = TurnTimesStatics.GetActionPointReserveLimit();
                dbPlayer.CleansesMeditatesThisRound = PvPStatics.MaxCleansesMeditatesPerUpdate;
                dbPlayer.TimesAttackingThisUpdate   = PvPStatics.MaxAttacksPerUpdate;

                // don't let the player spawn in the dungeon as they will have Back On Your Feet
                // and may not be meet the level and game mode requirements
                if (dbPlayer.IsInDungeon())
                {
                    dbPlayer.dbLocationName = LocationsStatics.GetRandomLocationNotInDungeon();
                }

                dbPlayer        = PlayerProcedures.ReadjustMaxes(dbPlayer, ItemProcedures.GetPlayerBuffs(dbPlayer));
                dbPlayer.Health = dbPlayer.MaxHealth / 3;
                dbPlayer.Mana   = dbPlayer.MaxHealth / 3;
                playerRepo.SavePlayer(dbPlayer);

                // drop any runes embedded on the player-item, or return them to the former owner's inventory
                DomainRegistry.Repository.Execute(new UnbembedRunesOnItem {
                    ItemId = dbPlayerItem.Id
                });

                // delete the item or animal that this player had turned into
                itemRepo.DeleteItem(dbPlayerItem.Id);

                // delete the inanimate XP item
                inanimXpRepo.DeleteInanimateXP(inanimXP.Id);

                // give the player the recovery buff
                EffectProcedures.GivePerkToPlayer(PvPStatics.Effect_BackOnYourFeetSourceId, dbPlayer);

                var msg = "You have managed to break free from your form as " + itemPlus.FriendlyName + " and occupy an animate body once again!";

                if (PvPStatics.ChaosMode)
                {
                    msg += $" [CHAOS MODE:  Struggle value overriden to {strugglebonus:0}% per struggle.]";
                }

                PlayerLogProcedures.AddPlayerLog(dbPlayer.Id, msg, false);

                StatsProcedures.AddStat(dbPlayer.MembershipId, StatsProcedures.Stat__SuccessfulStruggles, 1);

                return(msg);
            }

            // failure to break free; increase time struggles
            else
            {
                // raise the probability of success for next time somewhat proportion to how many turns they missed
                inanimXP.TimesStruggled     += Convert.ToInt32(strugglebonus);
                inanimXP.LastActionTimestamp = DateTime.UtcNow;
                inanimXP.LastActionTurnstamp = currentGameTurn;
                inanimXpRepo.SaveInanimateXP(inanimXP);

                playerRepo.SavePlayer(dbPlayer);

                if (dbPlayerItem.Owner != null)
                {
                    var message = $"{player.FirstName} {player.LastName}, your {itemPlus.FriendlyName}, struggles but fails to return to an animate form.  [Recovery chance next struggle:  {(int)GetStruggleChance(player, dungeonPenalty)}%]";
                    PlayerLogProcedures.AddPlayerLog(dbPlayerItem.Owner.Id, message, true);
                }

                PlayerLogProcedures.AddPlayerLog(dbPlayer.Id, "You struggled to return to a human form.", false);

                return($"Unfortunately you are not able to struggle free from your form as {itemPlus.FriendlyName}.  Keep trying and you might succeed later... [Recovery chance next struggle:  {(int)GetStruggleChance(player, dungeonPenalty)}%]");
            }
        }
Пример #13
0
        private static (IEnumerable <InstinctData> mcPlayers, IEnumerable <InstinctData> freePlayers) CatActions(IPlayerRepository playerRepo, IEnumerable <InstinctData> mcPlayers, IEnumerable <InstinctData> freePlayers, Random rand)
        {
            // Cats - chase rodents
            var mcCats2 = mcPlayers.Where(p => JokeShopProcedures.CATS_AND_NEKOS.Any(catForm => p.FormSourceId == catForm)).ToList();

            if (!mcCats2.IsEmpty())
            {
                var mcRodents   = mcPlayers.Where(p => JokeShopProcedures.RODENTS.Any(rodentForm => p.FormSourceId == rodentForm)).ToList();
                var freeRodents = freePlayers.Where(p => JokeShopProcedures.RODENTS.Any(rodentForm => p.FormSourceId == rodentForm)).ToList();

                while (!mcCats2.IsEmpty() && mcRodents.Count() + freeRodents.Count() > 0)
                {
                    // Find a cat
                    var catIndex = rand.Next(mcCats2.Count());
                    var cat      = mcCats2[catIndex];
                    mcCats2.RemoveAt(catIndex);
                    mcPlayers = mcPlayers.Where(p => p.Id != cat.Id);

                    int    rodentId;
                    string rodentLoc;

                    // Find a rodent for them to chase
                    if (!mcRodents.IsEmpty())
                    {
                        var rodentIndex = rand.Next(mcRodents.Count());
                        var rodent      = mcRodents[rodentIndex];
                        mcRodents.RemoveAt(rodentIndex);

                        rodentId  = rodent.Id;
                        rodentLoc = rodent.dbLocationName;
                        mcPlayers = mcPlayers.Where(p => p.Id != rodentId);
                    }
                    else  // !freeRodents.IsEmpty()
                    {
                        var rodentIndex = rand.Next(freeRodents.Count);
                        var rodent      = freeRodents[catIndex];
                        freeRodents.RemoveAt(rodentIndex);

                        rodentId    = rodent.Id;
                        rodentLoc   = rodent.dbLocationName;
                        freePlayers = freePlayers.Where(p => p.Id != rodentId);
                    }

                    var catPlayer    = playerRepo.Players.FirstOrDefault(p => p.Id == cat.Id);
                    var rodentPlayer = playerRepo.Players.FirstOrDefault(p => p.Id == rodentId);

                    // Move cat
                    var stoppedAt = EnvironmentPrankProcedures.MovePlayer(catPlayer, rodentLoc, 15, timestamp: false, callback: (p, loc) =>
                    {
                        var roll = rand.Next(4);
                        if (roll == 0)
                        {
                            LocationLogProcedures.AddLocationLog(loc, $"{catPlayer.GetFullName()} stealthily prowls the area, on the hunt for {rodentPlayer.GetFullName()}");
                        }
                    });

                    if (stoppedAt == rodentLoc)
                    {
                        var here = LocationsStatics.GetConnectionName(stoppedAt);
                        LocationLogProcedures.AddLocationLog(stoppedAt, $"{catPlayer.GetFullName()} lunges at a rodent, but {rodentPlayer.GetFullName()} is too quick and evades the cat's attack!</b>");

                        PlayerLogProcedures.AddPlayerLog(rodentId, $"{catPlayer.GetFullName()} jumps out at you, but you leap from their paws and deprive them of an easy snack!", true);
                        PlayerLogProcedures.AddPlayerLog(catPlayer.Id, $"You prowl to <b>{here}</b>, creep up on {rodentPlayer.GetFullName()} and pounce!  But they're too quick and evade your clutches!", true);
                    }
                    else if (stoppedAt != null)  // Cat moved, but didn't get to the rodent's location
                    {
                        var here = LocationsStatics.GetConnectionName(stoppedAt);
                        PlayerLogProcedures.AddPlayerLog(catPlayer.Id, $"You prowl to <b>{here}</b>, being careful not to get too close to your prey as you prepare for the hunt...", true);
                    }
                    else if (cat.dbLocationName == rodentLoc)
                    {
                        PlayerLogProcedures.AddPlayerLog(rodentId, $"{catPlayer.GetFullName()} hides in a bush, stealthily watching you, getting ready to pounce...", true);
                        PlayerLogProcedures.AddPlayerLog(catPlayer.Id, $"You slink behind a bush and focus your eyes on {rodentPlayer.GetFullName()}, getting ready to strike...", true);
                    }
                }
            }

            return(mcPlayers, freePlayers);
        }
Пример #14
0
        private static (IEnumerable <InstinctData> mcPlayers, IEnumerable <InstinctData> freePlayers) DogActions(IPlayerRepository playerRepo, IEnumerable <InstinctData> mcPlayers, IEnumerable <InstinctData> freePlayers, Random rand)
        {
            // Dogs - chase cats, possiby up a tree
            var mcDogs = mcPlayers.Where(p => JokeShopProcedures.DOGS.Any(dogForm => p.FormSourceId == dogForm)).ToList();

            if (!mcDogs.IsEmpty())
            {
                var mcCats   = mcPlayers.Where(p => JokeShopProcedures.CATS_AND_NEKOS.Any(catForm => p.FormSourceId == catForm)).ToList();
                var freeCats = freePlayers.Where(p => JokeShopProcedures.CATS_AND_NEKOS.Any(catForm => p.FormSourceId == catForm)).ToList();

                while (!mcDogs.IsEmpty() && mcCats.Count() + freeCats.Count() > 0)
                {
                    // Find a dog
                    var dogIndex = rand.Next(mcDogs.Count());
                    var dog      = mcDogs[dogIndex];
                    mcDogs.RemoveAt(dogIndex);
                    mcPlayers = mcPlayers.Where(p => p.Id != dog.Id);

                    int    catId;
                    string catLoc;
                    bool   catIsMindControlled;

                    // Find a cat for them to chase
                    if (!mcCats.IsEmpty())
                    {
                        var catIndex = rand.Next(mcCats.Count());
                        var cat      = mcCats[catIndex];
                        mcCats.RemoveAt(catIndex);

                        catId  = cat.Id;
                        catLoc = cat.dbLocationName;
                        catIsMindControlled = true;
                        mcPlayers           = mcPlayers.Where(p => p.Id != catId);
                    }
                    else  // !freeCats.IsEmpty()
                    {
                        var catIndex = rand.Next(freeCats.Count);
                        var cat      = freeCats[catIndex];
                        freeCats.RemoveAt(catIndex);

                        catId  = cat.Id;
                        catLoc = cat.dbLocationName;
                        catIsMindControlled = false;
                        freePlayers         = freePlayers.Where(p => p.Id != catId);
                    }

                    var dogPlayer = playerRepo.Players.FirstOrDefault(p => p.Id == dog.Id);
                    var catPlayer = playerRepo.Players.FirstOrDefault(p => p.Id == catId);

                    // Move dog
                    var stoppedAt = EnvironmentPrankProcedures.MovePlayer(dogPlayer, catLoc, 15, timestamp: false, callback: (p, loc) =>
                    {
                        var roll = rand.Next(4);
                        if (roll == 0)
                        {
                            LocationLogProcedures.AddLocationLog(loc, $"{dogPlayer.GetFullName()} barked here as they catch the scent of a cat, {catPlayer.GetFullName()}:  <b>Woof woof!</b>");
                        }
                        else if (roll == 1)
                        {
                            LocationLogProcedures.AddLocationLog(loc, $"{dogPlayer.GetFullName()} growled here as they get closer to {catPlayer.GetFullName()}, the cat:  <b>Grrrrrrrrr!</b>");
                        }
                    });

                    // Dog has arrived at the cat's location
                    if (stoppedAt == catLoc)
                    {
                        var here = LocationsStatics.GetConnectionName(stoppedAt);
                        LocationLogProcedures.AddLocationLog(stoppedAt, $"{dogPlayer.GetFullName()} barked at {catPlayer.GetFullName()}:  <b>Woof woof!</b>");

                        // If cat is mind controlled we can send them up a tree
                        if (catIsMindControlled)
                        {
                            var treeLoc = mcPlayers.FirstOrDefault(p => JokeShopProcedures.TREES.Any(treeForm => p.FormSourceId == treeForm))?.dbLocationName;

                            if (treeLoc == null)
                            {
                                treeLoc = freePlayers.FirstOrDefault(p => JokeShopProcedures.TREES.Any(treeForm => p.FormSourceId == treeForm))?.dbLocationName;
                            }

                            if (treeLoc == null)
                            {
                                treeLoc = "forest_ancestor_tree";
                            }

                            var catStoppedAt = EnvironmentPrankProcedures.MovePlayer(catPlayer, treeLoc, 15, timestamp: false, callback: (p, loc) =>
                            {
                                var roll = rand.Next(3);
                                if (roll == 0)
                                {
                                    LocationLogProcedures.AddLocationLog(loc, $"<b>Meoooww!</b> yowls {catPlayer.GetFullName()} as they quickly flee from {dogPlayer.GetFullName()}, the dog who is chasing them.");
                                }
                            });

                            if (catStoppedAt == treeLoc)
                            {
                                LocationLogProcedures.AddLocationLog(catLoc, $"{catPlayer.GetFullName()} runs to hide from {dogPlayer.GetFullName()}!");
                                LocationLogProcedures.AddLocationLog(treeLoc, $"{catPlayer.GetFullName()} leaps into a tree to hide from {dogPlayer.GetFullName()}, the dog who is chasing them.");
                                PlayerLogProcedures.AddPlayerLog(catId, $"<b>Woof woof!</b>  {dogPlayer.GetFullName()} barks at you, and you run off to the nearest tree!", true);
                                PlayerLogProcedures.AddPlayerLog(dogPlayer.Id, $"You chased a cat to <b>{here}</b> and started barking at {catPlayer.GetFullName()}:  <b>Woof woof!</b>.  They run off to the nearest tree to hide from you!", true);
                            }
                            else if (catStoppedAt == null)
                            {
                                PlayerLogProcedures.AddPlayerLog(catId, $"<b>Woof woof!</b>  {dogPlayer.GetFullName()} barks at you, but you can't seem to escape!", true);
                                PlayerLogProcedures.AddPlayerLog(dogPlayer.Id, $"You chased a cat to <b>{here}</b> and started barking at {catPlayer.GetFullName()}:  <b>Woof woof!</b>.", true);
                            }
                            else
                            {
                                LocationLogProcedures.AddLocationLog(catLoc, $"{catPlayer.GetFullName()} runs to hide from {dogPlayer.GetFullName()}!");
                                PlayerLogProcedures.AddPlayerLog(catId, $"<b>Woof woof!</b>  {dogPlayer.GetFullName()} barks at you, and you run away to try and hide!", true);
                                PlayerLogProcedures.AddPlayerLog(dogPlayer.Id, $"You chased a cat to <b>{here}</b> and started barking at {catPlayer.GetFullName()}:  <b>Woof woof!</b>.  They run off to try and hide from you!", true);
                            }
                        }
                        else  // Cat not mind controlled, dog can only bark
                        {
                            PlayerLogProcedures.AddPlayerLog(catId, $"{dogPlayer.GetFullName()} barked at you:  <b>Woof woof!</b>", true);
                            PlayerLogProcedures.AddPlayerLog(dogPlayer.Id, $"You chased a cat to <b>{here}</b> and started barking at {catPlayer.GetFullName()}:  <b>Woof woof!</b>", true);
                        }
                    }
                    else if (stoppedAt != null)  // Dog moved, but didn't get to the cat's location
                    {
                        var here = LocationsStatics.GetConnectionName(stoppedAt);
                        PlayerLogProcedures.AddPlayerLog(dogPlayer.Id, $"You caught scent of a cat and ran to <b>{here}</b>", true);
                    }
                    else if (dog.dbLocationName == catLoc)
                    {
                        PlayerLogProcedures.AddPlayerLog(catId, $"{dogPlayer.GetFullName()} barked at you:  <b>Woof woof!</b>", true);
                        PlayerLogProcedures.AddPlayerLog(dogPlayer.Id, $"You barked at {catPlayer.GetFullName()}:  <b>Woof woof!</b>", true);
                    }
                }
            }

            return(mcPlayers, freePlayers);
        }
Пример #15
0
        public static void CounterAttack(Player attacker)
        {
            IPlayerRepository playerRepo = new EFPlayerRepository();
            var malethief   = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.MaleRatBotId);
            var femalethief = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.FemaleRatBotId);
            var rand        = new Random(Guid.NewGuid().GetHashCode());

            // both thieves are full, dont' attack too hard
            if (malethief.Mobility == PvPStatics.MobilityFull && femalethief.Mobility == PvPStatics.MobilityFull)
            {
                if (malethief.Mobility == PvPStatics.MobilityFull)
                {
                    AttackProcedures.Attack(malethief, attacker, PvPStatics.Spell_WeakenId);
                    AIProcedures.DealBossDamage(malethief, attacker, true, 1);
                    malethief = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.MaleRatBotId);
                }

                if (femalethief.Mobility == PvPStatics.MobilityFull)
                {
                    AttackProcedures.Attack(femalethief, attacker, GoldenTrophySpellSourceId);
                    AttackProcedures.Attack(femalethief, attacker, GoldenTrophySpellSourceId);
                    AIProcedures.DealBossDamage(femalethief, attacker, true, 2);
                    femalethief = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.FemaleRatBotId);
                }


                var roll = rand.NextDouble();

                // random chance of moving to a new random location
                if (roll < .166)
                {
                    AttackProcedures.Attack(femalethief, attacker, StunSpellSourceId);
                    AIProcedures.DealBossDamage(femalethief, attacker, false, 1);
                    var locationMessage = "<b>" + malethief.GetFullName() + " and " + femalethief.GetFullName() + " ran off in an unknown direction.</b>";
                    LocationLogProcedures.AddLocationLog(femalethief.dbLocationName, locationMessage);
                    var newlocation = LocationsStatics.GetRandomLocation_NoStreets();
                    malethief.dbLocationName   = newlocation;
                    femalethief.dbLocationName = newlocation;
                    playerRepo.SavePlayer(malethief);
                    playerRepo.SavePlayer(femalethief);
                }
            }

            // one thief is defeated, the other goes berserk
            else
            {
                var roll = rand.NextDouble() * 3;
                if (malethief.Mobility == PvPStatics.MobilityFull)
                {
                    for (var i = 0; i < roll; i++)
                    {
                        AttackProcedures.Attack(malethief, attacker, GoldenTrophySpellSourceId);
                        AIProcedures.DealBossDamage(malethief, attacker, false, 2);
                    }
                }
                else if (femalethief.Mobility == PvPStatics.MobilityFull)
                {
                    for (var i = 0; i < roll; i++)
                    {
                        AttackProcedures.Attack(femalethief, attacker, GoldenTrophySpellSourceId);
                        AIProcedures.DealBossDamage(femalethief, attacker, false, 2);
                    }
                }
            }
        }
Пример #16
0
        public override string Execute(IDataContext context)
        {
            var output = "";

            ContextQuery = ctx =>
            {
                var player = ctx.AsQueryable <Player>()
                             .Include(p => p.Effects)
                             .Include(p => p.User)
                             .Include(p => p.User.Stats)
                             .SingleOrDefault(p => p.Id == playerId);

                if (player == null)
                {
                    throw new DomainException($"Player with Id '{playerId}' could not be found");
                }

                if (player.Mobility != PvPStatics.MobilityFull)
                {
                    throw new DomainException("You must be animate in order to take the bus.");
                }

                var originLocation = LocationsStatics.LocationList.GetLocation.First(l => l.dbName == player.Location);

                if (!LocationsStatics.BusStops.Contains(originLocation.dbName))
                {
                    throw new DomainException("You aren't at a valid bus stop.");
                }

                var destinationLocation = LocationsStatics.LocationList.GetLocation.First(l => l.dbName == destination);
                if (!LocationsStatics.BusStops.Contains(destinationLocation.dbName))
                {
                    throw new DomainException("Your destination is not a valid bus stop.");
                }

                if (originLocation.dbName == destinationLocation.dbName)
                {
                    throw new DomainException("You can't take the bus to the location you're already at.");
                }

                if (DateTime.UtcNow.Subtract(player.GetLastCombatTimestamp()).TotalMinutes < 15)
                {
                    throw new DomainException("You have been in combat too recently to take a bus.");
                }

                if (player.InDuel > 0)
                {
                    throw new DomainException("You cannot take the bus whilst in a duel.");
                }

                if (player.InQuest > 0)
                {
                    throw new DomainException("You cannot take the bus whilst in a quest.");
                }

                var distance    = LocationsStatics.GetDistanceBetweenLocations(player.Location, destination);
                var ticketPrice = LocationsStatics.GetTicketPriceBetweenLocations(player.Location, destination);

                if (player.ActionPoints < 3)
                {
                    throw new DomainException("You don't have enough AP to take the bus.");
                }

                if (player.Money < ticketPrice)
                {
                    throw new DomainException("You can't afford this bus ticket!");
                }

                if (player.Effects.FirstOrDefault(e => e.EffectSource != null && e.EffectSource.Id == MindControlStatics.MindControl__Movement_DebuffEffectSourceId) != null)
                {
                    throw new DomainException("You can't ride the bus while under the Forced March! mind control spell.");
                }

                if (player.MoveActionPointDiscount < -TurnTimesStatics.GetActionPointReserveLimit())
                {
                    throw new DomainException("You can't ride the bus while immobilized.");
                }

                output = $"You took the bus from <b>{originLocation.Name}</b> to <b>{destinationLocation.Name}</b> for <b>{ticketPrice}</b> Arpeyjis.";
                player.SetLocation(destination);
                player.AddLog(output, false);
                player.ChangeMoney(-ticketPrice);
                player.ChangeActionPoints(-3);
                player.SetOnlineActivityToNow();

                var originLocationLog      = LocationLog.Create(originLocation.dbName, $"{player.GetFullName()} got on a bus headed toward {destinationLocation.Name}.", 0);
                var destinationLocationLog = LocationLog.Create(destinationLocation.dbName, $"{player.GetFullName()} arrived via bus from {originLocation.Name}.", 0);

                // log statistics only for human players
                if (player.BotId == AIStatics.ActivePlayerBotId)
                {
                    player.User.AddStat(StatsProcedures.Stat__BusRides, distance);
                }

                ctx.Add(originLocationLog);
                ctx.Add(destinationLocationLog);
                ctx.Commit();
            };

            ExecuteInternal(context);
            return(output);
        }
Пример #17
0
        public static List <Exception> RunPsychopathActions(WorldDetail worldDetail)
        {
            var rand = new Random(DateTime.Now.Millisecond);

            var errors = new List <Exception>();

            IPlayerRepository playerRepo = new EFPlayerRepository();


            //spawn in more bots if there are less than the default
            var botCount = playerRepo.Players.Count(b => b.BotId == AIStatics.PsychopathBotId && b.Mobility == PvPStatics.MobilityFull);

            if (botCount < PvPStatics.PsychopathDefaultAmount)
            {
                SpawnAIPsychopaths(PvPStatics.PsychopathDefaultAmount - botCount);
            }

            var bots = playerRepo.Players.Where(p => p.BotId == AIStatics.PsychopathBotId && p.Mobility == PvPStatics.MobilityFull).ToList();

            foreach (var bot in bots)
            {
                try
                {
                    // if bot is no longer fully animate or is null, skip them
                    if (bot == null || bot.Mobility != PvPStatics.MobilityFull)
                    {
                        continue;
                    }

                    bot.LastActionTimestamp = DateTime.UtcNow;

                    if (!EffectProcedures.PlayerHasActiveEffect(bot.Id, JokeShopProcedures.PSYCHOTIC_EFFECT))
                    {
                        #region drop excess items

                        var botItems = DomainRegistry.Repository.Find(new GetItemsOwnedByPsychopath {
                            OwnerId = bot.Id
                        }).ToList();

                        string[] itemTypes =
                        {
                            PvPStatics.ItemType_Hat,        PvPStatics.ItemType_Accessory, PvPStatics.ItemType_Pants,
                            PvPStatics.ItemType_Pet,        PvPStatics.ItemType_Shirt,     PvPStatics.ItemType_Shoes,
                            PvPStatics.ItemType_Underpants, PvPStatics.ItemType_Undershirt
                        };

                        foreach (var typeToDrop in itemTypes)
                        {
                            if (botItems.Count(i => i.ItemSource.ItemType == typeToDrop) > 1)
                            {
                                var dropList = botItems.Where(i => i.ItemSource.ItemType == typeToDrop).Skip(1);

                                foreach (var i in dropList)
                                {
                                    ItemProcedures.DropItem(i.Id);

                                    var name = "a";

                                    if (i.FormerPlayer != null)
                                    {
                                        name = "<b>" + i.FormerPlayer.FullName + "</b> the";
                                    }

                                    if (i.ItemSource.ItemType == PvPStatics.ItemType_Pet)
                                    {
                                        LocationLogProcedures.AddLocationLog(bot.dbLocationName,
                                                                             "<b>" + bot.GetFullName() + "</b> released " + name + " pet <b>" + i.ItemSource.FriendlyName + "</b> here.");
                                    }
                                    else
                                    {
                                        LocationLogProcedures.AddLocationLog(bot.dbLocationName,
                                                                             "<b>" + bot.GetFullName() + "</b> dropped " + name + " <b>" + i.ItemSource.FriendlyName + "</b> here.");
                                    }
                                }
                            }
                        }

                        #endregion
                    }

                    var botbuffs = ItemProcedures.GetPlayerBuffs(bot);

                    var meditates = 0;

                    // meditate if needed
                    if (bot.Mana < bot.MaxMana * .5M)
                    {
                        var manaroll = (int)Math.Floor(rand.NextDouble() * 4.0D);
                        for (var i = 0; i < manaroll; i++)
                        {
                            DomainRegistry.Repository.Execute(new Meditate
                            {
                                PlayerId   = bot.Id,
                                Buffs      = botbuffs,
                                NoValidate = true
                            });
                            meditates++;
                        }
                    }

                    // cleanse if needed, less if psycho has cleansed lately
                    if (bot.Health < bot.MaxHealth * .5M)
                    {
                        var healthroll = (int)Math.Floor(rand.NextDouble() * 4.0D);
                        for (var i = meditates; i < healthroll; i++)
                        {
                            DomainRegistry.Repository.Execute(new Cleanse
                            {
                                PlayerId   = bot.Id,
                                Buffs      = botbuffs,
                                NoValidate = true
                            });
                        }
                    }


                    var directive = AIDirectiveProcedures.GetAIDirective(bot.Id);

                    // the bot has an attack target, so go chase it
                    if (directive.State == "attack")
                    {
                        var myTarget = PlayerProcedures.GetPlayer(directive.TargetPlayerId);
                        var(mySkills, weakenSkill, inanimateSkill) = GetPsychopathSkills(bot);

                        // if the target is offline, no longer animate, in the dungeon, or in the same form as the spells' target, go into idle mode
                        if (PlayerProcedures.PlayerIsOffline(myTarget) ||
                            myTarget.Mobility != PvPStatics.MobilityFull ||
                            mySkills.IsEmpty() || inanimateSkill == null ||
                            myTarget.FormSourceId == inanimateSkill.StaticSkill.FormSourceId ||
                            myTarget.IsInDungeon() ||
                            myTarget.InDuel > 0 ||
                            myTarget.InQuest > 0)
                        {
                            AIDirectiveProcedures.SetAIDirective_Idle(bot.Id);
                        }

                        // the target is okay for attacking
                        else
                        {
                            // the bot must move to its target location.
                            if (myTarget.dbLocationName != bot.dbLocationName)
                            {
                                if (botbuffs.MoveActionPointDiscount() > -100 && CanMove(worldDetail, myTarget))
                                {
                                    var maxSpaces = NumPsychopathMoveSpaces(bot);
                                    var newplace  = MoveTo(bot, myTarget.dbLocationName, maxSpaces);
                                    bot.dbLocationName = newplace;
                                }
                            }

                            // if the bot is now in the same place as the target, attack away, so long as the target is online and animate
                            if (bot.dbLocationName == myTarget.dbLocationName &&
                                !PlayerProcedures.PlayerIsOffline(myTarget) &&
                                myTarget.Mobility == PvPStatics.MobilityFull &&
                                CanAttack(worldDetail, bot, myTarget)
                                )
                            {
                                playerRepo.SavePlayer(bot);

                                var numAttacks = Math.Min(3, (int)(bot.Mana / PvPStatics.AttackManaCost));
                                var complete   = false;
                                for (var attackIndex = 0; attackIndex < numAttacks && !complete; ++attackIndex)
                                {
                                    var skill = SelectPsychopathSkill(myTarget, mySkills, weakenSkill, rand);
                                    (complete, _) = AttackProcedures.Attack(bot, myTarget, skill);
                                }

                                if (complete)
                                {
                                    EquipDefeatedPlayer(bot, myTarget);
                                }
                            }
                        }
                    }

                    // the bot has no target, so wander and try to find new targets and attack them.
                    else
                    {
                        if (botbuffs.MoveActionPointDiscount() > -100)
                        {
                            var newplace = MoveTo(bot, LocationsStatics.GetRandomLocationNotInDungeon(), 5);
                            bot.dbLocationName = newplace;
                        }


                        // attack stage
                        var playersHere = playerRepo.Players.Where
                                              (p => p.dbLocationName == bot.dbLocationName && p.Mobility == PvPStatics.MobilityFull &&
                                              p.Id != bot.Id && p.BotId == AIStatics.PsychopathBotId && p.Level >= bot.Level).ToList();

                        // filter out offline players and Lindella
                        var onlinePlayersHere = playersHere.Where(p => !PlayerProcedures.PlayerIsOffline(p)).ToList();

                        if (onlinePlayersHere.Count > 0)
                        {
                            var roll   = Math.Floor(rand.NextDouble() * onlinePlayersHere.Count);
                            var victim = onlinePlayersHere.ElementAt((int)roll);
                            AIDirectiveProcedures.SetAIDirective_Attack(bot.Id, victim.Id);
                            playerRepo.SavePlayer(bot);

                            var(mySkills, weakenSkill, inanimateSkill) = GetPsychopathSkills(bot);
                            if (!mySkills.IsEmpty())
                            {
                                var numAttacks = Math.Min(3, (int)(bot.Mana / PvPStatics.AttackManaCost));
                                var complete   = false;
                                for (var attackIndex = 0; attackIndex < numAttacks && !complete; ++attackIndex)
                                {
                                    var skill = SelectPsychopathSkill(victim, mySkills, weakenSkill, rand);
                                    (complete, _) = AttackProcedures.Attack(bot, victim, skill);
                                }

                                if (complete)
                                {
                                    EquipDefeatedPlayer(bot, victim);
                                }
                            }
                        }
                    }

                    playerRepo.SavePlayer(bot);
                }
                catch (Exception e)
                {
                    errors.Add(e);
                }
            }

            return(errors);
        }
        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);
        }
Пример #19
0
        public static void UpdateWorld()
        {
            var worldStats = DomainRegistry.Repository.FindSingle(new GetWorld());

            var turnNo = worldStats.TurnNumber;

            PvPStatics.LastGameTurn = turnNo;

            if (turnNo < PvPStatics.RoundDuration)
            {
                PvPStatics.AnimateUpdateInProgress = true;

                IServerLogRepository serverLogRepo = new EFServerLogRepository();
                var log = new ServerLog
                {
                    TurnNumber      = turnNo,
                    StartTimestamp  = DateTime.UtcNow,
                    FinishTimestamp = DateTime.UtcNow,
                    Errors          = 0,
                    FullLog         = "",
                    Population      = PlayerProcedures.GetWorldPlayerStats().CurrentOnlinePlayers,
                };
                log.AddLog($"Started new log for turn {turnNo} at <b>{DateTime.UtcNow}</b>.");
                serverLogRepo.SaveServerLog(log);
                var updateTimer = new Stopwatch();
                updateTimer.Start();

                IPlayerRepository playerRepo = new EFPlayerRepository();

                Player lindella = playerRepo.Players.FirstOrDefault(p => p.BotId == AIStatics.LindellaBotId);
                Player wuffie   = playerRepo.Players.FirstOrDefault(p => p.BotId == AIStatics.WuffieBotId);

                #region spawn NPCS
                // make sure the NPCs have been spawned early turn
                if (turnNo <= 3)
                {
                    if (lindella == null)
                    {
                        BossProcedures_Lindella.SpawnLindella();
                        lindella = playerRepo.Players.FirstOrDefault(p => p.BotId == AIStatics.LindellaBotId);
                    }

                    if (wuffie == null)
                    {
                        BossProcedures_PetMerchant.SpawnPetMerchant();
                        wuffie = playerRepo.Players.FirstOrDefault(p => p.BotId == AIStatics.WuffieBotId);
                    }

                    var fae = playerRepo.Players.FirstOrDefault(p => p.BotId == AIStatics.JewdewfaeBotId);
                    if (fae == null)
                    {
                        BossProcedures_Jewdewfae.SpawnFae();
                    }

                    var bartender = playerRepo.Players.FirstOrDefault(p => p.BotId == AIStatics.BartenderBotId);
                    if (bartender == null)
                    {
                        BossProcedures_Bartender.SpawnBartender();
                    }

                    var lorekeeper = playerRepo.Players.FirstOrDefault(p => p.BotId == AIStatics.LoremasterBotId);
                    if (lorekeeper == null)
                    {
                        BossProcedures_Loremaster.SpawnLoremaster();
                    }

                    var soulbinder = playerRepo.Players.FirstOrDefault(p => p.BotId == AIStatics.SoulbinderBotId);
                    if (soulbinder == null)
                    {
                        var id = DomainRegistry.Repository.Execute(new CreatePlayer
                        {
                            FirstName               = "Karin",
                            LastName                = "Kezesul-Adriz the Soulbinder",
                            FormSourceId            = 1000,
                            Location                = "stripclub_office",
                            Level                   = 10,
                            Mobility                = PvPStatics.MobilityFull,
                            Money                   = 0,
                            Gender                  = PvPStatics.GenderFemale,
                            Health                  = 9999,
                            MaxHealth               = 9999,
                            Mana                    = 9999,
                            MaxMana                 = 9999,
                            OnlineActivityTimestamp = DateTime.UtcNow,
                            BotId                   = AIStatics.SoulbinderBotId
                        });

                        var newSoulbinder = playerRepo.Players.FirstOrDefault(p => p.Id == id);
                        newSoulbinder.ReadjustMaxes(ItemProcedures.GetPlayerBuffs(newSoulbinder));
                        playerRepo.SavePlayer(newSoulbinder);
                    }
                }
                #endregion

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started loading animate players");

                IEffectRepository effectRepo = new EFEffectRepository();

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started loading effects");
                var temporaryEffects = effectRepo.Effects.Where(e => !e.IsPermanent).ToList();
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished loading effects");
                var effectsToDelete = new List <Effect>();

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started updating effects");
                var effectsExpiringThisTurn = temporaryEffects.Where(e => e.Duration == 1).ToList();
                var activeOrExpiringEffects = temporaryEffects.Where(e => e.Duration > 0).ToList();

                foreach (var e in temporaryEffects)
                {
                    e.Duration--;
                    e.Cooldown--;

                    if (e.Duration < 0)
                    {
                        e.Duration = 0;
                    }

                    if (e.Cooldown <= 0)
                    {
                        effectsToDelete.Add(e);
                    }
                    else
                    {
                        effectRepo.SaveEffect(e);
                    }
                }
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished updating effects");
                serverLogRepo.SaveServerLog(log);

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started running effect-expiry actions");
                try
                {
                    JokeShopProcedures.RunEffectExpiryActions(effectsExpiringThisTurn);
                }
                catch (Exception e)
                {
                    log.Errors++;
                    log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, " ERROR running effect-expiry actions", e));
                }
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished running effect-expiry actions");
                serverLogRepo.SaveServerLog(log);

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started deleting expired effects");
                foreach (var e in effectsToDelete)
                {
                    effectRepo.DeleteEffect(e.Id);
                }
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished deleting expired effects");
                serverLogRepo.SaveServerLog(log);

                #region playerExtra / protection cooldown loop
                IPlayerExtraRepository playerExtraRepo = new EFPlayerExtraRepository();
                var extrasToIncrement            = playerExtraRepo.PlayerExtras.ToList();
                var extrasToIncrement_SaveList   = new List <PlayerExtra>();
                var extrasToIncrement_DeleteList = new List <PlayerExtra>();
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started updating protection change cooldown (" + extrasToIncrement.Count + ")");

                foreach (var e in extrasToIncrement)
                {
                    var owner = PlayerProcedures.GetPlayer(e.PlayerId);
                    if (PlayerProcedures.PlayerIsOffline(owner))
                    {
                        extrasToIncrement_SaveList.Add(e);
                    }
                }

                foreach (var e in extrasToIncrement_SaveList)
                {
                    if (e.ProtectionToggleTurnsRemaining > 0)
                    {
                        e.ProtectionToggleTurnsRemaining--;
                        playerExtraRepo.SavePlayerExtra(e);
                    }
                    else if (e.ProtectionToggleTurnsRemaining <= 0)
                    {
                        extrasToIncrement_DeleteList.Add(e);
                    }
                }

                foreach (var e in extrasToIncrement_DeleteList)
                {
                    playerExtraRepo.DeletePlayerExtra(e.Id);
                }

                #endregion

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished updating protection change cooldown.");


                #region main player loop

                using (var context = new StatsContext())
                {
                    try
                    {
                        context.Database.ExecuteSqlCommand("UPDATE [dbo].[Players] SET TimesAttackingThisUpdate = 0, CleansesMeditatesThisRound = 0, ShoutsRemaining = 1, ActionPoints = ActionPoints + 10, ItemsUsedThisTurn = 0 WHERE Mobility='full'" +

                                                           $"UPDATE [dbo].[Players] SET ActionPoints_Refill = ActionPoints_Refill + (ActionPoints % {TurnTimesStatics.GetActionPointLimit()} / 2) WHERE ActionPoints >= {TurnTimesStatics.GetActionPointLimit()} AND Mobility='full'" +

                                                           $"UPDATE [dbo].[Players] SET ActionPoints = {TurnTimesStatics.GetActionPointLimit()} WHERE ActionPoints > {TurnTimesStatics.GetActionPointLimit()} AND Mobility='full'" +

                                                           $"UPDATE [dbo].[Players] SET ActionPoints_Refill = {TurnTimesStatics.GetActionPointReserveLimit()} WHERE ActionPoints_Refill > {TurnTimesStatics.GetActionPointReserveLimit()} AND Mobility='full'" +

                                                           $"UPDATE [dbo].[Players] SET ActionPoints = ActionPoints + 20, ActionPoints_Refill = ActionPoints_Refill - 20 WHERE ActionPoints <= {TurnTimesStatics.GetActionPointLimit()-20} AND ActionPoints_Refill >= 20 AND Mobility='full'");

                        if (PvPStatics.ChaosMode)
                        {
                            context.Database.ExecuteSqlCommand($"Update [dbo].[Players] SET ActionPoints = {TurnTimesStatics.GetActionPointLimit()}, ActionPoints_Refill = {TurnTimesStatics.GetActionPointReserveLimit()}, Mana = MaxMana");
                        }

                        log.AddLog(updateTimer.ElapsedMilliseconds + ":  ANIMATE SQL UPDATE SUCCEEDED!");
                        serverLogRepo.SaveServerLog(log);
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, " ANIMATE SQL UPDATE FAILED", e));
                        serverLogRepo.SaveServerLog(log);
                    }
                }

                var timeCutoff    = DateTime.UtcNow.AddHours(-8);
                var playersToSave = playerRepo.Players
                                    .Where(p => p.Mobility == PvPStatics.MobilityFull && p.LastActionTimestamp > timeCutoff).ToList();

                foreach (var player in playersToSave)
                {
                    //Skip regen stuff for those in quests.
                    if (player.InQuest > 0)
                    {
                        continue;
                    }

                    // extra AP condition checks
                    if (player.Covenant > 0)
                    {
                        var playerCov = CovenantDictionary.IdNameFlagLookup.FirstOrDefault(c => c.Key == player.Covenant).Value;

                        // give this player an extra AP refill if they are at their safeground, scaled up by level
                        if (playerCov != null && !playerCov.HomeLocation.IsNullOrEmpty() && player.dbLocationName == playerCov.HomeLocation)
                        {
                            player.ActionPoints_Refill += .25M * playerCov.CovLevel;
                        }

                        // give this player an extra AP refill if they are on a location that their covenane has enchanted
                        var currentLocation = LocationsStatics.LocationList.GetLocation.FirstOrDefault(l => l.dbName == player.dbLocationName);

                        if (currentLocation != null && currentLocation.CovenantController == player.Covenant)
                        {
                            if (currentLocation.TakeoverAmount < 25)
                            {
                                player.ActionPoints_Refill += .05M;
                            }
                            else if (currentLocation.TakeoverAmount <= 50)
                            {
                                player.ActionPoints_Refill += .10M;
                            }
                            else if (currentLocation.TakeoverAmount <= 75)
                            {
                                player.ActionPoints_Refill += .15M;
                            }
                            else if (currentLocation.TakeoverAmount < 100)
                            {
                                player.ActionPoints_Refill += .20M;
                            }
                            else if (currentLocation.TakeoverAmount >= 100)
                            {
                                player.ActionPoints_Refill += .25M;
                            }
                        }

                        // make sure AP reserve stays within maximum amount
                        if (player.ActionPoints_Refill > TurnTimesStatics.GetActionPointReserveLimit())
                        {
                            player.ActionPoints_Refill = TurnTimesStatics.GetActionPointReserveLimit();
                        }
                    }

                    var buffs = ItemProcedures.GetPlayerBuffs(player);
                    player.Health += buffs.HealthRecoveryPerUpdate();
                    player.Mana   += buffs.ManaRecoveryPerUpdate();

                    player.ReadjustMaxes(buffs);

                    playerRepo.SavePlayer(player);
                }

                log.AddLog($"{updateTimer.ElapsedMilliseconds}:  Finished updating animate players ({playersToSave.Count})");
                serverLogRepo.SaveServerLog(log);

                #endregion main player loop

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started updating inanimate/animal players");


                using (var context = new StatsContext())
                {
                    try
                    {
                        context.Database.ExecuteSqlCommand("UPDATE [dbo].[Players] SET TimesAttackingThisUpdate = 0, ItemsUsedThisTurn = 0 WHERE (Mobility = 'inanimate' OR Mobility = 'animal') AND BotId = 0");
                        log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished updating inanimate/animal players");
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, " ERROR UPDATING INANIMATE/ANIMAL PLAYERS", e));
                    }
                }

                serverLogRepo.SaveServerLog(log);

                #region decrement mind control timers
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started mind control cooldown.");

                using (var context = new StatsContext())
                {
                    try
                    {
                        context.Database.ExecuteSqlCommand("UPDATE [dbo].[MindControls] SET TurnsRemaining = TurnsRemaining - 1");
                        context.Database.ExecuteSqlCommand("DELETE FROM [dbo].[MindControls] WHERE TurnsRemaining <= 0");
                        context.Database.ExecuteSqlCommand("UPDATE [dbo].[MindControls] SET TimesUsedThisTurn = 0");

                        log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished mind control cooldown.");
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "MIND CONTROL COOLDOWN UPDATE FAILED", e));
                    }
                }
                #endregion

                serverLogRepo.SaveServerLog(log);

                PvPStatics.AnimateUpdateInProgress = false;

                // bump down the timer on all items that are reuseable consumables
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started updating items on cooldown");
                IItemRepository itemsRepo     = new EFItemRepository();
                var             itemsToUpdate = itemsRepo.Items.Where(i => i.TurnsUntilUse > 0).ToList();

                foreach (var item in itemsToUpdate)
                {
                    item.TurnsUntilUse--;
                }

                foreach (var item in itemsToUpdate)
                {
                    itemsRepo.SaveItem(item);
                }
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished updating items on cooldown");
                serverLogRepo.SaveServerLog(log);

                // find the ids for the merchants Lindella and Skaldyr
                var skaldyr      = PlayerProcedures.GetPlayerFromBotId(AIStatics.LoremasterBotId);
                var soulbinderId = PlayerProcedures.GetPlayerFromBotId(AIStatics.SoulbinderBotId).Id;

                // have abandoned items go to Lindella
                if (turnNo % 11 == 3 && lindella.Mobility == PvPStatics.MobilityFull)
                {
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started collecting all abandoned items for Lindella");

                    using (var context = new StatsContext())
                    {
                        try
                        {
                            context.Database.ExecuteSqlCommand($"UPDATE [dbo].[Items] SET OwnerId = {lindella.Id}, dbLocationName = '', PvPEnabled = {(int)GameModeStatics.GameModes.Any}, TimeDropped = '{DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")}' " +
                                                               $"FROM DbStaticItems WHERE dbLocationName <> '' AND dbLocationName IS NOT NULL AND TimeDropped < DATEADD(hour, -8, GETUTCDATE()) AND OwnerId IS NULL AND DbStaticItems.Id = Items.ItemSourceId AND ItemType != '{PvPStatics.ItemType_Pet}' AND ItemSourceId != {ItemStatics.ItemType_DungeonArtifactItemSourceId};" +
                                                               $"UPDATE [dbo].[Players] SET dbLocationName = '' FROM Items WHERE Items.FormerPlayerId = Players.Id AND Items.OwnerId = {lindella.Id};");



                            log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished collecting all abandoned items for Lindella");
                        }
                        catch (Exception e)
                        {
                            log.Errors++;
                            log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "ERROR collecting all abandoned items for Lindella", e));
                        }
                    }
                }

                // delete all consumable type items that have been sitting around on the ground for too long
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started deleting expired consumables");
                DomainRegistry.Repository.Execute(new DeleteExpiredConsumablesOnGround());
                DomainRegistry.Repository.Execute(new DeleteExpiredConsumablesOnMerchants {
                    LindellaId = lindella.Id, LorekeeperId = skaldyr.Id
                });

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished deleting expired consumables");
                serverLogRepo.SaveServerLog(log);

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started deleting expired runes");
                try
                {
                    DomainRegistry.Repository.Execute(new DeleteExpiredRunesOnMerchants());
                }
                catch (Exception e)
                {
                    log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "ERROR deleting expired runes", e));
                    log.Errors++;
                }

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished deleting expired runes");

                serverLogRepo.SaveServerLog(log);

                // allow all items that have been recently equipped to be taken back off
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started resetting items that have been recently equipped");
                var recentlyEquipped = itemsRepo.Items.Where(i => i.EquippedThisTurn).ToList();

                foreach (var item in recentlyEquipped)
                {
                    item.EquippedThisTurn = false;
                    itemsRepo.SaveItem(item);
                }
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished resetting items that have been recently equipped");

                #region give covenants money based on territories
                if (turnNo % 6 == 0)
                {
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started giving covenants money from territories");
                    ICovenantRepository covRepo = new EFCovenantRepository();
                    var covs = covRepo.Covenants.Where(c => c.HomeLocation != null && c.HomeLocation != "").ToList();


                    foreach (var c in covs)
                    {
                        var locationControlledSum = CovenantProcedures.GetLocationControlCount(c);
                        var moneyGain             = (decimal)Math.Floor(Convert.ToDouble(locationControlledSum));
                        c.Money += moneyGain;

                        if (moneyGain > 0)
                        {
                            CovenantProcedures.WriteCovenantLog("Your covenant collected " + moneyGain + " Arpeyjis from the locations you have enchanted.", c.Id, false);
                        }
                        covRepo.SaveCovenant(c);
                    }
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished giving covenants money from territories");
                }
                #endregion

                serverLogRepo.SaveServerLog(log);

                #region drop dungeon artifacts and spawn demons if needed

                try
                {
                    if (turnNo % 7 == 2)
                    {
                        log.AddLog(updateTimer.ElapsedMilliseconds + ":  Starting dungeon item / demon spawning");
                        var dungeonArtifactCount = itemsRepo.Items.Count(i => i.ItemSourceId == ItemStatics.ItemType_DungeonArtifactItemSourceId);
                        for (var x = 0; x < PvPStatics.DungeonArtifact_SpawnLimit - dungeonArtifactCount; x++)
                        {
                            var randDungeon = LocationsStatics.GetRandomLocation_InDungeon();

                            var cmd = new CreateItem
                            {
                                dbLocationName   = randDungeon,
                                OwnerId          = null,
                                EquippedThisTurn = false,
                                IsPermanent      = true,
                                Level            = 0,
                                PvPEnabled       = 2,
                                IsEquipped       = false,
                                TurnsUntilUse    = 0,
                                ItemSourceId     = ItemStatics.ItemType_DungeonArtifactItemSourceId
                            };
                            DomainRegistry.Repository.Execute(cmd);
                        }


                        IEnumerable <Player> demons = playerRepo.Players.Where(i => i.FormSourceId == PvPStatics.DungeonDemonFormSourceId);
                        var dungeonDemonCount       = demons.Count();

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

                        var demonNames = XmlResourceLoader.Load <List <string> >("TT.Domain.XMLs.DungeonDemonNames.xml");

                        for (var x = 0; x < PvPStatics.DungeonDemon_Limit - dungeonDemonCount; x++)
                        {
                            var randDungeon = LocationsStatics.GetRandomLocation_InDungeon();

                            // pull a random last demon name
                            double maxDemonNameCount = demonNames.Count();
                            var    num           = randLevel.NextDouble();
                            var    demonIndex    = Convert.ToInt32(Math.Floor(num * maxDemonNameCount));
                            var    demonlastName = demonNames.ElementAt(demonIndex);

                            // if there's already a demon with this last name, reroll and try again
                            if (demons.FirstOrDefault(d => d.LastName == demonlastName) != null)
                            {
                                x--;
                                continue;
                            }


                            var levelRoll = randLevel.NextDouble();
                            var level     = (int)Math.Floor(levelRoll * 8 + 3);

                            var cmd = new CreatePlayer
                            {
                                BotId        = AIStatics.DemonBotId,
                                FirstName    = "Spirit of ",
                                LastName     = demonlastName,
                                Mobility     = PvPStatics.MobilityFull,
                                FormSourceId = AIStatics.DungeonDemonFormId,
                                Gender       = PvPStatics.GenderFemale,
                                GameMode     = 2,
                                Health       = 10000,
                                Mana         = 10000,
                                Covenant     = -1,
                                Location     = randDungeon,
                                Level        = level,
                                MaxHealth    = 10000,
                                MaxMana      = 10000,
                            };

                            var id = DomainRegistry.Repository.Execute(cmd);

                            var newDemon = playerRepo.Players.FirstOrDefault(p => p.Id == id);

                            if (cmd.Level <= 5)
                            {
                                ItemProcedures.GiveNewItemToPlayer(newDemon, ItemStatics.SpellbookMediumItemSourceId);
                            }
                            else if (cmd.Level <= 7)
                            {
                                ItemProcedures.GiveNewItemToPlayer(newDemon, ItemStatics.SpellbookLargeItemSourceId);
                            }

                            else if (cmd.Level > 7)
                            {
                                ItemProcedures.GiveNewItemToPlayer(newDemon, ItemStatics.SpellbookGiantItemSourceId);
                            }

                            newDemon.ReadjustMaxes(ItemProcedures.GetPlayerBuffs(newDemon));
                            playerRepo.SavePlayer(newDemon);
                        }
                        log.AddLog(updateTimer.ElapsedMilliseconds + ":  FINISHED dungeon item / demon spawning");
                    }
                }
                catch (Exception e)
                {
                    log.Errors++;
                    log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "ERROR running dungeon actions", e));
                }


                #endregion

                serverLogRepo.SaveServerLog(log);

                #region forcibly terminate duels that have timed out
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started duel updates");
                try
                {
                    IDuelRepository duelRepo = new EFDuelRepository();
                    var             duels    = duelRepo.Duels.Where(d => d.Status == DuelProcedures.ACTIVE).ToList();

                    foreach (var d in duels)
                    {
                        // if the duel has timed out, end it forcibly
                        if ((turnNo - d.StartTurn) >= PvPStatics.MaximumDuelTurnLength)
                        {
                            DuelProcedures.EndDuel(d.Id, DuelProcedures.TIMEOUT);
                        }
                    }

                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Successfully completed duel updates");
                }
                catch (Exception e)
                {
                    log.Errors++;
                    log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "ERROR completing duel updates", e));
                }
                #endregion duel updates

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started Lindella actions");
                serverLogRepo.SaveServerLog(log);
                try
                {
                    BossProcedures_Lindella.RunActions(turnNo);
                }
                catch (Exception e)
                {
                    log.Errors++;
                    log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "ERROR running Lindella action", e));
                }
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished Lindella actions");

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started Wuffie actions");
                serverLogRepo.SaveServerLog(log);
                try
                {
                    BossProcedures_PetMerchant.RunPetMerchantActions(turnNo);
                }
                catch (Exception e)
                {
                    log.Errors++;
                    log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "ERROR running Wuffie actions", e));
                }
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished Wuffie actions");

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started running effect-related actions");
                try
                {
                    JokeShopProcedures.RunEffectActions(activeOrExpiringEffects);
                }
                catch (Exception e)
                {
                    log.Errors++;
                    log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, " ERROR running effect-related actions", e));
                }
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished running effect-related actions");
                serverLogRepo.SaveServerLog(log);

                #region furniture
                if (turnNo % 6 == 0)
                {
                    // move some furniture around on the market
                    try
                    {
                        FurnitureProcedures.MoveFurnitureOnMarket();
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(updateTimer.ElapsedMilliseconds + "ERROR MOVING FURNITURE ON MARKET:  " + e);
                    }

                    // move Jewdewfae to a new location if she has been in one place for more than 48 turns, 8 hours
                    try
                    {
                        var fae   = PlayerProcedures.GetPlayerFromBotId(-6);
                        var faeAI = AIDirectiveProcedures.GetAIDirective(fae.Id);

                        // if the turn since her last move has been long enough, relocate her
                        if (turnNo - (int)faeAI.Var2 > 48)
                        {
                            log.AddLog(updateTimer.ElapsedMilliseconds + ":  FORCED JEWDEWFAE TO MOVE.");
                            BossProcedures_Jewdewfae.MoveToNewLocation();
                        }
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(updateTimer.ElapsedMilliseconds + "ERROR TRYING TO MOVE JEWDEWFAE:  " + e);
                    }
                }
                #endregion furniture

                #region bosses

                // DONNA
                if (worldStats.Boss_Donna == AIStatics.ACTIVE)
                {
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started Donna actions");
                    serverLogRepo.SaveServerLog(log);
                    try
                    {
                        BossProcedures_Donna.RunDonnaActions();
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "Error running Donna actions", e));
                    }
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished Donna actions");
                }

                // VALENTINE
                if (worldStats.Boss_Valentine == AIStatics.ACTIVE || PlayerProcedures.GetAnimatePlayerFromBotId(AIStatics.ValentineBotId) != null)
                {
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started Valentine actions");
                    serverLogRepo.SaveServerLog(log);
                    try
                    {
                        BossProcedures_Valentine.RunValentineActions();
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "Error running Valentine actions", e));
                    }
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished Valentine actions");
                }

                // BIMBO
                if (worldStats.Boss_Bimbo == AIStatics.ACTIVE)
                {
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started Bimbo actions");
                    serverLogRepo.SaveServerLog(log);
                    try
                    {
                        BossProcedures_BimboBoss.RunActions(turnNo);
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "Error running Bimbo actions", e));
                    }
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished Bimbo actions");
                }

                // THIEVES
                if (worldStats.Boss_Thief == AIStatics.ACTIVE)
                {
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started Thieves actions");
                    serverLogRepo.SaveServerLog(log);
                    try
                    {
                        BossProcedures_Thieves.RunThievesAction(turnNo);
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "Error running Thieves actions", e));
                    }
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished Thieves actions");
                }

                // SISTERS
                if (worldStats.Boss_Sisters == AIStatics.ACTIVE)
                {
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started Sisters actions");
                    serverLogRepo.SaveServerLog(log);
                    try
                    {
                        BossProcedures_Sisters.RunSistersAction();
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "Error running Sisters actions", e));
                    }
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished Sisters actions");
                }

                // FAEBOSS
                if (worldStats.Boss_Faeboss == AIStatics.ACTIVE)
                {
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started Narcissa actions");
                    serverLogRepo.SaveServerLog(log);
                    try
                    {
                        BossProcedures_FaeBoss.RunTurnLogic();
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "Error running Narcissa actions", e));
                    }
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished Narcissa actions");
                }

                // BIKER GANG BOSS
                if (worldStats.Boss_MotorcycleGang == AIStatics.ACTIVE)
                {
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started BikerBoss actions");
                    serverLogRepo.SaveServerLog(log);
                    try
                    {
                        BossProcedures_MotorcycleGang.RunTurnLogic();
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(updateTimer.ElapsedMilliseconds + ":  BikerBoss ERROR:  " + e);
                    }
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished BikerBoss actions");
                }

                #endregion bosses

                // psychopaths
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started psychopath actions");
                serverLogRepo.SaveServerLog(log);

                var psychoExceptions = AIProcedures.RunPsychopathActions(worldStats);

                foreach (var e in psychoExceptions)
                {
                    log.Errors++;
                    log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "Error running pycho action", e));
                }

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished psychopath actions");

                // minibosses
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started miniboss actions");
                serverLogRepo.SaveServerLog(log);

                var minibossExceptions = BossProcedures_Minibosses.RunAll(worldStats.TurnNumber);

                foreach (var e in minibossExceptions)
                {
                    log.Errors++;
                    log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "Error running miniboss action", e));
                }

                serverLogRepo.SaveServerLog(log);
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished miniboss actions");

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Starting setting update status to done");
                try
                {
                    PvPWorldStatProcedures.UpdateWorldTurnCounter_UpdateDone();
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished setting update status to done");
                }
                catch (Exception e)
                {
                    log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "ERROR setting update status to done: ", e));
                    log.Errors++;
                }

                serverLogRepo.SaveServerLog(log);

                try
                {
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started stored procedure maintenance");
                    using (var context = new StatsContext())
                    {
                        context.Database.ExecuteSqlCommand(
                            "DELETE FROM [dbo].[LocationLogs] WHERE Timestamp < DATEADD(hour, -1, GETUTCDATE())");
                        context.Database.ExecuteSqlCommand(
                            "DELETE FROM [dbo].[Messages] WHERE Timestamp < DATEADD(hour, -72, GETUTCDATE()) AND DoNotRecycleMe = 0");
                        context.Database.ExecuteSqlCommand("DELETE FROM [dbo].[TFEnergies] WHERE Amount < .5");
                        context.Database.ExecuteSqlCommand(
                            "DELETE FROM [dbo].[PlayerLogs] WHERE Timestamp < DATEADD(hour, -72, GETUTCDATE())");
                        context.Database.ExecuteSqlCommand(
                            "DELETE FROM [dbo].[ChatLogs] WHERE Timestamp < DATEADD(hour, -72, GETUTCDATE())");
                        context.Database.ExecuteSqlCommand(
                            "DELETE FROM [dbo].[AIDirectives] WHERE Timestamp < DATEADD(hour, -72, GETUTCDATE()) AND DoNotRecycleMe = 0");
                        context.Database.ExecuteSqlCommand(
                            "DELETE FROM [dbo].[CovenantLogs] WHERE Timestamp < DATEADD(hour, -72, GETUTCDATE())");
                        context.Database.ExecuteSqlCommand(
                            "DELETE FROM [dbo].[RPClassifiedAds] WHERE RefreshTimestamp < DATEADD(hour, -72, GETUTCDATE())");
                        context.Database.ExecuteSqlCommand(
                            "DELETE FROM [dbo].[TFEnergies] WHERE Timestamp < DATEADD(hour, -72, GETUTCDATE())");
                        context.Database.ExecuteSqlCommand(
                            "DELETE FROM [dbo].[SelfRestoreEnergies] WHERE Timestamp < DATEADD(hour, -4, GETUTCDATE())");

                        // move soulbound items on the ground to the soulbinding NPC.
                        context.Database.ExecuteSqlCommand(
                            $"UPDATE[dbo].[Items] SET OwnerId = {soulbinderId}, dbLocationName = '' WHERE dbLocationName <> '' AND SoulboundToPlayerId IS NOT NULL;");
                    }
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished stored procedure maintenance");
                }
                catch (Exception e)
                {
                    log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "ERROR running stored procedure maintenance: ", e));
                    log.Errors++;
                }

                serverLogRepo.SaveServerLog(log);


                #region update joke shop
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Updating joke shop started.");
                try
                {
                    JokeShopProcedures.EjectOfflineCharacters();

                    if (new Random().Next(20) == 0)
                    {
                        LocationsStatics.MoveJokeShop();
                    }

                    ChallengeProcedures.CheckChallenges();
                }
                catch (Exception e)
                {
                    log.Errors++;
                    log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "Updating joke shop FAILED", e));
                }
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Updating joke shop completed.");
                serverLogRepo.SaveServerLog(log);
                #endregion update joke shop


                #region regenerate dungeon
                if (turnNo % 30 == 7)
                {
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Dungeon generation started.");
                    try
                    {
                        DungeonProcedures.GenerateDungeon();
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "Dungeon generation FAILED", e));
                    }
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Dungeon generation completed.");
                    serverLogRepo.SaveServerLog(log);
                }
                #endregion

                #region move tomb quest
                // Just to keep some things consistent, following the update pattern of the dungeon regen.
                if (turnNo > 6665 && turnNo % 30 == 7)
                {
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Updating tomb location started.");
                    try
                    {
                        // Get the quest stuff to start with.
                        int questId           = 39; //Nephthyma's Calling quest ID.
                        IQuestRepository repo = new EFQuestRepository();
                        var questStart        = repo.QuestStarts.FirstOrDefault(q => q.Id == questId);

                        if (questStart != null)
                        {
                            // Pick a random location.
                            string[] locationList   = { "mansion_mausoleum", "gym_laundry", "street_50e9th", "park_shrine" };
                            Random   locationRandom = new Random();
                            int      locationIndex  = locationRandom.Next(locationList.Length);
                            string   location       = locationList[locationIndex];

                            // Set it to the new location.

                            questStart.Location = location;
                            QuestWriterProcedures.SaveQuestStart(questStart);
                        }
                    }
                    catch (Exception e)
                    {
                        log.Errors++;
                        log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "Updating tomb location FAILED", e));
                    }
                    log.AddLog(updateTimer.ElapsedMilliseconds + ":  Updating tomb location completed.");
                    serverLogRepo.SaveServerLog(log);
                }
                #endregion

                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Started deleting unwanted psycho items/pets on Lindella/Wuffie");
                try
                {
                    DomainRegistry.Repository.Execute(new DeleteUnpurchasedPsychoItems());
                }
                catch (Exception e)
                {
                    log.Errors++;
                    log.AddLog(FormatExceptionLog(updateTimer.ElapsedMilliseconds, "ERROR deleting unwanted psycho items", e));
                }
                log.AddLog(updateTimer.ElapsedMilliseconds + ":  Finished deleting unwanted psycho items/pets on Lindella/Wuffie");
                log.FinishTimestamp = DateTime.UtcNow;
                serverLogRepo.SaveServerLog(log);
            }
        }
        public static void RunPetMerchantActions(int turnNumber)
        {
            IPlayerRepository playerRepo = new EFPlayerRepository();
            var petMerchant = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.WuffieBotId);


            if (petMerchant.Mobility == PvPStatics.MobilityFull)
            {
                if (petMerchant.Health < petMerchant.MaxHealth || petMerchant.Mana < petMerchant.MaxMana)
                {
                    var buffs = ItemProcedures.GetPlayerBuffs(petMerchant);
                    if (petMerchant.Health < petMerchant.MaxHealth)
                    {
                        petMerchant.Health += 200;
                        var logmessage = "<span class='playerCleansingNotification'>" + petMerchant.GetFullName() + " cleansed here.</span>";
                        LocationLogProcedures.AddLocationLog(petMerchant.dbLocationName, logmessage);
                    }
                    if (petMerchant.Mana < petMerchant.MaxMana)
                    {
                        petMerchant.Mana += 200;
                        var logmessage = "<span class='playerMediatingNotification'>" + petMerchant.GetFullName() + " meditated here.</span>";
                        LocationLogProcedures.AddLocationLog(petMerchant.dbLocationName, logmessage);
                    }

                    petMerchant.NormalizeHealthMana();
                }

                IAIDirectiveRepository aiRepo = new EFAIDirectiveRepository();

                var turnMod     = turnNumber % (24 * 4);
                var regionIndex = turnMod / 24;

                var newLocation = "";
                switch (regionIndex)
                {
                case 0:
                    newLocation = LocationsStatics.GetRandomLocation_InRegion("ranch_outside");
                    break;

                case 1:
                    newLocation = LocationsStatics.GetRandomLocation_InRegion("forest");
                    break;

                case 2:
                    newLocation = LocationsStatics.GetRandomLocation_InRegion("campground");
                    break;

                default:
                    newLocation = LocationsStatics.GetRandomLocation_InRegion("park");
                    break;
                }

                var actualNewLocation = AIProcedures.MoveTo(petMerchant, newLocation, 6);
                petMerchant.dbLocationName = actualNewLocation;
                playerRepo.SavePlayer(petMerchant);

                if (turnNumber % 11 == 5)
                {
                    DomainRegistry.Repository.Execute(new MoveAbandonedPetsToWuffie {
                        WuffieId = petMerchant.Id
                    });
                }
            }
        }
Пример #21
0
        public static void Run(int turnNumber, MinibossData data)
        {
            IPlayerRepository playerRepo = new EFPlayerRepository();
            var miniboss =
                playerRepo.Players.FirstOrDefault(p => p.BotId == data.BotId && p.Mobility == PvPStatics.MobilityFull);

            // spawn a new boss if last is null
            if (miniboss == null && rand.NextDouble() < ChanceToRespawn)
            {
                var spawnLocation = LocationsStatics.GetRandomLocation_InRegion(data.Region);

                var cmd = new CreatePlayer
                {
                    FirstName    = data.Title,
                    LastName     = NameService.GetRandomLastName(),
                    Location     = spawnLocation,
                    Gender       = PvPStatics.GenderFemale,
                    Health       = 100000,
                    Mana         = 100000,
                    MaxHealth    = 100000,
                    MaxMana      = 100000,
                    FormSourceId = data.FormSourceId,
                    Money        = 2000,
                    Mobility     = PvPStatics.MobilityFull,
                    Level        = GetLevel(turnNumber),
                    BotId        = data.BotId
                };
                var id = DomainRegistry.Repository.Execute(cmd);

                var minibossEF = playerRepo.Players.FirstOrDefault(p => p.Id == id);
                minibossEF.ReadjustMaxes(ItemProcedures.GetPlayerBuffs(minibossEF));
                playerRepo.SavePlayer(minibossEF);

                for (var i = 0; i < 2; i++)
                {
                    DomainRegistry.Repository.Execute(new GiveRune {
                        ItemSourceId = data.RuneIdToGive, PlayerId = minibossEF.Id
                    });
                }
            }

            if (miniboss != null && miniboss.Mobility == PvPStatics.MobilityFull)
            {
                // move to a randomn location in this region
                var nextLocation       = LocationsStatics.GetRandomLocation_InRegion(data.Region);
                var actualNextLocation = AIProcedures.MoveTo(miniboss, nextLocation, 11);
                miniboss.dbLocationName = actualNextLocation;
                miniboss.Mana           = miniboss.MaxMana;
                playerRepo.SavePlayer(miniboss);
                var playersHere = GetEligibleTargetsAtLocation(actualNextLocation);
                foreach (var target in playersHere)
                {
                    var(complete, _) = AttackProcedures.Attack(miniboss, target, ChooseSpell(miniboss, turnNumber, data.Spells));

                    if (complete)
                    {
                        AIProcedures.EquipDefeatedPlayer(miniboss, target);
                    }
                }
            }
        }
Пример #22
0
        public static void RunThievesAction(int turnNumber)
        {
            IPlayerRepository playerRepo = new EFPlayerRepository();
            var malethief   = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.MaleRatBotId);
            var femalethief = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.FemaleRatBotId);
            IAIDirectiveRepository aiRepo = new EFAIDirectiveRepository();
            var maleAI   = aiRepo.AIDirectives.FirstOrDefault(i => i.OwnerId == malethief.Id);
            var femaleAI = aiRepo.AIDirectives.FirstOrDefault(i => i.OwnerId == femalethief.Id);

            // both male and female are no longer animate, end boss event
            if (malethief.Mobility != PvPStatics.MobilityFull && femalethief.Mobility != PvPStatics.MobilityFull)
            {
                EndEvent();
            }

            #region both animate
            // both male and female are animate, have them go to players and loot them!
            if (malethief.Mobility == PvPStatics.MobilityFull && femalethief.Mobility == PvPStatics.MobilityFull)
            {
                // periodically refresh list of targets
                if (turnNumber % 12 == 0)
                {
                    maleAI.sVar1 = GetRichestPlayerIds();
                    maleAI.Var1  = 0;
                }

                if (malethief.Health < malethief.MaxHealth / 6)
                {
                    var malebuffs = ItemProcedures.GetPlayerBuffs(malethief);
                    DomainRegistry.Repository.Execute(new Cleanse {
                        PlayerId = malethief.Id, Buffs = malebuffs, NoValidate = true
                    });
                    malethief = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.MaleRatBotId);
                }

                if (femalethief.Health < femalethief.MaxHealth / 4)
                {
                    var femalebuffs = ItemProcedures.GetPlayerBuffs(femalethief);
                    DomainRegistry.Repository.Execute(new Cleanse {
                        PlayerId = femalethief.Id, Buffs = femalebuffs, NoValidate = true
                    });
                    femalethief = playerRepo.Players.FirstOrDefault(f => f.BotId == AIStatics.FemaleRatBotId);
                }


                var idArray = maleAI.sVar1.Split(';');
                idArray = idArray.Take(idArray.Length - 1).ToArray();

                if (maleAI.Var1 >= idArray.Length)
                {
                    maleAI.Var1 = 0;
                }

                var targetId = Convert.ToInt32(idArray[Convert.ToInt32(maleAI.Var1)]);

                var target = playerRepo.Players.FirstOrDefault(p => p.Id == targetId);

                while ((target == null || PlayerProcedures.PlayerIsOffline(target) || target.Mobility != PvPStatics.MobilityFull || target.Money < 20) && maleAI.Var1 < idArray.Length - 1)
                {
                    maleAI.Var1++;
                    targetId = Convert.ToInt32(idArray[Convert.ToInt32(maleAI.Var1)]);
                    target   = playerRepo.Players.FirstOrDefault(p => p.Id == targetId);
                }

                // we should hopefully by now have a valid target.  Hopefully.  Now move to them and loot away.
                try {
                    // Sometimes the rats will still teleport to a person in the dungeon if they move after being targetted.
                    // Check target location again.
                    var player = PlayerProcedures.GetPlayer(target.Id);

                    // This check should prevent that at the cost of the rats losing their turn, which seems alright to me.
                    if (!player.dbLocationName.Contains("dungeon_"))
                    {
                        malethief.dbLocationName   = target.dbLocationName;
                        femalethief.dbLocationName = target.dbLocationName;

                        // take money from victim and give some to the thieves with an uneven split.  Multiple the thieves' gain by 3
                        // because only about a third of Arpeyis are actually collected from a completed inanimation
                        target.Money       = Math.Floor(target.Money * .90M);
                        malethief.Money   += Math.Floor(target.Money * .025M);
                        femalethief.Money += Math.Floor(target.Money * .075M);

                        playerRepo.SavePlayer(target);
                        playerRepo.SavePlayer(malethief);
                        playerRepo.SavePlayer(femalethief);

                        AttackProcedures.Attack(femalethief, target, StunSpellSourceId);
                        AIProcedures.DealBossDamage(femalethief, target, false, 1);

                        var message         = malethief.GetFullName() + " and " + femalethief.GetFullName() + " the Seekshadow rat thieves suddenly appear in front of you!  In the blink of an eye they've swept you off your feet and have expertly swiped " + Math.Floor(target.Money * .10M) + " of your Arpeyjis.";
                        var locationMessage = "<b>" + malethief.GetFullName() + " and " + femalethief.GetFullName() + " robbed " + target.GetFullName() + " here.</b>";
                        PlayerLogProcedures.AddPlayerLog(target.Id, message, true);
                        LocationLogProcedures.AddLocationLog(malethief.dbLocationName, locationMessage);

                        maleAI.Var1++;

                        if (maleAI.Var1 >= 20)
                        {
                            maleAI.Var1 = 0;
                        }
                        aiRepo.SaveAIDirective(maleAI);
                    }
                    else
                    {
                        // If the target is in the dungeon, move it on to the next target.
                        maleAI.Var1++;

                        if (maleAI.Var1 >= 20)
                        {
                            maleAI.Var1 = 0;
                        }
                        aiRepo.SaveAIDirective(maleAI);
                    }
                }
                catch
                {
                    maleAI.Var1 = 0;
                }
            }
            #endregion

            #region veangance mode
            // one of the thieves has been taken down.  The other will try and steal their inanimate friend back!
            if (malethief.Mobility != PvPStatics.MobilityFull || femalethief.Mobility != PvPStatics.MobilityFull)
            {
                Player attackingThief;
                Player itemThief;

                if (malethief.Mobility == PvPStatics.MobilityFull && femalethief.Mobility != PvPStatics.MobilityFull)
                {
                    attackingThief = malethief;
                    itemThief      = femalethief;
                }
                else
                {
                    attackingThief = femalethief;
                    itemThief      = malethief;
                }

                var victimThiefItem = DomainRegistry.Repository.FindSingle(new GetItemByFormerPlayer {
                    PlayerId = itemThief.Id
                });

                // the transformed thief is owned by someone, try and get it back!
                if (victimThiefItem.Owner != null)
                {
                    var target = playerRepo.Players.FirstOrDefault(p => p.Id == victimThiefItem.Owner.Id);

                    if (target.BotId == AIStatics.MaleRatBotId || target.BotId == AIStatics.FemaleRatBotId)
                    {
                        // do nothing, the thief already has the item... equip it if not
                        if (!victimThiefItem.IsEquipped)
                        {
                            ItemProcedures.EquipItem(victimThiefItem.Id, true);
                        }
                        var newlocation = LocationsStatics.GetRandomLocation_NoStreets();
                        AIProcedures.MoveTo(attackingThief, newlocation, 100000);
                        attackingThief.dbLocationName = newlocation;
                        playerRepo.SavePlayer(attackingThief);
                        var buffs = ItemProcedures.GetPlayerBuffs(attackingThief);

                        if (attackingThief.Health < attackingThief.Health / 10)
                        {
                            DomainRegistry.Repository.Execute(new Cleanse {
                                PlayerId = attackingThief.Id, Buffs = buffs, NoValidate = true
                            });
                        }

                        DomainRegistry.Repository.Execute(new Meditate {
                            PlayerId = attackingThief.Id, Buffs = buffs, NoValidate = true
                        });
                    }

                    // Lindella, steal from her right away
                    else if (target.BotId == AIStatics.LindellaBotId)
                    {
                        ItemProcedures.GiveItemToPlayer(victimThiefItem.Id, attackingThief.Id);
                        LocationLogProcedures.AddLocationLog(target.dbLocationName, "<b>" + attackingThief.GetFullName() + " stole " + victimThiefItem.FormerPlayer.FullName + " the " + victimThiefItem.ItemSource.FriendlyName + " from Lindella.</b>");
                    }

                    // target is a human and they are not offline
                    else if (target != null && target.Mobility == PvPStatics.MobilityFull && !PlayerProcedures.PlayerIsOffline(target) && victimThiefItem.SoulboundToPlayer == null)
                    {
                        attackingThief.dbLocationName = target.dbLocationName;
                        playerRepo.SavePlayer(attackingThief);
                        AttackProcedures.Attack(attackingThief, target, PvPStatics.Spell_WeakenId);
                        AttackProcedures.Attack(attackingThief, target, PvPStatics.Spell_WeakenId);
                        AttackProcedures.Attack(attackingThief, target, GoldenTrophySpellSourceId);
                        AttackProcedures.Attack(attackingThief, target, GoldenTrophySpellSourceId);
                        AIProcedures.DealBossDamage(attackingThief, target, false, 4);
                        target = playerRepo.Players.FirstOrDefault(p => p.Id == victimThiefItem.Owner.Id && p.BotId != AIStatics.MaleRatBotId && p.BotId != AIStatics.FemaleRatBotId);

                        // if we have managed to turn the target, take back the victim-item
                        if (target.Mobility != PvPStatics.MobilityFull)
                        {
                            ItemProcedures.GiveItemToPlayer(victimThiefItem.Id, attackingThief.Id);
                            LocationLogProcedures.AddLocationLog(target.dbLocationName, "<b>" + attackingThief.GetFullName() + " recovered " + victimThiefItem.FormerPlayer.FullName + " the " + victimThiefItem.ItemSource.FriendlyName + ".</b>");
                        }
                    }

                    // target is a human and they are offline... just go and camp out there.
                    else if (target != null && PlayerProcedures.PlayerIsOffline(target))
                    {
                        attackingThief.dbLocationName = target.dbLocationName;
                        playerRepo.SavePlayer(attackingThief);
                    }
                }

                // item is on the ground, just go and pick it up.
                else
                {
                    attackingThief.dbLocationName = victimThiefItem.dbLocationName;
                    playerRepo.SavePlayer(attackingThief);
                    ItemProcedures.GiveItemToPlayer(victimThiefItem.Id, attackingThief.Id);
                    LocationLogProcedures.AddLocationLog(attackingThief.dbLocationName, "<b>" + attackingThief.GetFullName() + " recovered " + victimThiefItem.FormerPlayer.FullName + " the " + victimThiefItem.ItemSource.FriendlyName + ".</b>");
                }
            }
            #endregion
        }