Пример #1
0
        /// <summary>
        /// Check if the current attack is a chance to knockback the defender.
        /// </summary>
        /// <param name="attackerAttackFlags">Attacker attack flags</param>
        /// <returns></returns>
        public bool IsKnockback(AttackFlags attackerAttackFlags)
        {
            bool knockbackChance = RandomHelper.Random(0, 100) < 15;

            if (this._defender.Type == WorldEntityType.Player)
            {
                return(false);
            }

            if (this._attacker is IPlayerEntity player)
            {
                var weapon = player.Inventory[InventorySystem.RightWeaponSlot];

                if (weapon == null)
                {
                    weapon = InventorySystem.Hand;
                }
                if (weapon.Data.WeaponType == WeaponType.MELEE_YOYO || attackerAttackFlags.HasFlag(AttackFlags.AF_FORCE))
                {
                    return(false);
                }
            }

            bool canFly = false;

            // TODO: if is flying, return false
            if ((this._defender.Object.MovingFlags & ObjectState.OBJSTA_DMG_FLY_ALL) == 0 && this._defender is IMonsterEntity monster)
            {
                canFly = monster.Data.Class != MoverClassType.RANK_SUPER &&
                         monster.Data.Class != MoverClassType.RANK_MATERIAL &&
                         monster.Data.Class != MoverClassType.RANK_MIDBOSS;
            }

            return(canFly && knockbackChance);
        }
Пример #2
0
        /// <summary>
        /// Check if the current attack is a chance to knockback the defender.
        /// </summary>
        /// <param name="attackerAttackFlags">Attacker attack flags</param>
        /// <returns></returns>
        public bool IsKnockback(AttackFlags attackerAttackFlags)
        {
            var knockbackChance = RandomHelper.Random(0, 100) < 15;

            if (Defender.Type == WorldEntityType.Player)
            {
                return(false);
            }

            if (Attacker is IPlayerEntity player)
            {
                Item weapon = player.Inventory.GetEquipedItem(ItemPartType.RightWeapon) ?? player.Hand;

                if (weapon.Data.WeaponType == WeaponType.MELEE_YOYO || attackerAttackFlags.HasFlag(AttackFlags.AF_FORCE))
                {
                    return(false);
                }
            }

            var canFly = false;

            // TODO: if is flying, return false
            if ((Defender.Object.MovingFlags & ObjectState.OBJSTA_DMG_FLY_ALL) == 0 && Defender is IMonsterEntity monster)
            {
                canFly = monster.Data.Class != MoverClassType.RANK_SUPER &&
                         monster.Data.Class != MoverClassType.RANK_MATERIAL &&
                         monster.Data.Class != MoverClassType.RANK_MIDBOSS;
            }

            return(canFly && knockbackChance);
        }
Пример #3
0
        public override int GetDefense(Mover attacker, AttackFlags flags)
        {
            int defense = 0;

            if (attacker is Player)
            {
                if (flags.HasFlag(AttackFlags.AF_MAGIC))
                {
                    defense = (int)((this.Attributes[DefineAttributes.INT] * 9.04f) + (this.Level * 35.98f));
                }
                else
                {
                    // TODO: Generic hit PVP
                }
            }
            else
            {
                defense = (int)(((this.GetEquipedDefense() / 4 /*+ GetParam(DST_ADJDEF, 0)*/) +
                                 (this.Level + (this.Attributes[DefineAttributes.STA] / 2) + this.Attributes[DefineAttributes.DEX]) / 2.8f) - 4 + this.Level * 2);
            }

            if (defense < 0)
            {
                defense = 0;
            }

            return(defense);
        }
Пример #4
0
        public static AttackFlags GetAttackFlags()
        {
            AttackFlags attackFlags = 0;

            // determine if its a critical hit, knockback, miss hit, etc...

            return(attackFlags);
        }
Пример #5
0
    public bool HasFlag(AttackFlags flag)
    {
        // Checks if it has the flag
        if ((flags & flag) == flag)
        {
            return(true);
        }

        return(false);
    }
Пример #6
0
        public override int GetDefense(Mover attacker, AttackFlags flags)
        {
            float armor = this.Data.NaturalArmor;

            if (flags.HasFlag(AttackFlags.AF_MAGIC))
            {
                armor = this.Data.ResistMagic;
            }

            return((int)(armor / 7f + 1f));
        }
