Esempio n. 1
0
        /// <summary>
        /// Process a sensory message.
        /// </summary>
        /// <param name="message">The sensory message to be processed.</param>
        /// <returns>The rendered view of this sensory message.</returns>
        private string ProcessMessage(SensoryMessage message)
        {
            if (this.sensesBehavior.Senses.CanProcessSensoryMessage(message))
            {
                // Build the contexts from those added to the sensory message builder
                // and those added to the sensory message.
                Hashtable context = message.Context;

                if (message.Message != null)
                {
                    foreach (DictionaryEntry entry in message.Message.ViewEngineContext)
                    {
                        context.Add(entry.Key, entry.Value);
                    }

                    if (this.userControlledBehavior != null)
                    {
                        string parsedMessage = message.Message.Parse(this.userControlledBehavior.Parent);
                        string output        = this.userControlledBehavior.ViewEngine.RenderView(parsedMessage, context);
                        return(output);
                    }
                }
            }

            return(string.Empty);
        }
Esempio n. 2
0
        // TODO: OpensClosesBehavior needs to listen for movement events and set e.Cancel if the transition object
        //       is closed at the time.

        /// <summary>Move the entity to the specified destination.</summary>
        /// <param name="destination">
        /// TODO: The destination to move the entity to; if the destination has an ExitBehavior then this Thing is
        ///       automatically moved to the other destination of the exit (IE an adjacent room, portal destination,
        ///       or inside/outside of a vehicle, et cetera).
        /// </param>
        /// <param name="goingVia">The thing we are travelling via (IE an Exit, an Enterable thing, etc.)</param>
        /// <param name="leavingMessage">A sensory message describing this sort of 'leaving' movement.</param>
        /// <param name="arrivingMessage">A sensory message describing this sort of 'arriving' movement.</param>
        /// <returns>True if the entity was successfully moved, else false.</returns>
        public bool Move(Thing destination, Thing goingVia, SensoryMessage leavingMessage, SensoryMessage arrivingMessage)
        {
            Thing actor     = Parent;
            Thing goingFrom = actor.Parent;

            // Prepare events to request and send (if not cancelled).
            var leaveEvent  = new LeaveEvent(actor, goingFrom, destination, goingVia, leavingMessage);
            var arriveEvent = new ArriveEvent(actor, goingFrom, destination, goingVia, arrivingMessage);

            // Broadcast the Leave Request first to see if the player is allowed to leave.
            actor.Eventing.OnMovementRequest(leaveEvent, EventScope.ParentsDown);
            if (!leaveEvent.IsCancelled)
            {
                // Next see if the player is allowed to Arrive at the new location.
                destination.Eventing.OnMovementRequest(arriveEvent, EventScope.SelfDown);
                if (!arriveEvent.IsCancelled)
                {
                    actor.Eventing.OnMovementEvent(leaveEvent, EventScope.ParentsDown);
                    actor.RemoveFromParents();
                    destination.Add(actor);

                    // TODO: Ensure these automatically enqueue a save.
                    destination.Eventing.OnMovementEvent(arriveEvent, EventScope.SelfDown);
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 3
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            IController sender = actionInput.Controller;

            // Strings to be displayed when the effect is applied/removed.
            var muteString = new ContextualString(sender.Thing, this.playerToMute)
            {
                ToOriginator = "You mute $Target.",
                ToReceiver = "You are muted by $ActiveThing.",
                ToOthers = "$ActiveThing mutes $Target."
            };
            var unmuteString = new ContextualString(sender.Thing, this.playerToMute)
            {
                ToOriginator = "$Target is no longer mute.",
                ToReceiver = "You are no longer mute."
            };

            // Turn the above sets of strings into sensory messages.
            var muteMessage = new SensoryMessage(SensoryType.Sight, 100, muteString);
            var unmuteMessage = new SensoryMessage(SensoryType.Sight, 100, unmuteString);

            // Create the effect.
            var muteEffect = new MutedEffect(sender.Thing, this.muteDuration, muteMessage, unmuteMessage);

            // Apply the effect.
            this.playerToMute.Behaviors.Add(muteEffect);
        }
Esempio n. 4
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            IController sender = actionInput.Controller;

            this.itemToWieldBehavior.Wielder = sender.Thing;

            // Create an event handler that intercepts the ChangeOwnerEvent and
            // prevents dropping/trading the item around while it is wielded.
            // A reference is stored in the WieldableBehavior instance so it
            // can be easily removed by the unwield command.
            var interceptor = new CancellableGameEventHandler(this.Eventing_MovementRequest);
            this.itemToWieldBehavior.MovementInterceptor = interceptor;
            this.itemToWield.Eventing.MovementRequest += interceptor;

            var contextMessage = new ContextualString(sender.Thing, this.itemToWield.Parent)
            {
                ToOriginator = "You wield the $WieldedItem.Name.",
                ToOthers = "$ActiveThing.Name wields a $WieldedItem.Name.",
            };

            var sensoryMessage = new SensoryMessage(SensoryType.Sight, 100, contextMessage);

            var wieldEvent = new WieldUnwieldEvent(this.itemToWield, true, sender.Thing, sensoryMessage);

            sender.Thing.Eventing.OnCombatRequest(wieldEvent, EventScope.ParentsDown);

            if (!wieldEvent.IsCancelled)
            {
                sender.Thing.Eventing.OnCombatEvent(wieldEvent, EventScope.ParentsDown);
            }
        }
Esempio n. 5
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            // Generate an item changed owner event.
            IController sender = actionInput.Controller;
            ContextualStringBuilder csb = new ContextualStringBuilder(sender.Thing, this.parent);
            csb.Append(@"$ActiveThing.Name drops $Thing.Name.", ContextualStringUsage.WhenNotBeingPassedToOriginator);
            csb.Append(@"You drop $Thing.Name.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            SensoryMessage message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var changeOwnerEvent = new ChangeOwnerEvent(sender.Thing, message, sender.Thing, this.parent, this.thing);

            // Broadcast as a request and see if anything wants to prevent the event.
            this.parent.Eventing.OnMovementRequest(changeOwnerEvent, EventScope.ParentsDown);
            if (!changeOwnerEvent.IsCancelled)
            {
                // Always have to remove an item before adding it because of the event observer system.
                // @@@ TODO: Test, this may be broken now...
                this.thing.Parent.Remove(this.thing);
                this.parent.Add(this.thing);

                //// @@@ BUG: Saving currently throws a NotImplementedException. Disabled for now...
                this.thing.Save();
                this.parent.Save();

                // Broadcast the event.
                this.parent.Eventing.OnMovementEvent(changeOwnerEvent, EventScope.ParentsDown);
            }
        }
Esempio n. 6
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            IController sender = actionInput.Controller;

            this.itemToUnwieldBehavior.Wielder = null;

            // Remove the event handler that prevents dropping the item while wielded.
            var interceptor = this.itemToUnwieldBehavior.MovementInterceptor;
            this.itemToUnwield.Eventing.MovementRequest -= interceptor;

            var contextMessage = new ContextualString(sender.Thing, this.itemToUnwield.Parent)
            {
                ToOriginator = "You unwield the $WieldedItem.Name.",
                ToOthers = "$ActiveThing.Name unwields a $WieldedItem.Name.",
            };

            var sensoryMessage = new SensoryMessage(SensoryType.Sight, 100, contextMessage);

            var unwieldEvent = new WieldUnwieldEvent(this.itemToUnwield, true, sender.Thing, sensoryMessage);

            sender.Thing.Eventing.OnCombatRequest(unwieldEvent, EventScope.ParentsDown);

            if (!unwieldEvent.IsCancelled)
            {
                sender.Thing.Eventing.OnCombatEvent(unwieldEvent, EventScope.ParentsDown);
            }
        }
