Пример #1
0
double Item::getWeight() const
{
	if(isStackable())
		return items[id].weight * std::max((int32_t)1, (int32_t)count);

	return items[id].weight;
}
Пример #2
0
bool Item::serializeAttr(PropWriteStream& propWriteStream) const
{
	if (isStackable() || isFluidContainer() || isSplash()) {
		uint8_t _count = getSubType();
		propWriteStream.ADD_UCHAR(ATTR_COUNT);
		propWriteStream.ADD_UCHAR(_count);
	}

	if (hasCharges()) {
		uint16_t _count = getCharges();
		propWriteStream.ADD_UCHAR(ATTR_CHARGES);
		propWriteStream.ADD_USHORT(_count);
	}

	if (!isNotMoveable()) {
		uint16_t _actionId = getActionId();
		if (_actionId) {
			propWriteStream.ADD_UCHAR(ATTR_ACTION_ID);
			propWriteStream.ADD_USHORT(_actionId);
		}
	}

	const std::string& _text = getText();
	if (!_text.empty()) {
		propWriteStream.ADD_UCHAR(ATTR_TEXT);
		propWriteStream.ADD_STRING(_text);
	}

	const time_t _writtenDate = getDate();
	if (_writtenDate > 0) {
		propWriteStream.ADD_UCHAR(ATTR_WRITTENDATE);
		propWriteStream.ADD_ULONG(_writtenDate);
	}

	const std::string& _writer = getWriter();
	if (!_writer.empty()) {
		propWriteStream.ADD_UCHAR(ATTR_WRITTENBY);
		propWriteStream.ADD_STRING(_writer);
	}

	const std::string& _specialDesc = getSpecialDescription();
	if (!_specialDesc.empty()) {
		propWriteStream.ADD_UCHAR(ATTR_DESC);
		propWriteStream.ADD_STRING(_specialDesc);
	}

	if (hasAttribute(ATTR_ITEM_DURATION)) {
		uint32_t duration = getDuration();
		propWriteStream.ADD_UCHAR(ATTR_DURATION);
		propWriteStream.ADD_ULONG(duration);
	}

	ItemDecayState_t decayState = getDecaying();
	if (decayState == DECAYING_TRUE || decayState == DECAYING_PENDING) {
		propWriteStream.ADD_UCHAR(ATTR_DECAYING_STATE);
		propWriteStream.ADD_UCHAR(decayState);
	}

	return true;
}
Пример #3
0
double Item::getWeight() const {
	if(isStackable()){
		return items[id].weight * std::max(1, (int)count);
	}

	return items[id].weight;
}
Пример #4
0
double Item::getWeight() const
{
	if (isStackable()) {
		return items[id].weight * std::max<int32_t>(1, getItemCount());
	}

	return items[id].weight;
}
Пример #5
0
bool Item::serializeAttr(PropWriteStream& propWriteStream) const
{
	if(isStackable() || isFluidContainer() || isSplash())
	{
		propWriteStream.addByte(ATTR_COUNT);
		propWriteStream.addByte((uint8_t)getSubType());
	}

	if(attributes && !attributes->empty())
	{
		propWriteStream.addByte(ATTR_ATTRIBUTE_MAP);
		serializeMap(propWriteStream);
	}

	return true;
}
Пример #6
0
bool Item::serializeAttr(PropWriteStream& propWriteStream)
{
	if(isStackable() || isSplash() || isFluidContainer()){
		unsigned char _count = getItemCountOrSubtype();
		propWriteStream.ADD_UCHAR(ATTR_COUNT);
		propWriteStream.ADD_UCHAR(_count);
	}

	if(isRune()){
		unsigned char _count = getItemCharge();
		propWriteStream.ADD_UCHAR(ATTR_RUNE_CHARGES);
		propWriteStream.ADD_UCHAR(_count);
	}

	if(!isNotMoveable() /*moveable*/){
		if(actionId){
			unsigned short _actionId = getActionId();
			propWriteStream.ADD_UCHAR(ATTR_ACTION_ID);
			propWriteStream.ADD_USHORT(_actionId);
		}
	}

	/*we are not saving unique ids
	if(uniqueId){
		unsigned short _uniqueId = getUniqueId();
		propWriteStream.ADD_UCHAR(ATTR_UNIQUE_ID);
		propWriteStream.ADD_USHORT(_uniqueId);
	}
	*/

	const std::string& _text = getText();
	if(_text.length() > 0){
		propWriteStream.ADD_UCHAR(ATTR_TEXT);
		propWriteStream.ADD_STRING(_text);
	}

	const std::string& _specialDesc = getSpecialDescription();
	if(_specialDesc.length() > 0){
		propWriteStream.ADD_UCHAR(ATTR_DESC);
		propWriteStream.ADD_STRING(_specialDesc);
	}

	return true;
}
Пример #7
0
GameStateManager::EBlockPlacement GameStateManager::blockPlacement(int32_t eid,
    const WorldCoords & wc, Direction dir, BlockItemInfoMap::const_iterator it, uint8_t & meta)
{
  // I believe we are never allowed to place anything on an already occupied block.
  // If that's false, we have to refactor this check. Water counts as unoccupied.

  if (!m_map.haveChunk(getChunkCoords(wc + dir)) || !isBuildable(EBlockItem(m_map.chunk(getChunkCoords(wc + dir)).blockType(getLocalCoords(wc + dir)))))
  {
    std::cout << "Sorry, cannot place object on occupied block at " << wc + dir << "." << std::endl;
    return CANNOT_PLACE;
  }

  // Likewise, we exclude globally right-clicks on banned block types, aka non-stackables.
  // Actually, I don't think the official server has such a rule. In fact, I think when the
  // client sends a PLACEMENT packet, it already expects the placement to be legal.
  // We're not expected to tell the client off. Oh well.

  if (!m_map.haveChunk(getChunkCoords(wc)) ||
      !isStackable(EBlockItem(m_map.chunk(getChunkCoords(wc)).blockType(getLocalCoords(wc)))) )
  {
    std::cout << "Sorry, cannot place object on non-stackable block at " << wc << "." << std::endl;
    return CANNOT_PLACE;
  }

  // Target block is clear and source block is stackable, let's get to work.

  switch(it->first) // block ID
  {
  case BLOCK_WoodenStairs:
  case BLOCK_CobblestoneStairs:
    {
      std::cout << "Special block: #" << eid << " is trying to place stairs." << std::endl;

      if (wY(wc) == 0 || dir == BLOCK_YMINUS) return CANNOT_PLACE;

      // Stairs are oriented to have their low end pointing toward the player.
      meta = 5 - int(m_states[eid]->getRelativeXZDirection(midpointRealCoords(wc + dir)));
      return OK_WITH_META;
    }

  case BLOCK_FurnaceBlock:
    {
      std::cout << "Special block: #" << eid << " is trying to place a furnace." << std::endl;

      if (wY(wc) == 0 || dir == BLOCK_YMINUS) return CANNOT_PLACE_AIRFORCE;

      const int d = int(m_states[eid]->getRelativeXZDirection(midpointRealCoords(wc + dir)));

      if      (d == 2) meta = 3;
      else if (d == 3) meta = 2;
      else if (d == 4) meta = 5;
      else if (d == 5) meta = 4;

      return OK_WITH_META;
    }
  case BLOCK_Torch:
  case BLOCK_RedstoneTorchOff:
  case BLOCK_RedstoneTorchOn:
    {
      std::cout << "Special block: #" << eid << " is trying to place a torch." << std::endl;

      // Torches are oriented simply to attach to the face which the user clicked.
      switch (int(dir))
      {
      case 2: meta = 4; break;
      case 3: meta = 3; break;
      case 4: meta = 2; break;
      case 5: meta = 1; break;
      default: meta = 5; break;
      }

      m_map.blockAlerts().insert(std::make_pair(wc, Map::BlockAlert(Map::BlockAlert::SUPPORTS_CANDLE)));

      return OK_WITH_META;
    }

  case ITEM_WoodenDoor:
  case ITEM_IronDoor:
    {
      // Doors can only be placed from above.
      if (dir != BLOCK_YPLUS)
        return CANNOT_PLACE;

      // Doors cannot be placed on glass, it seems.
      if (m_map.chunk(getChunkCoords(wc)).blockType(getLocalCoords(wc)) == BLOCK_Glass)
        return CANNOT_PLACE;

      const auto d = m_states[eid]->getRelativeXZDirection(midpointRealCoords(wc + dir));
      const unsigned char b = it->first == ITEM_WoodenDoor ? BLOCK_WoodenDoor : BLOCK_IronDoor;

      uint8_t meta;

      enum { HINGE_NE = 0, HINGE_SE = 1, HINGE_SW = 2, HINGE_NW = 3, SWUNG = 4 };

      switch (d)
      {
      case BLOCK_XPLUS:
        {
          if (m_map.haveChunk(getChunkCoords(wc + dir + BLOCK_ZPLUS)) &&
              !isBuildable(EBlockItem(m_map.chunk(getChunkCoords(wc + dir + BLOCK_ZPLUS)).blockType(getLocalCoords(wc + dir + BLOCK_ZPLUS)))))
            meta = HINGE_NW | SWUNG;
          else
            meta = HINGE_NE;
          break;
        }
      case BLOCK_XMINUS:
        {
          if (m_map.haveChunk(getChunkCoords(wc + dir + BLOCK_ZMINUS)) &&
              !isBuildable(EBlockItem(m_map.chunk(getChunkCoords(wc + dir + BLOCK_ZMINUS)).blockType(getLocalCoords(wc + dir + BLOCK_ZMINUS)))))
            meta = HINGE_SE | SWUNG;
          else
            meta = HINGE_SW;
          break;
        }
      case BLOCK_ZPLUS:
        {
          if (m_map.haveChunk(getChunkCoords(wc + dir + BLOCK_XMINUS)) &&
              !isBuildable(EBlockItem(m_map.chunk(getChunkCoords(wc + dir + BLOCK_XMINUS)).blockType(getLocalCoords(wc + dir + BLOCK_XMINUS)))))
            meta = HINGE_NE | SWUNG;
          else
            meta = HINGE_SE;
          break;
        }
      case BLOCK_ZMINUS:
        {
          if (m_map.haveChunk(getChunkCoords(wc + dir + BLOCK_XPLUS)) &&
              !isBuildable(EBlockItem(m_map.chunk(getChunkCoords(wc + dir + BLOCK_XPLUS)).blockType(getLocalCoords(wc + dir + BLOCK_XPLUS)))))
            meta = HINGE_SW | SWUNG;
          else
            meta = HINGE_NW;
          break;
        }
      default: return CANNOT_PLACE;
      }

      // Double-door algorithm: only check for a door on the left (apparently that's what the client does).
      if      (d == BLOCK_XMINUS && m_map.chunk(getChunkCoords(wc + dir + BLOCK_ZPLUS)) .blockType(getLocalCoords(wc + dir + BLOCK_ZPLUS))  == b)
      {
        meta = HINGE_SE | SWUNG;
      }
      else if (d == BLOCK_XPLUS  && m_map.chunk(getChunkCoords(wc + dir + BLOCK_ZMINUS)).blockType(getLocalCoords(wc + dir + BLOCK_ZMINUS)) == b)
      {
        meta = HINGE_NW | SWUNG;
      }
      else if (d == BLOCK_ZMINUS && m_map.chunk(getChunkCoords(wc + dir + BLOCK_XMINUS)).blockType(getLocalCoords(wc + dir + BLOCK_XMINUS)) == b)
      {
        meta = HINGE_SW | SWUNG;
      }
      else if (d == BLOCK_ZPLUS  && m_map.chunk(getChunkCoords(wc + dir + BLOCK_XPLUS)) .blockType(getLocalCoords(wc + dir + BLOCK_XPLUS))  == b)
      {
        meta = HINGE_NE | SWUNG;
      }

      sendToAll(MAKE_CALLBACK(packetSCBlockChange, wc + dir, b, meta));
      sendToAll(MAKE_CALLBACK(packetSCBlockChange, wc + dir + BLOCK_YPLUS, b, meta | 0x8));

      Chunk & chunk = m_map.chunk(getChunkCoords(wc + dir));
      chunk.blockType(getLocalCoords(wc + dir)) = b;
      chunk.setBlockMetaData(getLocalCoords(wc + dir), meta);
      chunk.blockType(getLocalCoords(wc + dir + BLOCK_YPLUS)) = b;
      chunk.setBlockMetaData(getLocalCoords(wc + dir + BLOCK_YPLUS), meta | 0x8);

      return OK_NO_META;
    }

  default:
    return OK_NO_META;
  }

  return OK_NO_META;
}
Пример #8
0
void Item::calculatePatterns(int& xPattern, int& yPattern, int& zPattern)
{
    if(isStackable() && getNumPatternX() == 4 && getNumPatternY() == 2) {
        if(m_countOrSubType <= 0) {
            xPattern = 0;
            yPattern = 0;
        } else if(m_countOrSubType < 5) {
            xPattern = m_countOrSubType-1;
            yPattern = 0;
        } else if(m_countOrSubType < 10) {
            xPattern = 0;
            yPattern = 1;
        } else if(m_countOrSubType < 25) {
            xPattern = 1;
            yPattern = 1;
        } else if(m_countOrSubType < 50) {
            xPattern = 2;
            yPattern = 1;
        } else {
            xPattern = 3;
            yPattern = 1;
        }
    } else if(isHangable()) {
        const TilePtr& tile = getTile();
        if(tile) {
            if(tile->mustHookSouth())
                xPattern = getNumPatternX() >= 2 ? 1 : 0;
            else if(tile->mustHookEast())
                xPattern = getNumPatternX() >= 3 ? 2 : 0;
        }
    } else if(isSplash() || isFluidContainer()) {
        int color = Otc::FluidTransparent;
        switch(m_countOrSubType) {
            case Otc::FluidNone:
                color = Otc::FluidTransparent;
                break;
            case Otc::FluidWater:
                color = Otc::FluidBlue;
                break;
            case Otc::FluidMana:
                color = Otc::FluidPurple;
                break;
            case Otc::FluidBeer:
                color = Otc::FluidBrown;
                break;
            case Otc::FluidOil:
                color = Otc::FluidBrown;
                break;
            case Otc::FluidBlood:
                color = Otc::FluidRed;
                break;
            case Otc::FluidSlime:
                color = Otc::FluidGreen;
                break;
            case Otc::FluidMud:
                color = Otc::FluidBrown;
                break;
            case Otc::FluidLemonade:
                color = Otc::FluidYellow;
                break;
            case Otc::FluidMilk:
                color = Otc::FluidWhite;
                break;
            case Otc::FluidWine:
                color = Otc::FluidPurple;
                break;
            case Otc::FluidHealth:
                color = Otc::FluidRed;
                break;
            case Otc::FluidUrine:
                color = Otc::FluidYellow;
                break;
            case Otc::FluidRum:
                color = Otc::FluidBrown;
                break;
            case Otc::FluidFruidJuice:
                color = Otc::FluidYellow;
                break;
            case Otc::FluidCoconutMilk:
                color = Otc::FluidWhite;
                break;
            case Otc::FluidTea:
                color = Otc::FluidBrown;
                break;
            case Otc::FluidMead:
                color = Otc::FluidBrown;
                break;
            default:
                color = Otc::FluidTransparent;
                break;
        }

        xPattern = (color % 4) % getNumPatternX();
        yPattern = (color / 4) % getNumPatternY();
    } else if(isGround() || isOnBottom()) {
        xPattern = m_position.x % getNumPatternX();
        yPattern = m_position.y % getNumPatternY();
        zPattern = m_position.z % getNumPatternZ();
    }
}
Пример #9
0
int Item::getCount()
{
    if(isStackable())
        return m_countOrSubType;
    return 1;
}
void CGAddMouseToQuickSlotHandler::execute (CGAddMouseToQuickSlot* pPacket , Player* pPlayer)
	throw(ProtocolException, Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

	Assert(pPacket != NULL);
	Assert(pPlayer != NULL);

	GamePlayer*    pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer);
	Creature*      pCreature   = pGamePlayer->getCreature();
	bool           Success     = false;

	if (pCreature->isSlayer())
	{
		Slayer*        pSlayer    = dynamic_cast<Slayer*>(pCreature);
		InventorySlot* pExtraSlot = pSlayer->getExtraInventorySlot();
		Item*          pItem      = pExtraSlot->getItem();

		if (pItem == NULL)
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		ObjectID_t      ItemObjectID = pItem->getObjectID();
		SlotID_t        SlotID       = pPacket->getSlotID();
		Item::ItemClass IClass       = pItem->getItemClass();

		// 아이템의 ObjectID가 일치하는지 체크한다.
		if (ItemObjectID != pPacket->getObjectID()) 
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		// 벨트를 입고 있지 않다면 벨트에다 아이템을 더할 수가 없다.
		if (!pSlayer->isWear(Slayer::WEAR_BELT))
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		// 포션도 아니고, 탄창도 아니라면 더할 수가 없지.
		if (IClass != Item::ITEM_CLASS_POTION && IClass != Item::ITEM_CLASS_MAGAZINE && IClass != Item::ITEM_CLASS_EVENT_ETC && IClass != Item::ITEM_CLASS_KEY)
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}
		if (IClass == Item::ITEM_CLASS_EVENT_ETC && pItem->getItemType() < 14 )
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		Item*      pBelt          = pSlayer->getWearItem(Slayer::WEAR_BELT);
		Inventory* pBeltInventory = ((Belt*)pBelt)->getInventory();

		if (pBeltInventory->canAdding(SlotID, 0,  pItem)) 
		{
			// 현재 벨트에 있는 Item을 받아온다.
			Item* pPrevItem = pBeltInventory->getItem(SlotID, 0);

			// 지정한 자리에 아이템이 있다면...
			if (pPrevItem != NULL)
			{
				// 아이템이 완전히 같은 아이템이라면...
				if (isStackable(pItem) && isSameItem(pItem, pPrevItem))
				{
					int MaxStack = ItemMaxStack[pItem->getItemClass()];

					if (pItem->getNum() + pPrevItem->getNum() > MaxStack) 
					{
						ItemNum_t CurrentNum = pPrevItem->getNum();
						ItemNum_t AddNum     = pItem->getNum();
						ItemNum_t NewNum	 = AddNum + CurrentNum - MaxStack;

						pPrevItem->setNum(MaxStack);
						pItem->setNum(NewNum);
						pBeltInventory->increaseNum(MaxStack - CurrentNum);
						pBeltInventory->increaseWeight(pItem->getWeight()* (MaxStack - CurrentNum));
						//pPrevItem->save(pSlayer->getName(), STORAGE_BELT, pBelt->getItemID(), SlotID, 0);
						// item저장 최적화. by sigi. 2002.5.13
						char pField[80];
						sprintf(pField, "Num=%d, Storage=%d, StorageID=%lu, X=%d", MaxStack, STORAGE_BELT, pBelt->getItemID(), SlotID);
						pPrevItem->tinysave(pField);

						//pItem->save(pSlayer->getName(), STORAGE_EXTRASLOT, 0, 0, 0);
						// item저장 최적화. by sigi. 2002.5.13
						sprintf(pField, "Num=%d, Storage=%d", NewNum, STORAGE_EXTRASLOT);
						pItem->tinysave(pField);


						Success = true;
					} 
					else // 숫자가 9개를 넘지 않을 때.
					{
						pSlayer->deleteItemFromExtraInventorySlot();
						pPrevItem->setNum(pPrevItem->getNum() + pItem->getNum());
						pBeltInventory->increaseNum(pItem->getNum());
						pBeltInventory->increaseWeight(pItem->getWeight()* pItem->getNum());
						//pPrevItem->save(pSlayer->getName(), STORAGE_BELT , pBelt->getItemID(), SlotID, 0);
						// item저장 최적화. by sigi. 2002.5.13
						char pField[80];
						sprintf(pField, "Num=%d, Storage=%d, StorageID=%lu, X=%d", pPrevItem->getNum(), STORAGE_BELT, pBelt->getItemID(), SlotID);
						pPrevItem->tinysave(pField);

						pItem->destroy();
						SAFE_DELETE(pItem);
						Success = true;
					}
				} 
				else // 클래스랑 타입이 같지 않을때
				{
					// 마우스에 달려있는 아이템과 벨트에 있는 아이템을 제거한다.
					pSlayer->deleteItemFromExtraInventorySlot();
					pBeltInventory->deleteItem(pPrevItem->getObjectID());

					// 둘의 위치를 바꿔 준다.
					pSlayer->addItemToExtraInventorySlot(pPrevItem);
					pBeltInventory->addItem(SlotID , 0 , pItem);

					// DB에다가 저장을 한다.
					//pPrevItem->save(pSlayer->getName(), STORAGE_EXTRASLOT, 0, 0, 0);
					// item저장 최적화. by sigi. 2002.5.13
					char pField[80];
					sprintf(pField, "Storage=%d", STORAGE_EXTRASLOT);
					pPrevItem->tinysave(pField);

					//pItem->save(pSlayer->getName(), STORAGE_BELT , pBelt->getItemID(), SlotID, 0);
					// item저장 최적화. by sigi. 2002.5.13
					sprintf(pField, "Storage=%d, StorageID=%lu, X=%d", STORAGE_BELT, pBelt->getItemID(), SlotID);
					pItem->tinysave(pField);


					Success = true;
				}
			} 
			else // 슬랏에 아무런 기존의 아이템이 없을때.
			{
				// Inventory에 특정 아이템을 넣는다.
				pBeltInventory->addItem(SlotID, 0 , pItem);

				// 넣기에 성공하면 마우스에 달려있는 아이템을 없앤다.
				pSlayer->deleteItemFromExtraInventorySlot();
				//pItem->save(pSlayer->getName(), STORAGE_BELT, pBelt->getItemID(), SlotID, 0);
				// item저장 최적화. by sigi. 2002.5.13
				char pField[80];
				sprintf(pField, "Storage=%d, StorageID=%lu, X=%d", STORAGE_BELT, pBelt->getItemID(), SlotID);
				pItem->tinysave(pField);

				Success = true;
			}
		} // end of if (pBeltInventory->canAdding(SlotID, 0,  pItem)) 
	} // if (pCreature->isSlayer())
	else if (pCreature->isOusters())
	{
		Ousters*        pOusters  = dynamic_cast<Ousters*>(pCreature);
		InventorySlot* pExtraSlot = pOusters->getExtraInventorySlot();
		Item*          pItem      = pExtraSlot->getItem();

		if (pItem == NULL)
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		ObjectID_t      ItemObjectID = pItem->getObjectID();
		SlotID_t        SlotID       = pPacket->getSlotID();
		Item::ItemClass IClass       = pItem->getItemClass();

		// 아이템의 ObjectID가 일치하는지 체크한다.
		if (ItemObjectID != pPacket->getObjectID()) 
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		Ousters::WearPart part = (SlotID > 2 ? Ousters::WEAR_ARMSBAND2 : Ousters::WEAR_ARMSBAND1);
		if (SlotID > 2 ) SlotID -= 3;

		// 해당 암스밴드가 없다
		if (!pOusters->isWear(part)) 
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		// 푸파도 아니고, 콤포스메이도 아니라면 더할 수가 없지.
		if (IClass != Item::ITEM_CLASS_PUPA && IClass != Item::ITEM_CLASS_COMPOS_MEI && IClass != Item::ITEM_CLASS_EVENT_ETC )
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		if (IClass == Item::ITEM_CLASS_EVENT_ETC && pItem->getItemType() < 14 )
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		Item*      pArmsband          = pOusters->getWearItem(part);
		Inventory* pArmsbandInventory = ((OustersArmsband*)pArmsband)->getInventory();

		if (pArmsbandInventory->canAdding(SlotID, 0,  pItem)) 
		{
			// 현재 벨트에 있는 Item을 받아온다.
			Item* pPrevItem = pArmsbandInventory->getItem(SlotID, 0);

			// 지정한 자리에 아이템이 있다면...
			if (pPrevItem != NULL)
			{
				// 아이템이 완전히 같은 아이템이라면...
				if (isSameItem(pItem, pPrevItem))
				{
					int MaxStack = ItemMaxStack[pItem->getItemClass()];

					if (pItem->getNum() + pPrevItem->getNum() > MaxStack) 
					{
						ItemNum_t CurrentNum = pPrevItem->getNum();
						ItemNum_t AddNum     = pItem->getNum();
						ItemNum_t NewNum	 = AddNum + CurrentNum - MaxStack;

						pPrevItem->setNum(MaxStack);
						pItem->setNum(NewNum);
						pArmsbandInventory->increaseNum(MaxStack - CurrentNum);
						pArmsbandInventory->increaseWeight(pItem->getWeight()* (MaxStack - CurrentNum));
						//pPrevItem->save(pOusters->getName(), STORAGE_BELT, pArmsband->getItemID(), SlotID, 0);
						// item저장 최적화. by sigi. 2002.5.13
						char pField[80];
						sprintf(pField, "Num=%d, Storage=%d, StorageID=%lu, X=%d", MaxStack, STORAGE_BELT, pArmsband->getItemID(), SlotID);
						pPrevItem->tinysave(pField);

						//pItem->save(pOusters->getName(), STORAGE_EXTRASLOT, 0, 0, 0);
						// item저장 최적화. by sigi. 2002.5.13
						sprintf(pField, "Num=%d, Storage=%d", NewNum, STORAGE_EXTRASLOT);
						pItem->tinysave(pField);


						Success = true;
					} 
					else // 숫자가 9개를 넘지 않을 때.
					{
						pOusters->deleteItemFromExtraInventorySlot();
						pPrevItem->setNum(pPrevItem->getNum() + pItem->getNum());
						pArmsbandInventory->increaseNum(pItem->getNum());
						pArmsbandInventory->increaseWeight(pItem->getWeight()* pItem->getNum());
						//pPrevItem->save(pOusters->getName(), STORAGE_BELT , pArmsband->getItemID(), SlotID, 0);
						// item저장 최적화. by sigi. 2002.5.13
						char pField[80];
						sprintf(pField, "Num=%d, Storage=%d, StorageID=%lu, X=%d", pPrevItem->getNum(), STORAGE_BELT, pArmsband->getItemID(), SlotID);
						pPrevItem->tinysave(pField);

						pItem->destroy();
						SAFE_DELETE(pItem);
						Success = true;
					}
				} 
				else // 클래스랑 타입이 같지 않을때
				{
					// 마우스에 달려있는 아이템과 벨트에 있는 아이템을 제거한다.
					pOusters->deleteItemFromExtraInventorySlot();
					pArmsbandInventory->deleteItem(pPrevItem->getObjectID());

					// 둘의 위치를 바꿔 준다.
					pOusters->addItemToExtraInventorySlot(pPrevItem);
					pArmsbandInventory->addItem(SlotID , 0 , pItem);

					// DB에다가 저장을 한다.
					//pPrevItem->save(pOusters->getName(), STORAGE_EXTRASLOT, 0, 0, 0);
					// item저장 최적화. by sigi. 2002.5.13
					char pField[80];
					sprintf(pField, "Storage=%d", STORAGE_EXTRASLOT);
					pPrevItem->tinysave(pField);

					//pItem->save(pOusters->getName(), STORAGE_BELT , pArmsband->getItemID(), SlotID, 0);
					// item저장 최적화. by sigi. 2002.5.13
					sprintf(pField, "Storage=%d, StorageID=%lu, X=%d", STORAGE_BELT, pArmsband->getItemID(), SlotID);
					pItem->tinysave(pField);


					Success = true;
				}
			} 
			else // 슬랏에 아무런 기존의 아이템이 없을때.
			{
				// Inventory에 특정 아이템을 넣는다.
				pArmsbandInventory->addItem(SlotID, 0 , pItem);

				// 넣기에 성공하면 마우스에 달려있는 아이템을 없앤다.
				pOusters->deleteItemFromExtraInventorySlot();
				//pItem->save(pOusters->getName(), STORAGE_BELT, pArmsband->getItemID(), SlotID, 0);
				// item저장 최적화. by sigi. 2002.5.13
				char pField[80];
				sprintf(pField, "Storage=%d, StorageID=%lu, X=%d", STORAGE_BELT, pArmsband->getItemID(), SlotID);
				pItem->tinysave(pField);

				Success = true;
			}
		} // end of if (pArmsbandInventory->canAdding(SlotID, 0,  pItem)) 
	} // if (pCreature->isOusters())

	// QuickSlot에 넣는 것을 실패 하였을때 실패 패킷을 날린다.
	if (!Success) 
	{
		GCCannotAdd _GCCannotAdd;
		_GCCannotAdd.setObjectID(pPacket->getObjectID());
		pPlayer->sendPacket(&_GCCannotAdd);
	}

