Example #1
0
        private void OnKill(Session session)
        {
            IsAlive = false;
            // This will determine if the derived type is a player
            var isDerivedPlayer = Guid.IsPlayer();

            if (!isDerivedPlayer)
            {
                // Create and send the death notice
                string killMessage        = $"{session.Player.Name} has killed {Name}.";
                var    creatureDeathEvent = new GameEventDeathNotice(session, killMessage);
                session.Network.EnqueueSend(creatureDeathEvent);
            }

            // MovementEvent: (Hand-)Combat or in the case of smite: from Standing to Death
            // TODO: Check if the duration of the motion can somehow be computed
            UniversalMotion motionDeath = new UniversalMotion(MotionStance.Standing, new MotionItem(MotionCommand.Dead));

            CurrentLandblock.EnqueueBroadcastMotion(this, motionDeath);

            // If the object is a creature, Remove it from from Landblock
            if (!isDerivedPlayer)
            {
                CurrentLandblock.RemoveWorldObject(Guid, false);
            }
        }
Example #2
0
        public override void OnCollideObject(WorldObject target)
        {
            if (!PhysicsObj.is_active())
            {
                return;
            }

            //Console.WriteLine(string.Format("Projectile.OnCollideObject({0} - {1} || {2} - {3})", Guid.Full.ToString("X8"), Name, target.Guid.Full.ToString("X8"), target.Name));

            if (ProjectileTarget == null || !ProjectileTarget.Equals(target))
            {
                //Console.WriteLine("Unintended projectile target! (should be " + ProjectileTarget.Guid.Full.ToString("X8") + " - " + ProjectileTarget.Name + ")");
                OnCollideEnvironment();
                return;
            }

            // take damage
            var player = ProjectileSource as Player;

            if (player != null)
            {
                var damage = player.DamageTarget(target, this);

                if (damage > 0)
                {
                    player.Session.Network.EnqueueSend(new GameMessageSound(Guid, Sound.Collision, 1.0f));    // todo: landblock broadcast?
                }
            }

            CurrentLandblock.RemoveWorldObject(Guid, false);
            PhysicsObj.set_active(false);
        }
Example #3
0
        private void LogOut_Final(bool skipAnimations = false)
        {
            if (CurrentLandblock != null)
            {
                if (skipAnimations)
                {
                    CurrentLandblock?.RemoveWorldObject(Guid, false);
                    SetPropertiesAtLogOut();
                    SavePlayerToDatabase();
                    PlayerManager.SwitchPlayerFromOnlineToOffline(this);
                }
                else
                {
                    var logout = new Motion(MotionStance.NonCombat, MotionCommand.LogOut);
                    EnqueueBroadcastMotion(logout);

                    EnqueueBroadcastPhysicsState();

                    var logoutChain = new ActionChain();

                    var   motionTable           = DatManager.PortalDat.ReadFromDat <MotionTable>((uint)MotionTableId);
                    float logoutAnimationLength = motionTable.GetAnimationLength(MotionCommand.LogOut);
                    logoutChain.AddDelaySeconds(logoutAnimationLength);

                    // remove the player from landblock management -- after the animation has run
                    logoutChain.AddAction(WorldManager.ActionQueue, () =>
                    {
                        // If we're in the dying animation process, we cannot RemoveWorldObject and logout until that animation completes..
                        if (isInDeathProcess)
                        {
                            return;
                        }

                        CurrentLandblock?.RemoveWorldObject(Guid, false);
                        SetPropertiesAtLogOut();
                        SavePlayerToDatabase();
                        PlayerManager.SwitchPlayerFromOnlineToOffline(this);
                    });

                    // close any open landblock containers (chests / corpses)
                    if (LastOpenedContainerId != ObjectGuid.Invalid)
                    {
                        var container = CurrentLandblock.GetObject(LastOpenedContainerId) as Container;

                        if (container != null)
                        {
                            container.Close(this);
                        }
                    }

                    logoutChain.EnqueueChain();
                }
            }
            else
            {
                SetPropertiesAtLogOut();
                SavePlayerToDatabase();
                PlayerManager.SwitchPlayerFromOnlineToOffline(this);
            }
        }
