Beispiel #1
0
////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionMiniGame::execute (Creature * pCreature1 , Creature * pCreature2) 
	throw(Error)
{
	__BEGIN_TRY

	Assert(pCreature1 != NULL);
	Assert(pCreature2 != NULL);
	Assert(pCreature1->isNPC());
	Assert(pCreature2->isPC());

	GCNoticeEvent gcNoticeEvent;
	gcNoticeEvent.setCode(NOTICE_EVENT_MINI_GAME);
	gcNoticeEvent.setParameter((uint)m_GameType);
//	gcNoticeEvent.setNPCID(dynamic_cast<NPC*>(pCreature1)->getNPCID());

	Player* pPlayer = pCreature2->getPlayer();
	pPlayer->sendPacket(&gcNoticeEvent);

	__END_CATCH
}
void CGSelectWayPointHandler::execute(CGSelectWayPoint* pPacket , Player* pPlayer) throw(Error) {
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__
	Assert(pPacket != NULL);
	Assert(pPlayer != NULL);

	static map<Level_t,Price_t> sPriceMap;

	try {
		int targetDynamicZoneType = g_pDynamicZoneInfoManager->getDynamicZoneTypeByZoneID(pPacket->getZoneID());
		if (targetDynamicZoneType != DYNAMIC_ZONE_MAX) {
			executeEnterQuestZone(pPacket, pPlayer, targetDynamicZoneType);
		}

		// 게임 플레이어의 상태가 정상이 아니라면 걍 리턴한다.
		GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer);
		Assert(pGamePlayer != NULL);
		if (pGamePlayer->getPlayerStatus() != GPS_NORMAL) return;

		// 크리쳐가 슬레이어가 아니라면 리턴한다.
		Creature* pCreature = pGamePlayer->getCreature();
		Assert(pCreature != NULL);

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

		if (pPC->getStore()->isOpen()) return;
		if (pCreature->hasRelicItem()) return;

		// 크리쳐가 죽었으면 리턴
		if (pCreature->isDead()) return;

		// 초보존으로 들어가는 경우엔 종족 상관없이 보내준다.
		if (pPacket->getZoneID() == 1122) {
			ZONE_COORD pos(1122);

			if (pCreature->isSlayer()) {
				pos.x = 107;
				pos.y = 27;
			} else if (pCreature->isVampire()) {
				pos.x = 18;
				pos.y = 27;
			} else if (pCreature->isOusters()) {
				pos.x = 12;
				pos.y = 103;
			} else return;

			if (!canEnterBeginnerZone(pCreature)) return;

			// 초보존이 유료존일수도 있을라나...?
#if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__)
			ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(pos.id);
			
			// 유료존인데 유료사용자가 아니면...
      if (pZoneInfo == NULL ||
          ((pZoneInfo->isPayPlay() || pZoneInfo->isPremiumZone())
           && (!pGamePlayer->isPayPlaying() && !pGamePlayer->isFamilyFreePass()))) {
        //Statement* pStmt = NULL;
				string connectIP = pGamePlayer->getSocket()->getHost();

				// 유료 서비스 사용이 가능한가?
				if (pGamePlayer->loginPayPlay(connectIP, pGamePlayer->getID())) {
					sendPayInfo(pGamePlayer);
				} else if (pZoneInfo->isPayPlay()) {
					// 유료 서비스 사용 불가인 경우
					GCSystemMessage gcSystemMessage;

					if (g_pConfig->getPropertyInt("IsNetMarble") == 0) {
						gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER));
					} else {
						gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER));
					}

					pGamePlayer->sendPacket(&gcSystemMessage);

					return;
				}
			}
#endif

			pPC->getGQuestManager()->illegalWarp();
			transportCreature(pCreature, pos.id, pos.x, pos.y, false);
			return;
		}

		if (pPacket->getZoneID() == 1131) {

			if (g_pVariableManager->getVariable(ACTIVE_LEVEL_WAR) == 0) {
				GCSystemMessage gcSystemMessage;
				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER));
				pGamePlayer->sendPacket(&gcSystemMessage);
				return;
			}
/*
			if (g_pConfig->getPropertyInt("ServerID" ) != 0 )
			{
				GCNoticeEvent gcNoticeEvent;

				gcNoticeEvent.setCode(NOTICE_EVENT_NOT_FIRST_SERVER);
				pGamePlayer->sendPacket(&gcNoticeEvent);
//				GCSystemMessage gcSystemMessage;
//				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_LEVEL_WAR_ONLY_FIRST_SERVER ));
//				pGamePlayer->sendPacket (&gcSystemMessage);
				return;
			}
*/

			// 크리쳐 정보 보고 알아서 튕겨주자 =_=;;
			ZONE_COORD pos(g_pLevelWarZoneInfoManager->getCreatureZoneID(pCreature ));

			if (g_pSweeperBonusManager->isAble(g_pLevelWarZoneInfoManager->getCreatureZoneID(pCreature))) {
				GCSystemMessage gcSystemMessage;
				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NO_WAR_IN_ACTIVE ));
				pGamePlayer->sendPacket (&gcSystemMessage);
				return;
			}

			if (pCreature->isSlayer()) {
				pos.x = 12;
				pos.y =  9;
			} else if (pCreature->isVampire()) {
				pos.x = 117;
				pos.y =   8;
			} else if (pCreature->isOusters()) {
				pos.x =   9;
				pos.y = 111;
			}
			
#if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__)
			Zone* pZone = getZoneByZoneID(pos.id);
			Assert(pZone != NULL);
			
			LevelWarManager* pLevelWarManager = pZone->getLevelWarManager();
			Assert(pLevelWarManager != NULL);

			if (!pLevelWarManager->hasWar() && !g_pVariableManager->canEnterLevelWarZoneFree() && !pGamePlayer->isPayPlaying() && pGamePlayer->isFamilyFreePass() && !pLevelWarManager->canEnterFreeUser()) {
				GCSystemMessage gcSystemMessage;
				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER_LEVEL_WAR_ZONE));
				pGamePlayer->sendPacket(&gcSystemMessage);
				return;
			}
