Exemplo n.º 1
0
        public ActionChain DoSwingMotion(WorldObject target, out float animLength)
        {
            // FIXME: proper swing animation speeds
            var baseSpeed    = GetAnimSpeed();
            var animSpeedMod = IsDualWieldAttack ? 1.2f : 1.0f;     // dual wield swing animation 20% faster
            var animSpeed    = baseSpeed * animSpeedMod;

            var swingAnimation = new MotionItem(GetSwingAnimation(), animSpeed);

            animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, swingAnimation.Motion, animSpeed);

            var motion = new UniversalMotion(CurrentMotionState.Stance, swingAnimation);

            motion.MovementData.CurrentStyle = (uint)CurrentMotionState.Stance;
            motion.MovementData.TurnSpeed    = 2.25f;
            motion.HasTarget   = true;
            motion.TargetGuid  = target.Guid;
            CurrentMotionState = motion;

            var actionChain = new ActionChain();

            actionChain.AddAction(this, () => EnqueueBroadcastMotion(motion));
            actionChain.AddDelaySeconds(animLength);
            actionChain.AddAction(this, () => Session.Network.EnqueueSend(new GameEventAttackDone(Session)));
            actionChain.AddAction(this, () => Session.Network.EnqueueSend(new GameEventCombatCommmenceAttack(Session)));
            actionChain.AddAction(this, () => Session.Network.EnqueueSend(new GameEventAttackDone(Session)));
            return(actionChain);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Executes the weapon reload animation for the player
        /// </summary>
        public float ReloadMotion()
        {
            var reloadAnimation = new MotionItem(GetReloadAnimation(), 1.0f);
            var animLength      = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, reloadAnimation);

            var motion = new UniversalMotion(CurrentMotionState.Stance);

            motion.MovementData.CurrentStyle   = (uint)CurrentMotionState.Stance;
            motion.MovementData.ForwardCommand = (uint)MotionCommand.Reload;
            motion.MovementData.TurnSpeed      = 2.25f;
            //motion.HasTarget = true;
            //motion.TargetGuid = target.Guid;
            CurrentMotionState = motion;

            var actionChain = new ActionChain();

            actionChain.AddAction(this, () => DoMotion(motion));
            actionChain.AddDelaySeconds(animLength);
            actionChain.AddAction(this, () =>
            {
                motion.MovementData.ForwardCommand = (uint)MotionCommand.Invalid;
                DoMotion(motion);
                CurrentMotionState = motion;
            });
            actionChain.AddDelaySeconds(animLength);
            actionChain.AddAction(this, () => Session.Network.EnqueueSend(new GameEventAttackDone(Session)));
            actionChain.AddAction(this, () => Session.Network.EnqueueSend(new GameEventCombatCommmenceAttack(Session)));
            actionChain.AddAction(this, () => Session.Network.EnqueueSend(new GameEventAttackDone(Session)));
            actionChain.EnqueueChain();

            var weapon     = GetEquippedWeapon();
            var reloadTime = weapon.DefaultCombatStyle == CombatStyle.Crossbow ? 3.2f : 1.6f;

            return(animLength * reloadTime);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Switches a player or creature to magic casting stance
        /// </summary>
        public float HandleSwitchToMagicCombatMode()
        {
            var wand = GetEquippedWand();

            if (wand == null)
            {
                return(0.0f);
            }

            var animLength = SwitchCombatStyles();

            animLength += MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Ready, MotionCommand.Magic);

            var motion = new Motion(MotionStance.Magic);

            ExecuteMotion(motion);

            var player = this as Player;

            if (player != null)
            {
                player.HandleActionTradeSwitchToCombatMode(player.Session);
                player.Session.Network.EnqueueSend(new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.CombatMode, (int)CombatMode.Magic));
            }

            //Console.WriteLine("HandleSwitchToMagicCombatMode() - animLength: " + animLength);
            return(animLength);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Perform the melee attack swing animation
        /// </summary>
        public void DoSwingMotion(WorldObject target, MotionCommand motionCommand, out float animLength, out List <float> attackFrames)
        {
            if (ForcePos)
            {
                SendUpdatePosition();
            }

            //Console.WriteLine($"{maneuver.Style} - {maneuver.Motion} - {maneuver.AttackHeight}");

            var baseSpeed    = GetAnimSpeed();
            var animSpeedMod = IsDualWieldAttack ? 1.2f : 1.0f;     // dual wield swing animation 20% faster
            var animSpeed    = baseSpeed * animSpeedMod;

            animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, motionCommand, animSpeed);

            attackFrames = MotionTable.GetAttackFrames(MotionTableId, CurrentMotionState.Stance, motionCommand);

            var motion = new Motion(this, motionCommand, animSpeed);

            motion.MotionState.TurnSpeed = 2.25f;
            if (!AiImmobile)
            {
                motion.MotionFlags |= MotionFlags.StickToObject;
            }

            motion.TargetGuid  = target.Guid;
            CurrentMotionState = motion;

            EnqueueBroadcastMotion(motion);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Switches a player or creature to melee attack stance
        /// </summary>
        public float HandleSwitchToMeleeCombatMode()
        {
            // get appropriate combat stance for currently wielded items
            var combatStance = GetCombatStance();

            var animLength = SwitchCombatStyles();

            animLength += MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Ready, (MotionCommand)combatStance);

            var motion = new UniversalMotion(combatStance);

            motion.MovementData.CurrentStyle = (uint)combatStance;
            ExecuteMotion(motion);

            var player = this as Player;

            if (player != null)
            {
                player.HandleActionTradeSwitchToCombatMode(player.Session);
                player.Session.Network.EnqueueSend(new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.CombatMode, (int)CombatMode.Melee));
            }

            //Console.WriteLine("HandleSwitchToMeleeCombatMode() - animLength: " + animLength);
            return(animLength);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Perform the melee attack swing animation
        /// </summary>
        public void DoSwingMotion(WorldObject target, CombatManeuver maneuver, out float animLength, out List <float> attackFrames)
        {
            if (ForcePos)
            {
                SendUpdatePosition();
            }

            var animSpeed = GetAnimSpeed();

            animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, maneuver.Motion, animSpeed);

            attackFrames = MotionTable.GetAttackFrames(MotionTableId, CurrentMotionState.Stance, maneuver.Motion);

            var motion = new Motion(this, maneuver.Motion, animSpeed);

            motion.MotionState.TurnSpeed = 2.25f;
            if (!AiImmobile)
            {
                motion.MotionFlags |= MotionFlags.StickToObject;
            }

            motion.TargetGuid  = target.Guid;
            CurrentMotionState = motion;

            EnqueueBroadcastMotion(motion);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Handles switching between combat stances:
        /// old style -> peace mode -> hand combat (weapon swap) -> peace mode -> new style
        /// </summary>
        public float SwitchCombatStyles()
        {
            if (CurrentMotionState.Stance == MotionStance.NonCombat || CurrentMotionState.Stance == MotionStance.Invalid || IsMonster)
            {
                return(0.0f);
            }

            var combatStance = GetCombatStance();

            float peace1 = 0.0f, unarmed = 0.0f, peace2 = 0.0f;

            // this is now handled as a proper 2-step process in HandleActionChangeCombatMode / NextUseTime

            // FIXME: just call generic method to switch to HandCombat first
            peace1 = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Ready, MotionCommand.NonCombat);

            /*if (CurrentMotionState.Stance != MotionStance.HandCombat && combatStance != MotionStance.HandCombat)
             * {
             *  unarmed = MotionTable.GetAnimationLength(MotionTableId, MotionStance.NonCombat, MotionCommand.Ready, MotionCommand.HandCombat);
             *  peace2 = MotionTable.GetAnimationLength(MotionTableId, MotionStance.HandCombat, MotionCommand.Ready, MotionCommand.NonCombat);
             * }*/

            SetStance(MotionStance.NonCombat, false);

            //Console.WriteLine($"SwitchCombatStyle() - animLength: {animLength}");
            //Console.WriteLine($"SwitchCombatStyle() - peace1({peace1}) + unarmed({unarmed}) + peace2({peace2})");
            var animLength = peace1 + unarmed + peace2;

            return(animLength);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Handles switching between combat stances:
        /// old style -> peace mode -> hand combat (weapon swap) -> peace mode -> new style
        /// </summary>
        public float SwitchCombatStyles()
        {
            if (CurrentMotionState.Stance == MotionStance.NonCombat || CurrentMotionState.Stance == MotionStance.Invalid)
            {
                return(0.0f);
            }

            var combatStance = GetCombatStance();

            float peace1 = 0.0f, unarmed = 0.0f, peace2 = 0.0f;

            peace1 = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Ready, MotionCommand.NonCombat);
            if (CurrentMotionState.Stance != MotionStance.HandCombat && combatStance != MotionStance.HandCombat)
            {
                unarmed = MotionTable.GetAnimationLength(MotionTableId, MotionStance.NonCombat, MotionCommand.Ready, MotionCommand.HandCombat);
                peace2  = MotionTable.GetAnimationLength(MotionTableId, MotionStance.HandCombat, MotionCommand.Ready, MotionCommand.NonCombat);
            }

            CurrentMotionState = new UniversalMotion(MotionStance.NonCombat);

            //Console.WriteLine($"SwitchCombatStyle() - animLength: {animLength}");
            //Console.WriteLine($"SwitchCombatStyle() - peace1({peace1}) + unarmed({unarmed}) + peace2({peace2})");
            var animLength = peace1 + unarmed + peace2;

            return(animLength);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Handles switching between combat stances:
        /// old style -> peace mode -> hand combat (weapon swap) -> peace mode -> new style
        /// </summary>
        public float SwitchCombatStyles()
        {
            if (CurrentMotionState.Stance == MotionStance.NonCombat || CurrentMotionState.Stance == MotionStance.Invalid || IsMonster)
            {
                return(0.0f);
            }

            var combatStance = GetCombatStance();

            float peace1 = 0.0f, unarmed = 0.0f, peace2 = 0.0f;

            // FIXME: just call generic method to switch to HandCombat first
            peace1 = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Ready, MotionCommand.NonCombat);
            if (CurrentMotionState.Stance != MotionStance.HandCombat && combatStance != MotionStance.HandCombat)
            {
                unarmed = MotionTable.GetAnimationLength(MotionTableId, MotionStance.NonCombat, MotionCommand.Ready, MotionCommand.HandCombat);
                peace2  = MotionTable.GetAnimationLength(MotionTableId, MotionStance.HandCombat, MotionCommand.Ready, MotionCommand.NonCombat);
            }

            SetStance(MotionStance.NonCombat, false);

            //Console.WriteLine($"SwitchCombatStyle() - animLength: {animLength}");
            //Console.WriteLine($"SwitchCombatStyle() - peace1({peace1}) + unarmed({unarmed}) + peace2({peace2})");
            var animLength = peace1 + unarmed + peace2;

            return(animLength);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Executes the weapon reload animation for the player
        /// </summary>
        public float ReloadMotion()
        {
            var reloadAnimation = new MotionItem(GetReloadAnimation(), 1.0f);
            var animLength      = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, reloadAnimation);

            var motion = new UniversalMotion(CurrentMotionState.Stance);

            motion.MovementData.CurrentStyle   = (uint)CurrentMotionState.Stance;
            motion.MovementData.ForwardCommand = (uint)MotionCommand.Reload;
            motion.MovementData.TurnSpeed      = 2.25f;
            //motion.HasTarget = true;
            //motion.TargetGuid = target.Guid;
            CurrentMotionState = motion;

            var actionChain = new ActionChain();

            actionChain.AddAction(this, () => DoMotion(motion));

            actionChain.AddDelaySeconds(animLength);
            actionChain.AddAction(this, () =>
            {
                motion.MovementData.ForwardCommand = (uint)MotionCommand.Invalid;
                DoMotion(motion);
                CurrentMotionState = motion;
            });

            var ammo = GetEquippedAmmo();

            if (ammo != null)
            {
                actionChain.AddAction(this, () => EnqueueBroadcast(
                                          new GameMessageParentEvent(this, ammo, (int)ACE.Entity.Enum.ParentLocation.RightHand,
                                                                     (int)ACE.Entity.Enum.Placement.RightHandCombat)));
            }

            actionChain.AddDelaySeconds(animLength);

            var player = this as Player;

            if (player != null)
            {
                actionChain.AddAction(this, () => player.Session.Network.EnqueueSend(new GameEventAttackDone(player.Session)));
                actionChain.AddAction(this, () => player.Session.Network.EnqueueSend(new GameEventCombatCommmenceAttack(player.Session)));
                // TODO: This gets rid of the hourglass but doesn't seem to be sent in retail pcaps...
                actionChain.AddAction(this, () => player.Session.Network.EnqueueSend(new GameEventAttackDone(player.Session)));
            }
            actionChain.EnqueueChain();

            var weapon     = GetEquippedWeapon();
            var reloadTime = weapon.DefaultCombatStyle == CombatStyle.Crossbow ? 3.2f : 1.6f;

            return(animLength * reloadTime);
        }
