예제 #1
0
        /// <summary>
        /// Exits the Avatar from a previous Place and enters the current place. Sends notification to other avatars in the Place.
        /// </summary>
        /// <param name="who">The Avatar entering the room.</param>
        /// <param name="direction">The direction from which the avatar is entering.</param>
        public void Enter(IAvatar who, Direction direction)
        {
            if (who.Place != null)
            {
                who.Place.Exit(who, direction.CounterDirection);
            }

            who.Place = this;
            this.Children.Add(who);

            // Clear the target of the current avatar and the avatar's target's target.
            if (who.Target != null)
            {
                IAvatar target = who.Target as IAvatar;
                if (target != null)
                {
                    target.Target = null;
                    target.Context.AddRange(target.GetRdlProperties(Avatar.TargetIDProperty));
                }
                who.Target = null;
                who.Context.AddRange(who.GetRdlProperties(Avatar.TargetIDProperty));
            }

            // Send down the new x,y,z of the current avatar.
            who.Context.AddRange(who.GetRdlProperties(Avatar.XProperty, Avatar.YProperty, Avatar.ZProperty));

            // Raise the OnEnter event on the current place.
            if (!who.IsBuilder)
            {
                this.OnEnter(who, who.Context, direction);

                if (who is IPlayer)
                {
                    (who as IPlayer).OnPlaceEntered();
                }

                // Raise an event on all avatar instances in the current place that a new avatar has entered.
                var avatars = (from c in this.Children where c is IAvatar select c as IAvatar);
                var whoRdl  = who.ToSimpleRdl();
                foreach (var avatar in avatars)
                {
                    if (avatar.ID != who.ID)
                    {
                        avatar.OnEnter(who, who.Context, direction);
                    }
                }
            }

            // Cause the newly entered avatar to look at the place.
            this.Look(who);
        }
예제 #2
0
        public void Resurrect(IAvatar avatar)
        {
            avatar.SetBody(avatar.BodyMax);
            avatar.SetMind(avatar.MindMax);
            avatar.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Positive, "You have been resurrected!"));
            avatar.Context.AddRange(avatar.GetRdlProperties(
                                        Avatar.BodyProperty,
                                        Avatar.BodyMaxProperty,
                                        Avatar.MindProperty,
                                        Avatar.MindMaxProperty));

            this.Enter(avatar, Direction.Empty);
            // Don't want to send down the whole map. Just send down the zone.
            //avatar.Context.AddRange(this.World.GetRdlMap(avatar.X, avatar.Y));

            Character player = avatar as Character;

            if (player != null)
            {
                MapManager.MapDetail detail = this.World.Map.GetDetail(player.Location);
                if (detail != null)
                {
                    string zone = player.Properties.GetValue <string>(Character.ZoneProperty);
                    if (detail.Name != zone)
                    {
                        player.Properties.SetValue(Character.ZoneProperty, detail.Name);
                        player.Context.Add(new RdlProperty(player.ID, Character.ZoneProperty, zone));
                    }
                }
            }
        }
예제 #3
0
        public static void SetTarget(this IAvatar avatar, IAvatar target)
        {
            // If the target's target is not null then check to see if the target's target is in the current
            // place, if not release the target.
            // Will not need to do this because mobiles are cloned.
            //IAvatar targetTarget = target.Target as IAvatar;
            //if (targetTarget != null)
            //{
            //    if (targetTarget.Location != target.Location)
            //    {
            //        target.Target = null;
            //    }
            //}

            avatar.Target = target;
            if (target != null)
            {
                target.Target = avatar;

                // Send notification to avatar.
                avatar.Context.AddRange(avatar.GetRdlProperties(Avatar.TargetIDProperty));
                avatar.Context.AddRange(target.ToSimpleRdl());
                avatar.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.None,
                                                        String.Format(Resources.TargetSet, target.A())));

                // Send notification to target
                target.Context.AddRange(target.GetRdlProperties(Avatar.TargetIDProperty));
                target.Context.AddRange(avatar.ToSimpleRdl());
                // Do not send a message to the target, not really needed.
                //target.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.None,
                //    String.Format(Resources.TargetSet, avatar.A())));
            }
        }
