示例#1
0
        public override void OnUse(Player player)
        {
            string serverMessage = null;
            // validate within use range, taking into account the radius of the model itself, as well
            SetupModel csetup        = SetupModel.ReadFromDat(this.PhysicsData.CSetup);
            float      radiusSquared = (this.GameData.UseRadius + csetup.Radius) * (this.GameData.UseRadius + csetup.Radius);

            var motionSanctuary = new UniversalMotion(MotionStance.Standing, new MotionItem(MotionCommand.Sanctuary));

            var animationEvent = new GameMessageUpdateMotion(player, player.Session, motionSanctuary);

            // This event was present for a pcap in the training dungeon.. Why? The sound comes with animationEvent...
            var soundEvent = new GameMessageSound(this.Guid, Sound.LifestoneOn, 1);

            if (player.Location.SquaredDistanceTo(this.Location) >= radiusSquared)
            {
                serverMessage = "You wandered too far to attune with the Lifestone!";
            }
            else
            {
                player.SetCharacterPosition(PositionType.Sanctuary, player.Location);

                // create the outbound server message
                serverMessage = "You have attuned your spirit to this Lifestone. You will resurrect here after you die.";
                player.EnqueueMovementEvent(motionSanctuary, player.Guid);
                player.Session.Network.EnqueueSend(soundEvent);
            }

            var lifestoneBindMessage = new GameMessageSystemChat(serverMessage, ChatMessageType.Magic);
            // always send useDone event
            var sendUseDoneEvent = new GameEventUseDone(player.Session);

            player.Session.Network.EnqueueSend(lifestoneBindMessage, sendUseDoneEvent);
        }
示例#2
0
        public void BroadcastMovement(MoveToState moveToState)
        {
            var state = moveToState.RawMotionState;

            // update current style
            if ((state.Flags & RawMotionFlags.CurrentStyle) != 0)
            {
                // this lowercase stance field in Player doesn't really seem to be used anywhere
                stance = state.CurrentStyle;
            }

            // update CurrentMotionState here for substates?
            if ((state.Flags & RawMotionFlags.ForwardCommand) != 0)
            {
                if (((uint)state.ForwardCommand & (uint)CommandMask.SubState) != 0)
                {
                    CurrentMotionState.SetForwardCommand(state.ForwardCommand);
                }
            }
            else
            {
                CurrentMotionState.SetForwardCommand(MotionCommand.Ready);
            }

            if (state.CommandListLength > 0)
            {
                if (((uint)state.Commands[0].MotionCommand & (uint)CommandMask.SubState) != 0)
                {
                    CurrentMotionState.SetForwardCommand(state.Commands[0].MotionCommand);
                }
            }

            if (state.HasSoulEmote(false))
            {
                // prevent soul emote spam / bug where client sends multiples
                var soulEmote = state.Commands[0].MotionCommand;
                if (soulEmote == LastSoulEmote && DateTime.UtcNow < LastSoulEmoteEndTime)
                {
                    state.Commands.Clear();
                    state.CommandListLength = 0;
                }
                else
                {
                    var animLength = Physics.Animation.MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, soulEmote, state.Commands[0].Speed);

                    LastSoulEmote        = soulEmote;
                    LastSoulEmoteEndTime = DateTime.UtcNow + TimeSpan.FromSeconds(animLength);
                }
            }

            var movementData = new MovementData(this, moveToState);

            var movementEvent = new GameMessageUpdateMotion(this, movementData);

            EnqueueBroadcast(true, movementEvent);    // shouldn't need to go to originating player?

            // TODO: use real motion / animation system from physics
            //CurrentMotionCommand = movementData.Invalid.State.ForwardCommand;
            CurrentMovementData = movementData;
        }
示例#3
0
文件: Creature.cs 项目: zarlant/ACE
        public void SetMotionState(WorldObject obj, UniversalMotion motionState)
        {
            CurrentMotionState       = motionState;
            motionState.IsAutonomous = false;
            GameMessageUpdateMotion updateMotion = new GameMessageUpdateMotion(Guid, Sequences.GetCurrentSequence(SequenceType.ObjectInstance), obj.Sequences, motionState);

            CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, updateMotion);
        }