Example #4
0
 private void FinalizeLogout()
 {
     CurrentLandblock?.RemoveWorldObject(Guid, false);
     SetPropertiesAtLogOut();
     SavePlayerToDatabase();
     PlayerManager.SwitchPlayerFromOnlineToOffline(this);
 }
Example #5
0
File: Player.cs Project: Dimmae/ACE
        /// <summary>
        /// Do the player log out work.<para />
        /// If you want to force a player to logout, use Session.LogOffPlayer().
        /// </summary>
        public void LogOut(bool clientSessionTerminatedAbruptly = false)
        {
            if (Fellowship != null)
            {
                FellowshipQuit(false);
            }

            if (!clientSessionTerminatedAbruptly)
            {
                // Thie retail server sends a ChatRoomTracker 0x0295 first, then the status message, 0x028B. It does them one at a time for each individual channel.
                // The ChatRoomTracker message doesn't seem to change at all.
                // For the purpose of ACE, we simplify this process.
                var general  = new GameEventWeenieErrorWithString(Session, WeenieErrorWithString.YouHaveLeftThe_Channel, "General");
                var trade    = new GameEventWeenieErrorWithString(Session, WeenieErrorWithString.YouHaveLeftThe_Channel, "Trade");
                var lfg      = new GameEventWeenieErrorWithString(Session, WeenieErrorWithString.YouHaveLeftThe_Channel, "LFG");
                var roleplay = new GameEventWeenieErrorWithString(Session, WeenieErrorWithString.YouHaveLeftThe_Channel, "Roleplay");
                Session.Network.EnqueueSend(general, trade, lfg, roleplay);
            }

            if (CurrentLandblock != null)
            {
                var logout = new Motion(MotionStance.NonCombat, MotionCommand.LogOut);
                EnqueueBroadcastMotion(logout);

                EnqueueBroadcastPhysicsState();

                var logoutChain = new ActionChain();

                var   motionTable           = DatManager.PortalDat.ReadFromDat <MotionTable>((uint)MotionTableId);
                float logoutAnimationLength = motionTable.GetAnimationLength(MotionCommand.LogOut);
                logoutChain.AddDelaySeconds(logoutAnimationLength);

                // remove the player from landblock management -- after the animation has run
                logoutChain.AddAction(this, () =>
                {
                    if (PlayerKillerStatus == PlayerKillerStatus.PKLite)
                    {
                        PlayerKillerStatus = PlayerKillerStatus.NPK;
                    }

                    CurrentLandblock?.RemoveWorldObject(Guid, false);
                    SetPropertiesAtLogOut();
                    SavePlayerToDatabase();
                    PlayerManager.SwitchPlayerFromOnlineToOffline(this);
                });

                logoutChain.EnqueueChain();
            }
            else
            {
                SetPropertiesAtLogOut();
                SavePlayerToDatabase();
                PlayerManager.SwitchPlayerFromOnlineToOffline(this);
            }
        }
Example #6
0
        public ActionChain GetLogoutChain(bool clientSessionTerminatedAbruptly = false)
        {
            ActionChain logoutChain = new ActionChain(this, () => LogoutInternal(clientSessionTerminatedAbruptly));

            var   motionTable           = DatManager.PortalDat.ReadFromDat <MotionTable>((uint)MotionTableId);
            float logoutAnimationLength = motionTable.GetAnimationLength(MotionCommand.LogOut);

            logoutChain.AddDelaySeconds(logoutAnimationLength);

            if (CurrentLandblock != null)
            {
                // remove the player from landblock management -- after the animation has run
                logoutChain.AddAction(this, () => CurrentLandblock.RemoveWorldObject(Guid, false));
            }

            return(logoutChain);
        }
Example #7
0
        public override void OnCollideEnvironment()
        {
            if (!PhysicsObj.is_active())
            {
                return;
            }

            //Console.WriteLine("Projectile.OnCollideEnvironment(" + Guid.Full.ToString("X8") + ")");

            CurrentLandblock.RemoveWorldObject(Guid, false);
            PhysicsObj.set_active(false);

            var player = ProjectileSource as Player;

            if (player != null)
            {
                player.Session.Network.EnqueueSend(new GameMessageSystemChat("Your missile attack hit the environment.", ChatMessageType.Broadcast));
            }
        }