Exemplo n.º 11
0
        public float ReloadMissileAmmo(ActionChain actionChain = null)
        {
            var weapon = GetEquippedMissileWeapon();
            var ammo   = GetEquippedAmmo();

            if (weapon == null || ammo == null)
            {
                return(0.0f);
            }

            var newChain = actionChain == null;

            if (newChain)
            {
                actionChain = new ActionChain();
            }

            var animLength = 0.0f;

            if (weapon.IsAmmoLauncher)
            {
                var animSpeed = GetAnimSpeed();
                //Console.WriteLine($"AnimSpeed: {animSpeed}");

                animLength = EnqueueMotion(actionChain, MotionCommand.Reload, animSpeed); // start pulling out next arrow
                EnqueueMotion(actionChain, MotionCommand.Ready);                          // finish reloading
            }

            // ensure ammo visibility for players
            actionChain.AddAction(this, () =>
            {
                EnqueueActionBroadcast(p => p.TrackEquippedObject(this, ammo));

                var delayChain = new ActionChain();
                delayChain.AddDelaySeconds(0.001f);     // ensuring this message gets sent after player broadcasts above...
                delayChain.AddAction(this, () =>
                {
                    EnqueueBroadcast(new GameMessageParentEvent(this, ammo, ACE.Entity.Enum.ParentLocation.RightHand, ACE.Entity.Enum.Placement.RightHandCombat));
                });
                delayChain.EnqueueChain();
            });

            if (newChain)
            {
                actionChain.EnqueueChain();
            }

            var animLength2 = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Reload, MotionCommand.Ready);

            //Console.WriteLine($"AnimLength: {animLength} + {animLength2}");

            return(animLength + animLength2);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Perform the melee attack swing animation
        /// </summary>
        public void DoSwingMotion(WorldObject target, CombatManeuver maneuver, out float animLength)
        {
            var animSpeed = GetAnimSpeed();

            animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, maneuver.Motion, animSpeed);

            var motion = new Motion(this, maneuver.Motion, animSpeed);

            motion.MotionState.TurnSpeed = 2.25f;
            motion.MotionFlags          |= MotionFlags.StickToObject;
            motion.TargetGuid            = target.Guid;
            CurrentMotionState           = motion;

            EnqueueBroadcastMotion(motion);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Perform the melee attack swing animation
        /// </summary>
        public virtual ActionChain DoSwingMotion(WorldObject target, out float animLength)
        {
            var swingAnimation = new MotionItem(GetSwingAnimation(), 1.25f);

            animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, swingAnimation);

            var motion = new UniversalMotion(CurrentMotionState.Stance, swingAnimation);

            motion.MovementData.CurrentStyle = (uint)CurrentMotionState.Stance;
            motion.MovementData.TurnSpeed    = 2.25f;
            motion.HasTarget   = true;
            motion.TargetGuid  = target.Guid;
            CurrentMotionState = motion;

            CurrentLandblock.EnqueueBroadcastMotion(this, motion);

            return(null);
        }
