public override void Execute(IDataContext context) { ContextQuery = ctx => { var player = ctx.AsQueryable <Player>() .Include(p => p.User) .Include(i => i.PlayerLogs) .SingleOrDefault(p => p.User.Id == UserId); if (player == null) { throw new DomainException($"Player with user ID '{UserId}' could not be found"); } if (player.Mobility != PvPStatics.MobilityFull) { throw new DomainException("You must be animate in order to shout!"); } if (player.ShoutsRemaining <= 0) { throw new DomainException("You can only shout once per turn."); } var hushed = ctx.AsQueryable <Effect>() .Where(e => e.EffectSource.Id == CharacterPrankProcedures.HUSHED_EFFECT && e.Owner.Id == player.Id && e.Duration > 0) .Any(); if (hushed) { throw new DomainException("You have been hushed and cannot currently shout."); } Message = Message.Replace("<", "<").Replace(">", ">"); // remove suspicious characters var log = LocationLog.Create(player.Location, $"<span class='playerShoutNotification'>{player.GetFullName()} shouted <b>\"{Message}\"</b> here.</span>"); player.Shout(Message); ctx.Update(player); ctx.Add(log); ctx.Commit(); }; ExecuteInternal(context); }
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); }
public override string Execute(IDataContext context) { var result = ""; ContextQuery = ctx => { var player = ctx.AsQueryable <Player>() .Include(p => p.PlayerLogs) .Include(p => p.User) .Include(p => p.User.Stats) .Include(p => p.Effects) .Include(p => p.VictimMindControls) .SingleOrDefault(cr => cr.Id == PlayerId); if (player == null) { throw new DomainException($"Player with ID '{PlayerId}' could not be found"); } if (!NoValidate) { if (player.ActionPoints < PvPStatics.MeditateCost) { throw new DomainException("You don't have enough action points to meditate!"); } if (player.Mobility != PvPStatics.MobilityFull) { throw new DomainException("You must be animate in order to meditate!"); } if (player.CleansesMeditatesThisRound >= PvPStatics.MaxCleansesMeditatesPerUpdate) { throw new DomainException("You have cleansed and meditated the maximum number of times this update."); } var mcs = player.VictimMindControls.Select(m => m.FormSourceId); if (mcs.Contains(MindControlStatics.MindControl__MeditateFormSourceId)) { throw new DomainException("You try to meditate but find you cannot! The moment you try and focus, your head swims with nonsensical thoughts implanted by someone partially mind controlling you!"); } } result = player.Meditate(Buffs); // log statistics only for human players if (player.BotId == AIStatics.ActivePlayerBotId) { player.User.AddStat(StatsProcedures.Stat__TimesMeditated, 1); } ctx.Update(player); // TODO: Perform this as part of the Meditate method on the Player entity once known how var locationLog = LocationLog.Create(player.Location, $"<span class='playerMediatingNotification'>{player.GetFullName()} meditated here.</span>"); ctx.Add(locationLog); ctx.Commit(); }; ExecuteInternal(context); return(result); }
public override string Execute(IDataContext context) { var result = ""; ContextQuery = ctx => { var player = ctx.AsQueryable <Player>() .Include(p => p.TFEnergies) .Include(p => p.PlayerLogs) .Include(p => p.User) .Include(p => p.User.Stats) .SingleOrDefault(cr => cr.Id == PlayerId); if (player == null) { throw new DomainException($"Player with ID '{PlayerId}' could not be found"); } if (!NoValidate) { if (player.ActionPoints < PvPStatics.CleanseCost) { throw new DomainException("You don't have enough action points to cleanse!"); } if (player.Mobility != PvPStatics.MobilityFull) { throw new DomainException("You must be animate in order to cleanse!"); } if (player.Mana < PvPStatics.CleanseManaCost) { throw new DomainException("You don't have enough mana to cleanse!"); } if (player.CleansesMeditatesThisRound >= PvPStatics.MaxCleansesMeditatesPerUpdate) { throw new DomainException("You have cleansed and meditated the maximum number of times this update."); } } result = player.Cleanse(Buffs); foreach (var energy in player.TFEnergies.ToList().Where(energy => energy.Amount <= 0)) { ctx.Remove(energy); } // log statistics only for human players if (player.BotId == AIStatics.ActivePlayerBotId) { player.User.AddStat(StatsProcedures.Stat__TimesCleansed, 1); } ctx.Update(player); // TODO: Perform this as part of the Cleanse method on the Player entity once known how var locationLog = LocationLog.Create(player.Location, $"<span class='playerCleansingNotification'>{player.GetFullName()} cleansed here.</span>"); ctx.Add(locationLog); ctx.Commit(); }; ExecuteInternal(context); return(result); }
public override string Execute(IDataContext context) { var result = ""; ContextQuery = ctx => { var player = ctx.AsQueryable <Player>() .Include(p => p.Items) .Include(p => p.Item) .Include(p => p.User) .Include(p => p.User.Stats) .Include(p => p.VictimMindControls) .SingleOrDefault(cr => cr.Id == PlayerId); if (player == null) { throw new DomainException($"Player with ID '{PlayerId}' could not be found"); } if (String.IsNullOrWhiteSpace(destination)) { throw new DomainException("Destination must be specified"); } if (LocationsStatics.LocationList.GetLocation.FirstOrDefault(l => l.dbName == destination) == null) { throw new DomainException($"Location with dbName '{destination}' could not be found"); } if (player.Mobility == PvPStatics.MobilityFull && player.MoveActionPointDiscount < -TurnTimesStatics.GetActionPointReserveLimit()) { throw new DomainException("You can't move since you have been immobilized!"); } if (player.Mobility == PvPStatics.MobilityFull && player.ActionPoints < Math.Max(0, PvPStatics.LocationMoveCost - player.MoveActionPointDiscount)) { throw new DomainException("You don't have enough action points to move."); } if (player.Mobility == PvPStatics.MobilityInanimate) { throw new DomainException("You can't move because you are currently inanimate!"); } var lastAttackTimeAgo = Math.Abs(Math.Floor(player.LastCombatTimestamp.Subtract(DateTime.UtcNow).TotalSeconds)); if (lastAttackTimeAgo < TurnTimesStatics.GetNoMovingAfterAttackSeconds()) { throw new DomainException($"You are resting from a recent attack. You must wait {Math.Ceiling(TurnTimesStatics.GetNoMovingAfterAttackSeconds() - lastAttackTimeAgo)} more seconds before moving."); } if (player.Mobility == PvPStatics.MobilityPet && player.Item != null) { if (player.Item.Owner != null) { throw new DomainException($"You can't move because you are a non-feral pet owned by {player.Item.Owner.GetFullName()}."); } } if (player.Mobility == PvPStatics.MobilityFull && player.IsCarryingTooMuchToMove()) { var excessItemCount = player.GetCarriedItemCount() - player.GetMaxInventorySize(); var pluralize = excessItemCount == 1 ? "item" : "items"; throw new DomainException($"You are carrying too much to move. You need to drop at least {excessItemCount} {pluralize}."); } if (player.InDuel > 0) { throw new DomainException("You must finish your duel before you can move again."); } if (player.InQuest > 0) { throw new DomainException("You must end your quest before you can move again."); } // TODO: This might not work yet because it's considering mind controls this player has on others and not themself //if (player.CantMoveBecauseOfForcedMarch()) // throw new DomainException("You try to move but discover you cannot! Some other mage has partial control of your mind, disabling your ability to move on your own!"); // assert this location does have a connection to the next one var currentLocation = LocationsStatics.LocationList.GetLocation.First(l => l.dbName == player.Location); var nextLocation = LocationsStatics.LocationList.GetLocation.First(l => l.dbName == destination); if (currentLocation.Name_North != destination && currentLocation.Name_East != destination && currentLocation.Name_South != destination && currentLocation.Name_West != destination) { throw new DomainException($"You cannot move directly from {currentLocation.Name} to {nextLocation.Name}."); } MoveLogBox logs; if (player.Mobility == PvPStatics.MobilityPet) { logs = player.MoveToAsAnimal(destination); } else { logs = player.MoveTo(destination, Direction); } var oldLocationLog = LocationLog.Create(currentLocation.dbName, logs.SourceLocationLog, logs.ConcealmentLevel); var newLocationLog = LocationLog.Create(nextLocation.dbName, logs.DestinationLocationLog, logs.ConcealmentLevel); result = logs.PlayerLog; ctx.Add(oldLocationLog); ctx.Add(newLocationLog); ctx.Update(player); ctx.Commit(); }; ExecuteInternal(context); return(result); }
public override string Execute(IDataContext context) { var result = ""; ContextQuery = ctx => { var player = ctx.AsQueryable <Player>() .Include(p => p.Items) .Include(p => p.Item.ItemSource) .Include(p => p.User) .Include(p => p.User.Stats) .FirstOrDefault(p => p.Id == PlayerId); if (player == null) { throw new DomainException($"player with ID {PlayerId} could not be found."); } var item = player.Items.FirstOrDefault(i => i.Id == ItemId); if (item == null) { throw new DomainException($"Item with ID {ItemId} could not be found or does not belong to you."); } var cutoff = DateTime.UtcNow.AddMinutes(-TurnTimesStatics.GetOfflineAfterXMinutes()); var affectedPlayers = ctx.AsQueryable <Player>() .Where(p => p.Location == player.Location && p.Id != PlayerId && p.GameMode != (int)GameModeStatics.GameModes.Superprotection && p.InDuel <= 0 && p.InQuest <= 0 && p.FormSource.AltSexFormSource != null && p.LastActionTimestamp > cutoff ).Include(p => p.FormSource) .Include(p => p.FormSource.AltSexFormSource) .ToList(); foreach (var p in affectedPlayers) { p.ChangeForm(p.FormSource.AltSexFormSource); p.AddLog($"You yelp and feel your body change to that of the opposite sex from <b>{player.GetFullName()}</b>'s use of a TG Splash Orb in your location!", true); } player.SetOnlineActivityToNow(); player.UpdateItemUseCounter(1); if (affectedPlayers.Any()) { var xpGained = affectedPlayers.Where(p => p.Level >= player.Level - 2).Sum(p => p.Level < 3 ? 3 : p.Level); player.AddXP(xpGained); // can't do this as a LINQ select due to calling the a.GetFullName() method var playerNames = new List <string>(); foreach (var a in affectedPlayers) { playerNames.Add(a.GetFullName()); } result = $"You throw your TG Splash Orb and swap the sex of {affectedPlayers.Count()} other mages near you: {ListifyHelper.Listify(playerNames, true)} and gain <b>{xpGained}</b> XP!"; player.AddLog(result, false); // log statistics only for human players if (player.BotId == AIStatics.ActivePlayerBotId) { player.User.AddStat(StatsProcedures.Stat__TgOrbVictims, affectedPlayers.Count()); } } else { result = "You throw your TG Splash Orb, but unfortunately nobody is affected in this location."; } var locationLog = LocationLog.Create(player.Location, $"{player.GetFullName()} threw a TG splash orb, affecting {affectedPlayers.Count()} mages."); ctx.Add(locationLog); ctx.Update(player); ctx.Remove(item); ctx.Commit(); }; ExecuteInternal(context); return(result); // TODO: use event handler }