////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionGiveFinalLottoScript::execute (Creature * pCreature1 , Creature * pCreature2) 
	throw(Error)
{
	__BEGIN_TRY

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

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

	GCNPCAsk gcNPCAsk;
	gcNPCAsk.setObjectID(pCreature1->getObjectID());
	gcNPCAsk.setNPCID(dynamic_cast<NPC*>(pCreature1)->getNPCID());

	QuestID_t	qID;

	if (pPC->getQuestManager()->successEventQuest(4, qID ) )
	{
		ItemType_t fitItem = rand()%10;

		if (pPC->getInventory()->findItem(Item::ITEM_CLASS_EVENT_ITEM, fitItem ) != NULL )
		{
			pPC->getQuestManager()->getEventQuestAdvanceManager()->advanced(EventQuestAdvanceManager::EVENT_QUEST_LEVEL_MAX-1);
			gcNPCAsk.setScriptID(m_SuccessScriptID);
		}
		else
		{
			gcNPCAsk.setScriptID(m_FailScriptID);
		}

		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
	{
		gcNPCAsk.setScriptID(m_CounterScriptID); 
	}

	pPC->getPlayer()->sendPacket(&gcNPCAsk);

	__END_CATCH
}
예제 #2
0
////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionTradeGiftBox::execute(Creature * pCreature1 , Creature * pCreature2) 
	throw(Error)
{
	__BEGIN_TRY

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

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

	Player* pPlayer = pPC->getPlayer();
	Assert(pPlayer != NULL);

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

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

	FlagSet* pFlagSet = pPC->getFlagSet();

	Item::ItemClass ItemClass;
	ItemType_t		ItemType;
	OptionType_t	OptionType;

	Item*			pItem;
	Item*			pGiftBoxItem;

	// 이미 선물을 교환해 갔다면
	if (pFlagSet->isOn(FLAGSET_TRADE_GIFT_BOX_2002_12 ) )
	{
		GCNPCResponse response;
		response.setCode(NPC_RESPONSE_TRADE_GIFT_BOX_ALREADY_TRADE);
		pPlayer->sendPacket(&response);

		GCNPCResponse quit;
		quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
		pPlayer->sendPacket(&quit);

		return;
	}

	// 빨간 선물 상자가 있는지 확인한다.
	CoordInven_t X,Y;
	pGiftBoxItem = pInventory->findItem(Item::ITEM_CLASS_EVENT_GIFT_BOX, 1, X, Y);
	if (pGiftBoxItem == NULL )
	{
		GCNPCResponse response;
		response.setCode(NPC_RESPONSE_TRADE_GIFT_BOX_NO_ITEM);
		pPlayer->sendPacket(&response);

		GCNPCResponse quit;
		quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
		pPlayer->sendPacket(&quit);

		return;
	}

	LuaSelectItem*	pLuaSelectItem = NULL;
	string			luaFileName;

	if (pPC->isSlayer() )
	{
		// 루아에 슬레이어 능력치의 합을 set한다.
		Slayer* pSlayer = dynamic_cast<Slayer*>(pPC);
		Assert(pSlayer != NULL);

		Attr_t sum = pSlayer->getSTR(ATTR_BASIC )
				   + pSlayer->getDEX(ATTR_BASIC )
				   + pSlayer->getINT(ATTR_BASIC);

		m_pLuaSlayerItem->setSum(sum);
		pLuaSelectItem = m_pLuaSlayerItem;
		luaFileName = m_SlayerFilename;

	}
	else if (pPC->isVampire() )
	{
		// 루아에 뱀파이어의 레벨을 set한다.
		Vampire* pVampire = dynamic_cast<Vampire*>(pPC);
		Assert(pVampire != NULL);

		int level = pVampire->getLevel();
		m_pLuaVampireItem->setLevel(level);
		pLuaSelectItem = m_pLuaVampireItem;
		luaFileName = m_VampireFilename;
	}

	//--------------------------------------------------------
	// 속도 체크를 위해서 1000번 돌려보는 코드
	// 결과는.. 0.07초 정도 나왔다. 감덩~ -_-;
	/*
	Timeval beforeTime;
	getCurrentTime(beforeTime);

	for (int i=0; i<1000; i++)
	{
		// 루아의 계산 결과를 받아 아이템을 생성한다.
		pLuaSelectItem->prepare();
		
		int result = pLuaSelectItem->executeFile(luaFileName);
		LuaState::logError(result);
		pLuaSelectItem->clear();
	}

	Timeval afterTime;
	getCurrentTime(afterTime);

	cout << "luaExecute time before : " << beforeTime.tv_sec  << "." << beforeTime.tv_usec << endl;
	cout << "luaExecute time after  : " << afterTime.tv_sec  << "." << afterTime.tv_usec << endl;
	*/
	//--------------------------------------------------------

	// 루아의 계산 결과를 받아 아이템을 생성한다.
	pLuaSelectItem->prepare();
	
	int result = pLuaSelectItem->executeFile(luaFileName);
	LuaState::logError(result);

	ItemClass 	= pLuaSelectItem->getItemClass();
	ItemType  	= pLuaSelectItem->getItemType();
	OptionType	= pLuaSelectItem->getOptionType();

	pLuaSelectItem->clear();

	if(ItemClass >= Item::ITEM_CLASS_MAX )
	//||  ItemType  >= ITEM_TYPE_MAX || ItemType  < 0
	//	|| OptionType == 0)
	{
		filelog("XMasEventError.txt", "[ ItemInfo Error ] : ItemClass = %d , ItemType = %d , OptionType = %d", ItemClass, ItemType, OptionType);

		GCNPCResponse quit;
		quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
		pPlayer->sendPacket(&quit);

		return;
	}

	// 클라이언트에 선물상자를 지우도록 한다.
	GCDeleteInventoryItem gcDeleteInventoryItem;
	gcDeleteInventoryItem.setObjectID(pGiftBoxItem->getObjectID());
	pPlayer->sendPacket(&gcDeleteInventoryItem);

	// 선물상자를 지운다.
	pInventory->deleteItem(X, Y);
	// ItemTraceLog 를 남긴다
	if (pGiftBoxItem != NULL && pGiftBoxItem->isTraceItem() )
	{
		remainTraceLog(pGiftBoxItem, pCreature2->getName(), pCreature1->getName(), ITEM_LOG_DELETE, DETAIL_EVENTNPC);
	}
	pGiftBoxItem->destroy();
	SAFE_DELETE(pGiftBoxItem);


	// 선물(Item)을 만든다.
	list<OptionType_t> optionTypeList;
	if (OptionType != 0 )
		optionTypeList.push_back(OptionType);

	pItem = g_pItemFactoryManager->createItem(ItemClass, ItemType, optionTypeList);
	Assert(pItem != NULL);


	// 선물을 인벤토리에 추가한다.
	pZone->getObjectRegistry().registerObject(pItem);
	pInventory->addItem(X, Y, pItem);
	pItem->create(pPC->getName(), STORAGE_INVENTORY, 0, X, Y);

	// ItemTraceLog 를 남긴다
	if (pItem != NULL && pItem->isTraceItem() )
	{
		remainTraceLog(pItem, pCreature1->getName(), pCreature2->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC);
	}

	// 클라이언트에 선물이 추가되었음을 알린다.
	GCCreateItem gcCreateItem;
	makeGCCreateItem(&gcCreateItem, pItem, X, Y);
	pPlayer->sendPacket(&gcCreateItem);

	// Flag을 켠다.
	pFlagSet->turnOn(FLAGSET_TRADE_GIFT_BOX_2002_12);

	// Flag을 저장한다.
	pFlagSet->save(pPC->getName());

	// 아이템 교환이 이루어 졌다고 클라이언트에 알린다.
	GCNPCResponse response;
	response.setCode(NPC_RESPONSE_TRADE_GIFT_BOX_OK);
	pPlayer->sendPacket(&response);

	GCNPCResponse quit;
	quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
	pPlayer->sendPacket(&quit);

	__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

}
예제 #4
0
void CGTameMonsterHandler::execute (CGTameMonster* pPacket , Player* pPlayer)
	     throw(Error)
{
	__BEGIN_TRY

#ifdef __GAME_SERVER__

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

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

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

	Monster* pMonster = dynamic_cast<Monster*>(pZone->getCreature(pPacket->getObjectID() ));
	if (pMonster == NULL ) return;

	Item* pItem = pPC->getExtraInventorySlotItem();
	if (pItem == NULL || pItem->getItemClass() != Item::ITEM_CLASS_PET_FOOD || pItem->getNum() != 1 ) return;

	PetFoodInfo* pPetFoodInfo = dynamic_cast<PetFoodInfo*>(g_pPetFoodInfoManager->getItemInfo(pItem->getItemType() ));
	Assert(pPetFoodInfo != NULL);

	Inventory* pInventory = pPC->getInventory();
	if (pInventory == NULL ) return;

	ItemType_t petType = PET_COMMON;
	PetItem* pPetItem = dynamic_cast<PetItem*>(g_pItemFactoryManager->createItem(Item::ITEM_CLASS_PET_ITEM, petType, list<OptionType_t>() ));
	Assert(pPetItem != NULL);

	_TPOINT pt;
	if (!pInventory->getEmptySlot(pPetItem, pt ) )
	{
		GCCannotUse gcCannotUse;
		pGamePlayer->sendPacket(&gcCannotUse);
		SAFE_DELETE(pPetItem);
		return;
	}

	pPC->deleteItemFromExtraInventorySlot();
	GCDeleteInventoryItem gcDI;
	gcDI.setObjectID(pItem->getObjectID());
	pGamePlayer->sendPacket(&gcDI);

	pItem->destroy();
	SAFE_DELETE(pItem);

	/*
	 * 여기서 뭔가 확인을 해야 한다.
	 */

	int ratio = rand()%100;

	if (g_pVariableManager->getVariable(PET_DAY_EVENT) != 0 )
	{
		ratio = 100;
	}

	// 공용 펫만 꼬실 수 있다.
	PetTypeInfo* pPetTypeInfo = PetTypeInfoManager::getInstance()->getPetTypeInfo(petType);
	if (pPetTypeInfo == NULL || pPetTypeInfo->getOriginalMonsterType() != pMonster->getMonsterType() || ratio >= pPetFoodInfo->getTameRatio() )
	{
		//cout << "꼬시기 실패 : " << ratio << endl;
		SAFE_DELETE(pPetItem);
		pMonster->addEnemy(pPC);
		return;
	}

	pZone->deleteCreature(pMonster, pMonster->getX(), pMonster->getY());
	SAFE_DELETE(pMonster);

	/*
	 * 여기서 해당 펫의 정보를 가져와야 된다.
	 */

	PetInfo* pPetInfo = new PetInfo;

	pPetInfo->setPetType(petType);
	pPetInfo->setPetLevel(0);
	pPetInfo->setPetCreatureType(pPetTypeInfo->getPetCreatureType(0));
	pPetInfo->setPetAttr(0xff);
	pPetInfo->setPetExp(0);
	pPetInfo->setPetAttrLevel(0);
	pPetInfo->setFoodType(pPetFoodInfo->getItemType());
	pPetInfo->setGamble(0);
	pPetInfo->setCutHead(0);
	pPetInfo->setPetHP(pPetFoodInfo->getPetHP());
	pPetInfo->setFeedTime(VSDateTime::currentDateTime());

	// 양방향 링크
	pPetItem->setPetInfo(pPetInfo);
	pPetInfo->setPetItem(pPetItem);

	pZone->registerObject(pPetItem);
	pInventory->addItem(pPetItem, pt);
	Assert(pt.x != -1);

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

	// TraceLog 를 남긴다.
	remainTraceLog(pPetItem, "GOD", pPC->getName(), ITEM_LOG_CREATE, DETAIL_PICKUP);
	
	GCCreateItem gcCreateItem;
	makeGCCreateItem(&gcCreateItem, pPetItem, pt.x, pt.y);

	pGamePlayer->sendPacket(&gcCreateItem);

	//pPetItem->whenPCTake(pPC);

	pPC->getGQuestManager()->tamePet(pPetInfo);
	addOlympicStat(pPC, 9);

#endif

	__END_CATCH
}
예제 #5
0
////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionGiveLotto::execute (Creature * pCreature1 , Creature * pCreature2) 
	throw(Error)
{
	__BEGIN_TRY

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

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

	QuestID_t	qID;
	int questLevel = m_QuestLevel;

	if (questLevel < 0 ) questLevel = pPC->getQuestManager()->getEventQuestAdvanceManager()->getQuestLevel() - 1;

	//cout << "Activated : " << toString() << " ... " << pPC->getName() << " ...  " << questLevel << endl;

	EventQuestAdvance::Status status = pPC->getQuestManager()->getEventQuestAdvanceManager()->getStatus(questLevel);
	int ownerQuestLevel = pPC->getQuestManager()->getEventQuestAdvanceManager()->getQuestLevel();

	if (
		(ownerQuestLevel > questLevel && status == EventQuestAdvance::EVENT_QUEST_ADVANCED )
	||	((questLevel == 4 && ownerQuestLevel == -1 ) || pPC->getQuestManager()->successEventQuest(questLevel, qID ) )
	)
	{
		GamePlayer* pGP = dynamic_cast<GamePlayer*>(pPC->getPlayer());
		Assert (pGP != NULL);

//		if (g_pConfig->getPropertyInt("IsNetMarble" ) || !pGP->isPayPlaying() )
		if (true )
		{
			pPC->getQuestManager()->getEventQuestAdvanceManager()->rewarded(questLevel);
			pPC->getQuestManager()->getEventQuestAdvanceManager()->save();
			if (questLevel != 4 )
				pPC->getQuestManager()->questRewarded(qID);
			else
				pPC->getQuestManager()->cancelQuest();

			pPC->setLottoQuestLevel(questLevel);

			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();

			CGLotterySelect	cgLS;
			cgLS.setType(TYPE_FINISH_SCRATCH);
			cgLS.setQuestLevel(0);
			cgLS.setGiftID(0);
			CGLotterySelectHandler::execute(&cgLS, pPC->getPlayer());
//			cgLS.execute(pPC->getPlayer());

		}
		else
		{
			Player* pPlayer = pCreature2->getPlayer();
	//		pPlayer->sendPacket(&gcSM);

			GCNPCResponse gcNPCResponse;
			gcNPCResponse.setCode(NPC_RESPONSE_LOTTERY);
			gcNPCResponse.setParameter((uint)questLevel);

			pPlayer->sendPacket(&gcNPCResponse);

			filelog("EventQuest.log","ActionGiveLotto : %d to %s", questLevel, pPC->getName().c_str());
		}
	}

	GCNPCResponse gcNPCResponse;
	gcNPCResponse.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
	pPC->getPlayer()->sendPacket(&gcNPCResponse);

	__END_CATCH
}
예제 #6
0
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);
				}
			}