Exemplo n.º 14
0
        /// <summary>
        /// Perform the melee attack swing animation
        /// </summary>
        public void DoSwingMotion(WorldObject target, CombatManeuver maneuver, out float animLength)
        {
            var animSpeed = GetAnimSpeed();

            var swingAnimation = new MotionItem(maneuver.Motion, animSpeed);

            animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, maneuver.Motion, animSpeed);

            var motion = new UniversalMotion(CurrentMotionState.Stance, swingAnimation);

            motion.MovementData.CurrentStyle = (uint)CurrentMotionState.Stance;
            motion.MovementData.TurnSpeed    = 2.25f;
            motion.HasTarget   = true;
            motion.TargetGuid  = target.Guid;
            CurrentMotionState = motion;

            EnqueueBroadcastMotion(motion);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Switches a player or creature to non-combat mode
        /// </summary>
        public float HandleSwitchToPeaceMode()
        {
            var animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Ready, MotionCommand.NonCombat);

            var motion = new Motion(MotionStance.NonCombat);

            ExecuteMotion(motion);

            var player = this as Player;

            if (player != null)
            {
                player.stance = MotionStance.NonCombat;
                player.Session.Network.EnqueueSend(new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.CombatMode, (int)CombatMode.NonCombat));
            }

            //Console.WriteLine("HandleSwitchToPeaceMode() - animLength: " + animLength);
            return(animLength);
        }