Esempio n. 7
0
        // @@@ OpensClosesBehavior needs to listen for movement events and set e.Cancel if the transition object
        //     is closed at the time.
        /// <summary>
        /// Move the entity to the specified room.
        /// </summary>
        /// <param name="destination">
        /// @@@ TODO: The destination to move the entity to; if the destination has an ExitBehavior then this Thing is
        /// automatically moved to the other destination of the exit (IE an adjacent room, portal destination,
        /// or inside/outside of a vehicle, et cetera).
        /// </param>
        /// <param name="goingVia">The thing we are travelling via (IE an Exit, an Enterable thing, etc.)</param>
        /// <param name="leavingMessage">A sensory message describing this sort of 'leaving' movement.</param>
        /// <param name="arrivingMessage">A sensory message describing this sort of 'arriving' movement.</param>
        /// <returns>True if the entity was successfully moved, else false.</returns>
        public bool Move(Thing destination, Thing goingVia, SensoryMessage leavingMessage, SensoryMessage arrivingMessage)
        {
            Thing actor = this.Parent;
            Thing goingFrom = actor.Parent;

            // Prepare events to request and send (if not cancelled).
            var leaveEvent = new LeaveEvent(actor, goingFrom, destination, goingVia, leavingMessage);
            var arriveEvent = new ArriveEvent(actor, goingFrom, destination, goingVia, arrivingMessage);

            // Broadcast the Leave Request first to see if the player is allowed to leave.
            actor.Eventing.OnMovementRequest(leaveEvent, EventScope.ParentsDown);
            if (!leaveEvent.IsCancelled)
            {
                // Next see if the player is allowed to Arrive at the new location.
                destination.Eventing.OnMovementRequest(arriveEvent, EventScope.SelfDown);
                if (!arriveEvent.IsCancelled)
                {
                    actor.Eventing.OnMovementEvent(leaveEvent, EventScope.ParentsDown);
                    actor.RemoveFromParents();
                    destination.Add(actor);

                    // @@@ TODO: Ensure these automatically enqueue a save.
                    destination.Eventing.OnMovementEvent(arriveEvent, EventScope.SelfDown);
                    return true;
                }
            }

            return false;
        }
Esempio n. 8
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            IController sender = actionInput.Controller;
            var contextMessage = new ContextualString(sender.Thing, this.target)
            {
                ToOriginator = "You cast ThunderClap at $ActiveThing.Name!",
                ToReceiver = "$Aggressor.Name casts ThunderClap at you, you only hear a ringing in your ears now.",
                ToOthers = "You hear $Aggressor.Name cast ThunderClap at $ActiveThing.Name!  It was very loud.",
            };
            var sm = new SensoryMessage(SensoryType.Hearing, 100, contextMessage);

            var attackEvent = new AttackEvent(this.target, sm, sender.Thing);
            sender.Thing.Eventing.OnCombatRequest(attackEvent, EventScope.ParentsDown);
            if (!attackEvent.IsCancelled)
            {
                var deafenEffect = new AlterSenseEffect()
                {
                    SensoryType = SensoryType.Hearing,
                    AlterAmount = -1000,
                    Duration = new TimeSpan(0, 0, 45),
                };

                this.target.Behaviors.Add(deafenEffect);
                sender.Thing.Eventing.OnCombatEvent(attackEvent, EventScope.ParentsDown);
            }
        }
Esempio n. 9
0
        /// <summary>Process a sensory message.</summary>
        /// <param name="message">The sensory message to be processed.</param>
        /// <returns>The rendered view of this sensory message.</returns>
        private string ProcessMessage(SensoryMessage message)
        {
            if (sensesBehavior.Senses.CanProcessSensoryMessage(message) && message.Message != null && userControlledBehavior != null)
            {
                return(message.Message.Parse(userControlledBehavior.Parent));
            }

            return(string.Empty);
        }
Esempio n. 10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MutedEffect" /> class.
 /// </summary>
 /// <param name="activeThing">The active thing.</param>
 /// <param name="duration">The duration.</param>
 /// <param name="sensoryMessage">The sensory message.</param>
 /// <param name="expirationMessage">The expiration message.</param>
 public MutedEffect(Thing activeThing, TimeSpan duration, SensoryMessage sensoryMessage, SensoryMessage expirationMessage)
     : base(duration)
 {
     this.Name = "Mute";
     this.ActiveThing = activeThing;
     this.SensoryMessage = sensoryMessage;
     this.ExpirationMessage = expirationMessage;
     this.Duration = duration;
 }
Esempio n. 11
0
        /// <summary>Tries to move a Thing from its current location into the specified location, if that thing is movable.</summary>
        /// <param name="thing">The Thing to move.</param>
        /// <param name="destinationThing">The new container to house the Thing.</param>
        /// <param name="goingVia">The going via.</param>
        /// <param name="leavingMessage">The leaving message.</param>
        /// <param name="arrivingMessage">The arriving message.</param>
        public void MoveThing(Thing thing, Thing destinationThing, Thing goingVia, SensoryMessage leavingMessage, SensoryMessage arrivingMessage)
        {
            MovableBehavior movableBehavior = thing.Behaviors.FindFirst <MovableBehavior>();

            if (movableBehavior != null)
            {
                movableBehavior.Move(destinationThing, goingVia, leavingMessage, arrivingMessage);
            }
        }
