Ejemplo n.º 1
0
////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionGiveItem::execute (Creature * pCreature1 , Creature * pCreature2) 
	throw(Error)
{
	__BEGIN_TRY

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

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

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

	list<OptionType_t> optionTypeList;

	Item* pItem = g_pItemFactoryManager->createItem(m_ItemClass, m_ItemType, optionTypeList);
	Assert(pItem != NULL);
	
	_TPOINT pt;

	Inventory* pInventory = pPC->getInventory();
	Assert(pInventory != NULL);
	
	if (!pInventory->getEmptySlot(pItem, pt))
	{
		// ConditionHasInvenSpace 컨디션과 반드시 함께 써야만 한다.
		throw Error("ActionGiveItem: 제발 ConditionHasInvenSpace랑 같이 쓰자. 인벤토리에 자리없다.");
	}

	CoordInven_t X = pt.x;
	CoordInven_t Y = pt.y;

	pPC->getZone()->getObjectRegistry().registerObject(pItem);
	pInventory->addItem(X, Y, pItem);
	pItem->create(pPC->getName(), STORAGE_INVENTORY, 0, X, Y);

	if (pItem != NULL && pItem->isTraceItem() )
	{
		remainTraceLog(pItem, "ActionGiveItem", pCreature2->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC);
		remainTraceLogNew(pItem, pCreature2->getName(), ITL_GET, ITLD_EVENTNPC , pCreature2->getZone()->getZoneID());
	}

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

	__END_CATCH
}
Ejemplo n.º 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
}
Ejemplo n.º 3
0
void CGShopRequestSellHandler::executeOpSwapAdvancementItem(CGShopRequestSell* pPacket, Player* pPlayer)
	throw(ProtocolException, Error)
{
	__BEGIN_TRY

#ifdef __GAME_SERVER__

	ObjectID_t      NPCID        = pPacket->getObjectID();
	ObjectID_t      ITEMOID      = pPacket->getItemObjectID();
	GamePlayer*     pGamePlayer  = dynamic_cast<GamePlayer*>(pPlayer);
	Creature*       pCreature    = pGamePlayer->getCreature();
	PlayerCreature* pPC          = dynamic_cast<PlayerCreature*>(pCreature);

	if (!pPC->isAdvanced() )
	{
		return sendFailPacket(pPacket, pPlayer);
	}

	Zone* pZone = pPC->getZone();
	if (pZone == NULL) return sendFailPacket(pPacket, pPlayer);

	Creature*		pNPCBase = pZone->getCreature(NPCID); 
	if (pNPCBase == NULL || !pNPCBase->isNPC()) return sendFailPacket(pPacket, pPlayer);
	NPC* pNPC = dynamic_cast<NPC*>(pNPCBase);
	
	Inventory* pInventory  = pPC->getInventory();
	Item*      pItem       = pInventory->getItemWithObjectID(ITEMOID);

	if (pItem == NULL || pItem->isTimeLimitItem() )
	{
		return sendFailPacket(pPacket, pPlayer);
	}

	Item::ItemClass iClass = Item::ITEM_CLASS_MAX;
	ItemType_t		iType = 0;
	Grade_t			iGrade = 0;
	FlagSetType		fType = FLAGSET_MAX;

	ItemInfo* pItemInfo = g_pItemInfoManager->getItemInfo(pItem->getItemClass(), pItem->getItemType());
	Assert(pItemInfo!=NULL);

	switch (pItem->getItemClass() )
	{
		case Item::ITEM_CLASS_SWORD:
		case Item::ITEM_CLASS_BLADE:
		case Item::ITEM_CLASS_AR:
		case Item::ITEM_CLASS_SR:
		case Item::ITEM_CLASS_SG:
		case Item::ITEM_CLASS_SMG:
			{
				switch (pItem->getItemType() )
				{
					case 9:
						{
							iClass = pItem->getItemClass();
							iType = 14;
							iGrade = 2;
							break;
						}
					case 11:
						{
							iClass = pItem->getItemClass();
							iType = 14;
							iGrade = 4;
							break;
						}
					case 12:
						{
							iClass = pItem->getItemClass();
							iType = 14;
							iGrade = 6;
							break;
						}
					case 13:
						{
							iClass = pItem->getItemClass();
							iType = 14;
							iGrade = 8;
							break;
						}
					default:
						break;
				}
				if (iClass == Item::ITEM_CLASS_SG ) iClass = Item::ITEM_CLASS_SR;
				if (iClass == Item::ITEM_CLASS_SMG ) iClass = Item::ITEM_CLASS_AR;
				break;
			}
		case Item::ITEM_CLASS_CROSS:
		case Item::ITEM_CLASS_MACE:
			{
				switch (pItem->getItemType() )
				{
					case 7:
						{
							iClass = pItem->getItemClass();
							iType = 12;
							iGrade = 2;
							break;
						}
					case 9:
						{
							iClass = pItem->getItemClass();
							iType = 12;
							iGrade = 4;
							break;
						}
					case 10:
						{
							iClass = pItem->getItemClass();
							iType = 12;
							iGrade = 6;
							break;
						}
					case 11:
						{
							iClass = pItem->getItemClass();
							iType = 12;
							iGrade = 8;
							break;
						}
					default:
						break;
				}
				break;
			}

		case Item::ITEM_CLASS_COAT:
		case Item::ITEM_CLASS_TROUSER:
			{
				switch (pItem->getItemType() )
				{
					case 14:
					case 15:
						{
							iClass = pItem->getItemClass();
							iType = 24 + (pItem->getItemType()%2);
							iGrade = 2;
							break;
						}
					case 18:
					case 19:
					case 20:
					case 21:
					case 22:
					case 23:
						{
							iClass = pItem->getItemClass();
							iType = 24 + (pItem->getItemType()%2);
							iGrade = 4 + (((pItem->getItemType()-18)/2)*2);
							break;
						}
					default:
						break;
				}
				break;
			}
		case Item::ITEM_CLASS_VAMPIRE_WEAPON:
			{
				switch (pItem->getItemType() )
				{
					case 14:
						{
							iClass = pItem->getItemClass();
							iType = 19;
							iGrade = 2;
							break;
						}
					case 16:
						{
							iClass = pItem->getItemClass();
							iType = 19;
							iGrade = 4;
							break;
						}
					case 17:
						{
							iClass = pItem->getItemClass();
							iType = 19;
							iGrade = 6;
							break;
						}
					case 18:
						{
							iClass = pItem->getItemClass();
							iType = 19;
							iGrade = 8;
							break;
						}
					default:
						break;
				}
				break;
			}
		case Item::ITEM_CLASS_VAMPIRE_COAT:
			{
				switch (pItem->getItemType() )
				{
					case 10:
					case 11:
						{
							iClass = pItem->getItemClass();
							iType = 20 + (pItem->getItemType()%2);
							iGrade = 2;
							break;
						}
					case 14:
					case 15:
					case 16:
					case 17:
					case 18:
					case 19:
						{
							iClass = pItem->getItemClass();
							iType = 20 + (pItem->getItemType()%2);
							iGrade = 4 + (((pItem->getItemType()-14)/2)*2);
							break;
						}
					default:
						break;
				}
				break;
			}
		case Item::ITEM_CLASS_OUSTERS_CHAKRAM:
			{
				switch (pItem->getItemType() )
				{
					case 9:
						{
							iClass = pItem->getItemClass();
							iType = 14;
							iGrade = 2;
							break;
						}
					case 10:
						{
							iClass = pItem->getItemClass();
							iType = 14;
							iGrade = 4;
							break;
						}
					case 11:
						{
							iClass = pItem->getItemClass();
							iType = 14;
							iGrade = 6;
							break;
						}
					case 13:
						{
							iClass = pItem->getItemClass();
							iType = 14;
							iGrade = 8;
							break;
						}
					default:
						break;
				}
				break;
			}
		case Item::ITEM_CLASS_OUSTERS_WRISTLET:
			{
				switch (pItem->getItemType() )
				{
					case 9:
					case 30:
					case 31:
					case 39:
						{
							iClass = pItem->getItemClass();
							iType = 42;
							iGrade = pItemInfo->getItemLevel() * 2 - 16;
							break;
						}
					case 19:
					case 32:
					case 33:
					case 40:
						{
							iClass = pItem->getItemClass();
							iType = 43;
							iGrade = pItemInfo->getItemLevel() * 2 - 16;
							break;
						}
					case 29:
					case 34:
					case 35:
					case 41:
						{
							iClass = pItem->getItemClass();
							iType = 44;
							iGrade = pItemInfo->getItemLevel() * 2 - 16;
							break;
						}
					default:
						break;
				}
				break;
			}
		case Item::ITEM_CLASS_OUSTERS_COAT:
		case Item::ITEM_CLASS_OUSTERS_BOOTS:
			{
				switch (pItem->getItemType() )
				{
					case 7:
						{
							iClass = pItem->getItemClass();
							iType = 12;
							iGrade = 2;
							break;
						}
					case 8:
						{
							iClass = pItem->getItemClass();
							iType = 12;
							iGrade = 4;
							break;
						}
					case 9:
						{
							iClass = pItem->getItemClass();
							iType = 12;
							iGrade = 6;
							break;
						}
					case 11:
						{
							iClass = pItem->getItemClass();
							iType = 12;
							iGrade = 8;
							break;
						}
					default:
						break;
				}
				break;
			}
		default:
			break;
	}

	switch (iClass )
	{
		case Item::ITEM_CLASS_SWORD:
		case Item::ITEM_CLASS_BLADE:
		case Item::ITEM_CLASS_AR:
		case Item::ITEM_CLASS_SR:
		case Item::ITEM_CLASS_CROSS:
		case Item::ITEM_CLASS_MACE:
		case Item::ITEM_CLASS_VAMPIRE_WEAPON:
		case Item::ITEM_CLASS_OUSTERS_CHAKRAM:
		case Item::ITEM_CLASS_OUSTERS_WRISTLET:
			fType = FLAGSET_SWAP_WEAPON;
			break;
		case Item::ITEM_CLASS_COAT:
		case Item::ITEM_CLASS_VAMPIRE_COAT:
		case Item::ITEM_CLASS_OUSTERS_COAT:
			fType = FLAGSET_SWAP_COAT;
			break;
		case Item::ITEM_CLASS_TROUSER:
		case Item::ITEM_CLASS_OUSTERS_BOOTS:
			fType = FLAGSET_SWAP_TROUSER;
			break;
		default:
			break;
	}

	if (iClass == Item::ITEM_CLASS_MAX || fType == FLAGSET_MAX )
	{
		sendFailPacket(pPacket, pPlayer);
		return;
	}

	FlagSet* pFlagSet = pPC->getFlagSet();
	if (pFlagSet->isOn(fType) )
	{
		sendFailPacket(pPacket, pPlayer);
		return;
	}

	Item* pNewItem = g_pItemFactoryManager->createItem(iClass, iType, pItem->getOptionTypeList());
	if (pNewItem == NULL )
	{
		sendFailPacket(pPacket, pPlayer);
		return;
	}
	pNewItem->setGrade(iGrade);

	_TPOINT tp;
	if (!pInventory->getEmptySlot(pNewItem, tp) )
	{
		SAFE_DELETE(pNewItem);
		sendFailPacket(pPacket, pPlayer);
		return;
	}

	filelog("ItemSwap.log", "[%s:%s] %s <-> %s",
			pGamePlayer->getID().c_str(), pPC->getName().c_str(), pItem->toString().c_str(), pNewItem->toString().c_str());

	pNewItem->setTraceItem(bTraceLog(pNewItem ));

	pInventory->deleteItem(ITEMOID);
	pItem->whenPCLost(pPC);

	if (!pItem->destroy())
	{
		filelog("shopDBBug.txt", "NoSuchItemInDB-destroy: %s", pItem->toString().c_str());

		throw DisconnectException("아이템 지울려는데 DB에 없다.");
	}

	pZone->registerObject(pNewItem);

	GCShopSellOK okpkt;
	okpkt.setObjectID(NPCID);
	okpkt.setShopVersion(-1);
	okpkt.setItemObjectID(ITEMOID);
	okpkt.setPrice(0);
	pGamePlayer->sendPacket(&okpkt);

	// 삭제할 아이템의 ItemTrace Log 를 남겨야 한다면 남긴다
	if (pItem != NULL && pItem->isTraceItem() )
	{
		remainTraceLog(pItem, pCreature->getName() , pNPC->getName(), ITEM_LOG_DELETE, DETAIL_SHOPSELL);
	}

	// 인벤토리에 추가
	Assert(pInventory->addItem(pNewItem, tp ));

	// DB 에 생성
	pNewItem->create(pPC->getName(), STORAGE_INVENTORY, 0, tp.x, tp.y);

	// 교환해줄 아이템의 ItemTrace Log 를 남겨야 한다면 남긴다
	if (pNewItem->isTraceItem() )
	{
		remainTraceLog(pNewItem, pNPC->getName() , pCreature->getName(), ITEM_LOG_CREATE, DETAIL_SHOPBUY);
	}

	pFlagSet->turnOn(fType);
	pFlagSet->save(pPC->getName());

	GCCreateItem gcCI;
	makeGCCreateItem(&gcCI, pNewItem, tp.x, tp.y);

	pGamePlayer->sendPacket(&gcCI);

#endif

	__END_CATCH
}
Ejemplo n.º 4
0
//////////////////////////////////////////////////////////////////////////////
// 
// 일반 아이템을 처리한다.
//
//////////////////////////////////////////////////////////////////////////////
void CGShopRequestSellHandler::executeNormal (CGShopRequestSell* pPacket , Player* pPlayer)
	 throw(ProtocolException , Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

	ObjectID_t      NPCID        = pPacket->getObjectID();
	ObjectID_t      ITEMOID      = pPacket->getItemObjectID();
	GamePlayer*     pGamePlayer  = dynamic_cast<GamePlayer*>(pPlayer);
	Creature*       pCreature    = pGamePlayer->getCreature();
	PlayerCreature* pPC          = dynamic_cast<PlayerCreature*>(pCreature);
	BYTE            index        = 0;
	bool            bSpecialItem = false;

	Zone* pZone = pPC->getZone();
	if (pZone == NULL) return sendFailPacket(pPacket, pPlayer);

	Creature* pNPCBase = NULL;
	/*
	try 
	{ 
		pNPCBase = pZone->getCreature(NPCID); 
	}
	catch (NoSuchElementException & nsee) 
	{ 
		pNPCBase = NULL; 
	}
	*/

	// NoSuch제거. by sigi. 2002.5.2
	pNPCBase = pZone->getCreature(NPCID); 

	if (pNPCBase == NULL || !pNPCBase->isNPC()) return sendFailPacket(pPacket, pPlayer);

	NPC* pNPC = dynamic_cast<NPC*>(pNPCBase);
	
	// 플레이어가 팔려고 하는 아이템을 가지고 있는지 검사
	Inventory* pInventory  = pPC->getInventory();
	//Gold_t     playerMoney = pPC->getGold(); 
	Item*      pItem       = pInventory->getItemWithObjectID(ITEMOID);
	ItemNum_t  itemNumber  = pItem->getNum();
	Price_t    itemPrice   = g_pPriceManager->getPrice(pItem, pNPC->getMarketCondBuy(), SHOP_RACK_NORMAL, pPC) * itemNumber;

	// 플레이어의 인벤토리에 아이템을 제거한다.
	pInventory->deleteItem(ITEMOID);
	pItem->whenPCLost(pPC);

	if (!pItem->destroy()) {
		filelog("shopDBBug.txt", "NoSuchItemInDB-destroy: %s", pItem->toString().c_str());

		throw DisconnectException("아이템 지울려는데 DB에 없다.");
	}

	// 만약 벨트라면 안에 있는 포션을 삭제해준다.
	// DB에서 지우는 것은 Belt::destroy()를 부르는 것만으로 포션까지 삭제된다.
	if (pItem->getItemClass() == Item::ITEM_CLASS_BELT) {
		Inventory* pBeltInventory = dynamic_cast<Belt*>(pItem)->getInventory();
		for (int y=0; y<pBeltInventory->getHeight(); y++) {
			for (int x=0; x<pBeltInventory->getWidth(); x++) {
				Item* pBeltItem = pBeltInventory->getItem(x, y);
				if (pBeltItem != NULL) {
					pBeltInventory->deleteItem(x, y);
					SAFE_DELETE(pBeltItem);
				}
			}
		}
	}

	// Skull 일 경우 Variable Manager 에서 머리값 배수 값으로 가격을 새로 계산한다
	if (pItem->getItemClass() == Item::ITEM_CLASS_SKULL)
		itemPrice = itemPrice * (g_pVariableManager->getHeadPriceBonus() / 100);

	// ItemTrace Log 를 남겨야 한다면 남긴다
	if (pItem != NULL && pItem->isTraceItem() )
		remainTraceLog(pItem, pCreature->getName() , pNPC->getName(), ITEM_LOG_DELETE, DETAIL_SHOPSELL);

	// 플레이어에게 물건값을 지불한다.
	// pPC->setGoldEx(playerMoney+itemPrice);
	// by sigi. 2002.9.4
	pPC->increaseGoldEx(itemPrice);

	// 플레이어가 물건 팔 때 처리할 것들을 처리한다.
	pPC->sellItem(pItem);

	if (pItem->getItemClass() == Item::ITEM_CLASS_MOON_CARD && pItem->getItemType() == 4)
		addOlympicStat(pPC, 4, (uint)(itemNumber));

	bool bClearDefaultOptionTypes = false;
	if (pItem->getItemClass() == Item::ITEM_CLASS_EVENT_ITEM && pItem->getItemType() >= 32 && pItem->getItemType() <= 36)
		bClearDefaultOptionTypes = true;

	// NPC에게 자리가 충분하다면 플레이어가 판 아이템을 보관한다.
	// 운영자 명령어로 만든 아이템은 바로 없앤다.
	// 단 스페셜 아이템만을 보관한다. 노말 아이템은 그냥 버림.
	// 퀘스트 아이템은 보관하지 않고 버린다.
	if (pNPC->getShopType()==SHOPTYPE_NORMAL &&
		pItem->getCreateType()!=Item::CREATE_TYPE_CREATE &&
		!pItem->getOptionTypeList().empty() &&
		!pItem->isTimeLimitItem()) {
		bSpecialItem = true;
		index        = pNPC->getFirstEmptySlot(SHOP_RACK_SPECIAL);

		if (index < SHOP_RACK_INDEX_MAX) {
			// 아이템을 추가한다.
			pNPC->insertShopItem(SHOP_RACK_SPECIAL, index, pItem);

			// 스페셜 아이템을 NPC가 진열장에 추가했으므로, 상점 버전이 올라간다.
			pNPC->increaseShopVersion(SHOP_RACK_SPECIAL);

			////////////////////////////////////////////////////////////////////////////
			// 근처의 플레이어들에게는 GCShopBought를...
			////////////////////////////////////////////////////////////////////////////

			int         CenterX       = pNPC->getX();
			int         CenterY       = pNPC->getY();
			Creature*   pNearCreature = NULL;
			Player*     pNearPlayer   = NULL;

			GCShopBought boughtpkt;
			boughtpkt.setObjectID(NPCID);
			if (!pItem->getOptionTypeList().empty()) {
				boughtpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_SPECIAL));
				boughtpkt.setShopType(SHOP_RACK_SPECIAL);
			} else {
				boughtpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_NORMAL));
				boughtpkt.setShopType(SHOP_RACK_NORMAL);
			}
			boughtpkt.setShopIndex(index);
			boughtpkt.setItemObjectID(ITEMOID);
			boughtpkt.setItemClass(pItem->getItemClass());
			boughtpkt.setItemType(pItem->getItemType());
			boughtpkt.setOptionType(pItem->getOptionTypeList());
			boughtpkt.setDurability(pItem->getDurability());
			boughtpkt.setSilver(pItem->getSilver());
			boughtpkt.setGrade(pItem->getGrade());
			boughtpkt.setEnchantLevel(pItem->getEnchantLevel());

			//pZone->broadcastPacket(pNPC->getX(), pNPC->getY(), &boughtpkt, pPC);

			try
			{
				for (int zx=CenterX-5; zx<=CenterX+5; zx++)
				{
					for (int zy=CenterY-5; zy<=CenterY+5; zy++)
					{
						// 바운드를 넘어가지 않는가를 체크
						if (!isValidZoneCoord(pZone, zx, zy)) continue;

						Tile & tile = pZone->getTile(zx, zy);

						// 걸어다니는 크리쳐를 검색	
						if (tile.hasCreature(Creature::MOVE_MODE_WALKING))
						{
							pNearCreature = tile.getCreature(Creature::MOVE_MODE_WALKING);
							if (pNearCreature == NULL) continue;

							// 방금 물건을 판 플레이어라면 생략
							if (pNearCreature->getObjectID() == pPC->getObjectID()) continue;
							
							// 만약 플레이어라면 패킷을 보내준다.
							if (pNearCreature->isPC())
							{
								pNearPlayer = pNearCreature->getPlayer();
								if (pNearPlayer == NULL) continue;
								pNearPlayer->sendPacket(&boughtpkt);
							}
						}
						// 날아다니는 크리쳐를 검색
						if (tile.hasCreature(Creature::MOVE_MODE_FLYING))
						{
							pNearCreature = tile.getCreature(Creature::MOVE_MODE_FLYING);
							if (pNearCreature == NULL) continue;
							
							// 방금 물건을 판 플레이어라면 생략
							if (pNearCreature->getObjectID() == pPC->getObjectID()) continue;

							// 만약 플레이어라면 패킷을 보내준다.
							if (pNearCreature->isPC())
							{
								pNearPlayer = pNearCreature->getPlayer();
								if (pNearPlayer == NULL) continue;
								pNearPlayer->sendPacket(&boughtpkt);
							}
						}

					} // end of for (ZoneCoord_t zy=CenterY-5; zy<=CenterY+5; zy++)
				} // end of for (ZoneCoord_t zx=CenterX-5; zx<=CenterX+5; zx++)
			}
			catch (Throwable & t)
			{
				filelog("shopbug_packet.log", "%s", t.toString().c_str());
			}

		} // if (index < SHOP_RACK_INDEX_MAX)
		else
		{
			SAFE_DELETE(pItem);
		}
	} // if (pItem->getOptionType() != 0)
	else
	{
		bSpecialItem = false;
		SAFE_DELETE(pItem);
	}

	// 물건을 산 플레이어에게 GCShopSellOK를...보낸다.
	GCShopSellOK okpkt;
	okpkt.setObjectID(NPCID);
	if (bSpecialItem) okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_SPECIAL));
	else              okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_NORMAL));
	okpkt.setItemObjectID(ITEMOID);
	//okpkt.setPrice(playerMoney+itemPrice);
	// playerMoney + itemPrice 가 MAX_MONEY를 넘어갈 수 있다.
	// 2003.1.8 by bezz
	okpkt.setPrice(pPC->getGold());
	pPlayer->sendPacket(&okpkt);
	
	if (bClearDefaultOptionTypes )
	{
		pPC->clearDefaultOptionTypes();
		pPC->initAllStatAndSend();

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

			pSlayer->sendRealWearingInfo();
		}
		else if (pPC->isVampire() )
		{
			Vampire* pVampire = dynamic_cast<Vampire*>(pPC);
			Assert(pVampire != NULL);

			pVampire->sendRealWearingInfo();
		}
		else if (pPC->isOusters() )
		{
			Ousters* pOusters = dynamic_cast<Ousters*>(pPC);
			Assert(pOusters != NULL);

			pOusters->sendRealWearingInfo();
		}
	}