#endif
			
			pPC->getGQuestManager()->illegalWarp();
			transportCreature(pCreature, pos.id, pos.x, pos.y, false);
			return;
		}

		if (pPacket->getZoneID() == 72) {
			if (!g_pWarSystem->hasActiveRaceWar()) {
				GCSystemMessage gcSystemMessage;
				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NO_WAR_IN_ACTIVE));
				pGamePlayer->sendPacket (&gcSystemMessage);

				return;
			}
/*
			if (g_pConfig->getPropertyInt("ServerID" ) != 0 )
			{
				GCNoticeEvent gcNoticeEvent;

				gcNoticeEvent.setCode(NOTICE_EVENT_NOT_FIRST_SERVER);
				pGamePlayer->sendPacket(&gcNoticeEvent);
//				GCSystemMessage gcSystemMessage;
//				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_LEVEL_WAR_ONLY_FIRST_SERVER ));
//				pGamePlayer->sendPacket (&gcSystemMessage);
				return;
			}
*/

			// 크리쳐 정보 보고 알아서 튕겨주자 =_=;;
			ZONE_COORD pos;

			if (pCreature->isSlayer()) {
				pos.id = 73;
				pos.x = 30;
				pos.y = 124;
			} else if (pCreature->isVampire()) {
				pos.id = 71;
				pos.x = 104;
				pos.y = 128; 
			} else if (pCreature->isOusters()) {
				pos.id = 72;
				pos.x = 67;
				pos.y = 165;
			}
/*#if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__)
			ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(pos.id);
			
			// 유료존인데 유료사용자가 아니면...
			if (pZoneInfo==NULL
				|| (pZoneInfo->isPayPlay() || pZoneInfo->isPremiumZone())
					&& (!pGamePlayer->isPayPlaying() && !pGamePlayer->isFamilyFreePass() ))
			{
				//Statement* pStmt = NULL;
				string connectIP = pGamePlayer->getSocket()->getHost();

				// 유료 서비스 사용이 가능한가?
				if (pGamePlayer->loginPayPlay(connectIP, pGamePlayer->getID()))
				{
					sendPayInfo(pGamePlayer);
				}
				else if (pZoneInfo->isPayPlay())
				{
					// 유료 서비스 사용 불가인 경우
					GCSystemMessage gcSystemMessage;

					if (g_pConfig->getPropertyInt("IsNetMarble")==0)
					{
						gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER ));
					}
					else
					{
						gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER ));
					}

					pGamePlayer->sendPacket (&gcSystemMessage);

					return;
				}
			}
#endif*/
			if (!g_pVariableManager->isActiveRaceWarLimiter() || pCreature->isFlag(Effect::EFFECT_CLASS_RACE_WAR_JOIN_TICKET)) {
				pPC->getGQuestManager()->illegalWarp();
				transportCreature(pCreature, pos.id, pos.x, pos.y, false);
				return;
			} else {
				GCSystemMessage gcSystemMessage;
				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER_DURING_RACE_WAR));
				pGamePlayer->sendPacket(&gcSystemMessage);
				return;
			}
		}

		if (!pCreature->isSlayer() && !pCreature->isOusters()) {
			// 뭔가를 해야하지 않을까?
			return;
		}
		
		if (pCreature->isFlag(Effect::EFFECT_CLASS_HAS_FLAG)) {
			// 뭔가를 해야하지 않을까?
			return;
		}

		if (pCreature->isFlag(Effect::EFFECT_CLASS_HAS_SWEEPER)) {
			// 뭔가를 해야하지 않을까?
			return;
		}

		//Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature);
		//Assert(pSlayer != NULL);

		bool bCancel = false;

		// 이펙트가 걸려있어야 정상적인 이동이다.
		if (pCreature->isOusters() || (pCreature->isSlayer() && pCreature->isFlag(Effect::EFFECT_CLASS_SLAYER_PORTAL))) {
			ZoneID_t    id = pPacket->getZoneID();
			ZoneCoord_t x  = pPacket->getX();
			ZoneCoord_t y  = pPacket->getY();

			if (id == 0 && x == 0 && y == 0) {
				bCancel = true;
			} else {
				// 석화 상태일 경우 생깐다.
				if (pCreature->isFlag(Effect::EFFECT_CLASS_PARALYZE)) {
					bCancel = true;
				}

				// 웨이포인트 매니저를 통해서 클라이언트가 보내온
				// 웨이포인트가 정상적인 웨이포인트인지를 검증한다.
				if (!g_pWayPointManager->isValidWayPoint(id, x, y, pCreature->getRace())) {
					// 뭔가를 해야하지 않을까?
					bCancel = true;

					//return;
				}

				try {

					if (!bCancel) {

#if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__)
						ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(id);
						
						// 유료존인데 유료사용자가 아니면...
            if (pZoneInfo==NULL ||
                ((pZoneInfo->isPayPlay() || pZoneInfo->isPremiumZone()) && (!pGamePlayer->isPayPlaying() && !pGamePlayer->isFamilyFreePass()))) {
              //Statement* pStmt = NULL;
							string connectIP = pGamePlayer->getSocket()->getHost();

							// 유료 서비스 사용이 가능한가?
							if (pGamePlayer->loginPayPlay(connectIP, pGamePlayer->getID())) {
								sendPayInfo(pGamePlayer);
							} else if (pZoneInfo->isPayPlay()) {
								// 유료 서비스 사용 불가인 경우
								GCSystemMessage gcSystemMessage;

								if (g_pConfig->getPropertyInt("IsNetMarble") == 0) {
									gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER));
								} else {
									gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER));
								}

								pGamePlayer->sendPacket (&gcSystemMessage);

								bCancel = true;
							}
						}