示例#4
0
        public void SetMotionState(MotionState motionState)
        {
            Player p = (Player)this;

            PhysicsData.CurrentMotionState = motionState;
            var updateMotion = new GameMessageUpdateMotion(this, p.Session, motionState);

            p.Session.Network.EnqueueSend(updateMotion);
        }
示例#5
0
        public void SetMotionState(MotionState motionState)
        {
            Player p = (Player)this;

            PhysicsData.CurrentMotionState = motionState;
            var updateMotion = new GameMessageUpdateMotion(p.Guid,
                                                           p.Sequences.GetCurrentSequence(SequenceType.ObjectInstance), p.Sequences, motionState);

            p.Session.Network.EnqueueSend(updateMotion);
        }
示例#6
0
        //public DateTime LastSoulEmote;

        //private static TimeSpan SoulEmoteTime = TimeSpan.FromSeconds(2);

        public void BroadcastMovement(MoveToState moveToState)
        {
            var state = moveToState.RawMotionState;

            // update current style
            if ((state.Flags & RawMotionFlags.CurrentStyle) != 0)
            {
                // this lowercase stance field in Player doesn't really seem to be used anywhere
                stance = state.CurrentStyle;
            }

            // update CurrentMotionState here for substates?
            if ((state.Flags & RawMotionFlags.ForwardCommand) != 0)
            {
                if (((uint)state.ForwardCommand & (uint)CommandMask.SubState) != 0)
                {
                    CurrentMotionState.SetForwardCommand(state.ForwardCommand);
                }
            }
            else
            {
                CurrentMotionState.SetForwardCommand(MotionCommand.Ready);
            }

            if (state.CommandListLength > 0)
            {
                if (((uint)state.Commands[0].MotionCommand & (uint)CommandMask.SubState) != 0)
                {
                    CurrentMotionState.SetForwardCommand(state.Commands[0].MotionCommand);
                }
            }

            /*if (state.HasSoulEmote())
             * {
             *  // prevent soul emote spam / bug where client sends multiples
             *  var elapsed = DateTime.UtcNow - LastSoulEmote;
             *  if (elapsed < SoulEmoteTime) return;
             *
             *  LastSoulEmote = DateTime.UtcNow;
             * }*/

            var movementData = new MovementData(this, moveToState);

            var movementEvent = new GameMessageUpdateMotion(this, movementData);

            EnqueueBroadcast(false, movementEvent);    // shouldn't need to go to originating player?

            // TODO: use real motion / animation system from physics
            //CurrentMotionCommand = movementData.Invalid.State.ForwardCommand;
            CurrentMovementData = movementData;
        }
示例#7
0
        public override void HandleActionOnUse(ObjectGuid playerId)
        {
            // All data on a lifestone is constant -- therefore we just run in context of player
            ActionChain chain = new ActionChain();

            CurrentLandblock.ChainOnObject(chain, playerId, (WorldObject wo) =>
            {
                Player player        = wo as Player;
                string serverMessage = null;
                // validate within use range, taking into account the radius of the model itself, as well
                SetupModel csetup   = SetupModel.ReadFromDat(SetupTableId.Value);
                float radiusSquared = (UseRadius.Value + csetup.Radius) * (UseRadius.Value + csetup.Radius);

                // Run this animation...
                // Player Enqueue:
                var motionSanctuary = new UniversalMotion(MotionStance.Standing, new MotionItem(MotionCommand.Sanctuary));

                var animationEvent = new GameMessageUpdateMotion(player.Guid,
                                                                 player.Sequences.GetCurrentSequence(Network.Sequence.SequenceType.ObjectInstance),
                                                                 player.Sequences, motionSanctuary);

                // This event was present for a pcap in the training dungeon.. Why? The sound comes with animationEvent...
                var soundEvent = new GameMessageSound(Guid, Sound.LifestoneOn, 1);

                if (player.Location.SquaredDistanceTo(Location) >= radiusSquared)
                {
                    serverMessage = "You wandered too far to attune with the Lifestone!";
                }
                else
                {
                    player.SetCharacterPosition(PositionType.Sanctuary, player.Location);

                    // create the outbound server message
                    serverMessage = "You have attuned your spirit to this Lifestone. You will resurrect here after you die.";
                    player.HandleActionMotion(motionSanctuary);
                    player.Session.Network.EnqueueSend(soundEvent);
                }

                var lifestoneBindMessage = new GameMessageSystemChat(serverMessage, ChatMessageType.Magic);
                // always send useDone event
                var sendUseDoneEvent = new GameEventUseDone(player.Session);
                player.Session.Network.EnqueueSend(lifestoneBindMessage, sendUseDoneEvent);
            });
            chain.EnqueueChain();
        }