Exemplo n.º 16
0
        /// <summary>
        /// Performs the player melee swing animation
        /// </summary>
        public float DoSwingMotion(WorldObject target)
        {
            // get the proper animation speed for this attack,
            // based on weapon speed and player quickness
            var baseSpeed    = GetAnimSpeed();
            var animSpeedMod = IsDualWieldAttack ? 1.2f : 1.0f;     // dual wield swing animation 20% faster
            var animSpeed    = baseSpeed * animSpeedMod;

            var swingAnimation = GetSwingAnimation();
            var animLength     = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, swingAnimation, animSpeed);

            // broadcast player swing animation to clients
            var motion = new Motion(this, swingAnimation, animSpeed);

            motion.MotionState.TurnSpeed = 2.25f;
            motion.MotionFlags          |= MotionFlags.StickToObject;
            motion.TargetGuid            = target.Guid;
            CurrentMotionState           = motion;

            EnqueueBroadcastMotion(motion);
            return(animLength);
        }
Exemplo n.º 17
0
        public float ReloadMissileAmmo()
        {
            var weapon = GetEquippedMissileWeapon();
            var ammo   = GetEquippedAmmo();

            if (weapon == null || ammo == null)
            {
                return(0.0f);
            }

            var actionChain = new ActionChain();

            var animLength = 0.0f;

            if (weapon.IsBow)
            {
                EnqueueMotion(actionChain, MotionCommand.Reload);   // start pulling out next arrow
                EnqueueMotion(actionChain, MotionCommand.Ready);    // finish reloading

                animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Reload, MotionCommand.Ready);
                actionChain.AddDelaySeconds(animLength);
            }

            // ensure ammo visibility for players
            actionChain.AddAction(this, () =>
            {
                EnqueueBroadcast(new GameMessageParentEvent(this, ammo, (int)ACE.Entity.Enum.ParentLocation.RightHand, (int)ACE.Entity.Enum.Placement.RightHandCombat));
                EnqueueActionBroadcast((Player p) => p.TrackObject(this));
            });

            actionChain.EnqueueChain();

            var animLength2 = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Ready, MotionCommand.Reload);

            //Console.WriteLine($"AnimLength: {animLength} + {animLength2}");

            return(animLength + animLength2);
        }