#endif

						if (!bCancel) {
							// 이동시키기 전에 이펙트를 삭제한다.
							if (pCreature->isSlayer())
								pCreature->removeFlag(Effect::EFFECT_CLASS_SLAYER_PORTAL);

							if (pCreature->isOusters()) {
								Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);
								Assert(pOusters != NULL);

								GCNoticeEvent gcNoticeEvent;

								// 대지정령의 뿔을 사용할라면 시오람과 계약을 맺었어야 한다.
								if (!pOusters->getFlagSet()->isOn(FLAGSET_GNOMES_HORN)) {
									gcNoticeEvent.setCode(NOTICE_EVENT_CONTRACT_GNOMES_HORN);
									pPlayer->sendPacket(&gcNoticeEvent);
									return;
								}

								Level_t level = pOusters->getLevel();
								Price_t price = sPriceMap[level];

								if (price == 0) {
									price = (Price_t)(pow((double)level, 1.3) * 100) / 2;
									sPriceMap[level] = price;
								}

								/*if (g_pFlagManager->hasFlagWar() && 
										pPacket->getZoneID() == 32 &&
										pPacket->getX() == 124 &&
										pPacket->getY() == 144 ) price = 0;*/

								if (pOusters->getGold() < price) {
									gcNoticeEvent.setCode(NOTICE_EVENT_NOT_ENOUGH_MONEY);
									pPlayer->sendPacket(&gcNoticeEvent);
									return;
								} else {
									pOusters->decreaseGoldEx(price);
									GCModifyInformation gcMI;
									gcMI.addLongData(MODIFY_GOLD, pOusters->getGold());
									pPlayer->sendPacket(&gcMI);
								}
							}

							// 올바른 웨이포인트라면 슬레이어를 이동시켜준다.
							pPC->getGQuestManager()->illegalWarp();
							transportCreature(pCreature, id, x, y, false);
						}
					}
				} catch (NoSuchElementException&) {
					bCancel = true;
				}
			}
		}

		if (bCancel && pCreature->isSlayer()) {
			Zone* pZone = pCreature->getZone();
			Assert(pZone != NULL);

			// id, x, y가 모두 0일 경우 이동을 취소한다는 뜻이다.
			pCreature->removeFlag(Effect::EFFECT_CLASS_SLAYER_PORTAL);

			// 헬기를 제거하라고 뿌려준다.
			GCAddHelicopter gcAddHelicopter;
			gcAddHelicopter.setObjectID(pCreature->getObjectID());
			gcAddHelicopter.setCode(1);
			pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcAddHelicopter);
		}
	} 
	catch (Throwable & t) { 
		cerr << t.toString() << endl; 
	}

#endif	// __GAME_SERVER__
		
	__END_DEBUG_EX __END_CATCH
}
void CGAddMouseToInventoryHandler::execute(CGAddMouseToInventory* pPacket , Player* pPlayer)
	throw(ProtocolException, Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

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

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

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

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

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

		Inventory* pInventory = pPC->getInventory();
		Assert(pInventory != NULL);

		Item* pItem   = pPC->getExtraInventorySlot()->getItem();
		bool  Success = false;

		if (pItem == NULL) {
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}
        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 )
		{
//			cout << "서브 인벤토리에 넣기 : " << pPacket->getInventoryItemObjectID() << endl;
			CoordInven_t X, Y;
			pInventoryItem = dynamic_cast<SubInventory*>(pInventory->findItemOID(pPacket->getInventoryItemObjectID(), X, Y ));

			TradeManager* pTradeManager = pZone->getTradeManager();
			Assert(pTradeManager != NULL);

			if (pInventoryItem == NULL || pItem->getItemClass() == Item::ITEM_CLASS_SUB_INVENTORY || pTradeManager->hasTradeInfo(pPC->getName()) )
			{
//				cout << "근데 서브 인벤토리가 없다." <<endl;
				GCCannotAdd _GCCannotAdd;
				_GCCannotAdd.setObjectID(pPacket->getObjectID());
				pPlayer->sendPacket(&_GCCannotAdd);
				return;
			}

			pInventory = pInventoryItem->getInventory();
			invenID = pInventoryItem->getItemID();
		}
