コード例 #1
0
        public ActionChain GetCreateCorpseChain()
        {
            ActionChain createCorpseChain = new ActionChain(this, () =>
            {
                // Create Corspe and set a location on the ground
                // TODO: set text of killer in description and find a better computation for the location, some corpse could end up in the ground
                var corpse = CorpseObjectFactory.CreateCorpse(this, this.Location);
                // FIXME(ddevec): We don't have a real corpse yet, so these come in null -- this hack just stops them from crashing the game
                corpse.Location.PositionY -= (corpse.ObjScale ?? 0);
                corpse.Location.PositionZ -= (corpse.ObjScale ?? 0) / 2;

                // Corpses stay on the ground for 5 * player level but minimum 1 hour
                // corpse.DespawnTime = Math.Max((int)session.Player.PropertiesInt[Enum.Properties.PropertyInt.Level] * 5, 360) + WorldManager.PortalYearTicks; // as in live
                // corpse.DespawnTime = 20 + WorldManager.PortalYearTicks; // only for testing
                float despawnTime = GetCorpseSpawnTime();

                // Create corpse
                CurrentLandblock.AddWorldObject(corpse);
                // Create corpse decay
                ActionChain despawnChain = new ActionChain();
                despawnChain.AddDelaySeconds(despawnTime);
                despawnChain.AddAction(CurrentLandblock, () => corpse.CurrentLandblock.RemoveWorldObject(corpse.Guid, false));
                despawnChain.EnqueueChain();
            });

            return(createCorpseChain);
        }
コード例 #2
0
ファイル: WorldObject_Links.cs プロジェクト: acriaf/ACE
        public void ActivateLinks(List <LandblockInstance> sourceObjects, List <Biota> biotas)
        {
            if (LinkedInstances.Count == 0)
            {
                return;
            }

            if (IsGenerator)
            {
                AddGeneratorLinks();
                return;
            }

            foreach (var link in LinkedInstances)
            {
                WorldObject wo    = null;
                var         biota = biotas.FirstOrDefault(b => b.Id == link.Guid);
                if (biota == null)
                {
                    wo = WorldObjectFactory.CreateWorldObject(DatabaseManager.World.GetCachedWeenie(link.WeenieClassId), new ObjectGuid(link.Guid));
                }
                else
                {
                    wo = WorldObjectFactory.CreateWorldObject(biota);
                    //Console.WriteLine("Loaded child biota " + wo.Name);
                }

                if (wo == null)
                {
                    continue;
                }

                wo.Location = new Position(link.ObjCellId, link.OriginX, link.OriginY, link.OriginZ, link.AnglesX, link.AnglesY, link.AnglesZ, link.AnglesW);
                SetLinkProperties(wo);
                CurrentLandblock?.AddWorldObject(wo);

                wo.ParentLink = this;
                ChildLinks.Add(wo);

                // process nested links recursively
                foreach (var subLink in link.LandblockInstanceLink)
                {
                    var linkInstance = sourceObjects.FirstOrDefault(x => x.Guid == subLink.ChildGuid);

                    if (linkInstance != null)
                    {
                        wo.LinkedInstances.Add(linkInstance);
                    }
                }

                if (wo.LinkedInstances.Count > 0)
                {
                    wo.ActivateLinks(sourceObjects, biotas);
                }
            }
        }
コード例 #3
0
        public virtual void ActivateLinks(List <LandblockInstance> sourceObjects)
        {
            if (LinkedInstances.Count == 0)
            {
                return;
            }

            if (IsGenerator)
            {
                AddGeneratorLinks();
                return;
            }

            foreach (var link in LinkedInstances)
            {
                var wo = WorldObjectFactory.CreateWorldObject(DatabaseManager.World.GetCachedWeenie(link.WeenieClassId), new ObjectGuid(link.Guid));
                if (wo == null)
                {
                    continue;
                }

                wo.Location         = new Position(link.ObjCellId, link.OriginX, link.OriginY, link.OriginZ, link.AnglesX, link.AnglesY, link.AnglesZ, link.AnglesW);
                wo.ActivationTarget = Guid.Full;
                CurrentLandblock?.AddWorldObject(wo);

                // process nested links recursively
                foreach (var subLink in link.LandblockInstanceLink)
                {
                    var linkInstance = sourceObjects.FirstOrDefault(x => x.Guid == subLink.ChildGuid);

                    if (linkInstance != null)
                    {
                        wo.LinkedInstances.Add(linkInstance);
                    }
                }

                if (wo.LinkedInstances.Count > 0)
                {
                    wo.ActivateLinks(sourceObjects);
                }
            }
        }
