Exemple #1
0
int cItemGrid::HowManyCanFit(const cItem & a_ItemStack, bool a_AllowNewStacks)
{
	char NumLeft = a_ItemStack.m_ItemCount;
	int MaxStack = ItemHandler(a_ItemStack.m_ItemType)->GetMaxStackSize();
	for (int i = m_NumSlots - 1; i >= 0; i--)
	{
		if (m_Slots[i].IsEmpty())
		{
			if (a_AllowNewStacks)
			{
				NumLeft -= MaxStack;
			}
		}
		else if (m_Slots[i].IsStackableWith(a_ItemStack))
		{
			NumLeft -= MaxStack - m_Slots[i].m_ItemCount;
		}
		if (NumLeft <= 0)
		{
			// All items fit
			return a_ItemStack.m_ItemCount;
		}
	}  // for i - m_Slots[]
	return a_ItemStack.m_ItemCount - NumLeft;
}
Exemple #2
0
void cSlotAreaAnvil::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots)
{
	for (int i = 0; i < 2; i++)
	{
		const cItem * Slot = GetSlot(i, a_Player);
		if (!Slot->IsEqual(a_ItemStack) && (!Slot->IsEmpty() || a_KeepEmptySlots))
		{
			// Different items
			continue;
		}
		int NumFit = ItemHandler(Slot->m_ItemType)->GetMaxStackSize() - Slot->m_ItemCount;
		if (NumFit <= 0)
		{
			// Full stack already
			continue;
		}
		if (NumFit > a_ItemStack.m_ItemCount)
		{
			NumFit = a_ItemStack.m_ItemCount;
		}
		if (a_ShouldApply)
		{
			cItem NewSlot(a_ItemStack);
			NewSlot.m_ItemCount = Slot->m_ItemCount + NumFit;
			SetSlot(i, a_Player, NewSlot);
		}
		a_ItemStack.m_ItemCount -= NumFit;
		if (a_ItemStack.IsEmpty())
		{
			UpdateResult(a_Player);
			return;
		}
	}  // for i - Slots
	UpdateResult(a_Player);
}
Exemple #3
0
World::World() : attackHandler_(AttackHandler(this)),
movementHandler_(MovementHandler(this)),
itemHandler_(ItemHandler(this)) {
    attackHandler_.watchNotifier(&combatNotifier_);
    movementHandler_.watchNotifier(&movementNotifier_);
    itemHandler_.watchNotifier(&itemNotifier_);
}
Exemple #4
0
void cSlotAreaCrafting::ClickedResult(cPlayer & a_Player)
{
	const cItem * ResultSlot = GetSlot(0, a_Player);
	cItem & DraggingItem = a_Player.GetDraggingItem();

	// Get the current recipe:
	cCraftingRecipe & Recipe = GetRecipeForPlayer(a_Player);

	cItem * PlayerSlots = GetPlayerSlots(a_Player) + 1;
	cCraftingGrid Grid(PlayerSlots, m_GridSize, m_GridSize);

	// If possible, craft:
	if (DraggingItem.IsEmpty())
	{
		DraggingItem = Recipe.GetResult();
		Recipe.ConsumeIngredients(Grid);
		Grid.CopyToItems(PlayerSlots);
	}
	else if (DraggingItem.IsEqual(Recipe.GetResult()))
	{
		cItemHandler * Handler = ItemHandler(Recipe.GetResult().m_ItemType);
		if (DraggingItem.m_ItemCount + Recipe.GetResult().m_ItemCount <= Handler->GetMaxStackSize())
		{
			DraggingItem.m_ItemCount += Recipe.GetResult().m_ItemCount;
			Recipe.ConsumeIngredients(Grid);
			Grid.CopyToItems(PlayerSlots);
		}
	}

	// Get the new recipe and update the result slot:
	UpdateRecipe(a_Player);
	
	// We're done. Send all changes to the client and bail out:
	m_ParentWindow.BroadcastWholeWindow();
}
Exemple #5
0
void cInventory::UpdateItems(void)
{
	const cItem & Slot = GetEquippedItem();
	if (!Slot.IsEmpty())
	{
		ItemHandler(Slot.m_ItemType)->OnUpdate(m_Owner.GetWorld(), &m_Owner, Slot);
	}
}
Exemple #6
0
int cItemGrid::AddItem(cItem & a_ItemStack, bool a_AllowNewStacks, int a_PrioritarySlot)
{
	int NumLeft = a_ItemStack.m_ItemCount;
	int MaxStack = ItemHandler(a_ItemStack.m_ItemType)->GetMaxStackSize();

	// Try prioritarySlot first:
	if (
		(a_PrioritarySlot != -1) &&
		(
			m_Slots[a_PrioritarySlot].IsEmpty() ||
			m_Slots[a_PrioritarySlot].IsStackableWith(a_ItemStack)
		)
	)
	{
		NumLeft -= AddItemToSlot(a_ItemStack, a_PrioritarySlot, NumLeft, MaxStack);
	}

	// Scan existing stacks:
	for (int i = m_NumSlots - 1; i >= 0; i--)
	{
		if (m_Slots[i].IsStackableWith(a_ItemStack))
		{
			NumLeft -= AddItemToSlot(a_ItemStack, i, NumLeft, MaxStack);
		}
		if (NumLeft <= 0)
		{
			// All items fit
			return a_ItemStack.m_ItemCount;
		}
	}  // for i - m_Slots[]
	
	if (!a_AllowNewStacks)
	{
		return (a_ItemStack.m_ItemCount - NumLeft);
	}
	
	for (int i = m_NumSlots - 1; i >= 0; i--)
	{
		if (m_Slots[i].IsEmpty())
		{
			NumLeft -= AddItemToSlot(a_ItemStack, i, NumLeft, MaxStack);
		}
		if (NumLeft <= 0)
		{
			// All items fit
			return a_ItemStack.m_ItemCount;
		}
	}  // for i - m_Slots[]
	return (a_ItemStack.m_ItemCount - NumLeft);
}
Exemple #7
0
int cWindow::DistributeItemToSlots(cPlayer & a_Player, const cItem & a_Item, int a_NumToEachSlot, const cSlotNums & a_SlotNums)
{
	if ((size_t)(a_Item.m_ItemCount) < a_SlotNums.size())
	{
		LOGWARNING("%s: Distributing less items (%d) than slots (%u)", __FUNCTION__, (int)a_Item.m_ItemCount, a_SlotNums.size());
		// This doesn't seem to happen with the 1.5.1 client, so we don't worry about it for now
		return 0;
	}
	
	// Distribute to individual slots, keep track of how many items were actually distributed (full stacks etc.)
	int NumDistributed = 0;
	for (cSlotNums::const_iterator itr = a_SlotNums.begin(), end = a_SlotNums.end(); itr != end; ++itr)
	{
		int LocalSlotNum = 0;
		cSlotArea * Area = GetSlotArea(*itr, LocalSlotNum);
		if (Area == NULL)
		{
			LOGWARNING("%s: Bad SlotArea for slot %d", __FUNCTION__, *itr);
			continue;
		}
		
		// Modify the item at the slot
		cItem AtSlot(*Area->GetSlot(LocalSlotNum, a_Player));
		int MaxStack = ItemHandler(AtSlot.m_ItemType)->GetMaxStackSize();
		if (AtSlot.IsEmpty())
		{
			// Empty, just move all of it there:
			cItem ToStore(a_Item);
			ToStore.m_ItemCount = std::min(a_NumToEachSlot, (int)MaxStack);
			Area->SetSlot(LocalSlotNum, a_Player, ToStore);
			NumDistributed += ToStore.m_ItemCount;
		}
		else
		{
			// Occupied, add and cap at MaxStack:
			int CanStore = std::min(a_NumToEachSlot, (int)MaxStack - AtSlot.m_ItemCount);
			AtSlot.m_ItemCount += CanStore;
			Area->SetSlot(LocalSlotNum, a_Player, AtSlot);
			NumDistributed += CanStore;
		}
	}  // for itr - SlotNums[]
	return NumDistributed;
}
Exemple #8
0
void cWindow::OnMiddlePaintEnd(cPlayer & a_Player)
{
	if (!a_Player.IsGameModeCreative())
	{
		// Midle click paint is only valid for creative mode
		return;
	}

	// Fill available slots with full stacks of the dragging item
	const auto & DraggingItem = a_Player.GetDraggingItem();
	auto StackSize = ItemHandler(DraggingItem.m_ItemType)->GetMaxStackSize();
	if (0 < DistributeItemToSlots(a_Player, DraggingItem, StackSize, a_Player.GetInventoryPaintSlots(), false))
	{
		// If any items were distibuted, set dragging item empty
		a_Player.GetDraggingItem().Empty();
	}

	SendWholeWindow(*a_Player.GetClientHandle());
}
Exemple #9
0
void cInventory::UpdateItems(void)
{
	const cItem & Slot = GetEquippedItem();

	if (Slot.IsEmpty())
	{
		return;
	}

	switch (Slot.m_ItemType)
	{
		case E_ITEM_MAP:
		{
			ItemHandler(Slot.m_ItemType)->OnUpdate(m_Owner.GetWorld(), &m_Owner, Slot);
			break;
		}

		default: break;
	}
}
Exemple #10
0
int cInventory::HowManyCanFit(const cItem & a_ItemStack, int a_BeginSlotNum, int a_EndSlotNum, bool a_ConsiderEmptySlots)
{

	UNUSED(a_ConsiderEmptySlots);
	if ((a_BeginSlotNum < 0) || (a_BeginSlotNum >= invNumSlots))
	{
		LOGWARNING("%s: Bad BeginSlotNum, got %d, there are %d slots; correcting to 0.", __FUNCTION__, a_BeginSlotNum, invNumSlots - 1);
		a_BeginSlotNum = 0;
	}
	if ((a_EndSlotNum < 0) || (a_EndSlotNum >= invNumSlots))
	{
		LOGWARNING("%s: Bad EndSlotNum, got %d, there are %d slots; correcting to %d.", __FUNCTION__, a_BeginSlotNum, invNumSlots, invNumSlots - 1);
		a_EndSlotNum = invNumSlots - 1;
	}
	if (a_BeginSlotNum > a_EndSlotNum)
	{
		std::swap(a_BeginSlotNum, a_EndSlotNum);
	}

	char NumLeft = a_ItemStack.m_ItemCount;
	int MaxStack = ItemHandler(a_ItemStack.m_ItemType)->GetMaxStackSize();
	for (int i = a_BeginSlotNum; i <= a_EndSlotNum; i++)
	{
		const cItem & Slot = GetSlot(i);
		if (Slot.IsEmpty())
		{
			NumLeft -= MaxStack;
		}
		else if (Slot.IsEqual(a_ItemStack))
		{
			NumLeft -= MaxStack - Slot.m_ItemCount;
		}
		if (NumLeft <= 0)
		{
			// All items fit
			return a_ItemStack.m_ItemCount;
		}
	}  // for i - m_Slots[]
	return a_ItemStack.m_ItemCount - NumLeft;
}
Exemple #11
0
void cWolf::OnRightClicked(cPlayer & a_Player)
{
	const cItem & EquippedItem = a_Player.GetEquippedItem();
	const int EquippedItemType = EquippedItem.m_ItemType;

	if (!IsTame() && !IsAngry())
	{
		// If the player is holding a bone, try to tame the wolf:
		if (EquippedItemType == E_ITEM_BONE)
		{
			if (!a_Player.IsGameModeCreative())
			{
				a_Player.GetInventory().RemoveOneEquippedItem();
			}

			if (GetRandomProvider().RandBool(0.125))
			{
				// Taming succeeded
				SetMaxHealth(20);
				SetIsTame(true);
				SetOwner(a_Player.GetName(), a_Player.GetUUID());
				m_World->BroadcastEntityStatus(*this, esWolfTamed);
				m_World->BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
			}
			else
			{
				// Taming failed
				m_World->BroadcastEntityStatus(*this, esWolfTaming);
				m_World->BroadcastParticleEffect("smoke", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
			}
		}
	}
	else if (IsTame())
	{
		// Feed the wolf, restoring its health, or dye its collar:
		switch (EquippedItemType)
		{
			case E_ITEM_RAW_BEEF:
			case E_ITEM_STEAK:
			case E_ITEM_RAW_PORKCHOP:
			case E_ITEM_COOKED_PORKCHOP:
			case E_ITEM_RAW_CHICKEN:
			case E_ITEM_COOKED_CHICKEN:
			case E_ITEM_ROTTEN_FLESH:
			{
				if (m_Health < m_MaxHealth)
				{
					Heal(ItemHandler(EquippedItemType)->GetFoodInfo(&EquippedItem).FoodLevel);
					if (!a_Player.IsGameModeCreative())
					{
						a_Player.GetInventory().RemoveOneEquippedItem();
					}
				}
				break;
			}
			case E_ITEM_DYE:
			{
				if (a_Player.GetUUID() == m_OwnerUUID)  // Is the player the owner of the dog?
				{
					SetCollarColor(EquippedItem.m_ItemDamage);
					if (!a_Player.IsGameModeCreative())
					{
						a_Player.GetInventory().RemoveOneEquippedItem();
					}
				}
				break;
			}
			default:
			{
				if (a_Player.GetUUID() == m_OwnerUUID)  // Is the player the owner of the dog?
				{
					SetIsSitting(!IsSitting());
				}
			}
		}
	}

	m_World->BroadcastEntityMetadata(*this);
}
Exemple #12
0
bool cItem::IsFullStack(void) const
{
	return (m_ItemCount >= ItemHandler(m_ItemType)->GetMaxStackSize());
}
Exemple #13
0
/// Returns the cItemHandler responsible for this item type
cItemHandler * cItem::GetHandler(void) const
{
	return ItemHandler(m_ItemType);
}
Exemple #14
0
char cItem::GetMaxStackSize(void) const
{
	return ItemHandler(m_ItemType)->GetMaxStackSize();
}
Exemple #15
0
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();
	}
}