Exemplo n.º 18
0
        public override ActionChain DoSwingMotion(WorldObject target, out float animLength)
        {
            var swingAnimation = new MotionItem(GetSwingAnimation(), 1.25f);

            animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, swingAnimation);

            var motion = new UniversalMotion(CurrentMotionState.Stance, swingAnimation);

            motion.MovementData.CurrentStyle = (uint)CurrentMotionState.Stance;
            motion.MovementData.TurnSpeed    = 2.25f;
            motion.HasTarget   = true;
            motion.TargetGuid  = target.Guid;
            CurrentMotionState = motion;

            var actionChain = new ActionChain();

            actionChain.AddAction(this, () => DoMotion(motion));
            actionChain.AddDelaySeconds(animLength);
            actionChain.AddAction(this, () => Session.Network.EnqueueSend(new GameEventAttackDone(Session)));
            actionChain.AddAction(this, () => Session.Network.EnqueueSend(new GameEventCombatCommmenceAttack(Session)));
            actionChain.AddAction(this, () => Session.Network.EnqueueSend(new GameEventAttackDone(Session)));
            return(actionChain);
        }
Exemplo n.º 19
0
        /// <summary>
        /// Perform the melee attack swing animation
        /// </summary>
        public ActionChain DoSwingMotion(WorldObject target, CombatManeuver maneuver, out float animLength)
        {
            var animSpeed = GetAnimSpeed();

            var swingAnimation = new MotionItem(maneuver.Motion, animSpeed);

            animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, maneuver.Motion, null, animSpeed);

            var motion = new UniversalMotion(CurrentMotionState.Stance, swingAnimation);

            motion.MovementData.CurrentStyle = (uint)CurrentMotionState.Stance;
            motion.MovementData.TurnSpeed    = 2.25f;
            motion.HasTarget   = true;
            motion.TargetGuid  = target.Guid;
            CurrentMotionState = motion;

            EnqueueBroadcastMotion(motion);

            // play default script? (special attack)
            //if (MotionTable.HasDefaultScript(MotionTableId, maneuver.Motion, maneuver.Style))
            //EnqueueBroadcast(new GameMessageScript(Guid, (PlayScript)DefaultScriptId));

            return(null);
        }
Exemplo n.º 20
0
        /// <summary>
        /// Switches a player or creature to a missile combat stance
        /// </summary>
        public float HandleSwitchToMissileCombatMode()
        {
            // get appropriate combat stance for currently wielded items
            var weapon = GetEquippedMissileWeapon();

            if (weapon == null)
            {
                return(0.0f);
            }

            var combatStance = GetCombatStance();

            var animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, (MotionCommand)combatStance, MotionCommand.Ready);

            var motion = new UniversalMotion(combatStance);

            motion.MovementData.CurrentStyle = (uint)combatStance;
            SetMotionState(this, motion);

            var ammo = GetEquippedAmmo();

            if (ammo != null && weapon.IsAmmoLauncher)
            {
                animLength += ReloadMissileAmmo();
            }

            var player = this as Player;

            if (player != null)
            {
                player.HandleActionTradeSwitchToCombatMode(player.Session);
                player.Session.Network.EnqueueSend(new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.CombatMode, (int)CombatMode.Missile));
            }
            //Console.WriteLine("HandleSwitchToMissileCombatMode() - animLength: " + animLength);
            return(animLength);
        }