Пример #7
0
        void IUpdateable.Update(TimeSpan elapsedInFrame)
        {
            if (!initialized)
            {
                Initialize();
            }

            //if(Actor.IsOnGround.Active)
            //{
            //    if(JumpForward != null)
            //        JumpForwardMotion.Active = false;
            //}

            if (IsAttacking.JustStarted())
            {
                Actor.Face(Actor.Scene.Player);
            }

            if (IsAttacking && AttackFlags.HasFlag(AttackFlags.StopWhileAttacking))
            {
                Actor.Motion.Stop(Axis.X);
            }

            if (AttackFlags.HasFlag(AttackFlags.ThrowFireball))
            {
                if (IsAttacking.JustEnded())
                {
                    var bullet = new EnemyBullet();
                    bullet.Direction = Actor.Direction;
                    bullet.PositionRelativeTo(Actor, 0, 0);
                    bullet.MoveInDirection(bullet.Direction, new ConfigValue <int>("enemy bullet speed").Value);
                }
            }

            if (TileChecker.IsOnLedge)
            {
                ReactToObstacle(TileChecker.CurrentLedge, Reactions.WalkingOffLedge);
            }

            if (TileChecker.IsAtWall)
            {
                if (TileChecker.CurrentWall.ActorCouldJumpOver(Actor))
                {
                    ReactToObstacle(TileChecker.CurrentWall, Reactions.WalkingIntoShortWall);
                }
                else
                {
                    ReactToObstacle(TileChecker.CurrentWall, Reactions.WalkingIntoWall);
                }
            }
        }
Пример #8
0
        private static int GetDefense(Mover attacker, Mover defender, AttackFlags flags)
        {
            if (flags.HasFlag(AttackFlags.AF_MAGICSKILL))
            {
                // return Magic resist
                return 0;
            }

            if ((attacker is Player && defender is Player) || flags.HasFlag(AttackFlags.AF_GENERIC))
            {
            }

            return defender.GetDefense(attacker, flags);
        }
Пример #9
0
        /// <inheritdoc />
        public void SendAddDamage(ILivingEntity defender, ILivingEntity attacker, AttackFlags attackFlags, int damage)
        {
            using var packet = new FFPacket();

            packet.StartNewMergedPacket(defender.Id, SnapshotType.DAMAGE);
            packet.Write(attacker.Id);
            packet.Write(damage);
            packet.Write((int)attackFlags);

            if (attackFlags.HasFlag(AttackFlags.AF_FLYING))
            {
                packet.Write(defender.Moves.DestinationPosition.X);
                packet.Write(defender.Moves.DestinationPosition.Y);
                packet.Write(defender.Moves.DestinationPosition.Z);
                packet.Write(defender.Object.Angle);
            }

            SendToVisible(packet, defender, sendToPlayer: true);
        }
Пример #10
0
        internal void SendDamagesTo(Mover defender, int damages, AttackFlags flags, Vector3 position = null, float angle = 0f)
        {
            using (var packet = new FFPacket())
            {
                packet.StartNewMergedPacket(defender.ObjectId, SnapshotType.DAMAGE);
                packet.Write(this.ObjectId);
                packet.Write(damages);
                packet.Write((int)flags);

                if (flags.HasFlag(AttackFlags.AF_FLYING))
                {
                    packet.Write(position.X);
                    packet.Write(position.Y);
                    packet.Write(position.Z);
                    packet.Write(angle * 10f);
                }

                this.SendToVisible(packet);
            }
        }
Пример #11
0
        /// <summary>
        /// Check if the attacker's melee attack is a critical hit.
        /// </summary>
        /// <param name="attacker">Attacker</param>
        /// <param name="currentAttackFlags">Attack flags</param>
        /// <returns></returns>
        public bool IsCriticalAttack(ILivingEntity attacker, AttackFlags currentAttackFlags)
        {
            if (currentAttackFlags.HasFlag(AttackFlags.AF_MELEESKILL) || currentAttackFlags.HasFlag(AttackFlags.AF_MAGICSKILL))
            {
                return(false);
            }

            var criticalJobFactor   = attacker is IPlayerEntity player ? player.PlayerData.JobData.Critical : 1f;
            var criticalProbability = (int)(attacker.Attributes[DefineAttributes.DEX] / 10 * criticalJobFactor);

            // TODO: add DST_CHR_CHANCECRITICAL to criticalProbability

            if (criticalProbability < 0)
            {
                criticalProbability = 0;
            }

            // TODO: check if player is in party and if it has the MVRF_CRITICAL flag

            return(RandomHelper.Random(0, 100) < criticalProbability);
        }