Esempio n. 12
0
        /// <summary>Try to log this player into the game.</summary>
        /// <param name="session">The session.</param>
        /// <returns>True if the player successfully logged in.</returns>
        public bool LogIn(Session session)
        {
            var player = Parent;

            // If the player isn't located anywhere yet, try to drop them in the default room.
            // (Expect that even new characters may gain a starting position via custom character generation
            // flows which let the user to select a starting spawn area.)
            var targetPlayerStartingPosition = player.Parent != null ? player.Parent : FindDefaultRoom();

            if (targetPlayerStartingPosition == null)
            {
                session.WriteLine("Could not place character in the game world. Please contact an administrator.");
                return(false);
            }

            // Prepare a login request and event.
            var csb = new ContextualStringBuilder(player, targetPlayerStartingPosition);

            csb.Append($"{session.Thing.Name} enters the world.", ContextualStringUsage.WhenNotBeingPassedToOriginator);
            csb.Append($"You enter the world.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e       = new PlayerLogInEvent(player, message);

            // Broadcast the login request to the player's current location (IE their parent room), if applicable.
            player.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);

            // Also broadcast the request to any registered global listeners.
            PlayerManager.Instance.OnPlayerLogInRequest(player, e);

            // If nothing canceled this event request, carry on with the login.
            if (!e.IsCancelled)
            {
                targetPlayerStartingPosition.Add(player);

                DateTime universalTime = DateTime.Now.ToUniversalTime();
                PlayerData.LastLogin     = universalTime.ToString("s", DateTimeFormatInfo.InvariantInfo) + "Z";
                PlayerData.LastIPAddress = session.Connection.CurrentIPAddress.ToString();

                session.Thing = player;
                session.User.LastLogInTime = DateTime.Now; // Should this occur when user was authenticated instead?

                // Broadcast that the player successfully logged in, to their login location.
                player.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);

                // TODO: Fix: Sending this before the player has registered as being in the PlayingState causes some problems,
                //       including the last character creation or password prompt from printing again as the user's prompt.
                //       Need to figure out if this can be straightened out in a clean way.
                //       See: https://github.com/DavidRieman/WheelMUD/issues/86#issuecomment-787057858
                PlayerManager.Instance.OnPlayerLogIn(player, e);

                return(true);
            }

            return(false);
        }
Esempio n. 13
0
        /// <summary>Moves the Thing through.</summary>
        /// <param name="thingToMove">The thing to move.</param>
        /// <returns>Returns true if the move was successful, false if not.</returns>
        public bool MoveThrough(Thing thingToMove)
        {
            // If the thing isn't currently mobile, bail.
            var movableBehavior = thingToMove.Behaviors.FindFirst <MovableBehavior>();

            if (movableBehavior == null)
            {
                // TODO: Add messaging to thingToMove?
                return(false);
            }

            // Find the target location to be reached from here.
            DestinationInfo destinationInfo = GetDestinationFrom(thingToMove.Parent.Id);

            if (destinationInfo == null)
            {
                // There was no destination reachable from the thing's starting location.
                return(false);
            }

            // If the target location hasn't been cached already, try to do so now.
            if (destinationInfo.CachedTarget == null || destinationInfo.CachedTarget.Target == null)
            {
                Thing newTarget = ThingManager.Instance.FindThing(destinationInfo.TargetID);
                destinationInfo.CachedTarget = new SimpleWeakReference <Thing>(newTarget);
            }

            // If the destination can't be found, abort.
            Thing destination = destinationInfo.CachedTarget.Target;

            if (destination == null)
            {
                // TODO: Add messaging to thingToMove?
                return(false);
            }

            string dir = destinationInfo.ExitCommand;
            var    leaveContextMessage = new ContextualString(thingToMove, thingToMove.Parent)
            {
                ToOriginator = null,
                ToReceiver   = $"{thingToMove.Name} moves {dir}.",
                ToOthers     = $"{thingToMove.Name} moves {dir}.",
            };
            var arriveContextMessage = new ContextualString(thingToMove, destination)
            {
                ToOriginator = $"You move {dir} to {destination.Name}.",
                ToReceiver   = $"{thingToMove.Name} arrives, heading {dir}.",
                ToOthers     = $"{thingToMove.Name} arrives, heading {dir}.",
            };
            var leaveMessage  = new SensoryMessage(SensoryType.Sight, 100, leaveContextMessage);
            var arriveMessage = new SensoryMessage(SensoryType.Sight, 100, arriveContextMessage);

            return(movableBehavior.Move(destination, Parent, leaveMessage, arriveMessage));
        }
Esempio n. 14
0
        /// <summary>Determine if the specified sensory message can be processed.</summary>
        /// <param name="message">The sensory message.</param>
        /// <returns>True if it can be processed, else false.</returns>
        public bool CanProcessSensoryMessage(SensoryMessage message)
        {
            if (this.SenseDictionary.ContainsKey(message.TargetedSense) &&
                this.SenseDictionary[message.TargetedSense].LowThreshold <= message.MessageStrength &&
                this.SenseDictionary[message.TargetedSense].HighThreshold >= message.MessageStrength &&
                this.SenseDictionary[message.TargetedSense].Enabled)
            {
                return(true);
            }

            return(false);
        }
Esempio n. 15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="StatEffect" /> class.
 /// </summary>
 /// <param name="activeThing">The active thing.</param>
 /// <param name="stat">The stat.</param>
 /// <param name="valueMod">The modification to the stat's value.</param>
 /// <param name="minimumMod">The modification to the stat's minimum.</param>
 /// <param name="maximumMod">The modification to the stat's maximum.</param>
 /// <param name="duration">The duration of the effect.</param>
 /// <param name="sensoryMessage">The sensory message.</param>
 /// <param name="expirationMessage">The expiration message.</param>
 public StatEffect(Thing activeThing, GameStat stat, int valueMod, int minimumMod, int maximumMod, TimeSpan duration, SensoryMessage sensoryMessage, SensoryMessage expirationMessage)
     : base(duration)
 {
     this.Name = stat.Name;
     this.Stat = stat;
     this.ValueMod = valueMod;
     this.MinimumMod = minimumMod;
     this.MaximumMod = maximumMod;
     this.ActiveThing = activeThing;
     this.SensoryMessage = sensoryMessage;
     this.ExpirationMessage = expirationMessage;
     this.Duration = duration;
 }
Esempio n. 16
0
        /// <summary>
        /// Executes the command.
        /// TODO: Optionally allow the admin to create a new attribute if the target didn't
        /// already have the attribute available to modify.
        /// </summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            IController sender = actionInput.Controller;
            var originator = sender.Thing;

            // Strings to be displayed when the effect is applied/removed.
            var buffString = new ContextualString(sender.Thing, this.target)
            {
                ToOriginator = string.Format("\r\nThe '{0}' stat of {1} has changed by {2}.\r\n", this.stat.Name, this.target.Name, this.modAmount),
                ToReceiver = string.Format("\r\nYour '{0}' stat has changed by {1}.\r\n", this.stat.Name, this.modAmount)
            };
            var unbuffString = new ContextualString(sender.Thing, this.target)
            {
                ToReceiver = string.Format("\r\nYour '{0}' stat goes back to normal.", this.stat.Abbreviation)
            };

            // Turn the above sets of strings into sensory messages.
            var sensoryMessage = new SensoryMessage(SensoryType.Sight, 100, buffString);
            var expirationMessage = new SensoryMessage(SensoryType.Sight, 100, unbuffString);

            // Remove all existing effects on stats with the same abbreviation
            // to prevent the effects from being stacked, at least for now.
            foreach (var effect in this.target.Behaviors.OfType<StatEffect>())
            {
                if (effect.Stat.Abbreviation == this.stat.Abbreviation)
                {
                    sender.Thing.Behaviors.Remove(effect);
                }
            }

            // Create the effect, based on the type of modification.
            StatEffect statEffect = null;
            switch (this.modType)
            {
                case "value":
                    statEffect = new StatEffect(sender.Thing, this.stat, this.modAmount, 0, 0, this.duration, sensoryMessage, expirationMessage);
                    break;
                case "min":
                    statEffect = new StatEffect(sender.Thing, this.stat, 0, this.modAmount, 0, this.duration, sensoryMessage, expirationMessage);
                    break;
                case "max":
                    statEffect = new StatEffect(sender.Thing, this.stat, 0, 0, this.modAmount, this.duration, sensoryMessage, expirationMessage);
                    break;
            }

            // Apply the effect.
            if (statEffect != null)
            {
                this.target.Behaviors.Add(statEffect);
            }
        }