Example #8
0
        /// <summary>
        /// Launches a projectile from player to target
        /// </summary>
        public float LaunchProjectile(WorldObject target)
        {
            var ammo  = GetEquippedAmmo();
            var arrow = WorldObjectFactory.CreateNewWorldObject(ammo.WeenieClassId);

            var origin = Location.ToGlobal();

            origin.Z += Height;

            var dest = target.Location.ToGlobal();

            dest.Z += target.Height / GetAimHeight(target);

            var speed = 35.0f;
            var dir   = Vector3.Normalize(dest - origin);

            origin += dir * 2.0f;

            arrow.Velocity = GetProjectileVelocity(target, origin, dir, dest, speed, out var time);

            var loc = Location;

            origin         = Position.FromGlobal(origin).Pos;
            arrow.Location = new Position(loc.LandblockId.Raw, origin.X, origin.Y, origin.Z, loc.Rotation.X, loc.Rotation.Y, loc.Rotation.Z, loc.RotationW);
            SetProjectilePhysicsState(arrow);

            LandblockManager.AddObject(arrow);
            CurrentLandblock.EnqueueBroadcast(arrow.Location, new GameMessageScript(arrow.Guid, ACE.Entity.Enum.PlayScript.Launch, 1.0f));

            var actionChain = new ActionChain();

            actionChain.AddDelaySeconds(time);
            actionChain.AddAction(arrow, () => Session.Network.EnqueueSend(new GameMessageSound(arrow.Guid, Sound.Collision, 1.0f)));
            actionChain.AddAction(arrow, () => CurrentLandblock.RemoveWorldObject(arrow.Guid, false));
            actionChain.EnqueueChain();

            return(time);
        }
Example #9
0
        public void LogOut_Inner(bool clientSessionTerminatedAbruptly = false)
        {
            if (Fellowship != null)
            {
                FellowshipQuit(false);
            }

            if (IsTrading && TradePartner != null)
            {
                var tradePartner = PlayerManager.GetOnlinePlayer(TradePartner);

                if (tradePartner != null)
                {
                    tradePartner.HandleActionCloseTradeNegotiations();
                }
            }

            if (!clientSessionTerminatedAbruptly)
            {
                // Thie retail server sends a ChatRoomTracker 0x0295 first, then the status message, 0x028B. It does them one at a time for each individual channel.
                // The ChatRoomTracker message doesn't seem to change at all.
                // For the purpose of ACE, we simplify this process.
                var general  = new GameEventWeenieErrorWithString(Session, WeenieErrorWithString.YouHaveLeftThe_Channel, "General");
                var trade    = new GameEventWeenieErrorWithString(Session, WeenieErrorWithString.YouHaveLeftThe_Channel, "Trade");
                var lfg      = new GameEventWeenieErrorWithString(Session, WeenieErrorWithString.YouHaveLeftThe_Channel, "LFG");
                var roleplay = new GameEventWeenieErrorWithString(Session, WeenieErrorWithString.YouHaveLeftThe_Channel, "Roleplay");
                Session.Network.EnqueueSend(general, trade, lfg, roleplay);
            }

            if (CurrentActiveCombatPet != null)
            {
                CurrentActiveCombatPet.Destroy();
            }

            if (CurrentLandblock != null)
            {
                var logout = new Motion(MotionStance.NonCombat, MotionCommand.LogOut);
                EnqueueBroadcastMotion(logout);

                EnqueueBroadcastPhysicsState();

                var logoutChain = new ActionChain();

                var   motionTable           = DatManager.PortalDat.ReadFromDat <MotionTable>((uint)MotionTableId);
                float logoutAnimationLength = motionTable.GetAnimationLength(MotionCommand.LogOut);
                logoutChain.AddDelaySeconds(logoutAnimationLength);

                // remove the player from landblock management -- after the animation has run
                logoutChain.AddAction(this, () =>
                {
                    CurrentLandblock?.RemoveWorldObject(Guid, false);
                    SetPropertiesAtLogOut();
                    SavePlayerToDatabase();
                    PlayerManager.SwitchPlayerFromOnlineToOffline(this);
                });

                // close any open landblock containers (chests / corpses)
                if (LastOpenedContainerId != ObjectGuid.Invalid)
                {
                    var container = CurrentLandblock.GetObject(LastOpenedContainerId) as Container;

                    if (container != null)
                    {
                        container.Close(this);
                    }
                }

                logoutChain.EnqueueChain();
            }
            else
            {
                SetPropertiesAtLogOut();
                SavePlayerToDatabase();
                PlayerManager.SwitchPlayerFromOnlineToOffline(this);
            }
        }