*/
		//Item::ItemClass itemClass = pItem->getItemClass();
		//ItemType_t	itemType	 = pItem->getItemType();
		ObjectID_t  itemObjectID = pItem->getObjectID();
		CoordInven_t InvenX      = pPacket->getInvenX();
		CoordInven_t InvenY      = pPacket->getInvenY();

		if (InvenX >= pInventory->getWidth() || InvenY >= pInventory->getHeight() || itemObjectID != pPacket->getObjectID() ||
			!pInventory->canAdding(InvenX, InvenY, pItem)) {
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		TPOINT pt;
		pt.x = 99;
		pt.y = 99;

		// 넣을려는 Inventory Slot의 Item을 받아온다.
		Item* pPrevItem = pInventory->searchItem(InvenX, InvenY , pItem, pt);

		// 그 장소에 아이템이 있다면
		if (pPrevItem != NULL) {
			bool bisSame = true;
			// 아이템 클래스가 같을때 숫자를 올려 주고 마우스에 있는 것은 없앤다.
			if (canStack(pItem, pPrevItem)) {
				int MaxStack = ItemMaxStack[pItem->getItemClass()];

				VolumeWidth_t  ItemWidth  = pItem->getVolumeWidth();
				VolumeHeight_t ItemHeight = pItem->getVolumeHeight();
				VolumeWidth_t  InvenWidth = pInventory->getWidth();
				VolumeWidth_t  InvenHeight= pInventory->getHeight();


				if ((InvenX + ItemWidth <= InvenWidth) && (InvenY + ItemHeight <= InvenHeight)) {
					for (int x = InvenX; x < (InvenX + ItemWidth); x++) {
						for (int y = InvenY; y < (InvenY + ItemHeight); y++) {
							if (pInventory->hasItem(x, y)) {
								if(pInventory->getItem(x,y) != pPrevItem ) {
									bisSame = false;
									break;
								}
							} else {
								bisSame = false;
								break;
							}
						}
					}
				}

				// 들어갈 아이템과 들어있는 아이템의 좌표가 꼭 일치 한다면?
				if(bisSame) {
					// 숫자가 9개를 넘으면 9개 될때까지만 Add 하고 나머지는 마우스에 달아둔다.
					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);
						pInventory->increaseNum(MaxStack - CurrentNum);
						pInventory->increaseWeight(pItem->getWeight()* (MaxStack - CurrentNum));
						//pPrevItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY);
						// item저장 최적화. by sigi. 2002.5.13
						char pField[80];
						sprintf(pField, "Num=%d, Storage=%d, StorageID=%d, X=%d, Y=%d", MaxStack, STORAGE_INVENTORY, invenID, InvenX, InvenY);
						pPrevItem->tinysave(pField);

						//pItem->save(pPC->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 {
						pPC->deleteItemFromExtraInventorySlot();
						pPrevItem->setNum(pPrevItem->getNum() + pItem->getNum());
						pInventory->increaseNum(pItem->getNum());
						pInventory->increaseWeight(pItem->getWeight()* pItem->getNum());
						//pPrevItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY);
						// item저장 최적화. by sigi. 2002.5.13
						char pField[80];
						sprintf(pField, "Num=%d, Storage=%d, StorageID=%u, X=%d, Y=%d", pPrevItem->getNum(), STORAGE_INVENTORY, invenID, InvenX, InvenY);
						pPrevItem->tinysave(pField);

						pItem->destroy();
						SAFE_DELETE(pItem);
						Success = true;
					}

					if (g_pVariableManager->getVariable(NETMARBLE_CARD_EVENT) != 0 && pPrevItem->getItemClass() == Item::ITEM_CLASS_MOON_CARD && pPrevItem->getItemType() == 2 && pPrevItem->getNum() == 99) {
						GCNoticeEvent gcNE;
						gcNE.setCode(NOTICE_EVENT_NETMARBLE_CARD_FULL);
						pGamePlayer->sendPacket(&gcNE);
						//cout << "gcNE sent" << endl;
					}

					if (pPrevItem->getItemClass() == Item::ITEM_CLASS_LUCKY_BAG
						&& pPrevItem->getItemType() == 3
						&& pPrevItem->getNum() == 50 ) {
						GCDeleteInventoryItem gcDI;
						gcDI.setObjectID(pPrevItem->getObjectID());
						pGamePlayer->sendPacket(&gcDI);

						pInventory->deleteItem(pPrevItem->getObjectID());
						pPrevItem->destroy();
						SAFE_DELETE(pPrevItem);
						
						Item* pNewItem = g_pItemFactoryManager->createItem(Item::ITEM_CLASS_EVENT_ITEM, 28, list<OptionType_t>());
						pZone->registerObject(pNewItem);

						if (!pInventory->addItem(pt.x, pt.y, pNewItem) )
							return;

						pNewItem->create(pPC->getName(), STORAGE_INVENTORY, 0, pt.x, pt.y);

						if (pNewItem != NULL ) {
							GCCreateItem gcCI;
							makeGCCreateItem(&gcCI, pNewItem, pt.x, pt.y);
							pGamePlayer->sendPacket(&gcCI);
						}
					}

				} else {

					pInventory->deleteItem(pPrevItem->getObjectID());

					pPC->deleteItemFromExtraInventorySlot();

					pPC->addItemToExtraInventorySlot(pPrevItem);

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

					//pPrevItem->save(pPC->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(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY);
					// item저장 최적화. by sigi. 2002.5.13
					sprintf(pField, "Storage=%d, StorageID=%u, X=%d, Y=%d", STORAGE_INVENTORY, invenID, InvenX, InvenY);
					pItem->tinysave(pField);


					Success = true;
				}
			} 
			else {// 아이템 클래스가 다르거나, 쌓이는 아이템이 아니라면.
				pInventory->deleteItem(pPrevItem->getObjectID());

				pPC->deleteItemFromExtraInventorySlot();

				pPC->addItemToExtraInventorySlot(pPrevItem);

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

				//pPrevItem->save(pPC->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(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY);
				// item저장 최적화. by sigi. 2002.5.13
				sprintf(pField, "Storage=%d, StorageID=%u, X=%d, Y=%d", STORAGE_INVENTORY, invenID, InvenX, InvenY);
				pItem->tinysave(pField);


				Success = true;
			}
		} else { // 그 장소에 아이템이 없다면.
			//cout << "prevItem is NULL" << endl;

			// Inventory에 특정 아이템을 넣는다.
			pInventory->addItem(InvenX , InvenY , pItem);

			// 넣기에 성공하면 마우스에 달려있는 아이템을 없앤다.
			pPC->deleteItemFromExtraInventorySlot();

			//pItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY);
			// item저장 최적화. by sigi. 2002.5.13
			char pField[80];
			sprintf(pField, "Storage=%d, StorageID=%u, X=%d, Y=%d", STORAGE_INVENTORY, invenID, InvenX, InvenY);
			pItem->tinysave(pField);


			Success = true;
		}

		if (Success) {
			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_MOUSE_TO_INVENTORY_OK);
				pPlayer->sendPacket(&gcTradeVerify);
			}

			// 트리 조각일 경우
			if (pItem != NULL && pItem->getItemClass() == Item::ITEM_CLASS_EVENT_TREE) {
				ItemType_t itemtype = pItem->getItemType();

				// 크리스마스 트리 조각이면
				if (itemtype <= 11) {
					// 크리스마스 트리 조각이 맞춰지는지 본다.
					TPOINT pt = checkEventPuzzle(pPC, InvenX, InvenY, 0);
					if (pt.x != -1 && pt.y != -1 )
					{
						// 맞춰진 트리 조각을 지운다.
						deleteInventoryItem(pInventory, pt.x, pt.y, pt.x + 2, pt.y + 3);

						// 트리를 생성한다.
						list<OptionType_t> optionType;
						Item* pTreeItem = g_pItemFactoryManager->createItem(Item::ITEM_CLASS_EVENT_TREE, 12, optionType);
						pZone->getObjectRegistry().registerObject(pTreeItem);
						pInventory->addItem(pt.x, pt.y, pTreeItem);
						pTreeItem->create(pPC->getName(), STORAGE_INVENTORY, invenID, pt.x, pt.y);

						// 클라이언트에 트리가 만들어졌다는 걸 알린다.
						GCCreateItem gcCreateItem;
						makeGCCreateItem(&gcCreateItem, pTreeItem, pt.x, pt.y);
						pGamePlayer->sendPacket(&gcCreateItem);
					}
				}
				// 크리스마스 트리 조각이면
				else if (itemtype > 12 && itemtype <= 24) {
					// 크리스마스 트리 조각이 맞춰지는지 본다.
					TPOINT pt = checkEventPuzzle(pPC, InvenX, InvenY, 13);
					if (pt.x != -1 && pt.y != -1) {
						// 맞춰진 트리 조각을 지운다.
						deleteInventoryItem(pInventory, pt.x, pt.y, pt.x + 2, pt.y + 3);

						// 트리를 생성한다.
						list<OptionType_t> optionType;
						Item* pTreeItem = g_pItemFactoryManager->createItem(Item::ITEM_CLASS_EVENT_TREE, 25, optionType);
						pTreeItem->setQuestItem();
						pZone->getObjectRegistry().registerObject(pTreeItem);
						pInventory->addItem(pt.x, pt.y, pTreeItem);
						pTreeItem->create(pPC->getName(), STORAGE_INVENTORY, invenID, pt.x, pt.y);

						// 클라이언트에 트리가 만들어졌다는 걸 알린다.
						GCCreateItem gcCreateItem;
						makeGCCreateItem(&gcCreateItem, pTreeItem, pt.x, pt.y);
						pGamePlayer->sendPacket(&gcCreateItem);
					}
				}
				// 크리스마스 트리 조각이면
				else if (itemtype > 28 && itemtype <= 40) {
					// 크리스마스 트리 조각이 맞춰지는지 본다.
					TPOINT pt = checkEventPuzzle(pPC, InvenX, InvenY, 29);
					if (pt.x != -1 && pt.y != -1) {
						// 맞춰진 트리 조각을 지운다.
						deleteInventoryItem(pInventory, pt.x, pt.y, pt.x + 2, pt.y + 3);

						// 트리를 생성한다.
						list<OptionType_t> optionType;
						Item* pTreeItem = g_pItemFactoryManager->createItem(Item::ITEM_CLASS_EVENT_TREE, 41, optionType);
						pTreeItem->setQuestItem();
						pZone->getObjectRegistry().registerObject(pTreeItem);
						pInventory->addItem(pt.x, pt.y, pTreeItem);
						pTreeItem->create(pPC->getName(), STORAGE_INVENTORY, invenID, pt.x, pt.y);

						// 클라이언트에 트리가 만들어졌다는 걸 알린다.
						GCCreateItem gcCreateItem;
						makeGCCreateItem(&gcCreateItem, pTreeItem, pt.x, pt.y);
						pGamePlayer->sendPacket(&gcCreateItem);
					}
				}
			}
		} else {
			//cout << "cannot add" << endl;
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
		}
	} catch (Throwable & t) {}