Пример #12
0
        /// <summary>
        /// Calculates the player's defense.
        /// </summary>
        /// <param name="defenderPlayer">Current defender player.</param>
        /// <param name="flags">Attack flags.</param>
        /// <returns>Player's defense.</returns>
        private int GetPlayerDefense(IPlayerEntity defenderPlayer, AttackFlags flags)
        {
            var defense = 0;

            if (Attacker.Type == WorldEntityType.Player)
            {
                if (flags.HasFlag(AttackFlags.AF_MAGIC))
                {
                    defense = (int)(defenderPlayer.Attributes[DefineAttributes.INT] * 9.04f + defenderPlayer.Object.Level * 35.98f);
                }
                else
                {
                    // TODO: GetDefenseByItem()
                }
            }
            else
            {
                // TODO: GetDefenseByItem()
            }

            return(Math.Max(0, defense));
        }
Пример #13
0
        public static AttackFlags GetAttackFlags(Mover attacker, Mover defender)
        {
            AttackFlags flags = 0;

            if (IsMissedHit(attacker, defender))
                return AttackFlags.AF_MISS;
            else
                flags |= AttackFlags.AF_GENERIC;

            if (IsCriticalHit(attacker, defender))
            {
                flags |= AttackFlags.AF_CRITICAL;

                float chance = RandomHelper.Random(0, 100);

                if (chance < 30)
                    flags |= AttackFlags.AF_FLYING;
            }
            if (IsBlockingHit(attacker, defender))
                flags |= AttackFlags.AF_BLOCKING;

            return flags;
        }
        // melee attacks and throwing only
        public bool BeginAttack( AttackType attacktype, AttackFlags flags, bool playerInitiated )
        {
            if ( attacktype == AttackType.Invalid )
                return false;

            bool flashyFollowup = ( (flags&AttackFlags.FlashyFollowup) != AttackFlags.None );
            bool disregardDelay = ( (flags&AttackFlags.DisregardDelay) != AttackFlags.None );
            bool feint = false;
            bool flashy = false;
            Mobile attacker = AttachedTo as Mobile;
            IKhaerosMobile km = attacker as IKhaerosMobile;
            BaseWeapon weapon = attacker.Weapon as BaseWeapon;
            BaseShield shield = attacker.FindItemOnLayer( Layer.TwoHanded ) as BaseShield;

            if( attacker is PlayerMobile )
            {
                PlayerMobile m = attacker as PlayerMobile;

                if( !m.EnableOffHand )
                    m.OffHandWeapon = null;
                else
                {
                    m.EnableOffHand = false;

                    if( !Commands.OffHandThrow.EnableOffHand( m ) )
                        return false;
                }
            }

            m_OffHand = ( attacker is PlayerMobile && ( (PlayerMobile)attacker ).OffHandThrowing ) && attacktype == AttackType.Throw;

            if ( !CanBeginCombatAction( ) || !CanBeginAttack( flags ) )
                return false;

            if ( attacktype == AttackType.Throw )
            {
                if( m_OffHand )
                    weapon = ((PlayerMobile)attacker).OffHandWeapon;

                if ( !CanThrow() )
                    return false;
                if ( weapon is AzhuranBoomerang ) // requires still time
                {
                    if ( !((BaseRanged)weapon).IsStill( attacker ) )
                    {
                        if ( playerInitiated )
                        {
                            m_ErrorMessage = "";
                            DisplayQueueResultMessage( QueueRanged() );
                        }

                        return false;
                    }
                }
            }
            else if ( !CanBeginMeleeAttack() )
                return false;
            else if ( attacktype == AttackType.ShieldBash && shield == null )
            {
                m_ErrorMessage = "A shield is needed in order to perform a shield bash!";
                return false;
            }

            if ( attacker.Mounted )
            {
                if ( attacktype == AttackType.Swing || attacktype == AttackType.Circular )
                {
                    m_ErrorMessage = "Cannot perform swing attacks while mounted.";
                    return false;
                }
                else if ( attacktype == AttackType.Thrust && !(CanThrustOnMount()) )
                    return false;
                else if ( attacktype == AttackType.ShieldBash )
                {
                    m_ErrorMessage = "This attack cannot be performed while mounted.";
                    return false;
                }
            }

            StopAllActions( false );

            if ( attacktype == AttackType.Circular ) // it is important that all of these are part of the same if/elseif chain
            { // as some feats are actually additional attacks, but that does not mean they can be used together with maneuvers.
                PlayerMobile pm = attacker as PlayerMobile;
                if ( km.Feats.GetFeatLevel(FeatList.CircularAttack) <= 0 )
                {
                    m_ErrorMessage = "You do not have the required feat.";
                    return false;
                }
                else if ( pm == null || weapon.Layer != Layer.TwoHanded || weapon is BaseRanged )
                {
                    m_ErrorMessage = "You can only perform this attack with two-handed melee weapons.";
                    return false;
                }
                else if ( weapon.NameType != pm.WeaponSpecialization && weapon.NameType != pm.SecondSpecialization )
                {
                    m_ErrorMessage = "You can only perform this attack with a weapon you have specialized in.";
                    return false;
                }
                else if ( !BaseWeapon.CheckStam( attacker, km.Feats.GetFeatLevel(FeatList.CircularAttack), false, false ) )
                {
                    m_ErrorMessage = ""; // will be displayed by the checkstam thingy
                    return false;
                }
            }
            else if ( attacktype == AttackType.ShieldBash )
            {
                if ( km.Feats.GetFeatLevel(FeatList.ShieldBash) <= 0 )
                {
                    m_ErrorMessage = "You do not have the required feat.";
                    return false;
                }
                else if ( !BaseWeapon.CheckStam( attacker, km.Feats.GetFeatLevel(FeatList.ShieldBash), false, false ) )
                {
                    m_ErrorMessage = ""; // will be displayed by the checkstam thingy
                    return false;
                }

                km.CombatManeuver = new ShieldBash( km.Feats.GetFeatLevel(FeatList.ShieldBash) );
                km.OffensiveFeat = FeatList.ShieldBash;

            }
            else if ( km.OffensiveFeat == FeatList.Feint )
            {
                if ( BaseWeapon.CheckStam( attacker, km.Feats.GetFeatLevel(FeatList.Feint), false, false ) )
                    feint = true;

                weapon.EndManeuver( attacker );
            }
            else if ( km.OffensiveFeat == FeatList.FlashyAttack )
            {
                if ( BaseWeapon.CheckStam( attacker, km.Feats.GetFeatLevel(FeatList.FlashyAttack), false, false ) )
                    flashy = true;

                weapon.EndManeuver( attacker );
            }

            // standard delay is 1 second
            double delay = ComputeAnimationDelay();
            if ( attacktype == AttackType.ShieldBash )
                delay = 4.0 - (3.0*((attacker.Skills[SkillName.Parry].Base)/100.0));
            if ( feint )
                delay *= 2.5-(((double)km.Feats.GetFeatLevel(FeatList.Feint))*0.5); // lvl 1 -> 2x slower, lvl 2 -> 1.5x slower, lvl 3 -> same as normal

            if ( attacktype == AttackType.Throw )
            {
                if ( !(weapon is AzhuranBoomerang) ) // otherwise the duration is already calculated
                    delay = 0.5;
            }
            int animspeed = (int)(delay*2);
            IKhaerosMobile kmob = attacker as IKhaerosMobile;
            AttackTimer newTimer = null;
            if ( attacktype != AttackType.Circular )
            {
                newTimer = new AttackTimer( attacker, attacktype, TimeSpan.FromSeconds( delay ) );
                newTimer.Flashy = flashy;
                newTimer.Feint = feint;
                newTimer.FlashyFollowup = flashyFollowup;
            }

            if ( attacktype == AttackType.Throw ) // throws cannot have a rotationtimer anyway
            {
                SpellHelper.Turn( attacker, m_Opponent );
                m_AttackTimer = newTimer;
            }

            if ( attacktype != AttackType.Circular ) // not if we're spinning
            {
                m_AttackTimer = newTimer;
                if ( m_Opponent != null )
                { // checking of AoO is necessary so we don't force Turn, which causes jerky movement
                    m_NextAttackAction = DateTime.Now + ComputeNextSwingTime() + TimeSpan.FromSeconds( delay );
                    if ( !CheckForFreeAttack( m_Opponent, true ) ) // attack of opportunity
                    {
                        m_AttackTimer = null;
                        SpellHelper.Turn( attacker, m_Opponent );
                        m_AttackTimer = newTimer;
                    }
                    else // we DID get an AoO, so we're done here
                    {
                        if ( BandageContext.GetContext( attacker ) != null )
                        {
                            BandageContext.GetContext( attacker ).StopHeal();
                            if ( attacker is IKhaerosMobile )
                            {
                                if ( ((IKhaerosMobile)attacker).HealingTimer != null )
                                {
                                    ((IKhaerosMobile)attacker).HealingTimer.Stop();
                                    ((IKhaerosMobile)attacker).HealingTimer = null;
                                }
                            }
                        }
                        return true;
                    }
                }
            }
            int zMod = 0;
            if ( attacker is BaseCreature )
                zMod = ((BaseCreature)attacker).Height;
            if ( !feint )
            {
                if ( attacktype == AttackType.ShieldBash )
                    m_NextAttackAction = DateTime.Now + TimeSpan.FromSeconds( 1.0 );
                else
                    m_NextAttackAction = DateTime.Now + ComputeNextSwingTime() + TimeSpan.FromSeconds( delay );
            }

            switch ( (int)attacktype )
            {
                case (int)AttackType.ShieldBash:
                {
                    if ( attacker.Body.Type == BodyType.Human )
                        Animate( 30, 7, 1, true, false, animspeed );
                    else
                    {
                        int[] anim = BAData.GetAnimation( attacker, AttackType.ShieldBash );
                        if ( anim != null )
                            Animate( anim[0], anim[1], 1, true, false, animspeed );
                    }
                    break;
                }
                case (int)AttackType.Throw:
                {
                    if ( attacker.Body.Type == BodyType.Human )
                    {
                        if ( !attacker.Mounted )
                        {
                            if( weapon.Layer == Layer.OneHanded || m_OffHand )
                                Animate( 11, 7, 1, true, false, animspeed );
                            else
                                Animate( 12, 7, 1, true, false, animspeed );
                        }
                        else
                        {
                            if( weapon.Layer == Layer.OneHanded || m_OffHand )
                                Animate( 26, 8, 1, true, false, animspeed );
                            else
                                Animate( 29, 7, 1, true, false, animspeed );
                        }
                    }
                    else
                    {
                        int[] anim = BAData.GetAnimation( attacker, AttackType.Throw );
                        if ( anim == null )
                            anim = BAData.GetAnimation( attacker, AttackType.Thrust );
                        if ( anim == null )
                            anim = BAData.GetAnimation( attacker, AttackType.Overhead );
                        if ( anim == null )
                            anim = BAData.GetAnimation( attacker, AttackType.Swing );
                        if ( anim != null )
                            Animate( anim[0], anim[1], 1, true, false, animspeed );
                    }
                    break;
                }
                case (int)AttackType.Circular: goto case (int)AttackType.Swing;
                case (int)AttackType.Swing:
                {
                    IEntity from = new Entity( Server.Serial.Zero, new Point3D( attacker.X, attacker.Y, attacker.Z + zMod ), attacker.Map );
                    IEntity to = new Entity( Server.Serial.Zero, new Point3D( attacker.X, attacker.Y, attacker.Z + 25 + zMod*2 ), attacker.Map );
                    SendCombatAlerts( from, to, 9556, 3, 0, true, false, 3, 2, 9501, 1, 0, EffectLayer.Head, 0x100 );
                    if ( attacker.Body.Type == BodyType.Human )
                    {
                        if ( weapon is Fists )
                        {
                            if ( kmob.Stance is VenomousWay )
                                Animate( 9, 7, 1, true, false, animspeed ); // karate chop
                            else
                                Animate( 31, 7, 1, true, false, animspeed ); // regular wrestling
                        }
                        else
                        {
                            if ( weapon.Layer == Layer.TwoHanded )
                                Animate( 13, 7, 1, true, false, animspeed );
                            else
                                Animate( 9, 7, 1, true, false, animspeed );
                        }
                    }
                    else
                    {
                        int[] anim = BAData.GetAnimation( attacker, AttackType.Swing );
                        if ( anim == null )
                            anim = BAData.GetAnimation( attacker, AttackType.Thrust );
                        if ( anim == null )
                            anim = BAData.GetAnimation( attacker, AttackType.Overhead );
                        if ( anim != null )
                            Animate( anim[0], anim[1], 1, true, false, animspeed );
                    }
                    break;
                }

                case (int)AttackType.Thrust:
                {
                    IEntity from = new Entity( Server.Serial.Zero, new Point3D( attacker.X, attacker.Y, attacker.Z + zMod ), attacker.Map );
                    IEntity to = new Entity( Server.Serial.Zero, new Point3D( attacker.X, attacker.Y, attacker.Z + 25 + zMod*2 ), attacker.Map );
                    SendCombatAlerts( from, to, 9556, 3, 0, true, false, 62, 2, 9501, 1, 0, EffectLayer.Head, 0x100 );
                    if ( attacker.Body.Type == BodyType.Human )
                    {
                        if ( attacker.Mounted )
                            Animate( 28, 7, 1, false, false, animspeed );
                        else
                        {
                            if ( weapon.Layer == Layer.TwoHanded )
                                Animate( 14, 7, 1, true, false, animspeed );
                            else
                            {
                                if ( weapon is Fists && kmob.Stance is SearingBreath )
                                    Animate( 32, 5, 1, false, false, animspeed+2 ); // headbutt! Nah. People could abuse bow to do this.
                                else if ( weapon is Fists && kmob.Stance is TempestuousSea ) // this is fine, though, heartstopper punch!
                                    Animate( 16, 7, 1, true, false, animspeed );
                                else
                                    Animate( 10, 7, 1, true, false, animspeed );
                            }
                        }
                    }
                    else
                    {
                        int[] anim = BAData.GetAnimation( attacker, AttackType.Thrust );
                        if ( anim == null )
                            anim = BAData.GetAnimation( attacker, AttackType.Overhead );
                        if ( anim == null )
                            anim = BAData.GetAnimation( attacker, AttackType.Swing );
                        if ( anim != null )
                            Animate( anim[0], anim[1], 1, true, false, animspeed );
                    }
                    break;
                }

                case (int)AttackType.Overhead:
                {
                    IEntity from = new Entity( Server.Serial.Zero, new Point3D( attacker.X, attacker.Y, attacker.Z + zMod ), attacker.Map );
                    IEntity to = new Entity( Server.Serial.Zero, new Point3D( attacker.X, attacker.Y, attacker.Z + 25 + zMod*2 ), attacker.Map );
                    SendCombatAlerts( from, to, 9556, 3, 0, true, false, 37, 2, 9501, 1, 0, EffectLayer.Head, 0x100 );

                    if ( attacker.Body.Type == BodyType.Human )
                    {
                        if ( attacker.Mounted )
                        {
                            if ( weapon.Layer == Layer.TwoHanded )
                                Animate( 29, 7, 1, true, false, animspeed );
                            else
                                Animate( 26, 7, 1, true, false, animspeed );
                        }
                        else
                        {
                            if ( weapon.Layer == Layer.TwoHanded )
                                Animate( 12, 7, 1, true, false, animspeed );
                            else
                                Animate( 11, 7, 1, true, false, animspeed );
                        }
                    }
                    else
                    {
                        int[] anim = BAData.GetAnimation( attacker, AttackType.Overhead );
                        if ( anim == null )
                            anim = BAData.GetAnimation( attacker, AttackType.Thrust );
                        if ( anim == null )
                            anim = BAData.GetAnimation( attacker, AttackType.Swing );
                        if ( anim != null )
                            Animate( anim[0], anim[1], 1, true, false, animspeed );
                    }
                    break;
                }
            }
            if (attacktype == AttackType.Circular)
            {
                m_RotationTimer = new RotationTimer(attacker, TimeSpan.FromSeconds(delay));
                m_RotationTimer.Start();
            }
            else
            {
                if (m_AttackTimer == null)
                {
                    attacker.SendMessage("There was an error in the CombatSystemAttachment @ line 2226.");
                    return false;
                }
                else
                    m_AttackTimer.Start();
            }

            // this delays as if we were parried, but if we actually won't be, then the delay will shorten
            // what if we get interrupted, though? it should count as a hit on our part, no extra delay.
            if ( BandageContext.GetContext( attacker ) != null )
            {
                BandageContext.GetContext( attacker ).StopHeal();
                if ( attacker is IKhaerosMobile )
                {
                    if ( ((IKhaerosMobile)attacker).HealingTimer != null )
                    {
                        ((IKhaerosMobile)attacker).HealingTimer.Stop();
                        ((IKhaerosMobile)attacker).HealingTimer = null;
                    }
                }
            }

            if ( m_Opponent != null )
            {
                GetCSA( m_Opponent ).UpdateACBrainExternal();
            }

            return true;
        }