Exemplo n.º 21
0
        private static void HandleCreateItemRecipe(Player player, WorldObject source, WorldObject target, Recipe recipe)
        {
            ActionChain   craftChain     = new ActionChain();
            CreatureSkill skill          = null;
            bool          skillSuccess   = true; // assume success, unless there's a skill check
            double        percentSuccess = 1;

            UniversalMotion motion = new UniversalMotion(MotionStance.Standing, new MotionItem(MotionCommand.ClapHands));

            craftChain.AddAction(player, () => player.HandleActionMotion(motion));
            float craftAnimationLength = MotionTable.GetAnimationLength((uint)player.MotionTableId, MotionCommand.ClapHands);

            craftChain.AddDelaySeconds(craftAnimationLength);
            // craftChain.AddDelaySeconds(0.5);

            craftChain.AddAction(player, () =>
            {
                if (recipe.SkillId != null && recipe.SkillDifficulty != null)
                {
                    // there's a skill associated with this
                    Skill skillId = (Skill)recipe.SkillId.Value;

                    // this shouldn't happen, but sanity check for unexpected nulls
                    if (!player.Skills.ContainsKey(skillId))
                    {
                        log.Warn("Unexpectedly missing skill in Recipe usage");
                        player.SendUseDoneEvent();
                        return;
                    }

                    skill          = player.Skills[skillId];
                    percentSuccess = skill.GetPercentSuccess(recipe.SkillDifficulty.Value);
                }

                // straight skill check, if applciable
                if (skill != null)
                {
                    skillSuccess = _random.NextDouble() < percentSuccess;
                }

                if ((recipe.ResultFlags & (uint)RecipeResult.SourceItemDestroyed) > 0)
                {
                    player.DestroyInventoryItem(source);
                }

                if ((recipe.ResultFlags & (uint)RecipeResult.TargetItemDestroyed) > 0)
                {
                    player.DestroyInventoryItem(target);
                }

                if ((recipe.ResultFlags & (uint)RecipeResult.SourceItemUsesDecrement) > 0)
                {
                    if (source.Structure <= 1)
                    {
                        player.DestroyInventoryItem(source);
                    }
                    else
                    {
                        source.Structure--;
                        source.SendPartialUpdates(player.Session, _updateStructure);
                    }
                }

                if ((recipe.ResultFlags & (uint)RecipeResult.TargetItemUsesDecrement) > 0)
                {
                    if (target.Structure <= 1)
                    {
                        player.DestroyInventoryItem(target);
                    }
                    else
                    {
                        target.Structure--;
                        target.SendPartialUpdates(player.Session, _updateStructure);
                    }
                }

                if (skillSuccess)
                {
                    WorldObject newObject1 = null;
                    WorldObject newObject2 = null;

                    if ((recipe.ResultFlags & (uint)RecipeResult.SuccessItem1) > 0 && recipe.SuccessItem1Wcid != null)
                    {
                        newObject1 = player.AddNewItemToInventory(recipe.SuccessItem1Wcid.Value);
                    }

                    if ((recipe.ResultFlags & (uint)RecipeResult.SuccessItem2) > 0 && recipe.SuccessItem2Wcid != null)
                    {
                        newObject2 = player.AddNewItemToInventory(recipe.SuccessItem2Wcid.Value);
                    }

                    var text    = string.Format(recipe.SuccessMessage, source.Name, target.Name, newObject1?.Name, newObject2?.Name);
                    var message = new GameMessageSystemChat(text, ChatMessageType.Craft);
                    player.Session.Network.EnqueueSend(message);
                }
                else
                {
                    WorldObject newObject1 = null;
                    WorldObject newObject2 = null;

                    if ((recipe.ResultFlags & (uint)RecipeResult.FailureItem1) > 0 && recipe.FailureItem1Wcid != null)
                    {
                        newObject1 = player.AddNewItemToInventory(recipe.FailureItem1Wcid.Value);
                    }

                    if ((recipe.ResultFlags & (uint)RecipeResult.FailureItem2) > 0 && recipe.FailureItem2Wcid != null)
                    {
                        newObject2 = player.AddNewItemToInventory(recipe.FailureItem2Wcid.Value);
                    }

                    var text    = string.Format(recipe.FailMessage, source.Name, target.Name, newObject1?.Name, newObject2?.Name);
                    var message = new GameMessageSystemChat(text, ChatMessageType.Craft);
                    player.Session.Network.EnqueueSend(message);
                }

                player.SendUseDoneEvent();
            });

            craftChain.EnqueueChain();
        }
Exemplo n.º 22
0
        /// <summary>
        /// Launches a missile attack from monster to target
        /// </summary>
        public void LaunchMissile()
        {
            IsTurning = false;

            var weapon = GetEquippedMissileWeapon();

            if (weapon == null || AttackTarget == null)
            {
                return;
            }

            var ammo = weapon.IsAmmoLauncher ? GetEquippedAmmo() : weapon;

            if (ammo == null)
            {
                return;
            }

            // should this be called each launch?
            AttackHeight = ChooseAttackHeight();

            var dist = GetDistanceToTarget();
            //Console.WriteLine("RangeAttack: " + dist);

            // launch animation
            var actionChain = new ActionChain();
            var launchTime  = EnqueueMotion(actionChain, MotionCommand.AimLevel);
            //Console.WriteLine("LaunchTime: " + launchTime);

            // launch projectile
            float targetTime = 0.0f;

            actionChain.AddAction(this, () =>
            {
                var sound = GetLaunchMissileSound(weapon);
                EnqueueBroadcast(new GameMessageSound(Guid, sound, 1.0f));

                // TODO: monster stamina usage

                var projectile = LaunchProjectile(ammo, AttackTarget, out targetTime);
                UpdateAmmoAfterLaunch(ammo);
            });

            // reload animation
            var reloadTime = EnqueueMotion(actionChain, MotionCommand.Reload);

            //Console.WriteLine("ReloadTime: " + reloadTime);

            // reset for next projectile
            EnqueueMotion(actionChain, MotionCommand.Ready);
            var linkTime = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Ready, MotionCommand.Reload);

            //Console.WriteLine("LinkTime: " + linkTime);

            actionChain.AddAction(this, () => EnqueueBroadcast(new GameMessageParentEvent(this, ammo, (int)ACE.Entity.Enum.ParentLocation.RightHand,
                                                                                          (int)ACE.Entity.Enum.Placement.RightHandCombat)));

            actionChain.EnqueueChain();

            var timeOffset = launchTime + reloadTime + linkTime;

            if (timeOffset < MissileDelay)
            {
                timeOffset = MissileDelay;
            }

            NextAttackTime = Timer.CurrentTime + timeOffset;
        }
