/// <summary> /// This method is used to pick items off the world - out of 3D space and into our inventory or to a wielded slot. /// It checks the use case needed, sends the appropriate response messages. In addition, it will move to objects /// that are out of range in the attemp to pick them up. It will call update apperiance if needed and you have /// wielded an item from the ground. Og II /// </summary> /// <param name="container"></param> /// <param name="itemGuid"></param> /// <param name="placement"></param> /// <param name="iidPropertyId"></param> private void PickupItem(Container container, ObjectGuid itemGuid, int placement, PropertyInstanceId iidPropertyId) { // Logical operations: // !! FIXME: How to handle repeat on condition? // while (!objectInRange) // try Move to object // !! FIXME: How to handle conditional // Try acquire from landblock // if acquire successful: // add to container ActionChain pickUpItemChain = new ActionChain(); // Move to the object pickUpItemChain.AddChain(CreateMoveToChain(itemGuid, PickUpDistance)); // Pick up the object // Start pickup animation pickUpItemChain.AddAction(this, () => { var motion = new UniversalMotion(MotionStance.Standing); motion.MovementData.ForwardCommand = (uint)MotionCommand.Pickup; CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageUpdatePosition(this), new GameMessageUpdateMotion(Guid, Sequences.GetCurrentSequence(SequenceType.ObjectInstance), Sequences, motion)); }); // Wait for animation to progress var motionTable = DatManager.PortalDat.ReadFromDat <MotionTable>(MotionTableId); var pickupAnimationLength = motionTable.GetAnimationLength(MotionCommand.Pickup); pickUpItemChain.AddDelaySeconds(pickupAnimationLength); // Ask landblock to transfer item // pickUpItemChain.AddAction(CurrentLandblock, () => CurrentLandblock.TransferItem(itemGuid, containerGuid)); if (container.Guid.IsPlayer()) { CurrentLandblock.QueueItemTransfer(pickUpItemChain, itemGuid, container.Guid); } else { CurrentLandblock.ScheduleItemTransferInContainer(pickUpItemChain, itemGuid, (Container)GetInventoryItem(container.Guid)); } // Finish pickup animation pickUpItemChain.AddAction(this, () => { // If success, the item is in our inventory: WorldObject item = GetInventoryItem(itemGuid); if (item.ContainerId != Guid.Full) { //Burden += item.Burden ?? 0; if (item.WeenieType == WeenieType.Coin) { UpdateCurrencyClientCalculations(WeenieType.Coin); } } if (item is Container itemAsContainer) { Session.Network.EnqueueSend(new GameEventViewContents(Session, itemAsContainer)); foreach (var packItem in itemAsContainer.Inventory) { Session.Network.EnqueueSend(new GameMessageCreateObject(packItem.Value)); UpdateCurrencyClientCalculations(WeenieType.Coin); } } // Update all our stuff if we succeeded if (item != null) { item.SetPropertiesForContainer(placement); // FIXME(ddevec): I'm not 100% sure which of these need to be broadcasts, and which are local sends... var motion = new UniversalMotion(MotionStance.Standing); if (iidPropertyId == PropertyInstanceId.Container) { Session.Network.EnqueueSend( ////new GameMessagePrivateUpdatePropertyInt(Session.Player.Sequences, PropertyInt.EncumbranceVal, UpdateBurden()), new GameMessageSound(Guid, Sound.PickUpItem, 1.0f), new GameMessageUpdateInstanceId(itemGuid, container.Guid, iidPropertyId), new GameMessagePutObjectInContainer(Session, container.Guid, item, placement)); } else { AddToWieldedObjects(item, container, (EquipMask)placement); Session.Network.EnqueueSend(new GameMessageSound(Guid, Sound.WieldObject, (float)1.0), new GameMessageObjDescEvent(this), new GameMessageUpdateInstanceId(container.Guid, itemGuid, PropertyInstanceId.Wielder), new GameEventWieldItem(Session, itemGuid.Full, placement)); } CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageUpdateMotion(Guid, Sequences.GetCurrentSequence(SequenceType.ObjectInstance), Sequences, motion), new GameMessagePickupEvent(item)); if (iidPropertyId == PropertyInstanceId.Wielder) { CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageObjDescEvent(this)); } // TODO: Og II - check this later to see if it is still required. Session.Network.EnqueueSend(new GameMessageUpdateObject(item)); } // If we didn't succeed, just stand up and be ashamed of ourself else { var motion = new UniversalMotion(MotionStance.Standing); CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageUpdateMotion(Guid, Sequences.GetCurrentSequence(SequenceType.ObjectInstance), Sequences, motion)); // CurrentLandblock.EnqueueBroadcast(self shame); } }); // Set chain to run pickUpItemChain.EnqueueChain(); }