Пример #15
0
        public static void SendMeleeAttack(ILivingEntity attacker, ObjectMessageType motion, uint targetId, int unknwonParam, AttackFlags attackFlags)
        {
            using (var packet = new FFPacket())
            {
                packet.StartNewMergedPacket(attacker.Id, SnapshotType.MELEE_ATTACK);
                packet.Write((int)motion);
                packet.Write(targetId);
                packet.Write(unknwonParam);
                packet.Write((int)attackFlags);

                SendToVisible(packet, attacker);
            }
        }
        public bool CanBeginAttack( AttackFlags flags )
        {
            Mobile attacker = AttachedTo as Mobile;
            BaseWeapon weapon = attacker.Weapon as BaseWeapon;
            bool sbash = ( ((IKhaerosMobile)attacker).OffensiveFeat == FeatList.ShieldBash );
            bool disregardDelay = ((flags&AttackFlags.DisregardDelay) != AttackFlags.None);
            if ( m_PerformingSequence )
            {
                m_ErrorMessage = "You cannot do that right now.";
                return false;
            }
            else if ( ( m_AttackTimer != null && !m_AttackTimer.Feint ) || m_RotationTimer != null )
            {
                m_ErrorMessage = "You are too busy attacking.";
                return false;
            }
            else if ( weapon.CannotUseOnFoot && !attacker.Mounted && !sbash )
            {
                m_ErrorMessage = "That weapon cannot be used on foot.";
                return false;
            }
            else if ( weapon.ChargeOnly && !sbash )
            {
                m_ErrorMessage = "That weapon can only be charged with.";
                return false;
            }
            else if ( attacker.Mounted && sbash )
            {
                m_ErrorMessage = "That attack cannot be used while mounted.";
                return false;
            }
            else if( weapon.CannotUseOnMount && attacker.Mounted )
            {
                m_ErrorMessage = "That weapon cannot be used while mounted.";
                return false;
            }
            else if ( !disregardDelay && m_NextAttackAction > DateTime.Now )
            {
                m_ErrorMessage = "You must wait before performing another offensive action.";
                return false;
            }

            return true;
        }