#endif

	__END_DEBUG_EX __END_CATCH
}
Ejemplo n.º 5
0
////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionRewardEventQuest::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);

    if (pPC->getQuestItem() != NULL )
    {
        TPOINT pt;

        Item* pItem = pPC->getQuestItem();
        if (pItem == NULL || !pPC->getInventory()->getEmptySlot(pItem, pt ) )
        {
            GCNPCResponse gcNPCResponse;
            gcNPCResponse.setCode(NPC_RESPONSE_QUEST);
            gcNPCResponse.setParameter(COMPLETE_FAIL_NO_INVENTORY_SPACE);
            pPC->getPlayer()->sendPacket(&gcNPCResponse);

            return;
        }

        if (pPC->getInventory()->addItem(pItem, pt ) )
        {
            pPC->setQuestItem(NULL);
            pPC->getZone()->registerObject(pItem);

            pItem->create(pPC->getName(), STORAGE_INVENTORY, 0, pt.x, pt.y);
            if (pItem->isUnique() || pItem->isTimeLimitItem() )
            {
                pPC->addTimeLimitItem(pItem, 604800);
                pPC->sendTimeLimitItemInfo();
            }

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

            GCNPCResponse gcNPCResponse;
            gcNPCResponse.setCode(NPC_RESPONSE_QUEST);
            gcNPCResponse.setParameter(COMPLETE_SUCCESS);
            pPC->getPlayer()->sendPacket(&gcNPCResponse);

            remainTraceLog(pItem, pCreature1->getName(), pCreature2->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC);
            return;
        }
        else
        {
            GCNPCResponse gcNPCResponse;
            gcNPCResponse.setCode(NPC_RESPONSE_QUEST);
            gcNPCResponse.setParameter(COMPLETE_FAIL_NO_INVENTORY_SPACE);
            pPC->getPlayer()->sendPacket(&gcNPCResponse);
            return;
        }

    }

    int questLevel = pPC->getQuestManager()->getEventQuestAdvanceManager()->getQuestLevel();
    ScriptID_t sID = m_ScriptID[ questLevel ];
    QuestID_t qID;

    if (!pPC->getQuestManager()->successEventQuest(questLevel, qID ) ) sID = m_CounterScriptID;
    if (pPC->getQuestManager()->getEventQuestAdvanceManager()->getStatus(questLevel) == EventQuestAdvance::EVENT_QUEST_INIT &&
            questLevel > 1 ) sID = m_CancelScriptID;

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

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

    __END_CATCH
}
Ejemplo n.º 6
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
}
Ejemplo n.º 7
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);
				}
			}
