Exemple #1
0
// Miscellaneous
int LuaExports::dropItemReactor(lua_State *luaVm) {
	int32_t itemid = lua_tointeger(luaVm, 1);
	int16_t amount = 1;
	if (lua_isnumber(luaVm, 2)) {
		amount = lua_tointeger(luaVm, 2);
	}
	Reactor *reactor = getReactor(luaVm);
	Player *player = getPlayer(luaVm);
	Drop *drop;
	if (GameLogicUtilities::isEquip(itemid)) {
		Item f(itemid, true);
		drop = new Drop(reactor->getMapId(), f, reactor->getPos(), player != nullptr ? player->getId() : 0);
	}
	else {
		Item f(itemid, amount);
		drop = new Drop(reactor->getMapId(), f, reactor->getPos(), player != nullptr ? player->getId() : 0);
	}
	drop->setTime(player != nullptr ? 100 : 0); // FFA if player isn't around
	drop->doDrop(reactor->getPos());
	return 0;
}
void InventoryHandler::itemMove(Player *player, PacketReader &packet) {
	if (!player->updateTickCount(packet.get<int32_t>())) {
		// Tickcount was the same or less than 100 of the difference.
		return;
	}

	int8_t inv = packet.get<int8_t>();
	int16_t slot1 = packet.get<int16_t>();
	int16_t slot2 = packet.get<int16_t>();
	if (slot2 == 0) {
		// Dropping an item
		int16_t amount = packet.get<int16_t>();
		Item *item = player->getInventory()->getItem(inv, slot1);
		if (item == nullptr) {
			return;
		}

		if (!GameLogicUtilities::isStackable(item->getId())) {
			amount = item->getAmount();
		}
		else if (amount <= 0 || amount > item->getAmount()) {
			// Hacking
			return;
		}
		else if (ItemDataProvider::Instance()->isCash(item->getId())) {
			// Hacks or modded client.
			return;
		}

		Item droppeditem(item);
		droppeditem.setAmount(amount);
		if (item->getAmount() == amount) {
			InventoryPacket::moveItem(player, inv, slot1, slot2);
			player->getInventory()->deleteItem(inv, slot1);
		}
		else {
			item->decAmount(amount);
			player->getInventory()->changeItemAmount(item->getId(), -amount);
			InventoryPacket::updateItemAmounts(player, inv, slot1, item->getAmount(), 0, 0);
		}
		Drop *drop = new Drop(player->getMap(), droppeditem, player->getPos(), player->getId(), true);
		drop->setTime(0);

		bool istradeable = ItemDataProvider::Instance()->isTradeable(droppeditem.getId());
		drop->setTradeable(istradeable);

		drop->doDrop(player->getPos());
		if (istradeable) {
			// Drop is deleted otherwise, avoid like plague
			ReactorHandler::checkDrop(player, drop);
		}
	}
	else {
		// Change item slot (swapping)
		Item *item1 = player->getInventory()->getItem(inv, slot1);
		Item *item2 = player->getInventory()->getItem(inv, slot2);

		if (item1 == nullptr) {
			// Hacking
			return;
		}

		if (item2 != nullptr && GameLogicUtilities::isStackable(item1->getId()) && item1->getId() == item2->getId()) {
			if (item1->getAmount() + item2->getAmount() <= ItemDataProvider::Instance()->getMaxSlot(item1->getId())) {
				item2->incAmount(item1->getAmount());
				player->getInventory()->deleteItem(inv, slot1, false);
				InventoryPacket::updateItemAmounts(player, inv, slot2, item2->getAmount(), 0, 0);
				InventoryPacket::moveItem(player, inv, slot1, 0);
			}
			else {
				item1->decAmount(ItemDataProvider::Instance()->getMaxSlot(item1->getId()) - item2->getAmount());
				item2->setAmount(ItemDataProvider::Instance()->getMaxSlot(item2->getId()));
				InventoryPacket::updateItemAmounts(player, inv, slot1, item1->getAmount(), slot2, item2->getAmount());
			}
		}
		else {
			if (slot2 < 0) {
				bool iscash = ItemDataProvider::Instance()->isCash(item1->getId());
				uint8_t desiredslot = -(slot2 + (iscash ? 100 : 0));
				if (!EquipDataProvider::Instance()->validSlot(item1->getId(), desiredslot)) {
					// Hacking
					return;
				}
				Item *remove = nullptr;
				int16_t oldslot = 0;
				bool weapon = -slot2 == EquipSlots::Weapon;
				bool shield = -slot2 == EquipSlots::Shield;
				bool top = -slot2 == EquipSlots::Top;
				bool bottom = -slot2 == EquipSlots::Bottom;

				if (weapon && GameLogicUtilities::is2hWeapon(item1->getId()) && player->getInventory()->getEquippedId(EquipSlots::Shield) != 0) {
					oldslot = -EquipSlots::Shield;
				}
				else if (shield && GameLogicUtilities::is2hWeapon(player->getInventory()->getEquippedId(EquipSlots::Weapon))) {
					oldslot = -EquipSlots::Weapon;
				}
				else if (top && GameLogicUtilities::isOverall(item1->getId()) && player->getInventory()->getEquippedId(EquipSlots::Bottom) != 0) {
					oldslot = -EquipSlots::Bottom;
				}
				else if (bottom && GameLogicUtilities::isOverall(player->getInventory()->getEquippedId(EquipSlots::Top))) {
					oldslot = -EquipSlots::Top;
				}
				if (oldslot != 0) {
					remove = player->getInventory()->getItem(inv, oldslot);
					bool onlyswap = true;
					if ((player->getInventory()->getEquippedId(EquipSlots::Shield) != 0) && (player->getInventory()->getEquippedId(EquipSlots::Weapon) != 0)) {
						onlyswap = false;
					}
					else if ((player->getInventory()->getEquippedId(EquipSlots::Top) != 0) && (player->getInventory()->getEquippedId(EquipSlots::Bottom) != 0)) {
						onlyswap = false;
					}
					if (onlyswap) {
						int16_t swapslot = 0;
						if (weapon) {
							swapslot = -EquipSlots::Shield;
							player->getActiveBuffs()->stopBooster();
							player->getActiveBuffs()->stopCharge();
						}
						else if (shield) {
							swapslot = -EquipSlots::Weapon;
							player->getActiveBuffs()->stopBooster();
							player->getActiveBuffs()->stopCharge();
						}
						else if (top) {
							swapslot = -EquipSlots::Bottom;
						}
						else if (bottom) {
							swapslot = -EquipSlots::Top;
						}
						player->getInventory()->setItem(inv, swapslot, nullptr);
						player->getInventory()->setItem(inv, slot1, remove);
						player->getInventory()->setItem(inv, slot2, item1);

						InventoryPacket::moveItem(player, inv, slot1, slot2);
						InventoryPacket::moveItem(player, inv, swapslot, slot1);
						InventoryPacket::updatePlayer(player);
						return;
					}
					else {
						if (player->getInventory()->getOpenSlotsNum(inv) == 0) {
							InventoryPacket::blankUpdate(player);
							return;
						}
						int16_t freeslot = 0;
						for (int16_t s = 1; s <= player->getInventory()->getMaxSlots(inv); s++) {
							Item *olditem = player->getInventory()->getItem(inv, s);
							if (olditem == nullptr) {
								freeslot = s;
								break;
							}
						}
						player->getInventory()->setItem(inv, freeslot, remove);
						player->getInventory()->setItem(inv, oldslot, nullptr);
						InventoryPacket::moveItem(player, inv, oldslot, freeslot);
					}
				}
			}
			else if (slot1 < 0 && item2 != nullptr && !ItemDataProvider::Instance()->isCash(item2->getId())) {
				// Client tries to switch a cash item with a regular item
				return;
			}

			player->getInventory()->setItem(inv, slot1, item2);
			player->getInventory()->setItem(inv, slot2, item1);
			if (item1->getPetId() > 0) {
				player->getPets()->getPet(item1->getPetId())->setInventorySlot((int8_t) slot2);
			}
			if (item2 != nullptr && item2->getPetId() > 0) {
				player->getPets()->getPet(item2->getPetId())->setInventorySlot((int8_t) slot1);
			}
			InventoryPacket::moveItem(player, inv, slot1, slot2);
		}
	}
	if ((slot1 < 0 && -slot1 == EquipSlots::Weapon) || (slot2 < 0 && -slot2 == EquipSlots::Weapon)) {
		player->getActiveBuffs()->stopBooster();
		player->getActiveBuffs()->stopCharge();
		player->getActiveBuffs()->stopBulletSkills();
	}
	// Check if the label ring changed, so we can update the look of the pet.
	if ((slot1 < 0 && -slot1 - 100 == EquipSlots::PetLabelRing1) || (slot2 < 0 && -slot2 - 100 == EquipSlots::PetLabelRing1)) {
		if (Pet *pet = player->getPets()->getSummoned(0)) {
			PetsPacket::changeName(player, pet);
		}
	}
	if ((slot1 < 0 && -slot1 - 100 == EquipSlots::PetLabelRing2) || (slot2 < 0 && -slot2 - 100 == EquipSlots::PetLabelRing2)) {
		if (Pet *pet = player->getPets()->getSummoned(1)) {
			PetsPacket::changeName(player, pet);
		}
	}
	if ((slot1 < 0 && -slot1 - 100 == EquipSlots::PetLabelRing3) || (slot2 < 0 && -slot2 - 100 == EquipSlots::PetLabelRing3)) {
		if (Pet *pet = player->getPets()->getSummoned(2)) {
			PetsPacket::changeName(player, pet);
		}
	}
	if (slot1 < 0 || slot2 < 0) {
		InventoryPacket::updatePlayer(player);
	}
}