Esempio n. 17
0
        /// <summary>Try to log this player into the game.</summary>
        /// <param name="session">The session.</param>
        /// <returns>True if the player successfully logged in.</returns>
        public bool LogIn(Session session)
        {
            var player = this.Parent;

            // If the player isn't located anywhere yet, try to drop them in the default room.
            // (Expect that even new characters may gain a starting position via custom character generation
            // flows which let the user to select a starting spawn area.)
            var targetPlayerStartingPosition = player.Parent != null ? player.Parent : FindDefaultRoom();

            if (targetPlayerStartingPosition == null)
            {
                session.Write("Could not place character in the game world. Please contact an administrator.");
                return(false);
            }

            // Prepare a login request and event.
            var csb = new ContextualStringBuilder(player, targetPlayerStartingPosition);

            csb.Append(@"$ActiveThing.Name enters the world.", ContextualStringUsage.WhenNotBeingPassedToOriginator);
            csb.Append(@"You enter the world.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e       = new PlayerLogInEvent(player, message);

            // Broadcast the login request to the player's current location (IE their parent room), if applicable.
            player.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);

            // Also broadcast the request to any registered global listeners.
            PlayerManager.OnPlayerLogInRequest(player, e);

            // If nothing canceled this event request, carry on with the login.
            if (!e.IsCancelled)
            {
                player.Parent = targetPlayerStartingPosition;

                DateTime universalTime = DateTime.Now.ToUniversalTime();
                this.PlayerData.LastLogin     = universalTime.ToString("s", DateTimeFormatInfo.InvariantInfo) + "Z";
                this.PlayerData.LastIPAddress = session.Connection.CurrentIPAddress.ToString();

                session.Thing = player;
                session.User.LastLogInTime = DateTime.Now; // Should this occur when user was authenticated instead?

                // Broadcast that the player successfully logged in, to their login location.
                player.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);

                PlayerManager.OnPlayerLogIn(player, e);

                return(true);
            }

            return(false);
        }
Esempio n. 18
0
        /// <summary>
        /// Executes the command.
        /// </summary>
        /// <remarks>Verify that the Guards pass first.</remarks>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            IController sender = actionInput.Controller;
            var contextMessage = new ContextualString(sender.Thing, sender.Thing)
            {
                ToOriginator = "You have entered the combat state.",
                ToReceiver = "You see $Aggressor.Name shift into a combat stance.",
                ToOthers = "You see $Aggressor.Name shift into a combat stance.",
            };

            var sm = new SensoryMessage(SensoryType.Debug, 100, contextMessage);

            var senseEvent = new SensoryEvent(sender.Thing, sm);
        }
Esempio n. 19
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            IController sender = actionInput.Controller;
            var contextMessage = new ContextualString(sender.Thing, sender.Thing.Parent)
            {
                ToOriginator = @"You say: " + this.sayText,
                ToReceiver = @"$ActiveThing.Name says: " + this.sayText,
                ToOthers = @"$ActiveThing.Name says: " + this.sayText,
            };
            var sm = new SensoryMessage(SensoryType.Hearing, 100, contextMessage);

            var sayEvent = new VerbalCommunicationEvent(sender.Thing, sm, VerbalCommunicationType.Say);
            sender.Thing.Eventing.OnCommunicationRequest(sayEvent, EventScope.ParentsDown);
            if (!sayEvent.IsCancelled)
            {
                sender.Thing.Eventing.OnCommunicationEvent(sayEvent, EventScope.ParentsDown);
            }
        }
Esempio n. 20
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            IController sender = actionInput.Controller;

            var myBehaviors = sender.Thing.Behaviors;

            var followingBehavior = myBehaviors.FindFirst<FollowingBehavior>();
            if (followingBehavior != null)
            {
                var target = followingBehavior.Target;
                if (target != null)
                {
                    var targetBehaviors = target.Behaviors;
                    var followedBehavior = targetBehaviors.FindFirst<FollowedBehavior>();
                    if (followedBehavior != null)
                    {
                        lock (followedBehavior.Followers)
                        {
                            followedBehavior.Followers.Remove(sender.Thing);
                            if (followedBehavior.Followers.Count == 0)
                            {
                                targetBehaviors.Remove(followedBehavior);
                            }
                        }
                    }
                }

                myBehaviors.Remove(followingBehavior);
            }
            else
            {
                var message = new ContextualString(sender.Thing, null)
                {
                    ToOriginator = "You aren't following anybody."
                };

                var senseMessage = new SensoryMessage(SensoryType.All, 100, message);

                var followEvent = new FollowEvent(sender.Thing, senseMessage, sender.Thing, null);

                // Broadcast the event
                sender.Thing.Eventing.OnMiscellaneousEvent(followEvent, EventScope.ParentsDown);
            }
        }
Esempio n. 21
0
        /// <summary>Initializes a new instance of the GameEvent class.</summary>
        /// <param name="activeThing">The active thing.</param>
        /// <param name="sensoryMessage">The sensory message.</param>
        public GameEvent(Thing activeThing, SensoryMessage sensoryMessage)
        {
            ActiveThing = activeThing;
            if (sensoryMessage != null)
            {
                SensoryMessage = sensoryMessage;

                // TODO: This if-condition was added to deal with some cases where
                // two ActiveThings are attempted for one action, e.g. "get".
                // Should multiple ActiveThings be supported instead, or maybe
                // there's a way to prevent this scenario?
                if (!SensoryMessage.Context.ContainsKey("ActiveThing"))
                {
                    SensoryMessage.Context.Add("ActiveThing", ActiveThing);
                }

                SensoryMessage.Context.Add(GetType().Name, this);
            }
        }
Esempio n. 22
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            IController sender = actionInput.Controller;
            string emoteString = string.Format("<*$ActiveThing.Name {0}>", actionInput.Tail);

            var contextualString = new ContextualString(sender.Thing, sender.Thing.Parent)
            {
                ToOriginator = emoteString,
                ToOthers = emoteString
            };

            var msg = new SensoryMessage(SensoryType.Sight, 100, contextualString);
            var emoteEvent = new VerbalCommunicationEvent(sender.Thing, msg, VerbalCommunicationType.Emote);
            sender.Thing.Eventing.OnCommunicationRequest(emoteEvent, EventScope.ParentsDown);
            if (!emoteEvent.IsCancelled)
            {
                sender.Thing.Eventing.OnCommunicationEvent(emoteEvent, EventScope.ParentsDown);
            }
        }