#endif	// __GAME_SERVER__

    __END_DEBUG_EX __END_CATCH

}
void CGAddInventoryToMouseHandler::execute(CGAddInventoryToMouse* pPacket , Player* pPlayer)
	throw(ProtocolException, Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

	GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer);
	Assert(pGamePlayer != NULL);

	Creature* pCreature = pGamePlayer->getCreature();
	Assert(pCreature != NULL);

	PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature);
	Assert(pPC != NULL);

	Zone* pZone = pPC->getZone();
	Assert(pZone != NULL);

	if (pPC->getStore()->isOpen() )
	{
		GCCannotAdd _GCCannotAdd;
		_GCCannotAdd.setObjectID(pPacket->getObjectID());
		pPlayer->sendPacket(&_GCCannotAdd);
		return;
	}

	CoordInven_t InvenX = pPacket->getX();
	CoordInven_t InvenY = pPacket->getY();
	ObjectID_t   ItemOID = pPacket->getObjectID();

	Inventory* pInventory = pPC->getInventory();
	Assert(pInventory != NULL);
    int invenID = 0;
/* Commenting the SubInventory stuff, since it's not supported by the client we use
	SubInventory* pInventoryItem = NULL;
	int invenID = 0;

	if (pPacket->getInventoryItemObjectID() != 0 )
	{
		CoordInven_t X, Y;
		pInventoryItem = dynamic_cast<SubInventory*>(pInventory->findItemOID(pPacket->getInventoryItemObjectID(), X, Y ));
		if (pInventoryItem == NULL )
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		pInventory = pInventoryItem->getInventory();
		invenID = pInventoryItem->getItemID();
	}
*/
	// 인벤토리 좌표를 넘어가면 곤란하다...
	if (InvenX >= pInventory->getWidth() || InvenY >= pInventory->getHeight())
	{
		GCCannotAdd _GCCannotAdd;
		_GCCannotAdd.setObjectID(pPacket->getObjectID());
		pPlayer->sendPacket(&_GCCannotAdd);
		return;
	}

	Item* pItem          = pInventory->getItem(InvenX, InvenY);
	Item* pExtraSlotItem = pPC->getExtraInventorySlotItem();

	if (pPC->getStore()->hasItem(pItem ) )
	{
		GCCannotAdd _GCCannotAdd;
		_GCCannotAdd.setObjectID(pPacket->getObjectID());
		pPlayer->sendPacket(&_GCCannotAdd);
		return;
	}

	// 더하고자 하는 아이템이 없거나, 이미 마우스에 뭔가가 붙어있다면
	// 들 수 없다.
	if (pItem == NULL || pExtraSlotItem != NULL)
	{
		GCCannotAdd _GCCannotAdd;
		_GCCannotAdd.setObjectID(pPacket->getObjectID());
		pPlayer->sendPacket(&_GCCannotAdd);
		return;
	}

	// 일반적인 아이템 마우스 더하기 루틴
	if (ItemOID != 0)
	{
		// OID가 일치하지 않으면 곤란하다...
		if (pItem->getObjectID() != ItemOID)
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		pInventory->deleteItem(pItem->getObjectID());
		pPC->addItemToExtraInventorySlot(pItem);
		//pItem->save(pPC->getName(), STORAGE_EXTRASLOT, 0, 0, 0);
		// item저장 최적화. by sigi. 2002.5.13
		char pField[80];
		sprintf(pField, "Storage=%d, StorageID=0", STORAGE_EXTRASLOT);
		pItem->tinysave(pField);

		TradeManager* pTradeManager = pZone->getTradeManager();
		TradeInfo* pInfo = pTradeManager->getTradeInfo(pCreature->getName());
		if (pInfo != NULL && pInfo->getStatus() == TRADE_FINISH)
		{
			GCTradeVerify gcTradeVerify;
			gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_INVENTORY_TO_MOUSE_OK);
			pPlayer->sendPacket(&gcTradeVerify);
		}
	}
	// 겹치는 아이템 분리하기 루틴
	else
	{
		// 겹치는 아이템이 아니거나, 현재 숫자가 2 미만이라면 분리할 수 없다.
		if (!isStackable(pItem) || pItem->getNum() < 2
			|| (pItem->getItemClass() == Item::ITEM_CLASS_MOON_CARD && pItem->getItemType() == 2 && pItem->getNum() == 99) 
			|| pPC->getStore()->hasItem(pItem)
		)
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		// 기존의 아이템을 바탕으로 같은 아이템을 생성한다. 
		Item::ItemClass IClass = pItem->getItemClass();
		ItemType_t      IType  = pItem->getItemType();
		const list<OptionType_t>& OType  = pItem->getOptionTypeList();

		Item* pNewItem = g_pItemFactoryManager->createItem(IClass, IType, OType);
		Assert(pNewItem != NULL);

		// 마우스에다 더할 아이템은 기존의 OID를 가져가고,
		// 인벤토리에 남을 아이템은 새로운 OID를 받아야 한다.
		Zone* pZone = pPC->getZone();
		Assert(pZone != NULL);

		ObjectRegistry& OR = pZone->getObjectRegistry();
		OR.registerObject(pNewItem);

		// 인벤토리에 남아있는 아이템의 숫자는 원래 숫자에서 1을 뺀 숫자가 된다.
		// 기존의 아이템은 마우스로 옮겨졌으므로, 숫자가 1이 된다.
		// 인벤토리에서 마우스로 옮겨진 아이템을 삭제하고, 
		// 새로 생성된 아이템을 더한다.
		pInventory->deleteItem(pItem->getObjectID());
		pPC->addItemToExtraInventorySlot(pItem);

		int NewNum = pItem->getNum() - 1;
		pNewItem->setNum(NewNum); 
		pItem->setNum(1);

		pInventory->addItem(InvenX, InvenY, pNewItem);

		// 달라진 위치 정보를 세이브한다...
		//pItem->save(pPC->getName(), STORAGE_EXTRASLOT, 0, 0, 0);
		// item저장 최적화. by sigi. 2002.5.13
		char pField[80];
		sprintf(pField, "Num=%d, Storage=%d, StorageID=0", 1, STORAGE_EXTRASLOT);
		pItem->tinysave(pField);

		pNewItem->create(pPC->getName(), STORAGE_INVENTORY, invenID, InvenX, InvenY);
		//pNewItem->setNum(NewNum); // 위에서 했는데 또 하네. -_-;
		//pNewItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY);
		// item저장 최적화. by sigi. 2002.5.13
		sprintf(pField, "Num=%d, Storage=%d, StorageID=%u", NewNum, STORAGE_INVENTORY, invenID);
		pNewItem->tinysave(pField);


		// 클라이언트에게는 GCCreateItem 패킷을 이용해 
		// 인벤토리에 새로이(?) 생성된 아이템에 대한 정보를 보내준다.
		GCCreateItem gcCreateItem;
		gcCreateItem.setObjectID(pNewItem->getObjectID());
		gcCreateItem.setItemClass((BYTE)pNewItem->getItemClass());
		gcCreateItem.setItemType(pNewItem->getItemType());
		gcCreateItem.setOptionType(pNewItem->getOptionTypeList());
		gcCreateItem.setDurability(pNewItem->getDurability());
		gcCreateItem.setSilver(pNewItem->getSilver());
		gcCreateItem.setEnchantLevel(pNewItem->getEnchantLevel());
		gcCreateItem.setItemNum(pNewItem->getNum());
		gcCreateItem.setInvenX(InvenX);
		gcCreateItem.setInvenY(InvenY);
		pPlayer->sendPacket(&gcCreateItem);
	}
	