コード例 #4
0
        public void Decay(TimeSpan elapsed)
        {
            // http://asheron.wikia.com/wiki/Item_Decay

            if (decayCompleted)
            {
                return;
            }

            var previousTTR = TimeToRot;

            if (!TimeToRot.HasValue)
            {
                TimeToRot = DefaultTimeToRot.TotalSeconds;

                if (this is Corpse && Level.HasValue)
                {
                    log.Debug($"[CORPSE] {Name} (0x{Guid.ToString()}).Decay: TimeToRot had no value, set to {TimeToRot}");
                }

                return;
            }

            var corpse = this as Corpse;

            if (corpse != null)
            {
                if (!corpse.InventoryLoaded)
                {
                    return;
                }

                if (corpse.Inventory.Count == 0 && TimeToRot.Value > Corpse.EmptyDecayTime)
                {
                    TimeToRot = Corpse.EmptyDecayTime;
                    if (Level.HasValue && PropertyManager.GetBool("corpse_decay_tick_logging").Item)
                    {
                        log.Debug($"[CORPSE] {corpse.Name} (0x{corpse.Guid.ToString()}).Decay({elapsed.ToString()}): InventoryLoaded = {corpse.InventoryLoaded} | Inventory.Count = {corpse.Inventory.Count} | previous TimeToRot: {previousTTR} | current TimeToRot: {TimeToRot}");
                    }
                    return;
                }
            }

            if (TimeToRot > 0)
            {
                TimeToRot -= elapsed.TotalSeconds;

                if (this is Corpse && Level.HasValue && PropertyManager.GetBool("corpse_decay_tick_logging").Item)
                {
                    log.Debug($"[CORPSE] {corpse.Name} (0x{corpse.Guid.ToString()}).Decay({elapsed.ToString()}): previous TimeToRot: {previousTTR} | current TimeToRot: {TimeToRot}");
                }

                // Is there still time left?
                if (TimeToRot > 0)
                {
                    return;
                }

                TimeToRot = -2; // We force it to -2 to make sure it doesn't end up at 0 or -1. 0 indicates instant rot. -1 indicates no rot. 0 and -1 can be found in weenie defaults

                if (this is Corpse && Level.HasValue && PropertyManager.GetBool("corpse_decay_tick_logging").Item)
                {
                    log.Debug($"[CORPSE] {corpse.Name} (0x{corpse.Guid.ToString()}).Decay({elapsed.ToString()}): previous TimeToRot: {previousTTR} | current TimeToRot: {TimeToRot}");
                }
            }

            if (this is Container container && container.IsOpen)
            {
                // If you wanted to add a grace period to the container to give Player B more time to open it after Player A closes it, it would go here.

                return;
            }

            // Time to rot has elapsed, time to disappear...
            decayCompleted = true;

            // If this is a player corpse, puke out the corpses contents onto the landblock
            if (corpse != null && !corpse.IsMonster)
            {
                var inventoryGUIDs = corpse.Inventory.Keys.ToList();

                var pukedItems = "";

                foreach (var guid in inventoryGUIDs)
                {
                    if (corpse.TryRemoveFromInventory(guid, out var item))
                    {
                        item.Location  = new Position(corpse.Location);
                        item.Placement = ACE.Entity.Enum.Placement.Resting; // This is needed to make items lay flat on the ground.
                        CurrentLandblock.AddWorldObject(item);
                        item.SaveBiotaToDatabase();
                        pukedItems += $"{item.Name} (0x{item.Guid.Full.ToString("X8")}), ";
                    }
                }

                if (pukedItems.EndsWith(", "))
                {
                    pukedItems = pukedItems.Substring(0, pukedItems.Length - 2);
                }

                log.Debug($"[CORPSE] {corpse.Name} (0x{corpse.Guid.ToString()}) at {corpse.Location.ToLOCString()} has decayed{((pukedItems == "") ? "" : $" and placed the following items on the landblock: {pukedItems}")}.");
            }

            if (corpse != null)
            {
                EnqueueBroadcast(new GameMessageScript(Guid, PlayScript.Destroy));

                var actionChain = new ActionChain();
                actionChain.AddDelaySeconds(1.0f);
                actionChain.AddAction(this, () => Destroy());
                actionChain.EnqueueChain();
            }
            else
            {
                Destroy();
            }
        }