Esempio n. 23
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            // Build our knock messages for this room and the next.  Only send message to the door-type thing once.
            IController sender = actionInput.Controller;
            var thisRoomMessage = new ContextualString(sender.Thing, this.target)
            {
                ToOriginator = @"You knock on $ActiveThing.Name.",
                ToOthers = @"$Knocker.Name knocks on $ActiveThing.Name.",
                ToReceiver = @"$Knocker.Name knocks on you.",
            };
            var nextRoomMessage = new ContextualString(sender.Thing, this.target)
            {
                ToOriginator = null,
                ToOthers = @"Someone knocks on $ActiveThing.Name.",
                ToReceiver = null,
            };

            // Create sensory messages.
            var thisRoomSM = new SensoryMessage(SensoryType.Sight | SensoryType.Hearing, 100, thisRoomMessage, new Hashtable { { "Knocker", sender.Thing } });
            var nextRoomSM = new SensoryMessage(SensoryType.Hearing, 100, nextRoomMessage);

            // Generate our knock events.
            var thisRoomKnockEvent = new KnockEvent(this.target, thisRoomSM);
            var nextRoomKnockEvent = new KnockEvent(this.target, nextRoomSM);

            // Broadcast the requests/events; the events handle sending the sensory messages.
            sender.Thing.Eventing.OnCommunicationRequest(thisRoomKnockEvent, EventScope.ParentsDown);
            if (!thisRoomKnockEvent.IsCancelled)
            {
                // The knocking here happens regardless of whether it's cancelled on the inside.
                sender.Thing.Eventing.OnCommunicationEvent(thisRoomKnockEvent, EventScope.ParentsDown);

                // Next try to send a knock event into the adjacent place too.
                this.nextRoom.Eventing.OnCommunicationRequest(nextRoomKnockEvent, EventScope.SelfDown);
                if (!nextRoomKnockEvent.IsCancelled)
                {
                    this.nextRoom.Eventing.OnCommunicationEvent(nextRoomKnockEvent, EventScope.SelfDown);
                }
            }
        }
Esempio n. 24
0
        /// <summary>Open or close this behavior's parent, via the specified actor.</summary>
        /// <param name="actor">The actor doing the opening or closing.</param>
        /// <param name="verb">Whether this is an "open" or "close" action.</param>
        /// <param name="newOpenedState">The new IsOpen state to be set, if the request is not cancelled.</param>
        private void OpenOrClose(Thing actor, string verb, bool newOpenedState)
        {
            // If we're already in the desired opened/closed state, we're already done with state changes.
            if (newOpenedState == IsOpen)
            {
                // TODO: Message to the actor that it is already open/closed.
                return;
            }

            var thisThing = Parent;

            if (thisThing == null)
            {
                return; // Abort if the behavior is unattached (e.g. being destroyed).
            }

            // Prepare the Close/Open game event for sending as a request, and if not cancelled, again as an event.
            var contextMessage = new ContextualString(actor, thisThing)
            {
                ToOriginator = $"You {verb} {thisThing.Name}.",
                ToReceiver   = $"{actor.Name} {verb}s you.",
                ToOthers     = $"{actor.Name} {verb}s {thisThing.Name}.",
            };
            var message = new SensoryMessage(SensoryType.Sight, 100, contextMessage);
            var e       = new OpenCloseEvent(thisThing, newOpenedState, actor, message);

            // Broadcast the Open or Close Request and carry on if nothing cancelled it.
            // Broadcast from the parents of the openable/closable thing (IE the rooms an openable exit is attached to).
            thisThing.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);
            if (!e.IsCancelled)
            {
                // Open or Close the thing.
                IsOpen = newOpenedState;

                // Broadcast the Open or Close event.
                thisThing.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);
            }
        }
Esempio n. 25
0
        /// <summary>Try to log this player out of the game.</summary>
        /// <returns>Indicates whether the logout was successful or not.</returns>
        public bool LogOut()
        {
            var player = this.Parent;

            // Prepare a logout request and event.
            var csb = new ContextualStringBuilder(player, player.Parent);

            csb.Append(@"$ActiveThing.Name exits the world.", ContextualStringUsage.WhenNotBeingPassedToOriginator);
            csb.Append(@"You exit the world.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e       = new PlayerLogOutEvent(player, message);

            // Broadcast the logout request to the player's current location (if applicable).
            player.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);

            // Also broadcast the request to any registered global listeners.
            PlayerManager.OnPlayerLogOutRequest(player, e);

            // If nothing canceled this event request, carry on with the logout.
            if (!e.IsCancelled)
            {
                DateTime universalTime = DateTime.Now.ToUniversalTime();
                this.PlayerData.LastLogout = universalTime.ToString("s", DateTimeFormatInfo.InvariantInfo) + "Z";

                player.Save();
                this.Dispose();
                player.Dispose();

                // Broadcast that the player successfully logged out, to their parent (IE room).
                player.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);
                PlayerManager.OnPlayerLogOut(player, e);

                return(true);
            }

            return(false);
        }
Esempio n. 26
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            // Remove the item from the character's posession.
            // @@@ TODO: Test, this may be broken now... esp for numberToGive != max
            IController sender = actionInput.Controller;
            if (this.numberToGive > 0 && this.thing != null)
            {
                this.thing.RemoveFromParents();
            }

            var contextMessage = new ContextualString(sender.Thing, this.target)
            {
                ToOriginator = string.Format("You gave $Item.Name to {0}.", this.target),
                ToReceiver = "$ActiveThing.Name gave you $Item.Name.",
                ToOthers = string.Format("$ActiveThing.Name gave $Item.Name to {0}.", this.target),
            };
            var message = new SensoryMessage(SensoryType.Sight, 100, contextMessage);

            // Try to move the thing from the sender to the target; this handles eventing and whatnot for us.
            if (!this.movableBehavior.Move(this.target, sender.Thing, null, message))
            {
                sender.Write(string.Format("Failed to give {0} to {1}.", this.thing.Name, this.target.Name));
            }
        }
        /// <summary>Process an entry by the specified actor.</summary>
        /// <param name="actor">The actor.</param>
        public void Enter(Thing actor)
        {
            // Prepare the Close game event for sending as a request, and if not cancelled, again as an event.
            var movableBehavior = actor.FindBehavior <MovableBehavior>();

            if (movableBehavior == null)
            {
                // An actor tried to 'enter' even though it is not mobile; abort. This should probably message the actor.
                return;
            }

            // Move the actor into this enterable Thing. We're using the same message for going and arriving ATM.
            var message = new SensoryMessage(
                SensoryType.Sight,
                100,
                new ContextualString(actor, Parent)
            {
                ToOriginator = $"You enter {Parent.Name}.",
                ToReceiver   = $"{actor.Name} enters you.",
                ToOthers     = $"{actor.Name} enters {Parent.Name}.",
            });

            movableBehavior.Move(Parent, Parent, message, message);
        }