#endif	// __GAME_SERVER__

    __END_DEBUG_EX __END_CATCH

}
void CGDisplayItemHandler::execute (CGDisplayItem* pPacket , Player* pPlayer)
	 throw(Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX
		
#ifdef __GAME_SERVER__
	
//#ifndef __TEST_SERVER__
//	return;
//#endif

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

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

	PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pGamePlayer->getCreature());
	Assert(pPC != NULL);

	Inventory* pInventory = pPC->getInventory();
	Assert(pInventory != NULL);

	Store* pStore = pPC->getStore();
	Assert(pStore != NULL);

	GCSystemMessage errorMsg;
	GCNoticeEvent errorNotice;

	if (pPacket->getIndex() > MAX_ITEM_NUM )
	{
		filelog("Store.log", "[%s:%s] (%u) 잘못된 인덱스입니다.",
				pGamePlayer->getID().c_str(), pPC->getName().c_str(), pPacket->getIndex());
		return;
	}

	if (pPacket->getX() >= pInventory->getWidth() || pPacket->getY() >= pInventory->getHeight() )
	{
		filelog("Store.log", "[%s:%s] (%u,%u) 인벤토리 좌표를 잘못 보내줬습니다..",
				pGamePlayer->getID().c_str(), pPC->getName().c_str(), pPacket->getX(), pPacket->getY());
		return;
	}

	Item* pItem = pInventory->getItem(pPacket->getX(), pPacket->getY());
	if (pItem == NULL || pItem->getObjectID() != pPacket->getItemObjectID() )
	{
		filelog("Store.log", "[%s:%s] (%u, %u) : %u 아이템 좌표가 잘못되었거나 오브젝트 아이디가 잘못되었습니다.",
				pGamePlayer->getID().c_str(), pPC->getName().c_str(), pPacket->getX(), pPacket->getY(), pPacket->getItemObjectID());
		return;
	}

	if (pPC->getZone()->getTradeManager()->getTradeInfo(pPC->getName() ) != NULL )
	{
		filelog("Store.log", "[%s:%s] : 거래중에는 물건을 올려놓을 수 없습니다.",
				pGamePlayer->getID().c_str(), pPC->getName().c_str());
		return;
	}

	if (pStore->hasItem(pItem ) )
	{
		filelog("Store.log", "[%s:%s] (%u, %u) 이미 아이템이 상점에 있습니다.",
				pGamePlayer->getID().c_str(), pPC->getName().c_str(), pItem->getObjectID(), pPacket->getIndex());
//		errorMsg.setMessage("이미 진열된 아이템입니다.");
		errorNotice.setCode(NOTICE_EVENT_ALREADY_DISPLAYED);
		pGamePlayer->sendPacket(&errorNotice);
		return;
	}

	if (pItem->isTimeLimitItem() || !canSell(pItem ) || !canTrade(pItem ) || !canTradeInventoryItem(pItem ) )
	{
		filelog("Store.log", "[%s:%s] (%s) 팔 수 없는 아이템입니다.",
				pGamePlayer->getID().c_str(), pPC->getName().c_str(), pItem->toString().c_str());
//		errorMsg.setMessage("판매할 수 없는 아이템입니다.");
		errorNotice.setCode(NOTICE_EVENT_CANNOT_SELL);
		pGamePlayer->sendPacket(&errorNotice);
		return;
	}

	BYTE result = pStore->setStoreItem(pPacket->getIndex(), pItem, pPacket->getPrice());
	if ( result != 0 )
	{
		filelog("Store.log", "[%s:%s] (%u) 아이템을 놓을 수 없습니다.",
				pGamePlayer->getID().c_str(), pPC->getName().c_str(), result);
		return;
	}

	GCMyStoreInfo gcInfo;
	gcInfo.setStoreInfo(&(pStore->getStoreInfo()));
	pGamePlayer->sendPacket(&gcInfo);

	if (pStore->isOpen() )
	{
		GCAddStoreItem gcAdd;
		gcAdd.setOwnerObjectID(pPC->getObjectID());
		gcAdd.setIndex(pPacket->getIndex());
		pStore->getStoreItem(pPacket->getIndex() ).makeStoreItemInfo(gcAdd.getItem());
		pPC->getZone()->broadcastPacket(pPC->getX(), pPC->getY(), &gcAdd, pPC);
	}