示例#8
0
文件: Player.cs 项目: decaprime/ACE
        /// <summary>
        /// Detects changes in the player's RunRate --
        /// If there are changes, re-broadcasts player movement packet
        /// </summary>
        public bool HandleRunRateUpdate()
        {
            //Console.WriteLine($"{Name}.HandleRunRateUpdates()");

            if (CurrentMovementData.MovementType != MovementType.Invalid || CurrentMovementData.Invalid == null)
            {
                return(false);
            }

            var prevState = CurrentMovementData.Invalid.State;

            var movementData = new MovementData(this, CurrentMoveToState);
            var currentState = movementData.Invalid.State;

            var changed = currentState.ForwardSpeed != prevState.ForwardSpeed ||
                          currentState.TurnSpeed != prevState.TurnSpeed ||
                          currentState.SidestepSpeed != prevState.SidestepSpeed;

            if (!changed)
            {
                return(false);
            }

            //Console.WriteLine($"Old: {prevState.ForwardSpeed}, New: {currentState.ForwardSpeed}");

            if (!CurrentMovementData.Invalid.State.HasMovement() || IsJumping)
            {
                return(false);
            }

            //Console.WriteLine($"{Name}.OnRunRateChanged()");

            CurrentMovementData = new MovementData(this, CurrentMoveToState);

            // verify - forced commands from server should be non-autonomous, but could have been sent as autonomous in retail?
            // if set to autonomous here, the desired effect doesn't happen
            CurrentMovementData.IsAutonomous = false;

            var movementEvent = new GameMessageUpdateMotion(this, CurrentMovementData);

            EnqueueBroadcast(movementEvent);    // broadcast to all players, including self

            return(true);
        }
        public static void Handle(ClientMessage clientMessage, Session session)
        {
            string message = $"{session.Player.Name} is recalling to the marketplace.";

            var sysChatMessage = new GameMessageSystemChat(message, ChatMessageType.Recall);

            var updateCombatMode = new GameMessagePrivateUpdatePropertyInt(session, PropertyInt.CombatMode, 1);

            var motionMarketplaceRecall = new UniversalMotion(MotionStance.Standing, new MotionItem(MotionCommand.MarketplaceRecall));

            var animationEvent = new GameMessageUpdateMotion(session.Player, session, motionMarketplaceRecall);

            // TODO: This needs to be changed to broadcast sysChatMessage to only those in local chat hearing range
            // FIX: Recall text isn't being broadcast yet, need to address
            session.Network.EnqueueSend(updateCombatMode, sysChatMessage);
            session.Player.EnqueueMovementEvent(motionMarketplaceRecall, session.Player.Guid);

            session.Player.SetDelayedTeleport(TimeSpan.FromSeconds(14), marketplaceDrop);
        }
示例#10
0
        public void BroadcastMovement(MoveToState moveToState)
        {
            var state = moveToState.RawMotionState;

            // update current style
            if ((state.Flags & RawMotionFlags.CurrentStyle) != 0)
            {
                // this lowercase stance field in Player doesn't really seem to be used anywhere
                stance = state.CurrentStyle;
            }

            var movementData = new MovementData(this, moveToState);

            var movementEvent = new GameMessageUpdateMotion(this, movementData);

            EnqueueBroadcast(movementEvent);    // shouldn't need to go to originating player?

            // TODO: use real motion / animation system from physics
            CurrentMotionCommand = movementData.Invalid.State.ForwardCommand;
        }