Example #10
0
        public void LogOut_Inner(bool clientSessionTerminatedAbruptly = false)
        {
            IsBusy       = true;
            IsLoggingOut = true;

            if (Fellowship != null)
            {
                FellowshipQuit(false);
            }

            if (IsTrading && TradePartner != ObjectGuid.Invalid)
            {
                var tradePartner = PlayerManager.GetOnlinePlayer(TradePartner);

                if (tradePartner != null)
                {
                    tradePartner.HandleActionCloseTradeNegotiations();
                }
            }

            if (!clientSessionTerminatedAbruptly)
            {
                if (PropertyManager.GetBool("use_turbine_chat").Item)
                {
                    if (GetCharacterOption(CharacterOption.ListenToGeneralChat))
                    {
                        LeaveTurbineChatChannel("General");
                    }
                    if (GetCharacterOption(CharacterOption.ListenToTradeChat))
                    {
                        LeaveTurbineChatChannel("Trade");
                    }
                    if (GetCharacterOption(CharacterOption.ListenToLFGChat))
                    {
                        LeaveTurbineChatChannel("LFG");
                    }
                    if (GetCharacterOption(CharacterOption.ListenToRoleplayChat))
                    {
                        LeaveTurbineChatChannel("Roleplay");
                    }
                    if (GetCharacterOption(CharacterOption.ListenToAllegianceChat) && Allegiance != null)
                    {
                        LeaveTurbineChatChannel("Allegiance");
                    }
                    if (GetCharacterOption(CharacterOption.ListenToSocietyChat) && Society != FactionBits.None)
                    {
                        LeaveTurbineChatChannel("Society");
                    }
                }
            }

            if (CurrentActivePet != null)
            {
                CurrentActivePet.Destroy();
            }

            if (CurrentLandblock != null)
            {
                var logout = new Motion(MotionStance.NonCombat, MotionCommand.LogOut);
                EnqueueBroadcastMotion(logout);

                EnqueueBroadcastPhysicsState();

                var logoutChain = new ActionChain();

                var   motionTable           = DatManager.PortalDat.ReadFromDat <MotionTable>((uint)MotionTableId);
                float logoutAnimationLength = motionTable.GetAnimationLength(MotionCommand.LogOut);
                logoutChain.AddDelaySeconds(logoutAnimationLength);

                // remove the player from landblock management -- after the animation has run
                logoutChain.AddAction(this, () =>
                {
                    if (CurrentLandblock == null)
                    {
                        log.Debug($"0x{Guid}:{Name}.LogOut_Inner.logoutChain: CurrentLandblock is null, unable to remove from a landblock...");
                        if (Location != null)
                        {
                            log.Debug($"0x{Guid}:{Name}.LogOut_Inner.logoutChain: Location is not null, Location = {Location.ToLOCString()}");
                        }
                    }

                    CurrentLandblock?.RemoveWorldObject(Guid, false);
                    SetPropertiesAtLogOut();
                    SavePlayerToDatabase();
                    PlayerManager.SwitchPlayerFromOnlineToOffline(this);
                });

                // close any open landblock containers (chests / corpses)
                if (LastOpenedContainerId != ObjectGuid.Invalid)
                {
                    var container = CurrentLandblock.GetObject(LastOpenedContainerId) as Container;

                    if (container != null)
                    {
                        container.Close(this);
                    }
                }

                logoutChain.EnqueueChain();
            }
            else
            {
                log.Debug($"0x{Guid}:{Name}.LogOut_Inner: CurrentLandblock is null");
                if (Location != null)
                {
                    log.Debug($"0x{Guid}:{Name}.LogOut_Inner: Location is not null, Location = {Location.ToLOCString()}");
                    var validLoadedLandblock = LandblockManager.GetLandblock(Location.LandblockId, false);
                    if (validLoadedLandblock.GetObject(Guid.Full) != null)
                    {
                        log.Debug($"0x{Guid}:{Name}.LogOut_Inner: Player is still on landblock, removing...");
                        validLoadedLandblock.RemoveWorldObject(Guid, false);
                    }
                    else
                    {
                        log.Debug($"0x{Guid}:{Name}.LogOut_Inner: Player is not found on the landblock Location references.");
                    }
                }
                else
                {
                    log.Debug($"0x{Guid}:{Name}.LogOut_Inner: Location is null");
                }
                SetPropertiesAtLogOut();
                SavePlayerToDatabase();
                PlayerManager.SwitchPlayerFromOnlineToOffline(this);
            }
        }