예제 #4
0
        public override void Cast(IAvatar caster, IActor target, CastResults results)
        {
            IAvatar defender = target as IAvatar;

            // TODO: Defense against spells?
            int power = this.Foci.Power + results.CastSuccessCount;

            target.SetBody(target.Body - power);

            caster.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Cast,
                                                    String.Format(Resources.SpellDamagedTarget, target.A(), power)));
            if (defender != null)
            {
                defender.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Negative,
                                                          String.Format(Resources.SpellDamagedByTarget, power, caster.A())));
            }
            if (defender != null)
            {
                defender.Context.AddRange(defender.GetRdlProperties(Avatar.BodyProperty));
            }

            if (target.IsDead)
            {
                results.TargetDied = true;
                if (defender != null)
                {
                    // Killed an Avatar.
                    caster.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Cast,
                                                            String.Format(Resources.SpellKilledTarget, target.A())));
                    defender.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Negative,
                                                              String.Format(Resources.SpellKilledByTarget, caster.A())));
                }
                else
                {
                    // Destroyed an object.
                    caster.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Cast,
                                                            String.Format(Resources.SpellDestroyedTraget, target.A())));
                }
            }
            else if (defender != null && defender.IsUnconscious)
            {
                results.TargetUnconscious = true;
                caster.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Cast,
                                                        String.Format(Resources.SpellUnconsciousTarget, target.A())));
                if (defender != null)
                {
                    defender.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Negative,
                                                              String.Format(Resources.SpellUnconsciousByTarget, caster.A())));
                }
            }
        }
예제 #5
0
        private void RemoveAffect(IAvatar avatar, bool wornOff)
        {
            int power = this.AffectPower;

            if (power == 0)
            {
                power = this.Foci.Power;
            }
            avatar.Protection -= power;
            if (wornOff)
            {
                avatar.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.None,
                                                        String.Format("The affects of the {0} spell have worn off.", this.Name)));
            }
            avatar.Context.AddRange(avatar.GetRdlProperties(Avatar.ProtectionProperty));
            avatar.Context.Add(new RdlCommand("AFFECTREMOVE", String.Concat(avatar.Affects.Prefix, this.Name)));
        }
예제 #6
0
        /// <summary>
        /// Advances the skill level of the specified Avatar, accordng to the current level of the specified skill.
        /// </summary>
        /// <param name="avatar">The Avatar advancing the skill.</param>
        /// <param name="skillName">The name of the skill to advance.</param>
        /// <param name="context">The IMessageContext instance to write out the results to.</param>
        public static void AdvanceSkill(IAvatar avatar, string skillName, int requiredSkillLevel, IMessageContext context)
        {
            double skillLevel = avatar.Skills[skillName];

            // Can not advance skill beyond the required skill level + max skill offset.
            if (skillLevel >= (requiredSkillLevel + MaxSkillLevelOffset))
            {
                // Do not advance skill.
                Logger.LogDebug("[ {0} ] maxed at {1}, can not advance", skillName, skillLevel);
                return;
            }

            // Advance the skill level.
            if (skillLevel > 0 && skillLevel < 10)
            {
                skillLevel += 0.025;
            }
            else if (skillLevel >= 10 && skillLevel < 20)
            {
                skillLevel += 0.0075;
            }
            else if (skillLevel >= 20 && skillLevel < 30)
            {
                skillLevel += 0.005;
            }
            else if (skillLevel >= 30 && skillLevel < 40)
            {
                skillLevel += 0.0025;
            }
            else if (skillLevel >= 40 && skillLevel < 50)
            {
                skillLevel += 0.001;
            }
            else if (skillLevel >= 50 && skillLevel < 60)
            {
                skillLevel += 0.0005;
            }
            else if (skillLevel >= 60 && skillLevel < 70)
            {
                skillLevel += 0.00025;
            }
            else if (skillLevel >= 70 && skillLevel < 80)
            {
                skillLevel += 0.0001;
            }
            else if (skillLevel >= 80 && skillLevel < 90)
            {
                skillLevel += 0.000075;
            }
            else if (skillLevel >= 100)
            {
                skillLevel += 0.00005;
            }
            else
            {
                skillLevel += 0.000001;
            }
            int prevLevel = (int)avatar.Skills[skillName];

            avatar.Skills[skillName] = skillLevel;

            Logger.LogDebug("[ {0} ] :: prevSkill = {1}, updatedSkill = {2}", skillName, prevLevel, skillLevel);

            if ((int)skillLevel > prevLevel)
            {
                // Notify of skill advancement.
                context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Level, SR.SkillAdvanced(skillName.Trim(), (int)skillLevel)));

                // Send down the actual skill value.
                context.AddRange(avatar.GetRdlProperties(avatar.Skills.GetSkillKey(skillName)));
            }
        }