示例#11
0
        public void BroadcastMovement(MoveToState moveToState)
        {
            var state = moveToState.RawMotionState;

            // update current style
            if ((state.Flags & RawMotionFlags.CurrentStyle) != 0)
            {
                // this lowercase stance field in Player doesn't really seem to be used anywhere
                stance = state.CurrentStyle;
            }

            // update CurrentMotionState here for substates?
            if ((state.Flags & RawMotionFlags.ForwardCommand) != 0)
            {
                if (((uint)state.ForwardCommand & (uint)CommandMask.SubState) != 0)
                {
                    CurrentMotionState.SetForwardCommand(state.ForwardCommand);
                }
            }
            else
            {
                CurrentMotionState.SetForwardCommand(MotionCommand.Ready);
            }

            if (state.CommandListLength > 0)
            {
                if (((uint)state.Commands[0].MotionCommand & (uint)CommandMask.SubState) != 0)
                {
                    CurrentMotionState.SetForwardCommand(state.Commands[0].MotionCommand);
                }
            }

            var movementData = new MovementData(this, moveToState);

            var movementEvent = new GameMessageUpdateMotion(this, movementData);

            EnqueueBroadcast(movementEvent);    // shouldn't need to go to originating player?

            // TODO: use real motion / animation system from physics
            CurrentMotionCommand = movementData.Invalid.State.ForwardCommand;
        }