コード例 #5
0
        public void Decay(TimeSpan elapsed)
        {
            // http://asheron.wikia.com/wiki/Item_Decay

            if (decayCompleted)
            {
                return;
            }

            if (!TimeToRot.HasValue)
            {
                TimeToRot = DefaultTimeToRot.TotalSeconds;
                return;
            }

            var corpse = this as Corpse;

            if (corpse != null && corpse.Inventory.Count == 0 && TimeToRot.Value > Corpse.EmptyDecayTime)
            {
                TimeToRot = Corpse.EmptyDecayTime;
                return;
            }

            if (TimeToRot > 0)
            {
                TimeToRot -= elapsed.TotalSeconds;

                // Is there still time left?
                if (TimeToRot > 0)
                {
                    return;
                }

                TimeToRot = -2; // We force it to -2 to make sure it doesn't end up at 0 or -1. 0 indicates instant rot. -1 indicates no rot. 0 and -1 can be found in weenie defaults
            }

            if (this is Container container && container.IsOpen)
            {
                // If you wanted to add a grace period to the container to give Player B more time to open it after Player A closes it, it would go here.

                return;
            }

            // Time to rot has elapsed, time to disappear...
            decayCompleted = true;

            // If this is a player corpse, puke out the corpses contents onto the landblock
            if (corpse != null && !corpse.IsMonster)
            {
                var inventoryGUIDs = corpse.Inventory.Keys.ToList();

                foreach (var guid in inventoryGUIDs)
                {
                    if (corpse.TryRemoveFromInventory(guid, out var item))
                    {
                        item.Location  = new Position(corpse.Location);
                        item.Placement = ACE.Entity.Enum.Placement.Resting; // This is needed to make items lay flat on the ground.
                        CurrentLandblock.AddWorldObject(item);
                    }
                }
            }

            Destroy();
        }
コード例 #6
0
ファイル: Player_Inventory.cs プロジェクト: roidzilla/ACE
        public void HandleActionDropItem(ObjectGuid itemGuid)
        {
            // Goody Goody -- lets build  drop chain
            // First start drop animation
            new ActionChain(this, () =>
            {
                // check packs of item.
                WorldObject item;

                if (!TryRemoveFromInventory(itemGuid, out item))
                {
                    // check to see if this item is wielded
                    if (TryDequipObject(itemGuid, out item))
                    {
                        Session.Network.EnqueueSend(
                            new GameMessageSound(Guid, Sound.WieldObject, 1.0f),
                            new GameMessageObjDescEvent(this),
                            new GameMessageUpdateInstanceId(Guid, new ObjectGuid(0), PropertyInstanceId.Wielder));
                    }
                }

                item.SetPropertiesForWorld(this);

                UniversalMotion motion             = new UniversalMotion(MotionStance.Standing);
                motion.MovementData.ForwardCommand = (uint)MotionCommand.Pickup;
                Session.Network.EnqueueSend(new GameMessageUpdateInstanceId(itemGuid, new ObjectGuid(0), PropertyInstanceId.Container));

                // Set drop motion
                CurrentLandblock.EnqueueBroadcastMotion(this, motion);

                // Now wait for Drop Motion to finish -- use ActionChain
                ActionChain chain = new ActionChain();

                // Wait for drop animation
                var motionTable           = DatManager.PortalDat.ReadFromDat <MotionTable>(MotionTableId);
                var pickupAnimationLength = motionTable.GetAnimationLength(MotionCommand.Pickup);
                chain.AddDelaySeconds(pickupAnimationLength);

                // Play drop sound
                // Put item on landblock
                chain.AddAction(this, () =>
                {
                    motion = new UniversalMotion(MotionStance.Standing);
                    CurrentLandblock.EnqueueBroadcastMotion(this, motion);
                    Session.Network.EnqueueSend(
                        new GameMessageSound(Guid, Sound.DropItem, (float)1.0),
                        new GameMessagePutObjectIn3d(Session, this, itemGuid),
                        new GameMessageUpdateInstanceId(itemGuid, new ObjectGuid(0), PropertyInstanceId.Container));

                    // This is the sequence magic - adds back into 3d space seem to be treated like teleport.
                    Debug.Assert(item != null, "item != null");
                    item.Sequences.GetNextSequence(SequenceType.ObjectTeleport);
                    item.Sequences.GetNextSequence(SequenceType.ObjectVector);

                    CurrentLandblock.AddWorldObject(item);

                    Session.Network.EnqueueSend(new GameMessageUpdateObject(item));
                });

                chain.EnqueueChain();
                // Removed SaveSession - this was causing items that were dropped to not be removed from inventory.
                // If this causes a problem with vendor, we need to fix vendor.  Og II
            }).EnqueueChain();
        }