Exemplo n.º 23
0
        /// <summary>
        /// Launches a missile attack from monster to target
        /// </summary>
        public void LaunchMissile()
        {
            //IsTurning = false;

            var weapon = GetEquippedMissileWeapon();

            if (weapon == null || AttackTarget == null)
            {
                return;
            }

            var ammo = weapon.IsAmmoLauncher ? GetEquippedAmmo() : weapon;

            if (ammo == null)
            {
                return;
            }

            // ensure direct line of sight
            if (!IsDirectVisible(AttackTarget))
            {
                NextAttackTime = Timers.RunningTime + 1.0f;
                return;
            }

            // should this be called each launch?
            AttackHeight = ChooseAttackHeight();

            var dist = GetDistanceToTarget();

            //Console.WriteLine("RangeAttack: " + dist);

            if (DebugMove)
            {
                Console.WriteLine($"[{Timers.RunningTime}] - {Name} ({Guid}) - LaunchMissile");
            }

            // launch animation
            var actionChain = new ActionChain();
            var launchTime  = EnqueueMotion(actionChain, MotionCommand.AimLevel);
            //Console.WriteLine("LaunchTime: " + launchTime);

            // launch projectile
            float targetTime = 0.0f;

            actionChain.AddAction(this, () =>
            {
                if (IsDead)
                {
                    return;
                }

                var sound = GetLaunchMissileSound(weapon);
                EnqueueBroadcast(new GameMessageSound(Guid, sound, 1.0f));

                // TODO: monster stamina usage

                if (AttackTarget != null)
                {
                    var projectile = LaunchProjectile(weapon, ammo, AttackTarget, out targetTime);
                    UpdateAmmoAfterLaunch(ammo);
                }
            });

            // will ammo be depleted?

            /*if (ammo.StackSize == null || ammo.StackSize <= 1)
             * {
             *  // compare monsters: lugianmontokrenegade /  sclavusse / zombielichtowerarcher
             *  actionChain.EnqueueChain();
             *  NextMoveTime = NextAttackTime = Timers.RunningTime + launchTime + MissileDelay;
             *  return;
             * }*/

            // reload animation
            var animSpeed  = GetAnimSpeed();
            var reloadTime = EnqueueMotion(actionChain, MotionCommand.Reload, animSpeed);

            //Console.WriteLine("ReloadTime: " + reloadTime);

            // reset for next projectile
            EnqueueMotion(actionChain, MotionCommand.Ready);

            var linkTime = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Reload, MotionCommand.Ready);

            if (weapon.IsThrownWeapon)
            {
                actionChain.EnqueueChain();

                actionChain = new ActionChain();
                actionChain.AddDelaySeconds(linkTime);
            }
            //Console.WriteLine($"Reload time: launchTime({launchTime}) + reloadTime({reloadTime}) + linkTime({linkTime})");

            actionChain.AddAction(this, () => EnqueueBroadcast(new GameMessageParentEvent(this, ammo, ACE.Entity.Enum.ParentLocation.RightHand,
                                                                                          ACE.Entity.Enum.Placement.RightHandCombat)));

            actionChain.EnqueueChain();

            var timeOffset = launchTime + reloadTime + linkTime;

            var missileDelay = MissileDelay;

            if (!weapon.IsAmmoLauncher)
            {
                missileDelay *= 1.5f;
            }

            NextMoveTime = NextAttackTime = Timers.RunningTime + timeOffset + missileDelay;
        }
Exemplo n.º 24
0
        /// <summary>
        /// Launches a missile attack from monster to target
        /// </summary>
        public void LaunchMissile()
        {
            //IsTurning = false;

            var weapon = GetEquippedMissileWeapon();

            if (weapon == null || AttackTarget == null)
            {
                return;
            }

            var ammo = weapon.IsAmmoLauncher ? GetEquippedAmmo() : weapon;

            if (ammo == null)
            {
                return;
            }

            /*if (!IsDirectVisible(AttackTarget))
             * {
             *  // ensure direct line of sight
             *  //NextAttackTime = Timers.RunningTime + 1.0f;
             *  SwitchToMeleeAttack();
             *  return;
             * }*/
            if (SwitchWeaponsPending)
            {
                NextAttackTime = Timers.RunningTime + 1.0f;
                return;
            }

            // should this be called each launch?
            AttackHeight = ChooseAttackHeight();

            var dist = GetDistanceToTarget();

            //Console.WriteLine("RangeAttack: " + dist);

            if (DebugMove)
            {
                Console.WriteLine($"[{Timers.RunningTime}] - {Name} ({Guid}) - LaunchMissile");
            }

            var projectileSpeed = GetProjectileSpeed();

            // get z-angle for aim motion
            var aimVelocity = GetAimVelocity(AttackTarget, projectileSpeed);

            var aimLevel = GetAimLevel(aimVelocity);

            // calculate projectile spawn pos and velocity
            var localOrigin = GetProjectileSpawnOrigin(ammo.WeenieClassId, aimLevel);

            var velocity = CalculateProjectileVelocity(localOrigin, AttackTarget, projectileSpeed, out Vector3 origin, out Quaternion orientation);

            //Console.WriteLine($"Velocity: {velocity}");

            // launch animation
            var actionChain = new ActionChain();
            var launchTime  = EnqueueMotion(actionChain, aimLevel);

            //Console.WriteLine("LaunchTime: " + launchTime);

            // launch projectile
            actionChain.AddAction(this, () =>
            {
                if (IsDead)
                {
                    return;
                }

                var sound = GetLaunchMissileSound(weapon);
                EnqueueBroadcast(new GameMessageSound(Guid, sound, 1.0f));

                // TODO: monster stamina usage

                if (AttackTarget != null)
                {
                    var projectile = LaunchProjectile(weapon, ammo, AttackTarget, origin, orientation, velocity);
                    UpdateAmmoAfterLaunch(ammo);
                }
            });

            // will ammo be depleted?

            /*if (ammo.StackSize == null || ammo.StackSize <= 1)
             * {
             *  // compare monsters: lugianmontokrenegade /  sclavusse / zombielichtowerarcher
             *  actionChain.EnqueueChain();
             *  NextMoveTime = NextAttackTime = Timers.RunningTime + launchTime + MissileDelay;
             *  return;
             * }*/

            // reload animation
            var animSpeed  = GetAnimSpeed();
            var reloadTime = EnqueueMotion(actionChain, MotionCommand.Reload, animSpeed);

            //Console.WriteLine("ReloadTime: " + reloadTime);

            // reset for next projectile
            EnqueueMotion(actionChain, MotionCommand.Ready);

            var linkAnim = reloadTime > 0 ? MotionCommand.Reload : aimLevel;

            var linkTime = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, linkAnim, MotionCommand.Ready);

            if (weapon.IsThrownWeapon)
            {
                if (reloadTime > 0)
                {
                    actionChain.EnqueueChain();
                    actionChain = new ActionChain();
                }

                actionChain.AddDelaySeconds(linkTime);
            }

            //log.Info($"{Name}.Reload time: launchTime({launchTime}) + reloadTime({reloadTime}) + linkTime({linkTime})");

            actionChain.AddAction(this, () => EnqueueBroadcast(new GameMessageParentEvent(this, ammo,
                                                                                          ACE.Entity.Enum.ParentLocation.RightHand, ACE.Entity.Enum.Placement.RightHandCombat)));

            actionChain.EnqueueChain();

            PrevAttackTime = Timers.RunningTime;

            var timeOffset = launchTime + reloadTime + linkTime;

            NextMoveTime = NextAttackTime = PrevAttackTime + timeOffset + MissileDelay;
        }