Пример #17
0
 public virtual int GetDefense(Mover attacker, AttackFlags flags)
 {
     return(0);
 }
 public bool BeginAttack( AttackType attacktype, AttackFlags flags )
 {
     return BeginAttack( attacktype, flags, false );
 }
Пример #19
0
        public static void Process(Mover attacker, Mover defender)
        {
            AttackFlags flags = GetAttackFlags(attacker, defender);
            int damages = CalculateMeleeDamages(attacker, defender);

            if (flags.HasFlag(AttackFlags.AF_BLOCKING))
            {
                float blockFactor = GetBlockFactor(attacker, defender);

                if (blockFactor < 1f)
                    damages = (int)(damages * blockFactor);

                Log.Debug("=> {0} blocking {1}", defender.Name, attacker.Name);
            }
            if (flags.HasFlag(AttackFlags.AF_CRITICAL))
            {
                damages *= 2; // TODO: GetCriticalHitFactor

                Log.Debug("=> {0} inflicts a critical hit to {1}", attacker.Name, defender.Name);
            }
            
            damages -= GetDefense(attacker, defender, flags);

            if (flags == AttackFlags.AF_MISS)
            {
                Log.Debug("{0} misses {1}", attacker.Name, defender.Name);
                damages = 0;
            }

            if (damages < 0)
                damages = 0;

            Log.Debug("{0} inflicted {1} damages to {2}", attacker.Name, damages, defender.Name);

            // Send damages
            if (flags.HasFlag(AttackFlags.AF_FLYING)) // KnockBack
                SendDamagesFly(attacker, defender, damages, flags);
            else
                attacker.SendDamagesTo(defender, damages, flags);

            defender.Attributes[DefineAttributes.HP] -= damages;

            if (defender.Attributes[DefineAttributes.HP] <= 0)
                defender.Die();

            if (defender.IsDead)
            {
                if (defender is Monster && attacker is Player)
                {
                    var monster = defender as Monster;
                    var player = attacker as Player;
                    int experience = player.CalculateExperience(monster.Data.ExpValue);

                    // TODO: give experience for party
                    if (player.GiveExperience(experience))
                    {
                        player.SendSetLevel();
                        player.SendStatPoints();
                    }

                    player.SendExperience();
                }

                if (defender is Player && attacker is Monster)
                {
                }
            }
        }