示例#12
0
        private void HandleGameAction(QueuedGameAction action, Player player)
        {
            switch (action.ActionType)
            {
            case GameActionType.TalkDirect:
            {
                // TODO: remove this hack (using TalkDirect) ASAP
                var         g   = new ObjectGuid(action.ObjectId);
                WorldObject obj = (WorldObject)player;
                if (worldObjects.ContainsKey(g))
                {
                    obj = worldObjects[g];
                }
                DeathMessageArgs d = new DeathMessageArgs(action.ActionBroadcastMessage, new ObjectGuid(action.ObjectId), new ObjectGuid(action.SecondaryObjectId));
                HandleDeathMessage(obj, d);
                break;
            }

            case GameActionType.TeleToHouse:
            case GameActionType.TeleToLifestone:
            case GameActionType.TeleToMansion:
            case GameActionType.TeleToMarketPlace:
            case GameActionType.TeleToPkArena:
            case GameActionType.TeleToPklArena:
            {
                player.Teleport(action.ActionLocation);
                break;
            }

            case GameActionType.ApplyVisualEffect:
            {
                var         g   = new ObjectGuid(action.ObjectId);
                WorldObject obj = (WorldObject)player;
                if (worldObjects.ContainsKey(g))
                {
                    obj = worldObjects[g];
                }
                var particleEffect = (PlayScript)action.SecondaryObjectId;
                HandleParticleEffectEvent(obj, particleEffect);
                break;
            }

            case GameActionType.ApplySoundEffect:
            {
                var         g   = new ObjectGuid(action.ObjectId);
                WorldObject obj = (WorldObject)player;
                if (worldObjects.ContainsKey(g))
                {
                    obj = worldObjects[g];
                }
                var soundEffect = (Sound)action.SecondaryObjectId;
                HandleSoundEvent(obj, soundEffect);
                break;
            }

            case GameActionType.PutItemInContainer:
            {
                var playerId    = new ObjectGuid(action.ObjectId);
                var inventoryId = new ObjectGuid(action.SecondaryObjectId);
                if (playerId.IsPlayer())
                {
                    Player      aPlayer       = null;
                    WorldObject inventoryItem = null;

                    if (worldObjects.ContainsKey(playerId) && worldObjects.ContainsKey(inventoryId))
                    {
                        aPlayer       = (Player)worldObjects[playerId];
                        inventoryItem = worldObjects[inventoryId];
                    }

                    if ((aPlayer != null) && (inventoryItem != null))
                    {
                        var motion = new GeneralMotion(MotionStance.Standing);
                        motion.MovementData.ForwardCommand = (ushort)MotionCommand.Pickup;
                        aPlayer.Session.Network.EnqueueSend(new GameMessageUpdatePosition(aPlayer),
                                                            new GameMessageUpdateMotion(aPlayer, aPlayer.Session, motion),
                                                            new GameMessageSound(aPlayer.Guid, Sound.PickUpItem, (float)1.0));

                        // Add to the inventory list.
                        aPlayer.AddToInventory(inventoryItem);
                        LandblockManager.RemoveObject(inventoryItem);

                        motion = new GeneralMotion(MotionStance.Standing);
                        aPlayer.Session.Network.EnqueueSend(new GameMessagePrivateUpdatePropertyInt(aPlayer.Session,
                                                                                                    PropertyInt.EncumbVal,
                                                                                                    aPlayer.GameData.Burden),
                                                            new GameMessagePutObjectInContainer(aPlayer.Session, aPlayer, inventoryId),
                                                            new GameMessageUpdateMotion(aPlayer, aPlayer.Session, motion),
                                                            new GameMessageUpdateInstanceId(inventoryId, playerId),
                                                            new GameMessagePickupEvent(aPlayer.Session, inventoryItem));

                        aPlayer.TrackObject(inventoryItem);
                    }
                }
                break;
            }

            case GameActionType.DropItem:
            {
                var g = new ObjectGuid(action.ObjectId);
                // ReSharper disable once InconsistentlySynchronizedField
                if (worldObjects.ContainsKey(g))
                {
                    var playerId    = new ObjectGuid(action.ObjectId);
                    var inventoryId = new ObjectGuid(action.SecondaryObjectId);
                    if (playerId.IsPlayer())
                    {
                        Player      aPlayer       = null;
                        WorldObject inventoryItem = null;

                        if (worldObjects.ContainsKey(playerId))
                        {
                            aPlayer       = (Player)worldObjects[playerId];
                            inventoryItem = aPlayer.GetInventoryItem(inventoryId);
                            aPlayer.RemoveFromInventory(inventoryId);
                        }

                        if ((aPlayer != null) && (inventoryItem != null))
                        {
                            var targetContainer = new ObjectGuid(0);
                            aPlayer.Session.Network.EnqueueSend(
                                new GameMessagePrivateUpdatePropertyInt(
                                    aPlayer.Session,
                                    PropertyInt.EncumbVal,
                                    (uint)aPlayer.Session.Player.GameData.Burden));

                            var motion = new GeneralMotion(MotionStance.Standing);
                            motion.MovementData.ForwardCommand = (ushort)MotionCommand.Pickup;
                            aPlayer.Session.Network.EnqueueSend(
                                new GameMessageUpdateMotion(aPlayer, aPlayer.Session, motion),
                                new GameMessageUpdateInstanceId(inventoryId, targetContainer));

                            motion = new GeneralMotion(MotionStance.Standing);
                            aPlayer.Session.Network.EnqueueSend(
                                new GameMessageUpdateMotion(aPlayer, aPlayer.Session, motion),
                                new GameMessagePutObjectIn3d(aPlayer.Session, aPlayer, inventoryId),
                                new GameMessageSound(aPlayer.Guid, Sound.DropItem, (float)1.0),
                                new GameMessageUpdateInstanceId(inventoryId, targetContainer));

                            // This is the sequence magic - adds back into 3d space seem to be treated like teleport.
                            inventoryItem.Sequences.GetNextSequence(SequenceType.ObjectTeleport);
                            inventoryItem.Sequences.GetNextSequence(SequenceType.ObjectVector);
                            LandblockManager.AddObject(inventoryItem);
                            aPlayer.Session.Network.EnqueueSend(new GameMessageUpdatePosition(inventoryItem));
                        }
                    }
                }
                break;
            }

            case GameActionType.MovementEvent:
            {
                var         g   = new ObjectGuid(action.ObjectId);
                WorldObject obj = (WorldObject)player;
                if (worldObjects.ContainsKey(g))
                {
                    obj = worldObjects[g];
                }
                var motion = action.Motion;
                HandleMovementEvent(obj, motion);
                break;
            }

            case GameActionType.ObjectCreate:
            {
                this.AddWorldObject(action.WorldObject);
                break;
            }

            case GameActionType.ObjectDelete:
            {
                this.RemoveWorldObject(action.WorldObject.Guid, false);
                break;
            }

            case GameActionType.QueryHealth:
            {
                if (action.ObjectId == 0)
                {
                    // Deselect the formerly selected Target
                    player.SelectedTarget = 0;
                    break;
                }

                object target   = null;
                var    targetId = new ObjectGuid(action.ObjectId);

                // Remember the selected Target
                player.SelectedTarget = action.ObjectId;

                // TODO: once items are implemented check if there are items that can trigger
                //       the QueryHealth event. So far I believe it only gets triggered for players and creatures
                if (targetId.IsPlayer() || targetId.IsCreature())
                {
                    if (this.worldObjects.ContainsKey(targetId))
                    {
                        target = this.worldObjects[targetId];
                    }

                    if (target == null)
                    {
                        // check adjacent landblocks for the targetId
                        foreach (var block in adjacencies)
                        {
                            if (block.Value != null)
                            {
                                if (block.Value.worldObjects.ContainsKey(targetId))
                                {
                                    target = block.Value.worldObjects[targetId];
                                }
                            }
                        }
                    }
                    if (target != null)
                    {
                        float healthPercentage = 0;

                        if (targetId.IsPlayer())
                        {
                            Player tmpTarget = (Player)target;
                            healthPercentage = (float)tmpTarget.Health.Current / (float)tmpTarget.Health.MaxValue;
                        }
                        if (targetId.IsCreature())
                        {
                            Creature tmpTarget = (Creature)target;
                            healthPercentage = (float)tmpTarget.Health.Current / (float)tmpTarget.Health.MaxValue;
                        }
                        var updateHealth = new GameEventUpdateHealth(player.Session, targetId.Full, healthPercentage);
                        player.Session.Network.EnqueueSend(updateHealth);
                    }
                }

                break;
            }

            case GameActionType.Use:
            {
                var g = new ObjectGuid(action.ObjectId);
                if (worldObjects.ContainsKey(g))
                {
                    WorldObject obj = worldObjects[g];

                    switch (obj.Type)
                    {
                    case Enum.ObjectType.Portal:
                    {
                        // validate within use range :: set to a fixed value as static Portals are normally OnCollide usage
                        float rangeCheck = 5.0f;

                        if (player.Location.SquaredDistanceTo(obj.Location) < rangeCheck)
                        {
                            PortalDestination portalDestination = DatabaseManager.World.GetPortalDestination(obj.WeenieClassid);

                            if (portalDestination != null)
                            {
                                player.Session.Player.Teleport(portalDestination.Position);
                                // always send useDone event
                                var sendUseDoneEvent = new GameEventUseDone(player.Session);
                                player.Session.Network.EnqueueSend(sendUseDoneEvent);
                            }
                            else
                            {
                                string serverMessage    = "Portal destination for portal ID " + obj.WeenieClassid + " not yet implemented!";
                                var    usePortalMessage = new GameMessageSystemChat(serverMessage, ChatMessageType.System);
                                // always send useDone event
                                var sendUseDoneEvent = new GameEventUseDone(player.Session);
                                player.Session.Network.EnqueueSend(usePortalMessage, sendUseDoneEvent);
                            }
                        }
                        else
                        {
                            // always send useDone event
                            var sendUseDoneEvent = new GameEventUseDone(player.Session);
                            player.Session.Network.EnqueueSend(sendUseDoneEvent);
                        }

                        break;
                    }

                    case Enum.ObjectType.LifeStone:
                    {
                        string serverMessage = null;
                        // validate within use range
                        float radiusSquared = obj.GameData.UseRadius * obj.GameData.UseRadius;

                        var motionSanctuary = new GeneralMotion(MotionStance.Standing, new MotionItem(MotionCommand.Sanctuary));

                        var animationEvent = new GameMessageUpdateMotion(player, player.Session, motionSanctuary);

                        // This event was present for a pcap in the training dungeon.. Why? The sound comes with animationEvent...
                        var soundEvent = new GameMessageSound(obj.Guid, Sound.LifestoneOn, 1);

                        if (player.Location.SquaredDistanceTo(obj.Location) >= radiusSquared)
                        {
                            serverMessage = "You wandered too far to attune with the Lifestone!";
                        }
                        else
                        {
                            player.SetCharacterPosition(PositionType.Sanctuary, player.Location);

                            // create the outbound server message
                            serverMessage = "You have attuned your spirit to this Lifestone. You will resurrect here after you die.";
                            player.EnqueueMovementEvent(motionSanctuary, player.Guid);
                            player.Session.Network.EnqueueSend(soundEvent);
                        }

                        var lifestoneBindMessage = new GameMessageSystemChat(serverMessage, ChatMessageType.Magic);
                        // always send useDone event
                        var sendUseDoneEvent = new GameEventUseDone(player.Session);
                        player.Session.Network.EnqueueSend(lifestoneBindMessage, sendUseDoneEvent);

                        break;
                    }
                    }
                }
                break;
            }
            }
        }