class ActionAttachOnSelection: ActionSingleUseBase { void ActionAttachOnSelection() { m_Text = "#attach"; } override void CreateConditionComponents() { m_ConditionItem = new CCINonRuined(); m_ConditionTarget = new CCTCursor(); } override ActionData CreateActionData() { AttachActionData action_data = new AttachActionData(); return action_data; } int FindSlotIdToAttachOrCombine(PlayerBase player, ActionTarget target, ItemBase item) { EntityAI targetEntity = EntityAI.Cast(target.GetObject()); if (targetEntity && item) { GameInventory inv = targetEntity.GetInventory(); if (!inv) return InventorySlots.INVALID; int slotsCount = item.GetInventory().GetSlotIdCount(); array selections = new array(); targetEntity.GetActionComponentNameList(target.GetComponentIndex(), selections); foreach (string selection : selections) { int slotId = -1; if (!targetEntity.TranslateSlotFromSelection(selection, slotId)) slotId = InventorySlots.GetSlotIdFromString(selection); if (slotId == -1) continue; for (int i=0; i < slotsCount; ++i) { int itemSlotId = item.GetInventory().GetSlotId(i); if (slotId == itemSlotId) { ItemBase currentAttachment = ItemBase.Cast(inv.FindAttachment(slotId)); if (currentAttachment) { if (currentAttachment.CanBeCombined(item)) return itemSlotId; } else { if (inv.CanAddAttachment(item)) return itemSlotId; } } } } } return InventorySlots.INVALID; } override bool SetupAction(PlayerBase player, ActionTarget target, ItemBase item, out ActionData action_data, Param extra_data = null) { int attSlotId = InventorySlots.INVALID; if (!GetGame().IsDedicatedServer() ) { attSlotId = FindSlotIdToAttachOrCombine(player, target, item); } if (super.SetupAction( player, target, item, action_data, extra_data)) { if (!GetGame().IsDedicatedServer()) { if (attSlotId != InventorySlots.INVALID) { AttachActionData action_data_a = AttachActionData.Cast(action_data); action_data_a.m_AttSlot = attSlotId; return true; } return false; } return true; } return false; } override bool ActionCondition(PlayerBase player, ActionTarget target, ItemBase item) { if (GetGame().IsMultiplayer() && GetGame().IsServer()) return true; if (target.GetObject() && target.GetObject().CanUseConstruction()) return false; return FindSlotIdToAttachOrCombine(player, target, item) != InventorySlots.INVALID; } override void OnExecuteServer( ActionData action_data ) { if (GetGame().IsMultiplayer()) return; ClearInventoryReservationEx(action_data); AttachActionData action_data_a = AttachActionData.Cast(action_data); EntityAI entity; if (action_data.m_Target.IsProxy()) { entity = EntityAI.Cast(action_data.m_Target.GetParent()); } else { entity = EntityAI.Cast(action_data.m_Target.GetObject()); } if (entity && action_data.m_MainItem) { action_data.m_Player.PredictiveTakeEntityToTargetAttachmentEx(entity, action_data_a.m_MainItem, action_data_a.m_AttSlot); } } override void OnExecuteClient(ActionData action_data) { ClearInventoryReservationEx(action_data); EntityAI targetEntity = EntityAI.Cast(action_data.m_Target.GetObject()); EntityAI itemEntity = action_data.m_MainItem; AttachActionData action_data_a = AttachActionData.Cast(action_data); ItemBase attachment = ItemBase.Cast(targetEntity.GetInventory().FindAttachment(action_data_a.m_AttSlot)); if (attachment) { attachment.CombineItemsClient(itemEntity); } else { ItemBase item_base = ItemBase.Cast( itemEntity ); float stackable = item_base.GetTargetQuantityMax( action_data_a.m_AttSlot ); if (stackable == 0 || stackable >= item_base.GetQuantity()) { action_data.m_Player.PredictiveTakeEntityToTargetAttachmentEx(targetEntity, itemEntity, action_data_a.m_AttSlot); } else if (stackable != 0 && stackable < item_base.GetQuantity()) { item_base.SplitIntoStackMaxClient(targetEntity, action_data_a.m_AttSlot); } } } }