예제 #7
0
        /// <summary>
        /// Performs a cast of a spell from the caster onto the target Actor instance.
        /// </summary>
        /// <param name="spell">The spell being cast.</param>
        /// <param name="caster">The avatar casting the spell.</param>
        /// <param name="target">The target Actor instance, avatar or item.</param>
        /// <returns>The results of the casting.</returns>
        public static CastResults PerformCast(
            ISpell spell,
            IAvatar caster,
            IActor target)
        {
            CastResults results = new CastResults();

            // Used for sending messages to the defender's Context.
            IAvatar defender = target as IAvatar;

            // Ensure that the spell can be cast on the target.
            if (Object.ReferenceEquals(caster, target))
            {
                if (spell.IsDamageSpell)
                {
                    caster.Context.Add(new RdlErrorMessage(SR.CastNotSelf));
                    return(results);
                }
            }

            // To determine the effect’s difficulty rating, all foci scores are added together.
            int difficulty = spell.Foci.GetDifficulty();

            //The sphere or discipline skill test is then made vs. Intelligence, opposed by the opposing successes of the difficulty
            //rating roll (see Section 1.2.1). If no successes are remain, then the effect fails and the character burns no mind.
            //If a disastrous failure is rolled, the character takes the effect himself (if it’s offensive), it has its opposite effect, or
            //whatever the GM decides; the character also burns extra mind equal to the extent of the critical failure (if two 10s
            //were rolled on 2d10, the character would eat the effect and burn 2 extra mind).
            //Note that offensive effects with no area foci require a successful combat roll to strike the target, on the sphere or
            //discipline skill in the case of ranged attacks, or on an unarmed combat (or similar) skill in the case of touch effects.
            //Called shots can be made as in normal combat.
            //The defender may be allowed a Dodge roll for defense against being hit by some effects. Generally, if the attacker
            //must make a perception or dexterity roll to hit, the defender will probably be allowed a Dodge roll.
            int casterSuccessCount;

            SkillManager.PerformSkillTest(caster, spell.Skill, AttributeType.Intelligence, difficulty, spell.SkillLevelRequiredToEquip, true, out casterSuccessCount);

            // Raise the OnCastSkillRoll event to determine if the success roll should be overwritten.
            caster.OnCastSkillRoll(spell, ref casterSuccessCount);

            results.CastSuccessCount = casterSuccessCount;

            //Producing an effect, if successful, burns Mind. The amount of Mind burned is equal to the effect’s difficulty
            //minus the number of effective successes rolled (that is, what successes are left after the opposing successes are taken
            //into account), for a minimum of zero.
            int mindValueUsed = (difficulty - casterSuccessCount);

            if (mindValueUsed <= 0)
            {
                mindValueUsed = 1;
            }

            // Caster needs to the required amount of mind value.
            if (caster.Mind < mindValueUsed)
            {
                caster.Context.Add(new RdlErrorMessage("You do not have the required Willpower to cast this spell."));
                return(results);
            }

            if (casterSuccessCount < 0 && spell.IsDamageSpell)
            {
                // Disatrous failure, spell backfires!
                caster.SetMind(caster.Mind - mindValueUsed);
                caster.SetMind(caster.Mind + casterSuccessCount);

                // Apply damage to the caster.
                caster.SetBody(caster.Body - spell.Foci.Power);

                caster.Context.Add(new RdlErrorMessage(SR.CastBackfired));

                if (caster.IsDead)
                {
                    results.CasterDied = true;
                    caster.Context.Add(new RdlErrorMessage(SR.CastBackfiredKilledCaster));
                }
                else if (caster.IsUnconscious)
                {
                    results.CasterUnconscious = true;
                    caster.Context.Add(new RdlErrorMessage(SR.CastBackfiredUnconsciousCaster));
                }
            }
            else if (casterSuccessCount > 0)
            {
                results.CastSuccessful = true;

                // Spell successful.
                caster.SetMind(caster.Mind - mindValueUsed);

                // Inform the caster of the successful cast.
                //caster.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Positive,
                //    SR.CastSuccess(spell.Name, target.A())));

                spell.Cast(caster, target, results);

                caster.OnCastSuccess(spell);

                // Handle death messages.
                if (defender.IsDead)
                {
                    caster.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Cast,
                                                            SR.AttackYouKilledDefender(defender.The())));
                    defender.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Negative,
                                                              SR.AttackYouWereKilledByAttacker(caster.The())));
                }
                else if (defender.IsUnconscious)
                {
                    caster.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Cast,
                                                            SR.AttackUnconsciousDefender(defender.TheUpper())));
                    defender.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Negative,
                                                              SR.AttackYouAreUnconscious));
                }

                // Send down both the body and mind values of both the caster and the target to both the
                // caster and the target.
                RdlTag[] casterTags   = caster.GetRdlProperties(Avatar.BodyProperty, Avatar.MindProperty);
                RdlTag[] defenderTags = null;
                if (defender != null)
                {
                    defenderTags = defender.GetRdlProperties(Avatar.BodyProperty, Avatar.MindProperty);
                }

                caster.Context.AddRange(casterTags);
                if (defenderTags != null)
                {
                    caster.Context.AddRange(defenderTags);
                }

                if (defender != null)
                {
                    defender.Context.AddRange(defenderTags);
                    defender.Context.AddRange(casterTags);
                }
            }
            else
            {
                // Missed.
                caster.Context.Add(new RdlErrorMessage(SR.CastFailed));
                if (defender != null)
                {
                    defender.Context.Add(new RdlErrorMessage(SR.CasterCastFailed(caster.A())));
                }
            }

            //If an effect burns more mind than the character has available, then any overflow causes wounds. This is called
            //channeling, and can be done even when the caster has zero mind. If a character channels to below 0 body, his life
            //begins seeping away (treat it as any other wound below zero), and he must be magically or psionically healed or he
            //will die when he passes his negative physical endurance.
            if (caster.Mind < 0)
            {
                int channelingDamage = caster.Mind;
                caster.SetMind(0);
                caster.SetBody(caster.Body - channelingDamage);
                caster.Context.Add(new RdlSystemMessage(RdlSystemMessage.PriorityType.Negative, SR.CastChanneling));
            }

            // Regardless of outcome advance both the caster and target skills.
            SkillManager.AdvanceSkill(caster, spell.Skill, spell.SkillLevelRequiredToEquip, caster.Context);

            // NOTE: Do not have resist skills...
            //if (defender != null)
            //{
            //    // Use attackerWeapon as the required skill level so the defender can not elevate beyond the skill used
            //    // for the attack.
            //    SkillManager.AdvanceSkill(defender, defensiveSkill, spell.SkillLevelRequiredToEquip, defender.Context);
            //}

            return(results);
        }