const cSlotArea * cWindow::GetSlotArea(int a_GlobalSlotNum, int & a_LocalSlotNum) const { if ((a_GlobalSlotNum < 0) || (a_GlobalSlotNum >= GetNumSlots())) { LOGWARNING("%s: requesting an invalid SlotNum: %d out of %d slots", __FUNCTION__, a_GlobalSlotNum, GetNumSlots() - 1); ASSERT(!"Invalid SlotNum"); return NULL; } // Iterate through all the SlotAreas, find the correct one int LocalSlotNum = a_GlobalSlotNum; for (cSlotAreas::const_iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) { if (LocalSlotNum < (*itr)->GetNumSlots()) { a_LocalSlotNum = LocalSlotNum; return *itr; } LocalSlotNum -= (*itr)->GetNumSlots(); } // for itr - m_SlotAreas[] // We shouldn't be here - the check at the beginnning should prevent this. Log and assert LOGWARNING("%s: GetNumSlots() is out of sync: %d; LocalSlotNum = %d", __FUNCTION__, GetNumSlots(), LocalSlotNum); ASSERT(!"Invalid GetNumSlots"); return NULL; }
bool cSlotArea::CollectItemsToHand(cItem & a_Dragging, cPlayer & a_Player, bool a_CollectFullStacks) { int NumSlots = GetNumSlots(); for (int i = 0; i < NumSlots; i++) { const cItem & SlotItem = *GetSlot(i, a_Player); if (!SlotItem.IsEqual(a_Dragging)) { continue; } int ToMove = a_Dragging.GetMaxStackSize() - a_Dragging.m_ItemCount; if (ToMove > SlotItem.m_ItemCount) { ToMove = SlotItem.m_ItemCount; } a_Dragging.m_ItemCount += ToMove; cItem NewSlot(SlotItem); NewSlot.m_ItemCount -= ToMove; SetSlot(i, a_Player, NewSlot); if (!NewSlot.IsEmpty()) { // There are leftovers in the slot, so a_Dragging must be full return true; } } // for i - Slots[] // a_Dragging may be full if there were exactly the number of items needed to fill it return a_Dragging.IsFullStack(); }
bool Container::HasItems() { int8 TotalSlots = static_cast<int8>(GetNumSlots()); for (int8 i = 0; i < TotalSlots; i++) { if (m_Slot[i]) { return true; } } return false; }
int8 Container::FindFreeSlot() { int8 TotalSlots = static_cast<int8>(GetNumSlots()); for (int8 i = 0; i < TotalSlots; i++) { if (!m_Slot[i]) { return i; } } LOG_DEBUG("Container::FindFreeSlot: no slot available"); return ITEM_NO_SLOT_AVAILABLE; }
void cWindow::GetSlots(cPlayer & a_Player, cItems & a_Slots) const { a_Slots.clear(); a_Slots.reserve(GetNumSlots()); for (cSlotAreas::const_iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) { int NumSlots = (*itr)->GetNumSlots(); for (int i = 0; i < NumSlots; i++) { const cItem * Item = (*itr)->GetSlot(i, a_Player); if (Item == NULL) { a_Slots.push_back(cItem()); } else { a_Slots.push_back(*Item); } } } // for itr - m_SlotAreas[] }
void cWindow::Clicked( cPlayer & a_Player, int a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem ) { cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); if (a_WindowID != m_WindowID) { LOGWARNING("%s: Wrong window ID (exp %d, got %d) received from \"%s\"; ignoring click.", __FUNCTION__, m_WindowID, a_WindowID, a_Player.GetName().c_str()); return; } switch (a_ClickAction) { case caLeftClickOutside: case caRightClickOutside: { if (PlgMgr->CallHookPlayerTossingItem(a_Player)) { // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) return; } if (a_Player.IsGameModeCreative()) { a_Player.TossPickup(a_ClickedItem); } if (a_ClickAction == caLeftClickOutside) { // Toss all dragged items: a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); } else { // Toss one of the dragged items: a_Player.TossHeldItem(); } return; } case caLeftClickOutsideHoldNothing: case caRightClickOutsideHoldNothing: { // Nothing needed return; } case caLeftPaintBegin: OnPaintBegin (a_Player); return; case caRightPaintBegin: OnPaintBegin (a_Player); return; case caLeftPaintProgress: OnPaintProgress(a_Player, a_SlotNum); return; case caRightPaintProgress: OnPaintProgress(a_Player, a_SlotNum); return; case caLeftPaintEnd: OnLeftPaintEnd (a_Player); return; case caRightPaintEnd: OnRightPaintEnd(a_Player); return; default: { break; } } if (a_SlotNum < 0) { // TODO: Other click actions with irrelevant slot number (FS #371) return; } int LocalSlotNum = a_SlotNum; int idx = 0; for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) { if (LocalSlotNum < (*itr)->GetNumSlots()) { (*itr)->Clicked(a_Player, LocalSlotNum, a_ClickAction, a_ClickedItem); return; } LocalSlotNum -= (*itr)->GetNumSlots(); idx++; } LOGWARNING("Slot number higher than available window slots: %d, max %d received from \"%s\"; ignoring.", a_SlotNum, GetNumSlots(), a_Player.GetName().c_str() ); }
bool cWindow::IsSlotInPlayerInventory(int a_SlotNum) const { // Returns true if the specified slot is in the Player Main Inventory or Hotbar slotareas. Note that returns false for Armor. // The player combined inventory is always the last 36 slots return ((a_SlotNum >= GetNumSlots() - 36) && (a_SlotNum < GetNumSlots())); }
bool cWindow::IsSlotInPlayerHotbar(int a_SlotNum) const { // Returns true if the specified slot is in the Player Hotbar slotarea // The hotbar is always the last 9 slots return ((a_SlotNum >= GetNumSlots() - 9) && (a_SlotNum < GetNumSlots())); }
bool cWindow::IsSlotInPlayerMainInventory(int a_SlotNum) const { // Returns true if the specified slot is in the Player Main Inventory slotarea // The player main inventory is always 27 slots, 9 slots from the end of the inventory return ((a_SlotNum >= GetNumSlots() - 36) && (a_SlotNum < GetNumSlots() - 9)); }
void cSlotAreaAnvil::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots())); if (a_SlotNum != 2) { super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem); UpdateResult(a_Player); return; } bool bAsync = false; if (GetSlot(a_SlotNum, a_Player) == NULL) { LOGWARNING("GetSlot(%d) returned NULL! Ignoring click", a_SlotNum); return; } if (a_ClickAction == caDblClick) { return; } if ((a_ClickAction == caShiftLeftClick) || (a_ClickAction == caShiftRightClick)) { ShiftClicked(a_Player, a_SlotNum, a_ClickedItem); return; } cItem Slot(*GetSlot(a_SlotNum, a_Player)); if (!Slot.IsSameType(a_ClickedItem)) { LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots); LOGWARNING("My item: %s", ItemToFullString(Slot).c_str()); LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str()); bAsync = true; } cItem & DraggingItem = a_Player.GetDraggingItem(); if (Slot.IsEmpty()) { return; } if (!DraggingItem.IsEmpty()) { if (!(DraggingItem.IsEqual(Slot) && ((DraggingItem.m_ItemCount + Slot.m_ItemCount) <= cItemHandler::GetItemHandler(Slot)->GetMaxStackSize()))) { return; } } if (!CanTakeResultItem(a_Player)) { return; } cItem NewItem = cItem(Slot); NewItem.m_ItemCount += DraggingItem.m_ItemCount; Slot.Empty(); DraggingItem.Empty(); SetSlot(a_SlotNum, a_Player, Slot); DraggingItem = NewItem; OnTakeResult(a_Player); if (bAsync) { m_ParentWindow.BroadcastWholeWindow(); } }
void cSlotArea::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { /* LOGD("Slot area with %d slots clicked at slot number %d, clicked item %s, slot item %s", GetNumSlots(), a_SlotNum, ItemToFullString(a_ClickedItem).c_str(), ItemToFullString(*GetSlot(a_SlotNum, a_Player)).c_str() ); */ ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots())); bool bAsync = false; if (GetSlot(a_SlotNum, a_Player) == NULL) { LOGWARNING("GetSlot(%d) returned NULL! Ignoring click", a_SlotNum); return; } switch (a_ClickAction) { case caShiftLeftClick: case caShiftRightClick: { ShiftClicked(a_Player, a_SlotNum, a_ClickedItem); return; } case caDblClick: { DblClicked(a_Player, a_SlotNum); return; } default: { break; } } cItem Slot(*GetSlot(a_SlotNum, a_Player)); if (!Slot.IsSameType(a_ClickedItem)) { LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots); LOGWARNING("My item: %s", ItemToFullString(Slot).c_str()); LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str()); bAsync = true; } cItem & DraggingItem = a_Player.GetDraggingItem(); switch (a_ClickAction) { case caRightClick: { if (DraggingItem.m_ItemType <= 0) // Empty-handed? { DraggingItem = Slot.CopyOne(); // Obtain copy of slot to preserve lore, enchantments, etc. DraggingItem.m_ItemCount = (char)(((float)Slot.m_ItemCount) / 2.f + 0.5f); Slot.m_ItemCount -= DraggingItem.m_ItemCount; if (Slot.m_ItemCount <= 0) { Slot.Empty(); } } else if ((Slot.m_ItemType <= 0) || DraggingItem.IsEqual(Slot)) { // Drop one item in slot cItemHandler * Handler = ItemHandler(Slot.m_ItemType); if ((DraggingItem.m_ItemCount > 0) && (Slot.m_ItemCount < Handler->GetMaxStackSize())) { char OldSlotCount = Slot.m_ItemCount; Slot = DraggingItem.CopyOne(); // See above OldSlotCount++; Slot.m_ItemCount = OldSlotCount; DraggingItem.m_ItemCount--; } if (DraggingItem.m_ItemCount <= 0) { DraggingItem.Empty(); } } else if (!DraggingItem.IsEqual(Slot)) { // Swap contents cItem tmp(DraggingItem); DraggingItem = Slot; Slot = tmp; } break; } case caLeftClick: { // Left-clicked if (!DraggingItem.IsEqual(Slot)) { // Switch contents cItem tmp(DraggingItem); DraggingItem = Slot; Slot = tmp; } else { // Same type, add items: cItemHandler * Handler = ItemHandler(DraggingItem.m_ItemType); int FreeSlots = Handler->GetMaxStackSize() - Slot.m_ItemCount; if (FreeSlots < 0) { ASSERT(!"Bad item stack size - where did we get more items in a slot than allowed?"); FreeSlots = 0; } int Filling = (FreeSlots > DraggingItem.m_ItemCount) ? DraggingItem.m_ItemCount : FreeSlots; Slot.m_ItemCount += (char)Filling; DraggingItem.m_ItemCount -= (char)Filling; if (DraggingItem.m_ItemCount <= 0) { DraggingItem.Empty(); } } break; } default: { LOGWARNING("SlotArea: Unhandled click action: %d (%s)", a_ClickAction, ClickActionToString(a_ClickAction)); m_ParentWindow.BroadcastWholeWindow(); return; } } // switch (a_ClickAction SetSlot(a_SlotNum, a_Player, Slot); if (bAsync) { m_ParentWindow.BroadcastWholeWindow(); } }
void cWindow::Clicked( cPlayer & a_Player, int a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem ) { if (a_WindowID != m_WindowID) { LOGWARNING("%s: Wrong window ID (exp %d, got %d) received from \"%s\"; ignoring click.", __FUNCTION__, m_WindowID, a_WindowID, a_Player.GetName().c_str()); return; } switch (a_ClickAction) { case caRightClickOutside: { // Toss one of the dragged items: a_Player.TossItem(true); return; } case caLeftClickOutside: { // Toss all dragged items: a_Player.TossItem(true, a_Player.GetDraggingItem().m_ItemCount); return; } case caLeftClickOutsideHoldNothing: case caRightClickOutsideHoldNothing: { // Nothing needed return; } case caLeftPaintBegin: OnPaintBegin (a_Player); return; case caRightPaintBegin: OnPaintBegin (a_Player); return; case caLeftPaintProgress: OnPaintProgress(a_Player, a_SlotNum); return; case caRightPaintProgress: OnPaintProgress(a_Player, a_SlotNum); return; case caLeftPaintEnd: OnLeftPaintEnd (a_Player); return; case caRightPaintEnd: OnRightPaintEnd(a_Player); return; } if (a_SlotNum < 0) { // TODO: Other click actions with irrelevant slot number (FS #371) return; } int LocalSlotNum = a_SlotNum; int idx = 0; for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) { if (LocalSlotNum < (*itr)->GetNumSlots()) { (*itr)->Clicked(a_Player, LocalSlotNum, a_ClickAction, a_ClickedItem); return; } LocalSlotNum -= (*itr)->GetNumSlots(); idx++; } LOGWARNING("Slot number higher than available window slots: %d, max %d received from \"%s\"; ignoring.", a_SlotNum, GetNumSlots(), a_Player.GetName().c_str() ); }
void cSlotAreaEnchanting::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots())); bool bAsync = false; if (GetSlot(a_SlotNum, a_Player) == NULL) { LOGWARNING("GetSlot(%d) returned NULL! Ignoring click", a_SlotNum); return; } switch (a_ClickAction) { case caShiftLeftClick: case caShiftRightClick: { ShiftClicked(a_Player, a_SlotNum, a_ClickedItem); return; } case caDblClick: { DblClicked(a_Player, a_SlotNum); return; } default: { break; } } cItem Slot(*GetSlot(a_SlotNum, a_Player)); if (!Slot.IsSameType(a_ClickedItem)) { LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots); LOGWARNING("My item: %s", ItemToFullString(Slot).c_str()); LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str()); bAsync = true; } cItem & DraggingItem = a_Player.GetDraggingItem(); switch (a_ClickAction) { case caRightClick: { // Right-clicked if (DraggingItem.IsEmpty()) { DraggingItem = Slot.CopyOne(); Slot.Empty(); break; } if (Slot.IsEmpty()) { Slot = DraggingItem.CopyOne(); DraggingItem.m_ItemCount -= 1; if (DraggingItem.m_ItemCount <= 0) { DraggingItem.Empty(); } } else if ((!DraggingItem.IsEqual(Slot)) && (DraggingItem.m_ItemCount == 1)) { // Swap contents cItem tmp(DraggingItem); DraggingItem = Slot; Slot = tmp; } break; } case caLeftClick: { // Left-clicked if (DraggingItem.IsEmpty()) { DraggingItem = Slot.CopyOne(); Slot.Empty(); break; } if (DraggingItem.IsEqual(Slot)) { // Do nothing break; } if (!Slot.IsEmpty()) { if (DraggingItem.m_ItemCount == 1) { // Swap contents cItem tmp(DraggingItem); DraggingItem = Slot; Slot = tmp; } } else { Slot = DraggingItem.CopyOne(); DraggingItem.m_ItemCount -= 1; if (DraggingItem.m_ItemCount <= 0) { DraggingItem.Empty(); } } break; } default: { LOGWARNING("SlotArea: Unhandled click action: %d (%s)", a_ClickAction, ClickActionToString(a_ClickAction)); m_ParentWindow.BroadcastWholeWindow(); return; } } // switch (a_ClickAction SetSlot(a_SlotNum, a_Player, Slot); if (bAsync) { m_ParentWindow.BroadcastWholeWindow(); } UpdateResult(a_Player); }