Exemplo n.º 25
0
        /// <summary>
        /// Launches a missile attack from player to target
        /// </summary>
        public void LaunchMissile(WorldObject target)
        {
            var weapon = GetEquippedMissileWeapon();

            if (weapon == null || CombatMode == CombatMode.NonCombat)
            {
                return;
            }

            var ammo = weapon.IsAmmoLauncher ? GetEquippedAmmo() : weapon;

            if (ammo == null)
            {
                return;
            }

            var creature = target as Creature;

            if (!IsAlive || MissileTarget == null || !creature.IsAlive)
            {
                MissileTarget = null;
                return;
            }

            // launch animation
            var actionChain = new ActionChain();
            var launchTime  = EnqueueMotion(actionChain, MotionCommand.AimLevel);

            // launch projectile
            actionChain.AddAction(this, () =>
            {
                var sound = GetLaunchMissileSound(weapon);
                EnqueueBroadcast(new GameMessageSound(Guid, sound, 1.0f));

                // stamina usage
                // TODO: ensure enough stamina for attack
                // TODO: verify formulas - double/triple cost for bow/xbow?
                var staminaCost = GetAttackStamina(GetAccuracyRange());
                UpdateVitalDelta(Stamina, -staminaCost);

                float targetTime = 0.0f;
                var projectile   = LaunchProjectile(ammo, target, out targetTime);
                UpdateAmmoAfterLaunch(ammo);
            });

            // ammo remaining?
            if (ammo.StackSize == 1)
            {
                actionChain.AddAction(this, () =>
                {
                    SetCombatMode(CombatMode.NonCombat);
                });

                actionChain.EnqueueChain();
                return;
            }

            // reload animation
            var reloadTime = EnqueueMotion(actionChain, MotionCommand.Reload);

            // reset for next projectile
            EnqueueMotion(actionChain, MotionCommand.Ready);
            var linkTime = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Reload, MotionCommand.Ready);

            //var cycleTime = MotionTable.GetCycleLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Ready);

            actionChain.AddAction(this, () => EnqueueBroadcast(new GameMessageParentEvent(this, ammo, (int)ACE.Entity.Enum.ParentLocation.RightHand,
                                                                                          (int)ACE.Entity.Enum.Placement.RightHandCombat)));

            actionChain.AddDelaySeconds(linkTime);

            actionChain.AddAction(this, () =>
            {
                Session.Network.EnqueueSend(new GameEventAttackDone(Session));

                if (creature.IsAlive && GetCharacterOption(CharacterOption.AutoRepeatAttacks))
                {
                    Session.Network.EnqueueSend(new GameEventCombatCommenceAttack(Session));
                    Session.Network.EnqueueSend(new GameEventAttackDone(Session));

                    var nextAttack = new ActionChain();
                    nextAttack.AddDelaySeconds(AccuracyLevel + 0.1f);

                    // perform next attack
                    nextAttack.AddAction(this, () => { LaunchMissile(target); });
                    nextAttack.EnqueueChain();
                }
                else
                {
                    MissileTarget = null;
                }
            });

            actionChain.EnqueueChain();
        }