/// <summary> /// Executes the messaging, sending messages using WriteTo on all relevant entities /// </summary> /// <param name="Actor">The acting entity</param> /// <param name="Subject">The command's subject entity</param> /// <param name="Target">The command's target entity</param> /// <param name="OriginLocation">The location the acting entity acted in</param> /// <param name="DestinationLocation">The location the command is targetting</param> public void ExecuteMessaging(IEntity Actor, IEntity Subject, IEntity Target, IEntity OriginLocation, IEntity DestinationLocation) { Dictionary <MessagingTargetType, IEntity[]> entities = new Dictionary <MessagingTargetType, IEntity[]> { { MessagingTargetType.Actor, new IEntity[] { Actor } }, { MessagingTargetType.Subject, new IEntity[] { Subject } }, { MessagingTargetType.Target, new IEntity[] { Target } }, { MessagingTargetType.OriginLocation, new IEntity[] { OriginLocation } }, { MessagingTargetType.DestinationLocation, new IEntity[] { DestinationLocation } } }; if (Actor != null && ToActor.Any()) { if (ToActor.Select(msg => msg.Override).Any(str => !string.IsNullOrEmpty(str))) { Actor.WriteTo(TranslateOutput(ToActor.Select(msg => msg.Override), entities)); } else { Actor.WriteTo(TranslateOutput(ToActor.Select(msg => msg.Describe()), entities)); } } if (Subject != null && ToSubject.Any()) { if (ToSubject.Select(msg => msg.Override).Any(str => !string.IsNullOrEmpty(str))) { Subject.WriteTo(TranslateOutput(ToSubject.Select(msg => msg.Override), entities)); } else { Subject.WriteTo(TranslateOutput(ToSubject.Select(msg => msg.Describe()), entities)); } } if (Target != null && ToTarget.Any()) { ILanguage language = Target.IsPlayer() ? ((IPlayer)Target).Template <IPlayerTemplate>().Account.Config.UILanguage : null; if (ToTarget.Select(msg => msg.Override).Any(str => !string.IsNullOrEmpty(str))) { Target.WriteTo(TranslateOutput(ToTarget.Select(msg => msg.Override), entities)); } else { Target.WriteTo(TranslateOutput(ToTarget.Select(msg => msg.Describe()), entities)); } } //TODO: origin and destination are areas of effect on their surrounding areas if (OriginLocation != null && ToOrigin.Any()) { IContains oLoc = (IContains)OriginLocation; IEnumerable <IEntity> validContents = oLoc.GetContents <IEntity>().Where(dud => !dud.Equals(Actor) && !dud.Equals(Subject) && !dud.Equals(Target)); //Message dudes in the location, including non-person entities since they might have triggers foreach (IEntity dude in validContents) { if (ToOrigin.Select(msg => msg.Override).Any(str => !string.IsNullOrEmpty(str))) { dude.WriteTo(TranslateOutput(ToOrigin.Select(msg => msg.Override), entities)); } else { dude.WriteTo(TranslateOutput(ToOrigin.Select(msg => msg.Describe()), entities)); } } } if (DestinationLocation != null && ToDestination.Any()) { IContains oLoc = (IContains)DestinationLocation; //Message dudes in the location, including non-person entities since they might have triggers foreach (IEntity dude in oLoc.GetContents <IEntity>().Where(dud => !dud.Equals(Actor) && !dud.Equals(Subject) && !dud.Equals(Target))) { if (ToDestination.Select(msg => msg.Override).Any(str => !string.IsNullOrEmpty(str))) { dude.WriteTo(TranslateOutput(ToDestination.Select(msg => msg.Override), entities)); } else { dude.WriteTo(TranslateOutput(ToDestination.Select(msg => msg.Describe()), entities)); } } } }
/// <summary> /// Wraps sending messages to the connected descriptor /// </summary> /// <param name="strings">the output</param> /// <returns>success status</returns> public bool SendOutput(IEnumerable <string> strings) { //TODO: Stop hardcoding this but we have literally no sense of injury/self status yet SelfStatus self = new SelfStatus { Body = new BodyStatus { Health = _currentPlayer.CurrentHealth == 0 ? 100 : 100 / (2M * _currentPlayer.CurrentHealth), Stamina = _currentPlayer.CurrentStamina, Overall = OverallStatus.Excellent, Anatomy = new AnatomicalPart[] { new AnatomicalPart { Name = "Arm", Overall = OverallStatus.Good, Wounds = new string[] { "Light scrape" } }, new AnatomicalPart { Name = "Leg", Overall = OverallStatus.Excellent, Wounds = new string[] { } } } }, CurrentActivity = _currentPlayer.CurrentAction, Balance = _currentPlayer.Balance.ToString(), CurrentArt = _currentPlayer.LastAttack?.Name ?? "", CurrentCombo = _currentPlayer.LastCombo?.Name ?? "", CurrentTarget = _currentPlayer.GetTarget() == null ? "" : _currentPlayer.GetTarget() == _currentPlayer ? "Your shadow" : _currentPlayer.GetTarget().GetDescribableName(_currentPlayer), CurrentTargetHealth = _currentPlayer.GetTarget() == null || _currentPlayer.GetTarget() == _currentPlayer ? double.PositiveInfinity : _currentPlayer.GetTarget().CurrentHealth == 0 ? 100 : 100 / (2 * _currentPlayer.CurrentHealth), Position = _currentPlayer.StancePosition.ToString(), Stance = _currentPlayer.Stance, Stagger = _currentPlayer.Stagger.ToString(), Qualities = string.Join("", _currentPlayer.Qualities.Where(quality => quality.Visible).Select(quality => string.Format("<div class='qualityRow'><span>{0}</span><span>{1}</span></div>", quality.Name, quality.Value))), CurrentTargetQualities = _currentPlayer.GetTarget() == null || _currentPlayer.GetTarget() == _currentPlayer ? "" : string.Join("", _currentPlayer.GetTarget().Qualities.Where(quality => quality.Visible).Select(quality => string.Format("<div class='qualityRow'><span>{0}</span><span>{1}</span></div>", quality.Name, quality.Value))), Mind = new MindStatus { Overall = OverallStatus.Excellent, States = new string[] { "Fearful" } } }; IGlobalPosition currentLocation = _currentPlayer.CurrentLocation; IContains currentContainer = currentLocation.CurrentLocation(); IZone currentZone = currentContainer.CurrentLocation.CurrentZone; ILocale currentLocale = currentLocation.CurrentLocale; IRoom currentRoom = currentLocation.CurrentRoom; IGaia currentWorld = currentZone.GetWorld(); IEnumerable <string> pathways = Enumerable.Empty <string>(); IEnumerable <string> inventory = Enumerable.Empty <string>(); IEnumerable <string> populace = Enumerable.Empty <string>(); string locationDescription = string.Empty; LexicalContext lexicalContext = new LexicalContext(_currentPlayer) { Language = _currentPlayer.Template <IPlayerTemplate>().Account.Config.UILanguage, Perspective = NarrativePerspective.SecondPerson, Position = LexicalPosition.Near }; Message toCluster = new Message(currentContainer.RenderToVisible(_currentPlayer)); if (currentContainer != null) { pathways = ((ILocation)currentContainer).GetPathways().Select(data => data.GetDescribableName(_currentPlayer)); inventory = currentContainer.GetContents <IInanimate>().Select(data => data.GetDescribableName(_currentPlayer)); populace = currentContainer.GetContents <IMobile>().Where(player => !player.Equals(_currentPlayer)).Select(data => data.GetDescribableName(_currentPlayer)); locationDescription = toCluster.Unpack(TargetEntity.Actor, lexicalContext); } LocalStatus local = new LocalStatus { ZoneName = currentZone?.TemplateName, LocaleName = currentLocale?.TemplateName, RoomName = currentRoom?.TemplateName, Inventory = inventory.ToArray(), Populace = populace.ToArray(), Exits = pathways.ToArray(), LocationDescriptive = locationDescription }; //The next two are mostly hard coded, TODO, also fix how we get the map as that's an admin thing ExtendedStatus extended = new ExtendedStatus { Horizon = new string[] { "A hillside", "A dense forest" }, VisibleMap = currentLocation.CurrentRoom == null ? string.Empty : currentLocation.CurrentRoom.RenderCenteredMap(3, true) }; string timeOfDayString = string.Format("The hour of {0} in the day of {1} in {2} in the year of {3}", currentWorld.CurrentTimeOfDay.Hour , currentWorld.CurrentTimeOfDay.Day , currentWorld.CurrentTimeOfDay.MonthName() , currentWorld.CurrentTimeOfDay.Year); string sun = "0"; string moon = "0"; string visibilityString = "5"; Tuple <string, string, string[]> weatherTuple = new Tuple <string, string, string[]>("", "", new string[] { }); if (currentZone != null) { Tuple <PrecipitationAmount, PrecipitationType, HashSet <WeatherType> > forecast = currentZone.CurrentForecast(); weatherTuple = new Tuple <string, string, string[]>(forecast.Item1.ToString(), forecast.Item2.ToString(), forecast.Item3.Select(wt => wt.ToString()).ToArray()); visibilityString = currentZone.GetCurrentLuminosity().ToString(); if (currentWorld != null) { IEnumerable <ICelestial> bodies = currentZone.GetVisibileCelestials(_currentPlayer); ICelestial theSun = bodies.FirstOrDefault(cest => cest.Name.Equals("sun", StringComparison.InvariantCultureIgnoreCase)); ICelestial theMoon = bodies.FirstOrDefault(cest => cest.Name.Equals("moon", StringComparison.InvariantCultureIgnoreCase)); if (theSun != null) { ICelestialPosition celestialPosition = currentWorld.CelestialPositions.FirstOrDefault(celest => celest.CelestialObject == theSun); sun = AstronomicalUtilities.GetCelestialLuminosityModifier(celestialPosition.CelestialObject, celestialPosition.Position, currentWorld.PlanetaryRotation , currentWorld.OrbitalPosition, currentZone.Template <IZoneTemplate>().Hemisphere, currentWorld.Template <IGaiaTemplate>().RotationalAngle).ToString(); } if (theMoon != null) { ICelestialPosition celestialPosition = currentWorld.CelestialPositions.FirstOrDefault(celest => celest.CelestialObject == theMoon); moon = AstronomicalUtilities.GetCelestialLuminosityModifier(celestialPosition.CelestialObject, celestialPosition.Position, currentWorld.PlanetaryRotation , currentWorld.OrbitalPosition, currentZone.Template <IZoneTemplate>().Hemisphere, currentWorld.Template <IGaiaTemplate>().RotationalAngle).ToString(); } } } EnvironmentStatus environment = new EnvironmentStatus { Sun = sun, Moon = moon, Visibility = visibilityString, Weather = weatherTuple, Temperature = currentZone.EffectiveTemperature().ToString(), Humidity = currentZone.EffectiveHumidity().ToString(), TimeOfDay = timeOfDayString }; OutputStatus outputFormat = new OutputStatus { Occurrence = EncapsulateOutput(strings), Self = self, Local = local, Extended = extended, Environment = environment }; Send(Utility.SerializationUtility.Serialize(outputFormat)); return(true); }