////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionGiveAccountEventItem::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);

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

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

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

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

	Item*			pItem;

	// 이벤트가 진행중이지 않은 경우
	if (!g_pVariableManager->isActiveGiveEventItem())
	{
		GCNPCResponse response;
		response.setCode(NPC_RESPONSE_GIVE_EVENT_ITEM_FAIL_NOW);
		pPlayer->sendPacket(&response);

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

		return;
	}

	// 이미 받았는지 체크한다.
	if (pGamePlayer->getSpecialEventCount() & m_SpecialEventFlag)
	{
		GCNPCResponse response;
		response.setCode(NPC_RESPONSE_GIVE_EVENT_ITEM_FAIL);
		pPlayer->sendPacket(&response);

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

		return;
	}

	// 유료 사용자 여부를 체크한다.
	if (!PaySystem::isPayPlayingPeriodPersonal(pGamePlayer->getID() ) )
	{
		GCNPCResponse response;
		response.setCode(NPC_RESPONSE_GIVE_PREMIUM_USER_ONLY);
		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;
	}

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

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

	pLuaSelectItem->clear();

	if(ItemClass >= Item::ITEM_CLASS_MAX )
	{
		filelog("AccountEventItemError.txt", "[ ItemInfo Error ] : ItemClass = %d , ItemType = %d , OptionType = %d", ItemClass, ItemType, OptionType);

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

		return;
	}

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

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

	// 인벤토리에 아이템을 넣을 빈 자리를 받아온다.
	TPOINT p;
	
	if (!pInventory->getEmptySlot(pItem, p)) 
	{
		SAFE_DELETE(pItem);

		GCNPCResponse response;
		response.setCode(NPC_RESPONSE_NO_EMPTY_SLOT);
		pGamePlayer->sendPacket(&response);

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

		return;
	}

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

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

		remainTraceLogNew(pItem, pCreature2->getName(), ITL_GET, ITLD_EVENTNPC, pCreature1->getZone()->getZoneID(), pCreature1->getX(), pCreature1->getY());
	}

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

	// 선물을 받았다고 Flag 를 켠다.
	pGamePlayer->setSpecialEventCount(pGamePlayer->getSpecialEventCount() | m_SpecialEventFlag);
	// Flag 를 저장한다.
	pGamePlayer->saveSpecialEventCount();

	// 보상을 받았다고 클라이언트에 보낸다.
	GCNPCResponse response;
	response.setCode(NPC_RESPONSE_GIVE_EVENT_ITEM_OK);
	pPlayer->sendPacket(&response);

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

	__END_CATCH
}
Ejemplo n.º 9
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
}
Ejemplo n.º 10
0
////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionGiveEventItem::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;
	OptionType_t	OptionType2;

	Item*			pItem;

	// 이벤트 진행 기간이 아닌 경우
	if (!g_pVariableManager->isActiveGiveEventItem())
	{
		GCNPCResponse response;
		response.setCode(NPC_RESPONSE_GIVE_EVENT_ITEM_FAIL_NOW);
		pPlayer->sendPacket(&response);

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

		return;
	}

	// 이 값과 관련해서
	// 캐릭터 생성시에 FlagSet을 바꿔줘야한다. (default ON 으로)
	// 이미 선물을 교환해 갔다면
	if (pFlagSet->isOn(m_FlagSetType ) )
	{
		GCNPCResponse response;
		response.setCode(NPC_RESPONSE_GIVE_EVENT_ITEM_FAIL);
		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();
	OptionType2	= pLuaSelectItem->getOptionType2();

	pLuaSelectItem->clear();

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

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

		return;
	}

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

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

	_TPOINT pt;
	if (!pInventory->getEmptySlot(pItem, pt))
	{
		SAFE_DELETE(pItem);

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

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

		return;
	}
	 
	CoordInven_t X = pt.x;
	CoordInven_t Y = pt.y;

	// 선물을 인벤토리에 추가한다.
	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);

		remainTraceLogNew(pItem, pCreature2->getName(), ITL_GET, ITLD_EVENTNPC, pCreature1->getZone()->getZoneID(), pCreature1->getX(), pCreature1->getY());
	}

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

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

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

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

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

	__END_CATCH
}