#endif	// __GAME_SERVER__

    __END_DEBUG_EX __END_CATCH

}
Пример #12
0
std::string Item::getDescription(int32_t lookDistance) const
{
	std::stringstream s;
	const ItemType& it = items[id];

	if (it.name.length()) {
		if(isStackable() && count > 1){
			s << (int)count << " " << it.name << "s.";

			if(lookDistance <= 1) {
				s << std::endl << "They weight " << std::fixed << std::setprecision(2) << ((double) count * it.weight) << " oz.";
			}
		}		
		else{
			if(items[id].runeMagLevel != -1)
			{
				s << "a spell rune for level " << it.runeMagLevel << "." << std::endl;

				s << "It's an \"" << it.name << "\" spell (";
				if(getItemCharge())
					s << (int)getItemCharge();
				else
					s << "1";

				s << "x).";
			}
			else if(isWeapon() && (getAttack() || getDefense()))
			{
				if(getAttack()){
					s << "a " << it.name << " (Atk:" << (int)getAttack() << " Def:" << (int)getDefense() << ").";
				}
				else{
					s << "a " << it.name << " (Def:" << (int)getDefense() << ").";	
				}
			}
			else if(getArmor()){
				s << "a " << it.name << " (Arm:" << (int)getArmor() << ").";
			}
			else if(isFluidContainer()){
				s << "a " << it.name;
				if(fluid == 0){
					s << ". It is empty.";
				}
				else{
					s << " of " << items[fluid].name << ".";
				}
			}
			else if(isSplash()){
				s << "a " << it.name << " of ";
				if(fluid == 0){
					s << items[1].name << ".";
				}
				else{
					s << items[fluid].name << ".";
				}
			}
			else if(it.isKey()){
				s << "a " << it.name << " (Key:" << actionId << ").";
			}
			else if(it.isGroundTile()){
				s << it.name << ".";
			}
			else if(it.isContainer()){
				s << "a " << it.name << " (Vol:" << getContainer()->capacity() << ").";
			}
			else if(it.allowDistRead){
				s << it.name << "." << std::endl;

				if(lookDistance <= 4){
					if(text && text->length() > 0){
						s << "You read: " << *text;
					}
					else
						s << "Nothing is written on it.";
				}
				else
					s << "You are too far away to read it.";
			}
			else{
				s << "a " << it.name << ".";
			}

			if(lookDistance <= 1){
				double weight = getWeight();
				if(weight > 0)
					s << std::endl << "It weighs " << std::fixed << std::setprecision(2) << weight << " oz.";
			}

			if(specialDescription)
				s << std::endl << specialDescription->c_str();
			else if(lookDistance <= 1 && it.description.length()){
				s << std::endl << it.description;
			}
		}
	}
	else
		s << "an item of type " << id <<".";
	
	return s.str();
}
Пример #13
0
/*!
 * \brief Check if a card can be stacked over this one
 * \param card The card to check
 * \return boolean
 */
bool Card::canStackCard(Card* card)
{
    return isStackable() && getChild() == 0 && card->isMovable() && isValidParentOf(card);
}