#endif	// __GAME_SERVER__
		
	__END_DEBUG_EX __END_CATCH
}
void CGLotterySelectHandler::execute (CGLotterySelect* pPacket , Player* pPlayer)
	 throw(Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX
		
#ifdef __GAME_SERVER__

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

	Creature* pCreature = pGP->getCreature();
	Assert(pCreature != NULL);
		
	PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature);
	Assert(pPC != NULL);

	filelog("EventQuest.log", "CGLotterySelectHandler : got [%d:%d:%d] from %s", pPacket->getType(), pPacket->getGiftID(), pPacket->getQuestLevel(),
			pPC->getName().c_str());

	switch (pPacket->getType() )
	{
		case TYPE_SELECT_LOTTERY:
			{
				// 인벤에서 퀘스트 아이템 삭제
				QuestID_t qID;
				EventQuestAdvance::Status status = pPC->getQuestManager()->getEventQuestAdvanceManager()->getStatus(pPacket->getQuestLevel());
				int ownerQuestLevel = pPC->getQuestManager()->getEventQuestAdvanceManager()->getQuestLevel();
				if (
					(ownerQuestLevel > pPacket->getQuestLevel() && status == EventQuestAdvance::EVENT_QUEST_ADVANCED ) ||	
					(pPacket->getQuestLevel() == 4 &&  ownerQuestLevel== -1 ) ||
					pPC->getQuestManager()->successEventQuest(pPacket->getQuestLevel(), qID ) )
				{
					pPC->getQuestManager()->getEventQuestAdvanceManager()->rewarded(pPacket->getQuestLevel());
					pPC->getQuestManager()->getEventQuestAdvanceManager()->save();
					pPC->getQuestManager()->questRewarded(qID);
					pPC->sendCurrentQuestInfo();

					list<Item*> iList;
					pPC->getInventory()->clearQuestItem(iList);

					list<Item*>::iterator itr = iList.begin();
					list<Item*>::iterator endItr = iList.end();

					for (; itr != endItr ; ++itr )
					{
						GCDeleteInventoryItem gcDII;
						gcDII.setObjectID((*itr)->getObjectID());
						pPC->getPlayer()->sendPacket(&gcDII);
						(*itr)->destroy();
						SAFE_DELETE(*itr);
					}

					iList.clear();
				}
				else
				{
					filelog("EventBug.txt", "CGLotterySelectHandler : 복권 선택이 날라왔는데 완료한 퀘스트가 없다. -_-; %s[%d:%d]",
							pPC->getName().c_str(), pPacket->getQuestLevel(), pPacket->getGiftID());

					return;
				}

				GCNoticeEvent gcNE;
				gcNE.setCode(NOTICE_EVENT_RESULT_LOTTERY);
				if (bWinPrize(pPacket->getGiftID(), pPacket->getQuestLevel() ) ) 
				{
					// PlayerCreature 에 정보를 저장한다
					pPC->setLotto(true);
					pPC->setLottoRewardID(pPacket->getGiftID());
					pPC->setLottoQuestLevel(pPacket->getQuestLevel());
					gcNE.setParameter((uint)1);
				}
				else
				{
					// PlayerCreature 에 정보를 저장한다
					pPC->setLotto(false);
					pPC->setLottoRewardID(pPacket->getGiftID());
					pPC->setLottoQuestLevel(pPacket->getQuestLevel());
					gcNE.setParameter((uint)0);
				}
				pGP->sendPacket(&gcNE);

				filelog("EventQuest.log", "CGLotterySelectHandler : %d to %s", gcNE.getParameter(), pPC->getName().c_str());
			}
			break;
		case TYPE_FINISH_SCRATCH:
			{
				// 당첨된 경우 디비에 저장
				if (pPC->isLotto() )
				{
					// 다시 false 로 만들어줘야함.
					// 아님 담번 퀘스트에서 무조건 당첨으로 처리되니 ;;
					pPC->setLotto(false);

					Statement* pStmt = NULL;

					BEGIN_DB
					{
						pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement();

						pStmt->executeQuery("INSERT INTO EventQuestRewardRecord (PlayerID, RewardID, Time, RealPlayerID) VALUES ('%s', %d, now(), '%s' )",
								pCreature->getName().c_str(),
								pPC->getLottoRewardID(),
								pPC->getPlayer()->getID().c_str());

						SAFE_DELETE(pStmt);
					}
					END_DB(pStmt)

					// 이쪽 서버에 브로드 캐스트 하고 (allworld 는 해당 서버는 처리 안함)
					GCNotifyWin gcNW;
					gcNW.setGiftID(pPC->getLottoRewardID());
					gcNW.setName(pCreature->getName());

					g_pZoneGroupManager->broadcast(&gcNW);

					// 전 월드에 브로드캐스트해준다 
					char sCommand[200];
					string worldName = g_pGameWorldInfoManager->getGameWorldInfo(g_pConfig->getPropertyInt("WorldID" ))->getName();
					sprintf(sCommand, "*allworld *command NotifyWin %s(%s) %lu", pCreature->getName().c_str(), worldName.c_str(), pPC->getLottoRewardID());
					CGSayHandler::opworld(NULL, sCommand, 0, false);

				}
				else
				{
					// 아니면 그냥 퀘스트 아이템만 인벤에 넣어주면 되는듯
					Item::ItemClass iClass;
					ItemType_t iType;
					list<OptionType_t> oList;
					bool isTimeLimit = false;
					bool isLairItem = false;
					bool isUnique = false;
					MonsterType_t masterType;

					switch(pPC->getLottoQuestLevel() )
//					switch(pPC->getQuestManager()->getEventQuestAdvanceManager()->getQuestLevel() )
					{
						case 0:
							{
								static const string options1[] =
								{
									"STR+2",
									"DEX+2",
									"INT+2",
									"ASPD+2",
									"HP+2"
								};

								static const string options2[] =
								{
									"STR+3",
									"DEX+3",
									"INT+3",
									"ASPD+3",
									"HP+3"
								};
								if (pPC->isSlayer() )
								{
									Slayer* pSlayer = dynamic_cast<Slayer*>(pPC);
									QuestGrade_t qGrade = pSlayer->getTotalAttr(ATTR_BASIC);

									iClass = Item::ITEM_CLASS_RING;

									if (qGrade < 131 )
									{
										iType = 1;
										makeOptionList(options1[ rand()%5 ], oList);
									}
									else if (qGrade < 211 )
									{
										iType = 2;
										makeOptionList(options1[ rand()%5 ], oList);
									}
									else if (qGrade < 271 )
									{
										iType = 3;
										makeOptionList(options2[ rand()%5 ], oList);
									}
									else if (qGrade < 300 )
									{
										iType = 4;
										makeOptionList(options2[ rand()%5 ], oList);
									}
									else
									{
										iType = 5;
										makeOptionList(options2[ rand()%5 ], oList);
									}
								}
								else if (pPC->isVampire() )
								{
									Vampire* pVampire = dynamic_cast<Vampire*>(pPC);
									Level_t level = pVampire->getLevel();

									iClass = Item::ITEM_CLASS_VAMPIRE_RING;

									if (level < 31 )
									{
										iType = 1;
										makeOptionList(options1[ rand()%5 ], oList);
									}
									else if (level < 51 )
									{
										iType = 2;
										makeOptionList(options1[ rand()%5 ], oList);
									}
									else if (level < 71 )
									{
										iType = 3;
										makeOptionList(options2[ rand()%5 ], oList);
									}
									else if (level < 91 )
									{
										iType = 4;
										makeOptionList(options2[ rand()%5 ], oList);
									}
									else
									{
										iType = 5;
										makeOptionList(options2[ rand()%5 ], oList);
									}
								}
								else if (pPC->isOusters() )
								{
									Ousters* pOusters = dynamic_cast<Ousters*>(pPC);
									Level_t level = pOusters->getLevel();

									iClass = Item::ITEM_CLASS_OUSTERS_RING;

									if (level < 31 )
									{
										iType = 1;
										makeOptionList(options1[ rand()%5 ], oList);
									}
									else if (level < 51 )
									{
										iType = 2;
										makeOptionList(options1[ rand()%5 ], oList);
									}
									else if (level < 71 )
									{
										iType = 3;
										makeOptionList(options2[ rand()%5 ], oList);
									}
									else if (level < 91 )
									{
										iType = 4;
										makeOptionList(options2[ rand()%5 ], oList);
									}
									else
									{
										iType = 5;
										makeOptionList(options2[ rand()%5 ], oList);
									}
								}
							}
							break;
						case 1:
							{
								static const string oSlayer1[] =
								{
									"DAM+2",
									"VIS+3",
									"MP+2",
									"LUCK+1",
									"HP+2"
								};
								static const string oSlayer2[] =
								{
									"DAM+3",
									"VIS+3",
									"MP+3",
									"LUCK+2",
									"HP+3"
								};
								static const string oVampire1[] =
								{
									"DAM+2",
									"VIS+3",
									"ASPD+2",
									"LUCK+1",
									"HP+2"
								};
								static const string oVampire2[] =
								{
									"DAM+3",
									"VIS+3",
									"ASPD+3",
									"LUCK+2",
									"HP+3"
								};
								if (pPC->isSlayer() )
								{
									Slayer* pSlayer = dynamic_cast<Slayer*>(pPC);
									QuestGrade_t qGrade = pSlayer->getTotalAttr(ATTR_BASIC);

									iClass = Item::ITEM_CLASS_RING;

									if (qGrade < 131 )
									{
										iType = 2;
										makeOptionList(oSlayer1[ rand()%5 ], oList);
									}
									else if (qGrade < 211 )
									{
										iType = 3;
										makeOptionList(oSlayer1[ rand()%5 ], oList);
									}
									else if (qGrade < 271 )
									{
										iType = 4;
										makeOptionList(oSlayer2[ rand()%5 ], oList);
									}
									else if (qGrade < 300 )
									{
										iType = 5;
										makeOptionList(oSlayer2[ rand()%5 ], oList);
									}
									else
									{
										iType = 6;
										makeOptionList(oSlayer2[ rand()%5 ], oList);
									}
								}
								else if (pPC->isVampire() )
								{
									Vampire* pVampire = dynamic_cast<Vampire*>(pPC);
									Level_t level = pVampire->getLevel();

									iClass = Item::ITEM_CLASS_VAMPIRE_RING;
									
									if (level < 31 )
									{
										iType = 2;
										makeOptionList(oVampire1[ rand()%5 ], oList);
									}
									else if (level < 51 )
									{
										iType = 3;
										makeOptionList(oVampire1[ rand()%5 ], oList);
									}
									else if (level < 71 )
									{
										iType = 4;
										makeOptionList(oVampire2[ rand()%5 ], oList);
									}
									else if (level < 91 )
									{
										iType = 5;
										makeOptionList(oVampire2[ rand()%5 ], oList);
									}
									else
									{
										iType = 6;
										makeOptionList(oVampire2[ rand()%5 ], oList);
									}
								}
								else if (pPC->isOusters() )
								{
									Ousters* pOusters = dynamic_cast<Ousters*>(pPC);
									Level_t level = pOusters->getLevel();

									iClass = Item::ITEM_CLASS_OUSTERS_RING;
									
									if (level < 31 )
									{
										iType = 2;
										makeOptionList(oVampire1[ rand()%5 ], oList);
									}
									else if (level < 51 )
									{
										iType = 3;
										makeOptionList(oVampire1[ rand()%5 ], oList);
									}
									else if (level < 71 )
									{
										iType = 4;
										makeOptionList(oVampire2[ rand()%5 ], oList);
									}
									else if (level < 91 )
									{
										iType = 5;
										makeOptionList(oVampire2[ rand()%5 ], oList);
									}
									else
									{
										iType = 6;
										makeOptionList(oVampire2[ rand()%5 ], oList);
									}
								}
							}
							break;
						case 2:
							{
								isLairItem = true;
								masterType = 432;
							}
							break;
						case 3:
							{
								isLairItem = true;
								masterType = 433;
							}
							break;
						case 4:
							{
								isTimeLimit = true;
								if (pPC->isSlayer() )
								{
									isUnique = true;
									static const Item::ItemClass iClasses[] =
									{
										Item::ITEM_CLASS_COAT,
										Item::ITEM_CLASS_TROUSER,
										Item::ITEM_CLASS_GLOVE,
										Item::ITEM_CLASS_HELM,
										Item::ITEM_CLASS_SHOES,
//										Item::ITEM_CLASS_BELT,
										Item::ITEM_CLASS_NECKLACE,
										Item::ITEM_CLASS_BRACELET
									};
									static const ItemType_t iTypes[] =
									{
										16,
										16,
										8,
										9,
										7,
//										4,
										10,
										10
									};

									int index = rand() % 7;
									iClass = iClasses[index];
									iType = iTypes[index];
								}
								else if (pPC->isVampire() )
								{
									isUnique = true;
									static const Item::ItemClass iClasses[] =
									{
										Item::ITEM_CLASS_VAMPIRE_COAT,
										Item::ITEM_CLASS_VAMPIRE_WEAPON,
										Item::ITEM_CLASS_VAMPIRE_RING,
										Item::ITEM_CLASS_VAMPIRE_NECKLACE,
										Item::ITEM_CLASS_VAMPIRE_BRACELET,
										Item::ITEM_CLASS_VAMPIRE_AMULET,
										Item::ITEM_CLASS_VAMPIRE_EARRING
									};
									static const ItemType_t iTypes[] =
									{
										12,
										15,
										10,
										10,
										9,
										10,
										10
									};
									int index = rand() % 7;
									iClass = iClasses[index];
									iType = iTypes[index];
								}
								else if (pPC->isOusters() )
								{
									static const Item::ItemClass iClasses[] =
									{
										Item::ITEM_CLASS_OUSTERS_COAT,
										Item::ITEM_CLASS_OUSTERS_CIRCLET,
										Item::ITEM_CLASS_OUSTERS_ARMSBAND,
										Item::ITEM_CLASS_OUSTERS_BOOTS,
										Item::ITEM_CLASS_OUSTERS_PENDENT,
										Item::ITEM_CLASS_OUSTERS_RING
									};
									static const ItemType_t iTypes[] =
									{
										7,
										9,
										9,
										7,
										9,
										9
									};
									static const string options[] =
									{
										"DAM+3",
										"ASPD+3",
										"LUCK+2",
										"HP+9",
										"STR+3",
										"DEX+3",
										"INT+3",
										"ATTR+2",
										"RES+3",
										"MP+4"
									};
									int index = rand() % 6;
									iClass = iClasses[index];
									iType = iTypes[index];

									int option1 = rand()%10;
									int option2 = rand()%10;

									while (option1 == option2 ) option2 = rand()%10;

									makeOptionList(options[ option1 ] + "," + options[ option2 ], oList);
								}
							}
							break;
						default:
							break;
					}

					Item* pItem;

					if (isLairItem )
					{
						const MonsterInfo* pMonsterInfo = g_pMonsterInfoManager->getMonsterInfo(masterType);
						TreasureList *pTreasureList = NULL;

						if (pPC->isSlayer())
							pTreasureList = pMonsterInfo->getSlayerTreasureList();
						else if (pPC->isVampire() )
							pTreasureList = pMonsterInfo->getVampireTreasureList();
						else if (pPC->isOusters() )
							pTreasureList = pMonsterInfo->getOustersTreasureList();

						const list<Treasure*>& treasures = pTreasureList->getTreasures();

						list<Treasure*>::const_iterator itr = treasures.begin();

						ITEM_TEMPLATE it;

						for(; itr != treasures.end(); itr++)
						{
							Treasure* pTreasure = (*itr);

							it.ItemClass = Item::ITEM_CLASS_MAX;
							it.ItemType = 0;

							it.NextOptionRatio = 0;

							//cout << "TradeLairItem: BonusRatio = " << it.NextOptionRatio << endl;

							if (pTreasure->getRandomItem(&it) )
							{
								pItem = g_pItemFactoryManager->createItem(it.ItemClass, it.ItemType, it.OptionType);
								Assert(pItem != NULL);
							}
						}

					}
					else
					{
						pItem = g_pItemFactoryManager->createItem(iClass, iType, oList);
					}

					GenderRestriction gender = GENDER_BOTH;
					switch(pPC->getSex() )
					{
						case MALE:
							gender = GENDER_MALE;
							break;
						case FEMALE:
							gender = GENDER_FEMALE;
							break;
						default:
							break;
					}

					setItemGender(pItem, gender);

					_TPOINT tp;

					if (pItem != NULL && pPC->getInventory()->addItem(pItem, tp ) )
					{
						pPC->getZone()->registerObject(pItem);
						pItem->create(pPC->getName(), STORAGE_INVENTORY, 0, tp.x, tp.y);

						if (isTimeLimit )
						{
							pPC->addTimeLimitItem(pItem, 604800);
							pPC->sendTimeLimitItemInfo();
						}

						GCCreateItem gcCreateItem;
						makeGCCreateItem(&gcCreateItem, pItem, tp.x, tp.y);
						pPC->getPlayer()->sendPacket(&gcCreateItem);

						remainTraceLog(pItem, "GOD", pCreature->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC);
					}
					else
					{
						if (isUnique )
							pItem->setUnique();

						if (isTimeLimit )
							pItem->setTimeLimitItem();

						pPC->setQuestItem(pItem);

						remainTraceLog(pItem, "GOD", pCreature->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC);
					}

				}

				if (pPC->getLottoQuestLevel() == 4 )
				{
					pPC->getQuestManager()->cancelQuest();
					GCNoticeEvent gcNE;
					gcNE.setCode(NOTICE_EVENT_START_QUEST_ENDING);
					pPC->getPlayer()->sendPacket(&gcNE);
				}
			}