예제 #7
0
////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionTradeLairItem::execute(Creature * pCreature1 , Creature * pCreature2) 
	throw(Error)
{
	__BEGIN_TRY

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

	if (m_Type <= 5 )
	{
		SYSTEM_RETURN_IF_NOT(SYSTEM_MASTER_LAIR);
	}

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

	Player* pPlayer = pPC->getPlayer();
	Assert(pPlayer != NULL);

	GCNPCResponse okpkt;
	pPlayer->sendPacket(&okpkt);
	StringStream message;

	/*

	GCSystemMessage gcSystemMessage;
	gcSystemMessage.setMessage("아직 지원되지 않는 기능입니다");
	pPlayer->sendPacket(&gcSystemMessage);
	*/


	//cout << "ActionTradeLairItem" << ":" << m_Type;

	Inventory* pInventory = pPC->getInventory();

	// 먼저 아이템을 가지고 있는가를 체크한다.
	Item* pMasterItem = NULL;
	MonsterType_t MonsterType = 0;

	Item* pItem1 = NULL;
	bool bUpgrade = false;
	
	// 옵션에 따라서 다른 아이템을 검사해야 한다.
	// 코난 : 팬던트/ 비쥬만 체크한다.
	// 브리콜라카스: 테페즈 펜던트/비쥬만 체크해야 한다
	// 카임 : 바토리 팬던트/비쥬만 체크해야 한다.

	if (m_Type == 0) // 코난, 비쥬
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 0);
		MonsterType = BATORI_TYPE;

		if (pMasterItem == NULL )
		{
			pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 2);
			MonsterType = TEPEZ_TYPE;
			if (pMasterItem == NULL )
			{
				pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); //질드레 비쥬
				MonsterType = GDR_TYPE;
				bUpgrade = true;
			}
		}
	}
	else if (m_Type == 1) // 코난, 팬던트
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 1);
		MonsterType = BATORI_TYPE;

		if (pMasterItem == NULL)
		{
			pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 3);
			MonsterType = TEPEZ_TYPE;
			if (pMasterItem == NULL )
			{
				pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); //질드레 펜던트
				MonsterType = GDR_TYPE;
				bUpgrade = true;
			}
		}
	}
	else if (m_Type == 2) // 브리콜라카스, 비쥬
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 2);
//		if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); //질드레 비쥬
		MonsterType = TEPEZ_TYPE;
	}
	else if (m_Type == 3) // 브리콜라카스, 팬던트
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 3);
//		if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); //질드레 펜던트
		MonsterType = TEPEZ_TYPE;
	}
	else if (m_Type == 4) // 카임, 비쥬
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 0);
//		if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); //질드레 비쥬
		MonsterType = BATORI_TYPE;
	}
	else if (m_Type == 5) // 카임, 팬던트
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 1);
//		if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); //질드레 펜던트
		MonsterType = BATORI_TYPE;
	}
	else if (m_Type == 10) // 질드레, 비쥬
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8);
		bUpgrade = true;
		MonsterType = GDR_TYPE;
	}
	else if (m_Type == 11) // 질드레, 팬던트
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9);
		bUpgrade = true;
		MonsterType = GDR_TYPE;
	}
	else if (m_Type == 6) // 젬스톤이지롱~
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 4);
		MonsterType = BATORI_TYPE;
	}
	else if (m_Type == 7) // 보름달~
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 5);
		ItemMineInfo* pItemMineInfo;

		if (pPC->isSlayer() )
		{
			Slayer* pSlayer = dynamic_cast<Slayer*>(pPC);
			Assert(pSlayer != NULL);

			Attr_t totalAttr = pSlayer->getTotalAttr(ATTR_BASIC);

			if (totalAttr <= 130 )	// 하드코딩 ㅜ.ㅠ
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(0);
			else if (totalAttr <= 210 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(1);
			else if (totalAttr <= 270 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(2);
			else if (totalAttr <= 300 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(3);
			else
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(4);
		}
		else if (pPC->isVampire() )
		{
			Vampire* pVampire = dynamic_cast<Vampire*>(pPC);
			Assert(pVampire != NULL);

			Level_t level = pVampire->getLevel();

			if (level <= 20 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(5);
			else if (level <= 40 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(6);
			else if (level <= 60 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(7);
			else if (level <= 90 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(8);
			else
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(9);
		}
		else if (pPC->isOusters() )
		{
			Ousters* pOusters = dynamic_cast<Ousters*>(pPC);
			Assert(pOusters != NULL);

			Level_t level = pOusters->getLevel();

			if (level <= 20 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(10);
			else if (level <= 40 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(11);
			else if (level <= 60 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(12);
			else if (level <= 90 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(13);
			else
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(14);
		}
		else Assert(false);

		pItem1 = pItemMineInfo->getItem();
		setItemGender(pItem1, (pPC->getSex()==FEMALE)?GENDER_FEMALE:GENDER_MALE);
	}
	else if (m_Type == 8) // 그믐달~
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 6);

		if (pPC->isSlayer() )
		{
			pItem1 = g_pItemMineInfoManager->getRandomItem(15, 32);
		}
		else if (pPC->isVampire() )
		{
			pItem1 = g_pItemMineInfoManager->getRandomItem(33, 45);
		}
		else if (pPC->isOusters() )
		{
			pItem1 = g_pItemMineInfoManager->getRandomItem(46, 61);
		}

		setItemGender(pItem1, (pPC->getSex()==FEMALE)?GENDER_FEMALE:GENDER_MALE);
	}
	else if (m_Type == 9) // 빨간색 복주머니
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 7);

		if (pPC->isSlayer() )
		{
			pItem1 = g_pItemMineInfoManager->getRandomItem(62, 81);
		}
		else if (pPC->isVampire() )
		{
			pItem1 = g_pItemMineInfoManager->getRandomItem(82, 96);
		}
		else if (pPC->isOusters() )
		{
			pItem1 = g_pItemMineInfoManager->getRandomItem(97, 112);
		}
	}
	else
	{
		// 거래를 위한 NPC의 Property가 잘못되었다. 이런 경우에는
		// 운영팀으로 문의를 하면 바로 처리를 할 수 있다.
		GCSystemMessage gcSystemMessage;
		gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NPC_ERROR ));
		pPlayer->sendPacket(&gcSystemMessage);

		GCNPCResponse response;
		response.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
		pPlayer->sendPacket(&response);
		return;
	}
	
	if (pMasterItem == NULL)
	{
		GCSystemMessage gcSystemMessage;
		gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NO_LAIR_ITEM ));
		pPlayer->sendPacket(&gcSystemMessage);

		GCNPCResponse response;
		response.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
		pPlayer->sendPacket(&response);

		return;
	}

	Zone* pZone = pPC->getZone();

//	if (MonsterType != 0 ) // 루팅표를 참조해서 아이템을 만들어오는 경우
	if (pItem1 == NULL )
	{
		QuestItemInfo* pItemInfo = dynamic_cast<QuestItemInfo*>(g_pQuestItemInfoManager->getItemInfo(pMasterItem->getItemType() ));
		Assert(pItemInfo!=NULL);

		///////////////////////////////////////////////////////////////////////////////
		// 가장 난감한 부분
		//   아이템을 랜덤하게 선택해야 한다.
		//   일단은 기본 아이템 하나로 한다.
		//////////////////////////////////////////////////////////////////////////////
		const MonsterInfo* pMonsterInfo = g_pMonsterInfoManager->getMonsterInfo(MonsterType);
		TreasureList *pTreasureList = NULL;

		// 종족에 따라서 주는 아이템도 달라야 한다.
		if (pCreature2->isSlayer())
			pTreasureList = pMonsterInfo->getSlayerTreasureList();
		else if (pCreature2->isVampire())
			pTreasureList = pMonsterInfo->getVampireTreasureList();
		else if (pCreature2->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;

			// QuestItem 마다 다른.. 옵션이 2개 붙을 확률
			it.NextOptionRatio = pItemInfo->getBonusRatio();

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

			if (pTreasure->getRandomItem(&it) )
			{
/*				if (bUpgrade && isPossibleUpgradeItemType(it.ItemClass ) )
				{
					it.ItemType = getUpgradeItemType(it.ItemClass, it.ItemType, 1);
				}
*/
				pItem1 = g_pItemFactoryManager->createItem(it.ItemClass, it.ItemType, it.OptionType);
				Assert(pItem1 != NULL);
			}
		}

		if (pItem1 == NULL)
		{
			StringStream msg;
			msg << "ActionTradeLairItem: "
				<< (int)it.ItemClass << ", "
				<< (int)it.ItemType << ", "
				<< (int)it.bCreateOption << ", "
				<< getOptionTypeToString(it.OptionType);

			filelog("tradeLairItemBUG.txt", "%s", msg.toString().c_str());

			GCSystemMessage gcSystemMessage;
			gcSystemMessage.setMessage(g_pStringPool->getString(STRID_ITEM_CREATE_ERROR ));
			pPlayer->sendPacket(&gcSystemMessage);

			GCNPCResponse response;
			response.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
			pPlayer->sendPacket(&response);

			return;
		}
	}

	TPOINT pt;

	pItem1->setGrade(min(7,ItemGradeManager::Instance().getRandomBeadGrade()));
	pZone->registerObject(pItem1);

	// 만약 inventory에 공간이 있다면, 넣는다. 
	if(pInventory->addItem(pItem1, pt))
	{
		pItem1->create(pPC->getName(), STORAGE_INVENTORY, 0, pt.x, pt.y);

		GCCreateItem gcCreateItem;
/*		gcCreateItem.setObjectID(pItem1->getObjectID());
		gcCreateItem.setItemClass(pItem1->getItemClass());
		gcCreateItem.setItemType(pItem1->getItemType());
		gcCreateItem.setOptionType(pItem1->getOptionTypeList());
		gcCreateItem.setDurability(pItem1->getDurability());
		gcCreateItem.setItemNum(pItem1->getNum());
		gcCreateItem.setInvenX(pt.x);
		gcCreateItem.setInvenY(pt.y);
		gcCreateItem.setGrade(pItem1->getGrade());*/

		makeGCCreateItem(&gcCreateItem, pItem1, pt.x, pt.y);

		pPlayer->sendPacket(&gcCreateItem);

		// ItemTraceLog 를 남긴다
		if (pItem1 != NULL && pItem1->isTraceItem() )
		{
			remainTraceLog(pItem1, pCreature1->getName(), pCreature2->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC);
		}

		// 기존의 아이템을 없앤다
		GCDeleteInventoryItem gcDeleteInventoryItem;
		gcDeleteInventoryItem.setObjectID(pMasterItem->getObjectID());
		pPlayer->sendPacket(&gcDeleteInventoryItem);

		// 서버에서 없애준다.
		pInventory->deleteItem(pMasterItem->getObjectID());	// 좌표로 바꿔주면 좋을건데..
		// ItemTraceLog 를 남긴다
		if (pMasterItem != NULL && pMasterItem->isTraceItem() )
		{
			remainTraceLog(pMasterItem, pCreature2->getName(), pCreature1->getName(), ITEM_LOG_DELETE, DETAIL_EVENTNPC);
		}
		pMasterItem->destroy();
		SAFE_DELETE(pMasterItem);

		// 사용자에게 성공 메시지 출력
//		StringStream message;
//		message << "성공적으로 교환되었습니다";
		GCSystemMessage gcSystemMessage;
		gcSystemMessage.setMessage(g_pStringPool->getString(STRID_TRADE_SUCCESS ));
		pPlayer->sendPacket(&gcSystemMessage);
	}
	else
	{
//		StringStream buf;
//		buf << "인벤토리에 공간이 부족합니다";

		GCSystemMessage gcSystemMessage;
		gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NOT_ENOUGH_INVENTORY_SPACE ));
		pPlayer->sendPacket(&gcSystemMessage);
	}

	GCNPCResponse response;
	response.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
	pPlayer->sendPacket(&response);

	__END_CATCH
}