Пример #20
0
        private static void SendDamagesFly(Mover attacker, Mover defender, int damages, AttackFlags flags)
        {
            var delta = new Vector3();
            float angle = MathHelper.ToRadian(defender.Angle);
            float angleY = MathHelper.ToRadian(145f);

            delta.Y = (float)(-Math.Cos(angleY) * 0.18f);
            float dist = (float)(Math.Sin(angleY) * 0.18f);
            delta.X = (float)(Math.Sin(angle) * dist);
            delta.Z = (float)(-Math.Cos(angle) * dist);

            defender.DestinationPosition.X += delta.X;
            defender.DestinationPosition.Z += delta.Z;
            attacker.SendDamagesTo(defender, damages, flags, defender.Position, angle);
        }
Пример #21
0
        void AddBehaviorsBasedOnFlags()
        {
            var player = Actor.Scene.Player;

            Actor.RecoilsWhenHit = Flags.HasFlag(EnemyBehaviorFlags.HasGravity);

            //if(AttackFlags.HasFlag(AttackFlags.AttackWhenClose))
            //{
            //    beginAttackCondition = beginAttackCondition.Or(Actor.IsCloseTo(player, 64)); //todo - config
            //}

            if (AttackFlags.HasFlag(AttackFlags.AttackPeriodically))
            {
                isStartingAttack = new Timer(Actor).OnceEvery(QuickGameConfig.NormalAttackFrequency).And(Actor.IsOnGround);
            }

            IsAttacking = isStartingAttack.ContinueWhile(Actor.Animations.IsAnimationPlaying(AnimationKeys.Attack));

            ////todo - config
            //if (AttackFlags.HasFlag(AttackFlags.ThrowFireball))
            //    throwFireballCondition = beginAttackCondition.And(
            //        WaitUntil(new PlayingAnimationCondition(Actor.Animations, AnimationKeys.Attack).Negate());


            //if (Flags.HasFlag(EnemyBehaviorFlags.Shoots))
            //{
            //    beginAttackCondition = new OnceEvery(new Timer(TimeSpan.FromSeconds(5), Actor), Condition.True);
            //    attackDurationCondition = beginAttackCondition.ContinueWhileAnimationPlaying(Actor.Animations, AnimationKeys.Attack);
            //}

            //    new AnimationController<TEnemy>(Actor, attackDurationCondition, null);


            //if (Flags.HasFlag(EnemyBehaviorFlags.FollowsPlayer))
            //{
            //    Actor.Face(player);
            //    Actor.AlwaysFace(player, new OnceEvery(new Timer(TimeSpan.FromSeconds(2), Actor)));
            //}
            //else
            //{
            //    Actor.Direction = Direction.Left;
            //}

            if (Flags.HasFlag(EnemyBehaviorFlags.MovesFast))
            {
                Actor.Motion.AddAdjuster(new GroundMotion <TEnemy>(Actor, Config.ReadValue <AxisMotionConfig>("fast motion")));
            }
            else if (Flags.HasFlag(EnemyBehaviorFlags.MovesMore))
            {
                Actor.Motion.AddAdjuster(new GroundMotion <TEnemy>(Actor, Config.ReadValue <AxisMotionConfig>("medium motion")));
            }
            else if (Flags.HasFlag(EnemyBehaviorFlags.Moves))
            {
                Actor.Motion.AddAdjuster(new GroundMotion <TEnemy>(Actor, Config.ReadValue <AxisMotionConfig>("slow motion")));
            }

            if (Flags.HasFlag(EnemyBehaviorFlags.HasGravity))
            {
                Actor.AddGravity();
            }

            //    //todo - make work better with FacePlayer

            //    //if(!Flags.HasFlag(EnemyBehaviorFlags.FallsOfLedges))
            //    //{
            //    //    new LambdaAction<Actor>(Actor, UpdatePriority.Behavior, Actor.Scene, TileChecker.IsAtWall.Or(TileChecker.IsOnLedge),
            //    //        (a, t) =>
            //    //        {
            //    //            //if (a.Position.GetEdgeDistanceTo(TileChecker.NextWallTile.Position, Axis.X) <= 1)
            //    //                a.Direction = a.DirectionAwayFrom(TileChecker.NextWallTile, Axis.X);
            //    //        });
            //    //}

            //    if(Flags.HasFlag(EnemyBehaviorFlags.CanJump))
            //    {
            //        throw new NotImplementedException();
            //        //var jumpMotion = new AxisMotion("enemy jump", Actor).Set(deactivateAfterStart: true);
            //        //JumpForwardMotion = new AxisMotion("enemy jump X", Actor).Set(flipWhen: Direction.Left, deactivateWhenTargetReached:false);

            //        //Actor.Motion.Forces.Add(jumpMotion);

            //        //new LambdaAction<Actor>(Actor, UpdatePriority.Behavior, Actor.Scene, TileChecker.IsAtWall.Or(TileChecker.IsOnLedge),
            //        //   (a, t) =>
            //        //   {
            //        //       if (TileChecker.IsAtWall.IsActive ||
            //        //            Flags.HasFlag(EnemyBehaviorFlags.FallsOfLedges) && TileChecker.IsOnDangerousLedge.IsActive)
            //        //       {
            //        //           jumpMotion.Active = true;
            //        //           JumpForwardMotion.Active = true;
            //        //       }
            //        //   });
            //    }
            //}
        }
Пример #22
0
        /// <summary>
        /// Calculates the given monster defense.
        /// </summary>
        /// <param name="defenderMonster">Monster entity defending an attack.</param>
        /// <param name="attackFlags">Attack flags.</param>
        /// <returns>Monster's defense.</returns>
        private int GetMonsterDefense(IMonsterEntity defenderMonster, AttackFlags attackFlags)
        {
            var monsterDefenseArmor = attackFlags.HasFlag(AttackFlags.AF_MAGIC) ? defenderMonster.Data.MagicResitance : defenderMonster.Data.NaturalArmor;

            return((int)(monsterDefenseArmor / 7f + 1));
        }