Esempio n. 28
0
        /// <summary>Open or close this behavior's parent, via the specified actor.</summary>
        /// <param name="actor">The actor doing the opening or closing.</param>
        /// <param name="verb">Whether this is an "open" or "close" action.</param>
        /// <param name="newOpenedState">The new IsOpen state to be set, if the request is not cancelled.</param>
        private void OpenOrClose(Thing actor, string verb, bool newOpenedState)
        {
            // If we're already in the desired opened/closed state, we're already done with state changes.
            if (newOpenedState == this.IsOpen)
            {
                // @@@ TODO: Message to the actor that it is already open/closed.
                return;
            }

            // Prepare the Close/Open game event for sending as a request, and if not cancelled, again as an event.
            var csb = new ContextualStringBuilder(actor, this.Parent);

            csb.Append(@"You " + verb + " $TargetThing.Name.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            csb.Append(@"$ActiveThing.Name " + verb + "s you.", ContextualStringUsage.OnlyWhenBeingPassedToReceiver);
            csb.Append(@"$ActiveThing.Name " + verb + "s $TargetThing.Name.", ContextualStringUsage.WhenNotBeingPassedToReceiverOrOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e       = new OpenCloseEvent(this.Parent, newOpenedState, actor, message);

            // Broadcast the Open or Close Request and carry on if nothing cancelled it.
            // Use a temporary ref to our own parent to avoid race conditions like sudden parent removal.
            var thisThing = this.Parent;

            if (thisThing != null)
            {
                // Broadcast from the parents of the openable/closable thing (IE the rooms an openable exit is attached to).
                thisThing.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);
                if (!e.IsCancelled)
                {
                    // Open or Close the thing.
                    this.IsOpen = newOpenedState;

                    // Broadcast the Open or Close event.
                    thisThing.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);
                }
            }
        }
Esempio n. 29
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        /// <remarks>
        /// TODO: ability to block via ear muffs, send tell to NPC? Also remote rtell via @
        /// </remarks>
        public override void Execute(ActionInput actionInput)
        {
            IController sender = actionInput.Controller;
            string fixedSentence = "\"<%yellow%>" + this.sentence + "<%n%>\"";
            var contextMessage = new ContextualString(sender.Thing, this.target)
            {
                ToOriginator = this.BuildOriginatorMessage(fixedSentence),
                ToReceiver = string.Format("{0} tells you: {1}", sender.Thing.Name, fixedSentence),
                ToOthers = null,
            };
            var sm = new SensoryMessage(SensoryType.Hearing, 100, contextMessage);

            var tellEvent = new VerbalCommunicationEvent(sender.Thing, sm, VerbalCommunicationType.Tell);

            // Make sure both the user is allowed to do the tell and the target is allowed to receive it.
            this.target.Eventing.OnCommunicationRequest(tellEvent, EventScope.SelfDown);
            sender.Thing.Eventing.OnCommunicationRequest(tellEvent, EventScope.SelfDown);
            if (!tellEvent.IsCancelled)
            {
                // Printing the sensory message is all that's left to do, which the event itself will take care of.
                this.target.Eventing.OnCommunicationEvent(tellEvent, EventScope.SelfDown);
                sender.Thing.Eventing.OnCommunicationEvent(tellEvent, EventScope.SelfDown);
            }
        }
Esempio n. 30
0
        /// <summary>Lock or unlock this behavior's parent, via the specified actor.</summary>
        /// <param name="actor">The actor doing the locking or unlocking.</param>
        /// <param name="verb">Whether this is an "lock" or "unlock" action.</param>
        /// <param name="newLockedState">The new IsLocked state to be set, if the request is not cancelled.</param>
        private void LockOrUnlock(Thing actor, string verb, bool newLockedState)
        {
            // If we're already in the desired locked/unlocked state, we're already done with state changes.
            if (newLockedState == this.IsLocked)
            {
                // @@@ TODO: Message to the actor that it is already locked/unlocked.
                return;
            }

            // Use a temporary ref to our own parent to avoid race conditions like sudden parent removal.
            var thisThing = this.Parent;

            if (newLockedState && thisThing != null)
            {
                // If we are attempting to lock an opened thing, cancel the lock attempt.
                var opensClosesBehavior = thisThing.Behaviors.FindFirst<OpensClosesBehavior>();
                if (opensClosesBehavior != null && opensClosesBehavior.IsOpen)
                {
                    // @@@ TODO: Message to the actor that they can't lock an open thing.
                    return;
                }
            }

            // Prepare the Lock/Unlock game event for sending as a request, and if not cancelled, again as an event.
            var csb = new ContextualStringBuilder(actor, this.Parent);
            csb.Append(@"You " + verb + " $TargetThing.Name.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            csb.Append(@"$ActiveThing.Name " + verb + "s you.", ContextualStringUsage.OnlyWhenBeingPassedToReceiver);
            csb.Append(@"$ActiveThing.Name " + verb + "s $TargetThing.Name.", ContextualStringUsage.WhenNotBeingPassedToReceiverOrOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e = new LockUnlockEvent(this.Parent, false, actor, message);

            // Broadcast the Lock or Unlock Request and carry on if nothing cancelled it.
            if (thisThing != null)
            {
                // Broadcast from the parents of the lockable/unlockable thing (IE a room or inventory where the lockable resides).
                thisThing.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);
                if (!e.IsCancelled)
                {
                    // Lock or Unlock the thing.
                    this.IsLocked = newLockedState;

                    // Broadcast the Lock or Unlock event.
                    thisThing.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);
                }
            }
        }
Esempio n. 31
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            // Contextual message text to be supplied based on the action below
            var response = new ContextualString(this.sender.Thing, this.room.Parent);

            if (this.command == "add")
            {
                // Add or update the description
                this.room.Visuals[this.visualName] = this.visualDescription;
                response.ToOriginator = string.Format("Visual '{0}' added/updated on room {1} [{2}].", this.visualName, this.roomName, this.roomId);

                //// TODO: Save change
                this.room.Save();
            }
            else if (this.command == "remove")
            {
                if (this.room.Visuals.ContainsKey(this.visualName))
                {
                    this.room.Visuals.Remove(this.visualName);

                    response.ToOriginator = string.Format("Visual '{0}' removed from room {1} [{2}]", this.visualName, this.roomName, this.roomId);
                }

                //// TODO: Save change
                this.room.Save();
            }
            else if (this.command == "show")
            {
                var output = new StringBuilder();

                if (this.room.Visuals.Count > 0)
                {
                    output.AppendLine(string.Format("Visuals for {0} [{1}]:", this.roomName, this.roomId)).AppendLine();

                    foreach (var name in this.room.Visuals.Keys)
                    {
                        output.AppendLine(string.Format("  {0}: {1}", name, this.room.Visuals[name]));
                    }
                }
                else
                {
                    output.Append(string.Format("No visuals found for {0} [{1}].", this.roomName, this.roomId));
                }

                //// HACK: Using sender.Write() for now to avoid the ViewEngine stripping newlines.
                this.sender.Write(output.ToString());

                // No need to raise event.
                return;
            }

            var message = new SensoryMessage(SensoryType.Sight, 100, response);
            var evt = new GameEvent(this.sender.Thing, message);
            this.sender.Thing.Eventing.OnMiscellaneousEvent(evt, EventScope.SelfDown);
        }
Esempio n. 32
0
 /// <summary>Initializes a new instance of the <see cref="CancellableGameEvent"/> class.</summary>
 /// <param name="activeThing">The active thing.</param>
 /// <param name="sensoryMessage">The sensory message.</param>
 public CancellableGameEvent(Thing activeThing, SensoryMessage sensoryMessage)
     : base(activeThing, sensoryMessage)
 {
 }