Example #11
0
        /// <summary>
        /// Launches a projectile from player to target
        /// </summary>
        public WorldObject LaunchProjectile(WorldObject target, out float time)
        {
            var ammo  = GetEquippedAmmo();
            var arrow = WorldObjectFactory.CreateNewWorldObject(ammo.WeenieClassId);

            var origin = Location.ToGlobal();

            origin.Z += Height;

            var dest = target.Location.ToGlobal();

            dest.Z += target.Height / GetAimHeight(target);

            var speed = 35.0f;
            var dir   = Vector3.Normalize(dest - origin);

            origin += dir * 2.0f;

            arrow.Velocity = GetProjectileVelocity(target, origin, dir, dest, speed, out time);

            var loc = Location;

            origin         = Position.FromGlobal(origin).Pos;
            arrow.Location = new Position(loc.LandblockId.Raw, origin.X, origin.Y, origin.Z, loc.Rotation.X, loc.Rotation.Y, loc.Rotation.Z, loc.RotationW);
            SetProjectilePhysicsState(arrow);

            var actionChain = new ActionChain();

            // TODO: Get correct aim level based on arrow velocity and add aim motion delay.
            var motion = new UniversalMotion(CurrentMotionState.Stance);

            motion.MovementData.CurrentStyle   = (uint)CurrentMotionState.Stance;
            motion.MovementData.ForwardCommand = (uint)MotionCommand.AimLevel;
            CurrentMotionState = motion;

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

            actionChain.AddAction(this, () => LandblockManager.AddObject(arrow));
            actionChain.AddAction(this, () => CurrentLandblock.EnqueueBroadcast(arrow.Location, new GameMessagePickupEvent(ammo)));

            var player = this as Player;

            // TODO: Add support for monster ammo depletion. For now only players will use up ammo.
            if (player != null)
            {
                actionChain.AddAction(this, () => UpdateAmmoAfterLaunch(ammo));
            }
            // Not sure why this would be needed but it is sent in retail pcaps.
            actionChain.AddAction(arrow, () => CurrentLandblock.EnqueueBroadcast(arrow.Location, new GameMessageSetStackSize(arrow)));

            if (player != null)
            {
                actionChain.AddAction(arrow, () => CurrentLandblock.EnqueueBroadcast(arrow.Location, new GameMessagePublicUpdatePropertyInt(
                                                                                         arrow, PropertyInt.PlayerKillerStatus, (int)(player.PlayerKillerStatus ?? ACE.Entity.Enum.PlayerKillerStatus.NPK))));
            }
            else
            {
                actionChain.AddAction(arrow, () => CurrentLandblock.EnqueueBroadcast(arrow.Location, new GameMessagePublicUpdatePropertyInt(
                                                                                         arrow, PropertyInt.PlayerKillerStatus, (int)ACE.Entity.Enum.PlayerKillerStatus.Creature)));
            }

            actionChain.AddAction(arrow, () => CurrentLandblock.EnqueueBroadcast(arrow.Location, new GameMessageScript(arrow.Guid, ACE.Entity.Enum.PlayScript.Launch, 0f)));
            actionChain.AddDelaySeconds(time);
            // todo: landblock broadcast?

            if (player != null)
            {
                actionChain.AddAction(arrow, () => player.Session.Network.EnqueueSend(new GameMessageSound(arrow.Guid, Sound.Collision, 1.0f)));
            }

            actionChain.AddAction(arrow, () => CurrentLandblock.RemoveWorldObject(arrow.Guid, false));
            actionChain.EnqueueChain();

            return(arrow);
        }