Example #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AIBase"/> class.
        /// </summary>
        /// <param name="actor">Character for this AI module to control.</param>
        /// <exception cref="ArgumentNullException"><paramref name="actor" /> is <c>null</c>.</exception>
        protected AIBase(Character actor)
        {
            if (actor == null)
                throw new ArgumentNullException("actor");

            _actor = actor;
        }
        /// <summary>
        /// If the character is currently casting a skill, then attempts to cancel the skill.
        /// </summary>
        /// <returns>True if there was a skill being casted and it was successfully stopped; false if there was
        /// no skill being casted or the skill could not be canceled.</returns>
        public bool TryCancelCastingSkill()
        {
            if (!IsCastingSkill)
                return false;

            Debug.Assert(_currentCastingSkill != null);

            // Clear the casting status variables
            _currentCastingSkill = null;
            _castingSkillTarget = null;

            // Tell the caster that they stopped casting
            if (_character is INetworkSender)
            {
                using (var pw = ServerPacket.SkillStopCasting_ToUser())
                {
                    ((INetworkSender)_character).Send(pw, ServerMessageType.GUIUserStatus);
                }
            }

            // Tell everyone that the casting stopped
            using (var pw = ServerPacket.SkillStopCasting_ToMap(_character.MapEntityIndex))
            {
                _character.Map.Send(pw, ServerMessageType.MapDynamicEntityProperty);
            }

            return true;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="CharacterSPSynchronizer"/> class.
        /// </summary>
        /// <param name="character">The Character to synchronize the values of.</param>
        /// <exception cref="ArgumentNullException"><paramref name="character" /> is <c>null</c>.</exception>
        public CharacterSPSynchronizer(Character character)
        {
            if (character == null)
                throw new ArgumentNullException("character");

            _character = character;
            _isUser = (_character is User);
        }
Example #4
0
        /// <summary>
        /// When overridden in the derived class, makes the <paramref name="user"/> Character use this skill.
        /// </summary>
        /// <param name="user">The Character that used this skill. Will never be null.</param>
        /// <param name="target">The optional Character that the skill was used on. Can be null if there was
        /// no targeted Character.</param>
        /// <returns>True if the skill was successfully used; otherwise false.</returns>
        protected override bool HandleUse(Character user, Character target)
        {
            if (target == null)
                target = user;

            var power = user.ModStats[StatType.Int] * 2 + 5;
            target.HP += power;

            return true;
        }
Example #5
0
        /// <summary>
        /// When overridden in the derived class, makes the <paramref name="user"/> Character use this skill.
        /// </summary>
        /// <param name="user">The Character that used this skill. Will never be null.</param>
        /// <param name="target">The optional Character that the skill was used on. Can be null if there was
        /// no targeted Character.</param>
        /// <returns>True if the skill was successfully used; otherwise false.</returns>
        protected override bool HandleUse(Character user, Character target)
        {
            if (target == null)
                target = user;

            int power = user.ModStats[StatType.Int];
            var successful = target.StatusEffects.TryAdd(StatusEffectType.Strengthen, (ushort)power);

            return successful;
        }
Example #6
0
        /// <summary>
        /// Handles the real updating of the AI.
        /// </summary>
        protected override void DoUpdate()
        {
            var time = GetTime();

            // Ensure the target is still valid, or enough time has elapsed to check for a better target
            if ((_target != null && !IsValidTarget(_target)) || (_lastTargetUpdateTime + _targetUpdateRate < time))
            {
                _lastTargetUpdateTime = time;
                _target = GetClosestHostile();
            }

            // Check if we have a target or not
            if (_target == null)
                UpdateNoTarget();
            else
                UpdateWithTarget();
        }
        static Character GetTargetCharacter(Character user, MapEntityIndex? index)
        {
            if (!index.HasValue)
                return null;

            // Check for a valid user
            if (user == null || user.Map == null)
                return null;

            // Check for a valid target index
            var target = user.Map.GetDynamicEntity<Character>(index.Value);
            if (target == null || target.Map != user.Map)
                return null;

            // Check for a valid distance
            if (user.GetDistance(target) > GameData.MaxTargetDistance)
                return null;

            return target;
        }
Example #8
0
        /// <summary>
        /// Handles attacking with a melee weapon.
        /// </summary>
        /// <param name="weapon">The weapon to attack with. Cannot be null.</param>
        /// <param name="target">The target to attack. Can be null.</param>
        void AttackMelee(IItemTable weapon, Character target)
        {
            if (weapon == null)
            {
                Debug.Fail("Weapon should not be null...");
                return;
            }

            OnAttacked();
            if (Attacked != null)
                Attacked.Raise(this, EventArgs.Empty);

            // If melee and no target was defined, try to find one automatically
            if (target == null)
            {
                var hitArea = GameData.GetMeleeAttackArea(this, weapon.Range);
                target = Map.Spatial.Get<Character>(hitArea, x => x != this && x.IsAlive && Alliance.CanAttack(x.Alliance));
            }

            // Display the attack
            var targetID = (target != null ? target.MapEntityIndex : (MapEntityIndex?)null);
            using (var charAttack = ServerPacket.CharAttack(MapEntityIndex, targetID, weapon.ActionDisplayID))
            {
                Map.SendToArea(this, charAttack, ServerMessageType.MapEffect);
            }

            // Check that we managed to find a target
            if (target == null)
                return;

            // We found a target, so attack it
            AttackApplyReal(target);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="TestAI"/> class.
 /// </summary>
 /// <param name="actor">Character for this AI module to control.</param>
 public TestAI(Character actor) : base(actor)
 {
 }
Example #10
0
        /// <summary>
        /// Handles attacking with a ranged weapon.
        /// </summary>
        /// <param name="weapon">The weapon to attack with. Cannot be null.</param>
        /// <param name="target">The target to attack. Can be null.</param>
        void AttackRanged(ItemEntity weapon, Character target)
        {
            if (weapon == null)
            {
                Debug.Fail("Weapon should not be null...");
                return;
            }

            // We can't do anything with ranged attacks if no target is given
            if (target == null)
            {
                TrySend(GameMessage.CannotAttackNeedTarget, ServerMessageType.GUI);
                return;
            }

            Ray2D ray = new Ray2D(this, Position, target.Position, Map.Spatial);

            Vector2 rayCollideWall;

            // FUTURE: Use to create some sort of wasted ammo on a wall or something.  e.g. Grenade item explodes on walls.
            bool hasHitWall = ray.Intersects<WallEntity>(out rayCollideWall);

            if (hasHitWall)
            {
                TrySend(GameMessage.CannotAttackNotInSight, ServerMessageType.GUI);
                return;
            }

            List<ISpatial> rayCollideCharacters;

            // Use IntersectsMany here if you want to damage all characters in the attack path
            bool hasHitCharacter = ray.Intersects<Character>(out rayCollideCharacters);

            if (hasHitCharacter)
            {
                var ammoUsed = false;

                // Check for the needed ammo
                switch (weapon.WeaponType)
                {
                    case WeaponType.Projectile:
                        // Grab projectile ammo out of the inventory first if possible to avoid having to constantly reload
                        var invAmmo = Inventory.FirstOrDefault(x => weapon.CanStack(x.Value));
                        if (invAmmo.Value != null)
                            Inventory.DecreaseItemAmount(invAmmo.Key);
                        else
                            weapon.Destroy();

                        ammoUsed = true;
                        break;

                    case WeaponType.Ranged:
                        // By default, guns won't use ammo. But if you want to require guns to use ammo, you can do so here
                        ammoUsed = true;
                        break;
                }

                if (!ammoUsed)
                    return;

                foreach (var character in rayCollideCharacters)
                {
                    var c = character as Character;

                    if (!Alliance.CanAttack(c.Alliance))
                        continue;

                    // Attack
                    using (var charAttack = ServerPacket.CharAttack(MapEntityIndex, c.MapEntityIndex, weapon.ActionDisplayID))
                    {
                        Map.SendToArea(this, charAttack, ServerMessageType.MapEffect);
                    }

                    OnAttacked();

                    if (Attacked != null)
                        Attacked.Raise(this, EventArgs.Empty);

                    AttackApplyReal(c);
                }
            }
        }
Example #11
0
        /// <summary>
        /// Removes the explicit hostility towards a specific <see cref="Character"/>. Only applies to
        /// hostility set through <see cref="SetHostileTowards"/> and has no affect on hostility created through
        /// the <see cref="Alliance"/>.
        /// </summary>
        /// <param name="target">The <see cref="Character"/> to remove the explicit hostility on.</param>
        /// <returns>True if the explicit hostility towards the <paramref name="target"/> was removed; false if the
        /// hostility towards the <paramref name="target"/> is implicitly defined through the <see cref="Alliance"/>
        /// settings or there was no explicit hostility set on the <paramref name="target"/>.</returns>
        public bool RemoveHostileTowards(Character target)
        {
            if (target == null)
            {
                Debug.Fail("target parameter should not be null.");
                return false;
            }

            return _explicitHostiles.Remove(target);
        }
Example #12
0
        /// <summary>
        /// Gets if the actor is hostile towards the given <see cref="Character"/>.
        /// </summary>
        /// <param name="character">The character to check if the actor is hostile towards.</param>
        /// <returns>True if the actor is hostile towards the <paramref name="character"/>; otherwise false.</returns>
        public virtual bool IsHostileTowards(Character character)
        {
            var ret = Actor.Alliance.IsHostile(character.Alliance);
            if (!ret)
            {
                if (_explicitHostiles.ContainsKey(character))
                    ret = true;
            }

            return ret;
        }
Example #13
0
File: Map.cs Project: wtfcolt/game
        /// <summary>
        /// Handles when a Character is added to the Map. This is an extension of EntityAdded that handles
        /// special stuff just for Characters.
        /// </summary>
        /// <param name="character">The Character that was added to the map.</param>
        /// <exception cref="TypeException">Unknown Character type - not a NPC or User...?</exception>
        void CharacterAdded(Character character)
        {
            // If the character was already on a map, so remove them from the old map
            if (character.Map != null && character.Map != this)
            {
                const string errmsg = "Character `{0}` [{1}] added to new map, but is already on a map!";
                if (log.IsWarnEnabled)
                    log.WarnFormat(errmsg, character, character.MapEntityIndex);
                Debug.Fail(string.Format(errmsg, character, character.MapEntityIndex));
                character.Map.RemoveEntity(character);
            }

            // Added character is a User
            var user = character as User;
            if (user != null)
            {
                EventCounterManager.Map.Increment(ID, MapEventCounterType.UserAdded);

                Debug.Assert(!Users.Contains(user), string.Format("Users list already contains `{0}`!", user));
                _users.Add(user);
                SendMapData(user);
                return;
            }

            // Added character is a NPC
            var npc = character as NPC;
            if (npc != null)
            {
                EventCounterManager.Map.Increment(ID, MapEventCounterType.NPCAdded);

                Debug.Assert(!NPCs.Contains(npc), string.Format("NPCs list already contains `{0}`!", npc));
                _npcs.Add(npc);
                return;
            }

            // Unknown added character type - not actually an error, but it is likely an oversight
            throw new TypeException("Unknown Character type - not a NPC or User...?");
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="CharacterSkillCaster"/> class.
 /// </summary>
 /// <param name="character">The character.</param>
 public CharacterSkillCaster(Character character)
 {
     _character = character;
     _cooldownManager = new SkillCooldownManager();
 }
        /// <summary>
        /// Calls a skill to be used, and applies the respective cooldown values.
        /// </summary>
        /// <param name="skill">The skill to be used.</param>
        /// <param name="target">The optional character to use the skill on. Can be null.</param>
        /// <param name="castedImmediately">True if this skill was casted immediately (that is, there was no delay before casting);
        /// false if the skill had a delay before casting.</param>
        void UseSkill(ISkill<SkillType, StatType, Character> skill, Character target, bool castedImmediately)
        {
            Debug.Assert(skill != null);
            Debug.Assert(castedImmediately || _currentCastingSkill == skill);
            Debug.Assert(castedImmediately || _castingSkillTarget == target);

            // Clear the casting status variables
            _currentCastingSkill = null;
            _castingSkillTarget = null;

            // Tell the caster that they stopped casting
            if (_character is INetworkSender)
            {
                using (var pw = ServerPacket.SkillStopCasting_ToUser())
                {
                    ((INetworkSender)_character).Send(pw, ServerMessageType.GUIUserStatus);
                }
            }

            // If the skill had a casting time, tell everyone that the casting stopped
            if (!castedImmediately)
            {
                using (var pw = ServerPacket.SkillStopCasting_ToMap(_character.MapEntityIndex))
                {
                    _character.Map.Send(pw, ServerMessageType.MapDynamicEntityProperty);
                }
            }

            // Actually use the skill
            var skillSuccessfullyUsed = skill.Use(_character, target);

            // If the skill was not used for whatever reason, then return
            if (!skillSuccessfullyUsed)
                return;

            // Only set the cooldown if it was successfully used
            _cooldownManager.SetCooldown(skill.CooldownGroup, skill.CooldownTime, _character.GetTime());

            // Update the character's skill cooldown
            if (_character is INetworkSender)
            {
                using (var pw = ServerPacket.SkillSetGroupCooldown(skill.CooldownGroup, skill.CooldownTime))
                {
                    ((INetworkSender)_character).Send(pw, ServerMessageType.GUIUserStatus);
                }
            }

            // Notify the clients on the map that the character used the skill
            var targetEntityIndex = target != null ? (MapEntityIndex?)target.MapEntityIndex : null;
            using (var pw = ServerPacket.SkillUse(_character.MapEntityIndex, targetEntityIndex, skill.SkillType))
            {
                _character.Map.Send(pw, ServerMessageType.MapDynamicEntityProperty);
            }
        }
Example #16
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CharacterKillEventArgs"/> class.
 /// </summary>
 /// <param name="killer">The <see cref="Character"/> that killed the sender.</param>
 public CharacterKillEventArgs(Character killer)
 {
     _killer = killer;
 }
Example #17
0
 /// <summary>
 /// When overridden in the derived class, gets the MP cost of using this Skill.
 /// </summary>
 /// <param name="user">The Character using the skill. Will not be null.</param>
 /// <param name="target">The optional Character that the skill was used on. Can be null if there was
 /// no targeted Character.</param>
 /// <returns>The MP cost of using this Skill.</returns>
 public override int GetMPCost(Character user, Character target)
 {
     return 2;
 }
Example #18
0
        /// <summary>
        /// Gets the amount of damage for a normal attack.
        /// </summary>
        /// <param name="target">Character being attacked.</param>
        /// <returns>The amount of damage to inflict for a normal attack.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="target" /> is <c>null</c>.</exception>
        public int GetAttackDamage(Character target)
        {
            if (target == null)
                throw new ArgumentNullException("target");

            int minHit = ModStats[StatType.MinHit];
            int maxHit = ModStats[StatType.MaxHit];

            if (minHit > maxHit)
                maxHit = minHit;

            var damage = Rand.Next(minHit, maxHit);

            // Apply the defence, and ensure the damage is in a valid range
            int defence = target.ModStats[StatType.Defence];

            damage -= defence / 2;

            if (damage < 1)
                damage = 1;

            return damage;
        }
Example #19
0
File: Map.cs Project: wtfcolt/game
        /// <summary>
        /// Handles when a Character is removed from the Map. This is an extension of EntityRemoved that handles
        /// special stuff just for Characters.
        /// </summary>
        /// <param name="character">The Character that was removed from the Map.</param>
        void CharacterRemoved(Character character)
        {
            User user;
            NPC npc;

            if ((user = character as User) != null)
                _users.Remove(user);
            else if ((npc = character as NPC) != null)
                _npcs.Remove(npc);
        }
        /// <summary>
        /// Tells the skill user to start using the given <paramref name="skill"/>. This is more of a suggestion than a
        /// request since the skill user does not actually have to start casting the skill. If this skill user decides
        /// to use the skill, the CurrentCastingSkill must be set to the <paramref name="skill"/>.
        /// </summary>
        /// <param name="skill">The skill to be used.</param>
        /// <param name="target">The optional character to use the skill on. Can be null.</param>
        /// <returns>True if the <paramref name="skill"/> started being casted; otherwise false. This does not indicate
        /// whether or not the skill was or will be successfully used, just that it was attempted to be used. Common
        /// times this will return false is if there is a skill already being casted, or if the skill that was
        /// attempted to be used still needs to cool down.</returns>
        public bool TryStartCastingSkill(ISkill<SkillType, StatType, Character> skill, Character target)
        {
            if (!_character.IsAlive)
                return false;

            // Check that the character knows the skill
            if (!_character.KnownSkills.Knows(skill.SkillType))
                return false;

            // Don't interrupt a skill that the character is already casting
            if (IsCastingSkill)
                return false;

            // Check that the group is available for usage
            if (_cooldownManager.IsCoolingDown(skill.CooldownGroup, _character.GetTime()))
                return false;

            // Only allow immediate-usage skills when moving
            if (_character.Velocity != Vector2.Zero && skill.CastingTime > 0)
                return false;

            if (skill.CastingTime == 0)
            {
                // The skill to use has no usage delay, so use it immediately
                UseSkill(skill, target, true);
            }
            else
            {
                // The skill does have a delay, so queue it for usage
                _currentCastingSkill = skill;
                _castingSkillTarget = target;
                var castingTime = skill.CastingTime;
                _castingSkillUsageTime = _character.GetTime() + castingTime;

                // Tell the character the details about the skill they are casting
                if (_character is INetworkSender)
                {
                    using (var pw = ServerPacket.SkillStartCasting_ToUser(skill.SkillType, castingTime))
                    {
                        ((INetworkSender)_character).Send(pw, ServerMessageType.GUIUserStatus);
                    }
                }

                // Tell the users on the map that the character is casting
                using (var pw = ServerPacket.SkillStartCasting_ToMap(_character.MapEntityIndex, skill.SkillType))
                {
                    _character.Map.Send(pw, ServerMessageType.MapDynamicEntityProperty);
                }
            }

            return true;
        }
Example #21
0
        /// <summary>
        /// Checks if the <paramref name="target"/> is valid.
        /// </summary>
        /// <param name="target">The target <see cref="Character"/>.</param>
        /// <returns>True if the <paramref name="target"/> is valid; otherwise false.</returns>
        protected virtual bool IsValidTarget(Character target)
        {
            if (target == null)
                return false;

            if (!target.IsAlive)
                return false;

            if (target.Map != Actor.Map)
                return false;

            if (target.IsDisposed)
                return false;

            return true;
        }
        /// <summary>
        /// Checks if the User can start a dialog with the given <paramref name="npc"/>.
        /// </summary>
        /// <param name="npc">The NPC to start the dialog with.</param>
        /// <returns>True if the User can start a dialog with the given <paramref name="npc"/>; otherwise false.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="npc" /> is <c>null</c>.</exception>
        bool CanStartChat(Character npc)
        {
            const string errmsg = "Cannot start chat between `{0}` and `{1}` - {2}.";

            // Check if a chat is already going
            if (IsChatting)
            {
                if (log.IsInfoEnabled)
                    log.InfoFormat(errmsg, _user, npc, "Chat dialog already open");
                return false;
            }

            // Check for valid states
            if (npc == null)
                throw new ArgumentNullException("npc");

            if (!_user.IsAlive)
            {
                if (log.IsInfoEnabled)
                    log.InfoFormat(errmsg, _user, npc, "User is dead");
                return false;
            }

            if (!npc.IsAlive)
            {
                if (log.IsInfoEnabled)
                    log.InfoFormat(errmsg, _user, npc, "NPC is dead");
                return false;
            }

            if (!_user.IsOnGround)
            {
                if (log.IsInfoEnabled)
                    log.InfoFormat(errmsg, _user, npc, "User is not on the ground");
                return false;
            }

            if (_user.Map == null)
            {
                if (log.IsInfoEnabled)
                    log.InfoFormat(errmsg, _user, npc, "User's map is null");
                return false;
            }

            if (npc.ChatDialog == null)
            {
                if (log.IsInfoEnabled)
                    log.InfoFormat(errmsg, _user, npc, "NPC has no chat dialog");
                return false;
            }

            // Check for a valid distance
            if (_user.Map != npc.Map)
            {
                if (log.IsInfoEnabled)
                    log.InfoFormat(errmsg, _user, npc, "Characters are on different maps");
                return false;
            }

            if (_user.GetDistance(npc) > GameData.MaxNPCChatDistance)
            {
                if (log.IsInfoEnabled)
                    log.InfoFormat(errmsg, _user, npc, "Too far away from the NPC to chat");
                return false;
            }

            return true;
        }
Example #23
0
        /// <summary>
        /// Explicitly sets the AI to be hostile towards a specific <see cref="Character"/> for a set amount
        /// of time. Has no affect if the target <see cref="Character"/>'s <see cref="Alliance"/> already makes
        /// the <see cref="AIBase.Actor"/> hostile towards them, or if they cannot be attacked by the
        /// <see cref="AIBase.Actor"/>.
        /// </summary>
        /// <param name="target">The <see cref="Character"/> to set as hostile towards.</param>
        /// <param name="timeout">How long, in milliseconds, this hostility will last. It is recommended that
        /// this value remains relatively low (5-10 minutes max). Must be greater than 0.</param>
        /// <param name="increaseTimeOnly">If true, the given <paramref name="timeout"/> will not be
        /// used if the <paramref name="target"/> is already marked as being hostile towards, and the
        /// existing timeout is greater than the given <paramref name="timeout"/>. That is, the longer
        /// of the two timeouts will be used.</param>
        public void SetHostileTowards(Character target, TickCount timeout, bool increaseTimeOnly)
        {
            if (target == null)
            {
                Debug.Fail("target parameter should not be null.");
                return;
            }

            if (timeout < 0)
            {
                Debug.Fail("timeout parameter should be greater than 0.");
                return;
            }

            // Ignore characters that are already marked as hostile by the alliance, along with those
            // who cannot be attacked
            if (Actor.Alliance.IsHostile(target.Alliance) || !Actor.Alliance.CanAttack(target.Alliance))
                return;

            // Get the absolute timeout time
            var timeoutTime = GetTime() + timeout;

            if (_explicitHostiles.ContainsKey(target))
            {
                // Target already exists in the list, so update the time
                try
                {
                    if (!increaseTimeOnly)
                        _explicitHostiles[target] = timeoutTime;
                    else
                        _explicitHostiles[target] = Math.Max(timeoutTime, _explicitHostiles[target]);
                }
                catch (KeyNotFoundException ex)
                {
                    const string errmsg = "Possible thread-safety issue in AI's ExplicitHostile. Exception: {0}";
                    if (log.IsErrorEnabled)
                        log.ErrorFormat(errmsg, ex);
                    Debug.Fail(string.Format(errmsg, ex));

                    // Retry
                    SetHostileTowards(target, timeoutTime, increaseTimeOnly);
                }
            }
            else
            {
                // Target not in the list yet, so add them
                try
                {
                    _explicitHostiles.Add(target, timeoutTime);
                }
                catch (ArgumentException ex)
                {
                    const string errmsg = "Possible thread-safety issue in AI's ExplicitHostile. Exception: {0}";
                    if (log.IsErrorEnabled)
                        log.ErrorFormat(errmsg, ex);
                    Debug.Fail(string.Format(errmsg, ex));

                    // Retry
                    SetHostileTowards(target, timeoutTime, increaseTimeOnly);
                }
            }
        }
Example #24
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UserInventory"/> class.
 /// </summary>
 /// <param name="user">User that the inventory is for</param>
 public UserInventory(Character user) : base(user)
 {
     _inventoryUpdater = new UserInventoryUpdater(this);
 }
Example #25
0
 /// <summary>
 /// Gets if the actor can attack the given <see cref="Character"/>.
 /// </summary>
 /// <param name="character">The <see cref="Character"/> to check if the actor can attack.</param>
 /// <returns>True if the actor can attack the <paramref name="character"/>; otherwise false.</returns>
 public virtual bool CanAttack(Character character)
 {
     return Actor.Alliance.CanAttack(character.Alliance);
 }
Example #26
0
 /// <summary>
 /// Initializes a new instance of the <see cref="NPCInventory"/> class.
 /// </summary>
 /// <param name="npc">The NPC.</param>
 public NPCInventory(Character npc) : base(npc)
 {
 }
        static bool TryGetMap(Character user, out Map map)
        {
            // Check for a valid user
            if (user == null)
            {
                const string errmsg = "user is null.";
                if (log.IsErrorEnabled)
                    log.Error(errmsg);
                Debug.Fail(errmsg);
                map = null;
                return false;
            }

            // Get the map
            map = user.Map;
            if (map == null)
            {
                // Invalid map
                const string errorMsg = "Received UseWorld from user `{0}`, but their map is null.";
                if (log.IsWarnEnabled)
                    log.WarnFormat(errorMsg, user);
                Debug.Fail(string.Format(errorMsg, user));
                return false;
            }

            // Valid map
            return true;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="NonPersistentCharacterStatusEffects"/> class.
 /// </summary>
 /// <param name="character">The <see cref="Character"/> that this collection belongs to.</param>
 public NonPersistentCharacterStatusEffects(Character character) : base(character)
 {
 }
Example #29
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CharacterAttackEventArgs"/> class.
 /// </summary>
 /// <param name="attacked">The <see cref="Character"/> that was attacked.</param>
 /// <param name="damage">The amount of damage inflicted on the <paramref name="attacked"/> by
 /// the attacker.</param>
 public CharacterAttackEventArgs(Character attacked, int damage)
 {
     _attacked = attacked;
     _damage = damage;
 }
Example #30
0
        /// <summary>
        /// Performs the actual attacking of a specific character. This should only be called by
        /// <see cref="AttackMelee"/> or <see cref="AttackRanged"/>.
        /// </summary>
        /// <param name="target">Character to attack.</param>
        void AttackApplyReal(Character target)
        {
            // Get the damage
            var damage = GetAttackDamage(target);

            // Apply the damage to the target
            target.Damage(this, damage);

            // Raise attack events
            OnAttackedCharacter(target, damage);
            if (AttackedCharacter != null)
                AttackedCharacter.Raise(this, new CharacterAttackEventArgs(target, damage));

            target.OnAttackedByCharacter(this, damage);
            if (target.AttackedByCharacter != null)
                target.AttackedByCharacter.Raise(this, new CharacterAttackEventArgs(target, damage));
        }