Esempio n. 33
0
        private void CreateYellEvent(Thing entity)
        {
            var contextMessage = new ContextualString(entity, null)
            {
                ToOriginator = "You yell: " + this.yellSentence,
                ToReceiver = "You hear $ActiveThing.Name yell: " + this.yellSentence,
                ToOthers = "You hear $ActiveThing.Name yell: " + this.yellSentence,
            };
            var sm = new SensoryMessage(SensoryType.Hearing, 100, contextMessage);

            this.yellEvent = new VerbalCommunicationEvent(entity, sm, VerbalCommunicationType.Yell);
        }
Esempio n. 34
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            // Send just one message to the command sender since they know what's going on.
            IController sender = actionInput.Controller;

            // Attempt exact ID match
            var targetPlace = ThingManager.Instance.FindThing(actionInput.Tail);

            // If input is a simple number, assume we mean a room
            int roomNum;
            targetPlace = int.TryParse(actionInput.Tail, out roomNum) ? ThingManager.Instance.FindThing("room/" + roomNum) : ThingManager.Instance.FindThingByName(actionInput.Tail, false, true);

            if (targetPlace == null)
            {
                sender.Write("Room or Entity not found.\n");
                return;
            }

            if (targetPlace.FindBehavior<RoomBehavior>() == null)
            {
                // If the target's parent is a room, go there instead
                if (targetPlace.Parent != null && targetPlace.Parent.FindBehavior<RoomBehavior>() != null)
                {
                    targetPlace = targetPlace.Parent;
                }
                else
                {
                    sender.Write("Target is not a room and is not in a room!\n");
                    return;
                }
            }

            var leaveContextMessage = new ContextualString(sender.Thing, sender.Thing.Parent)
            {
                ToOriginator = null,
                ToReceiver = @"$ActiveThing.Name disappears into nothingness.",
                ToOthers = @"$ActiveThing.Name disappears into nothingness.",
            };
            var arriveContextMessage = new ContextualString(sender.Thing, targetPlace)
            {
                ToOriginator = "You teleport to " + targetPlace.Name + ".",
                ToReceiver = @"$ActiveThing.Name appears from nothingness.",
                ToOthers = @"$ActiveThing.Name appears from nothingness.",
            };
            var leaveMessage = new SensoryMessage(SensoryType.Sight, 100, leaveContextMessage);
            var arriveMessage = new SensoryMessage(SensoryType.Sight, 100, arriveContextMessage);

            // If we successfully move (IE the move may get cancelled if the user doesn't have permission
            // to enter a particular location, some other behavior cancels it, etc), then perform a 'look'
            // command to get immediate feedback about the new location.
            // @@@ TODO: This should not 'enqueue' a command since, should the player have a bunch of
            //     other commands entered, the 'look' feedback will not immediately accompany the 'goto'
            //     command results like it should.
            var movableBehavior = sender.Thing.FindBehavior<MovableBehavior>();

            if (movableBehavior != null && movableBehavior.Move(targetPlace, sender.Thing, leaveMessage, arriveMessage))
            {
                CommandManager.Instance.EnqueueAction(new ActionInput("look", sender));
            }
        }
        /// <summary>
        /// Process an entry by the specified actor.
        /// </summary>
        /// <param name="actor">The actor.</param>
        public void Enter(Thing actor)
        {
            // Prepare the Close game event for sending as a request, and if not cancelled, again as an event.
            var movableBehavior = actor.Behaviors.FindFirst<MovableBehavior>();
            if (movableBehavior == null)
            {
                // An actor tried to 'enter' even though it is not mobile; abort. This should probably message the actor.
                return;
            }

            // Move the actor into this enterable Thing. We're using the same message for going and arriving ATM.
            var message = new SensoryMessage(
                SensoryType.Sight,
                100,
                new ContextualString(actor, this.Parent)
                {
                    ToOriginator = @"You enter $TargetThing.Name.",
                    ToReceiver = @"$ActiveThing.Name enters you.",
                    ToOthers = @"$ActiveThing.Name enters $TargetThing.Name.",
                });

            movableBehavior.Move(this.Parent, this.Parent, message, message);
        }
Esempio n. 36
0
        /// <summary>
        /// Choose sensory messaging based on whether or not the hit landed.
        /// </summary>
        /// <param name="attacker">The Thing performing the attack.</param>
        /// <param name="target">The Thing being attacked.</param>
        /// <param name="attackRoll">Die roll for the attack.</param>
        /// <param name="defendRoll">Die roll for the defense.</param>
        /// <param name="damage">Amount of damage to be inflicted if the attack is successful.</param>
        /// <returns>A SensoryMessage describing the successful or failed attack.</returns>
        private SensoryMessage CreateResultMessage(Thing attacker, Thing target, int attackRoll, int defendRoll, int damage)
        {
            ContextualString message;

            if (attackRoll > defendRoll)
            {
                message = new ContextualString(attacker, target)
                {
                    ToOriginator = @"You punch $ActiveThing.Name for $Damage health.",
                    ToReceiver = @"$Aggressor.Name punches you for $Damage health.",
                    ToOthers = @"$Aggressor.Name punches $ActiveThing.Name for $Damage health.",
                };
            }
            else
            {
                message = new ContextualString(attacker, target)
                {
                    ToOriginator = @"You attempt to punch $ActiveThing.Name, but miss.",
                    ToReceiver = @"$Aggressor.Name attempts to punch you, but misses.",
                    ToOthers = @"$Aggressor.Name attempts to punch $ActiveThing.Name, but misses.",
                };
            }

            var sm = new SensoryMessage(SensoryType.Sight, 100, message, new Hashtable { { "Damage", damage } });

            return sm;
        }
Esempio n. 37
0
        /// <summary>
        /// Determine if the specified sensory message can be processed.
        /// </summary>
        /// <param name="message">The sensory message.</param>
        /// <returns>True if it can be processed, else false.</returns>
        public bool CanProcessSensoryMessage(SensoryMessage message)
        {
            if (this.senses.ContainsKey(message.TargetedSense) &&
                this.senses[message.TargetedSense].LowThreshold <= message.MessageStrength &&
                this.senses[message.TargetedSense].HighThreshold >= message.MessageStrength &&
                this.senses[message.TargetedSense].Enabled)
            {
                return true;
            }

            return false;
        }
Esempio n. 38
0
        /// <summary>
        /// Process a sensory message.
        /// </summary>
        /// <param name="message">The sensory message to be processed.</param>
        /// <returns>The rendered view of this sensory message.</returns>
        private string ProcessMessage(SensoryMessage message)
        {
            if (this.sensesBehavior.Senses.CanProcessSensoryMessage(message))
            {
                // Build the contexts from those added to the sensory message builder
                // and those added to the sensory message.
                Hashtable context = message.Context;

                if (message.Message != null)
                {
                    foreach (DictionaryEntry entry in message.Message.ViewEngineContext)
                    {
                        context.Add(entry.Key, entry.Value);
                    }

                    if (this.userControlledBehavior != null)
                    {
                        string parsedMessage = message.Message.Parse(this.userControlledBehavior.Parent);
                        string output = this.userControlledBehavior.ViewEngine.RenderView(parsedMessage, context);
                        return output;
                    }
                }
            }

            return string.Empty;
        }