コード例 #7
0
        /// <summary>
        /// This is raised when we drop an item. It can be a wielded item, or an item in our inventory.
        /// </summary>
        public void HandleActionDropItem(ObjectGuid itemGuid)
        {
            // Goody Goody -- lets build  drop chain
            // First start drop animation
            new ActionChain(this, () =>
            {
                // check packs of item.
                WorldObject item;

                if (!TryRemoveFromInventory(itemGuid, out item))
                {
                    // check to see if this item is wielded
                    if (TryDequipObject(itemGuid, out item))
                    {
                        Children.Remove(Children.Find(s => s.Guid == item.Guid.Full));

                        Session.Network.EnqueueSend(
                            new GameMessageSound(Guid, Sound.WieldObject, 1.0f),
                            new GameMessageObjDescEvent(this),
                            new GameMessageUpdateInstanceId(Guid, new ObjectGuid(0), PropertyInstanceId.Wielder));
                    }
                }

                if (item == null)
                {
                    log.Error("Player_Inventory HandleActionDropItem item is null");
                    return;
                }

                item.SetPropertiesForWorld(this);

                // It's important that we save an item after it's been removed from inventory.
                // We want to avoid the scenario where the server crashes and a player has too many items.
                item.SaveBiotaToDatabase();

                var motion = new UniversalMotion(MotionStance.Standing);
                motion.MovementData.ForwardCommand = (uint)MotionCommand.Pickup;
                Session.Network.EnqueueSend(new GameMessageUpdateInstanceId(itemGuid, new ObjectGuid(0), PropertyInstanceId.Container));

                // Set drop motion
                CurrentLandblock.EnqueueBroadcastMotion(this, motion);

                // Now wait for Drop Motion to finish -- use ActionChain
                var chain = new ActionChain();

                // Wait for drop animation
                var motionTable           = DatManager.PortalDat.ReadFromDat <MotionTable>(MotionTableId);
                var pickupAnimationLength = motionTable.GetAnimationLength(MotionCommand.Pickup);
                chain.AddDelaySeconds(pickupAnimationLength);

                // Play drop sound
                // Put item on landblock
                chain.AddAction(this, () =>
                {
                    motion = new UniversalMotion(MotionStance.Standing);
                    CurrentLandblock.EnqueueBroadcastMotion(this, motion);
                    Session.Network.EnqueueSend(
                        new GameMessageSound(Guid, Sound.DropItem, (float)1.0),
                        new GameMessagePutObjectIn3d(Session, this, itemGuid),
                        new GameMessageUpdateInstanceId(itemGuid, new ObjectGuid(0), PropertyInstanceId.Container),
                        new GameMessagePrivateUpdatePropertyInt(Sequences, PropertyInt.EncumbranceVal, EncumbranceVal ?? 0));

                    // This is the sequence magic - adds back into 3d space seem to be treated like teleport.
                    item.Sequences.GetNextSequence(SequenceType.ObjectTeleport);
                    item.Sequences.GetNextSequence(SequenceType.ObjectVector);

                    CurrentLandblock.AddWorldObject(item);

                    Session.Network.EnqueueSend(new GameMessageUpdateObject(item));
                });

                chain.EnqueueChain();
            }).EnqueueChain();
        }