Esempio n. 39
0
        /// <summary>
        /// Open or close this behavior's parent, via the specified actor.
        /// </summary>
        /// <param name="actor">The actor doing the opening or closing.</param>
        /// <param name="verb">Whether this is an "open" or "close" action.</param>
        /// <param name="newOpenedState">The new IsOpen state to be set, if the request is not cancelled.</param>
        private void OpenOrClose(Thing actor, string verb, bool newOpenedState)
        {
            // If we're already in the desired opened/closed state, we're already done with state changes.
            if (newOpenedState == this.IsOpen)
            {
                // @@@ TODO: Message to the actor that it is already open/closed.
                return;
            }

            // Prepare the Close/Open game event for sending as a request, and if not cancelled, again as an event.
            var csb = new ContextualStringBuilder(actor, this.Parent);
            csb.Append(@"You " + verb + " $TargetThing.Name.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            csb.Append(@"$ActiveThing.Name " + verb + "s you.", ContextualStringUsage.OnlyWhenBeingPassedToReceiver);
            csb.Append(@"$ActiveThing.Name " + verb + "s $TargetThing.Name.", ContextualStringUsage.WhenNotBeingPassedToReceiverOrOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e = new OpenCloseEvent(this.Parent, newOpenedState, actor, message);

            // Broadcast the Open or Close Request and carry on if nothing cancelled it.
            // Use a temporary ref to our own parent to avoid race conditions like sudden parent removal.
            var thisThing = this.Parent;
            if (thisThing != null)
            {
                // Broadcast from the parents of the openable/closable thing (IE the rooms an openable exit is attached to).
                thisThing.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);
                if (!e.IsCancelled)
                {
                    // Open or Close the thing.
                    this.IsOpen = newOpenedState;

                    // Broadcast the Open or Close event.
                    thisThing.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);
                }
            }
        }
Esempio n. 40
0
 /// <summary>
 /// Tries to move a Thing from its current location into the specified location, if that thing is movable.
 /// </summary>
 /// <param name="thing">The Thing to move.</param>
 /// <param name="destinationThing">The new container to house the Thing.</param>
 /// <param name="goingVia">The going via.</param>
 /// <param name="leavingMessage">The leaving message.</param>
 /// <param name="arrivingMessage">The arriving message.</param>
 public void MoveThing(Thing thing, Thing destinationThing, Thing goingVia, SensoryMessage leavingMessage, SensoryMessage arrivingMessage)
 {
     MovableBehavior movableBehavior = thing.Behaviors.FindFirst<MovableBehavior>();
     if (movableBehavior != null)
     {
         movableBehavior.Move(destinationThing, goingVia, leavingMessage, arrivingMessage);
     }
 }
Esempio n. 41
0
        /// <summary>
        /// Moves the Thing through.
        /// </summary>
        /// <param name="thingToMove">The thing to move.</param>
        /// <returns>Returns true if the move was successful, false if not.</returns>
        public bool MoveThrough(Thing thingToMove)
        {
            // If the thing isn't currently mobile, bail.
            var movableBehavior = thingToMove.Behaviors.FindFirst<MovableBehavior>();
            if (movableBehavior == null)
            {
                // @@@ TODO: Add messaging to thingToMove?
                return false;
            }

            // Find the target location to be reached from here.
            DestinationInfo destinationInfo = this.GetDestinationFrom(thingToMove.Parent.ID);
            if (destinationInfo == null)
            {
                // There was no destination reachable from the thing's starting location.
                return false;
            }

            // If the target location hasn't been cached already, try to do so now.
            if (destinationInfo.CachedTarget == null || destinationInfo.CachedTarget.Target == null)
            {
                Thing newTarget = ThingManager.Instance.FindThing(destinationInfo.TargetID);
                destinationInfo.CachedTarget = new WeakReference<Thing>(newTarget);
            }

            // If the destination can't be found, abort.
            Thing destination = destinationInfo.CachedTarget.Target;
            if (destination == null)
            {
                // @@@ TODO: Add messaging to thingToMove?
                return false;
            }

            string dir = destinationInfo.ExitCommand;
            var leaveContextMessage = new ContextualString(thingToMove, thingToMove.Parent)
            {
                ToOriginator = null,
                ToReceiver = @"$ActiveThing.Name moves " + dir + ".",
                ToOthers = @"$ActiveThing.Name moves " + dir + ".",
            };
            var arriveContextMessage = new ContextualString(thingToMove, destination)
            {
                ToOriginator = @"You move " + dir + " to $GoingTo.Name.",
                ToReceiver = @"$ActiveThing.Name arrives, heading " + dir + ".",
                ToOthers = @"$ActiveThing.Name arrives, heading " + dir + ".",
            };
            var leaveMessage = new SensoryMessage(SensoryType.Sight, 100, leaveContextMessage);
            var arriveMessage = new SensoryMessage(SensoryType.Sight, 100, arriveContextMessage);

            return movableBehavior.Move(destination, this.Parent, leaveMessage, arriveMessage);
        }
Esempio n. 42
0
        /// <summary>
        /// Try to log this player out of the game.
        /// </summary>
        /// <returns>Indicates whether the logout was successful or not.</returns>
        public bool LogOut()
        {
            var player = this.Parent;

            // Prepare a logout request and event.
            var csb = new ContextualStringBuilder(player, player.Parent);
            csb.Append(@"$ActiveThing.Name exits the world.", ContextualStringUsage.WhenNotBeingPassedToOriginator);
            csb.Append(@"You exit the world.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e = new PlayerLogOutEvent(player, message);

            // Broadcast the logout request to the player's current location (if applicable).
            player.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);

            // Also broadcast the request to any registered global listeners.
            PlayerManager.OnPlayerLogOutRequest(player, e);

            // If nothing canceled this event request, carry on with the logout.
            if (!e.IsCancelled)
            {
                DateTime universalTime = DateTime.Now.ToUniversalTime();
                this.PlayerData.LastLogout = universalTime.ToString("s", DateTimeFormatInfo.InvariantInfo) + "Z";

                player.Save();
                this.Dispose();
                player.Dispose();

                // Broadcast that the player successfully logged out, to their parent (IE room).
                player.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);
                PlayerManager.OnPlayerLogOut(player, e);

                return true;
            }

            return false;
        }
Esempio n. 43
0
 /// <summary>Initializes a new instance of the <see cref="TimeEvent" /> class.</summary>
 /// <param name="activeThing">The active thing.</param>
 /// <param name="callback">The callback.</param>
 /// <param name="endTime">The end time.</param>
 /// <param name="sensoryMessage">The sensory message.</param>
 public TimeEvent(Thing activeThing, Action callback, DateTime endTime, SensoryMessage sensoryMessage)
     : base(activeThing, sensoryMessage)
 {
     Callback = callback;
     EndTime  = endTime;
 }