コード例 #1
0
ファイル: Creature.cpp プロジェクト: jun199004/server
//////////////////////////////////////////////////////////////////////////////
// (nx,ny)·Î À̵¿ÇÒ ¼ö Àִ°¡?
//////////////////////////////////////////////////////////////////////////////
bool Creature::canMove (ZoneCoord_t nx , ZoneCoord_t ny) const
	throw(Error)
{
	Assert(m_pZone != NULL);

	// ¿Ã¹Ù¸¥ ÁÂÇ¥Àΰ¡?
	// ¸·ÇôÀÖÁö´Â ¾ÊÀº°¡?
	if (//isFlag(Effect::EFFECT_CLASS_SANCTUARY)
		// m_Flag.test(Effect::EFFECT_CLASS_SANCTUARY)
		m_Flag.test(Effect::EFFECT_CLASS_POISON_MESH)
		|| m_Flag.test(Effect::EFFECT_CLASS_TENDRIL)
		|| m_Flag.test(Effect::EFFECT_CLASS_BLOODY_WALL_BLOCKED)
		|| m_Flag.test(Effect::EFFECT_CLASS_CASKET)
		|| !isValidZoneCoord(m_pZone, nx, ny)) return false;

	/*
	// ¼º¹°À» °¡Áö°í ÀÖ´Â °æ¿ì¶ó¸é..
	if (m_Flag.test(Effect::EFFECT_CLASS_HAS_SLAYER_RELIC)
		|| m_Flag.test(Effect::EFFECT_CLASS_HAS_VAMPIRE_RELIC))
	{
		ZoneLevel_t ZoneLevel = m_pZone->getZoneLevel(nx, ny);

		// ½½·¹À̾îÀÌ¸é ½½·¹ÀÌ¾î ¾ÈÀüÁö´ë¿¡ ¸ø µé¾î°£´Ù.
		// ¹ìÆÄÀ̾îÀÌ¸é  ¹ìÆÄÀ̾î¾ÈÀüÁö´ë¿¡ ¸ø µé¾î°£´Ù.
		// °øÅë ¾ÈÀüÁö´ëÀÌ¸é ¸ø µé¾î°£´Ù.
		if (isSlayer() && (ZoneLevel & SLAYER_SAFE_ZONE)
			|| isVampire() && (ZoneLevel & VAMPIRE_SAFE_ZONE)
			|| (ZoneLevel & COMPLETE_SAFE_ZONE))
		{
			return false;
		}
	}
	*/

	Tile& rTile = m_pZone->getTile(nx,ny);

	if (rTile.isBlocked(m_MoveMode)
		// BloodyWallBlock³ª
		// Sanctuary ÀÌÆåÆ®°¡ °É·ÁÀÖ´Ù¸é ¸ø °£´Ù.
		|| rTile.hasEffect() 
			&& (rTile.getEffect(Effect::EFFECT_CLASS_BLOODY_WALL_BLOCKED)
				|| rTile.getEffect(Effect::EFFECT_CLASS_SANCTUARY))
		)
	{
		return false;
	}

	Tile& rNewTile = m_pZone->getTile(getX(), getY());

	if (rNewTile.getEffect(Effect::EFFECT_CLASS_SANCTUARY) )
		return false;

	return true;
}
コード例 #2
0
ファイル: Creature.cpp プロジェクト: jun199004/server
//////////////////////////////////////////////////////////////////////////////
// (nx,ny)ÀÌ ¸Ê¿¡ ÀÇÇØ ¸·È÷´Â°¡?
//////////////////////////////////////////////////////////////////////////////
bool Creature::isBlockedByCreature (ZoneCoord_t nx , ZoneCoord_t ny) const
	throw(Error)
{
	Assert(m_pZone != NULL);

	// ¿Ã¹Ù¸¥ ÁÂÇ¥Àΰ¡?
	// °°Àº ¹«µå ¸ðµåÀÇ Å©¸®ÃÄ°¡ Á¸ÀçÇÏÁö ¾Ê´Â°¡?
	if (!isValidZoneCoord(m_pZone, nx, ny)
		|| !m_pZone->getTile(nx,ny).hasCreature(m_MoveMode)) return false;

	return true;
}
コード例 #3
0
//----------------------------------------------------------------------
// remove effect from target
//----------------------------------------------------------------------
void EffectDecayMotorcycle::unaffect (Zone* pZone , ZoneCoord_t x , ZoneCoord_t y , Object* pTarget, Slayer* pSlayer)
	throw(Error)
{
	__BEGIN_TRY

	// 올바른 좌표이어야 한다.
	Assert(isValidZoneCoord(pZone, x, y));

	// TempItem 변수를 잡는다.
	Item* pTempItem = NULL;

	// 여기서는 지정 아이템이 없을 수 있으며, 또 다른 아이템이 놓여 있을 수도 있다.
	// 이 경우는 오리지널 아이템과 지금 현재 바닥에 있는 아이템을 비교하여 삭제해야 한다.
	// 없을 경우는 무시하면 된다.
	Tile & tile = pZone->getTile(x, y);

	if (tile.hasItem()) {

		pTempItem = tile.getItem();

		if (pTempItem != NULL) {
			// ObjectID가 같다는 말은 같은 아이템이란 말이다.
			//if (pTempItem->getObjectID() == m_ObjectID) {
			if (pTempItem->getObjectID() == m_ObjectID) {

				pZone->deleteItem(pTempItem , x, y);

				// 아이템이 사라졌다는 패킷을 날린다.
				GCDeleteObject gcDeleteObject;
				gcDeleteObject.setObjectID(m_ObjectID);

				pZone->broadcastPacket(x, y , &gcDeleteObject);

				if (m_bDeleteFromDB)
				{
					pTempItem->destroy();
				}

				SAFE_DELETE(pTempItem);
			}
		}
	}

	// heartbeat시 EffectDecayMotorcycle이 처리된다. 그 이후 다음 heartbeat시에
	// 사용자에게 오토바이를 호출해 주어야 한다.
	// 사용자는 오토바이의 오브젝트와

	//EffectCallMotorcycle* pEffectCallMotorcycle = new EffectCallMotorcycle(pMotorcycleObject, pSlayer);
	//pTarget = NULL;

	__END_CATCH
}
コード例 #4
0
ファイル: EffectDestinies.cpp プロジェクト: jun199004/server
void EffectDestinies::affect()
	throw(Error)
{
	__BEGIN_TRY

	setDeadline(0);

	Creature* pCaster = dynamic_cast<Creature*>(m_pTarget);
	int cx = pCaster->getX();
	int cy = pCaster->getY();

	Zone* pZone = pCaster->getZone();

	for (int i=-8; i<=8; ++i )
	for (int j=-8; j<=8; ++j )
	{
		int tx = cx + i;
		int ty = cy + j;
		if (tx < 0 || ty < 0 ) continue;
		if (!isValidZoneCoord(pZone, tx, ty ) ) continue;

		list<Object*>& olist = pZone->getTile(tx, ty).getObjectList();
		list<Object*>::iterator itr = olist.begin();
		for (; itr != olist.end() ; ++itr )
		{
			Object* pObject = *itr;
			if (pObject == NULL || pObject->getObjectClass() != Object::OBJECT_CLASS_CREATURE ) continue;

			Creature* pCreature = dynamic_cast<Creature*>(pObject);
			if (pCreature == NULL ) continue;

			bool isTarget = false;
			if (pCreature->getCreatureClass() == m_TargetClass )
			{
				isTarget = true;
				if (m_TargetClass == Creature::CREATURE_CLASS_MONSTER )
				{
					Monster* pTargetMonster = dynamic_cast<Monster*>(pCreature);
					if (pTargetMonster->getSpriteType() != m_TargetSpriteType ) isTarget = false;
				}
			}

			if (isTarget ) affect(pCreature);
		}
	}

	//cout << "EffectDestinies" << "affect BEGIN" << endl;

	__END_CATCH 
}
コード例 #5
0
void EffectPKZoneRegen::affect()
	throw(Error)
{
	__BEGIN_TRY

	Assert(m_pZone != NULL);

	Assert(isValidZoneCoord(m_pZone, m_Rect.left, m_Rect.top ));
	Assert(isValidZoneCoord(m_pZone, m_Rect.right, m_Rect.bottom ));

	for (ZoneCoord_t X = m_Rect.left ; X <= m_Rect.right ; X++ )
	{
		for (ZoneCoord_t Y = m_Rect.top ; Y <= m_Rect.bottom ; Y++ )
		{
			Tile& tile = m_pZone->getTile(X, Y);

			const list<Object*>& oList = tile.getObjectList();
			for (list<Object*>::const_iterator itr = oList.begin() ; itr != oList.end() ; itr++ )
			{
				Object* pTargetObject = (*itr);

				if (pTargetObject != NULL && pTargetObject->getObjectClass() == Object::OBJECT_CLASS_CREATURE )
				{
					Creature* pCreature = dynamic_cast<Creature*>(pTargetObject);
					Assert(pCreature != NULL);

					affect(pCreature);
				}
			}
		}
	}

	setNextTime(m_Turn);

	__END_CATCH
}
コード例 #6
0
void EffectDecayCorpse::unaffect (Zone* pZone , ZoneCoord_t x , ZoneCoord_t y , Object* pTarget)
	throw(Error)
{
	__BEGIN_TRY

	// 올바른 좌표이어야 한다.
	Assert(isValidZoneCoord(pZone, x, y));

	// 시체에 접근한다.
	if (pZone->getTile(x,y).hasItem()) 
	{
		Item* pItem = pZone->getTile(x,y).getItem();

		if (pItem != NULL) 
		{
			// 타일위에 아이템이 있고 그 아이템의 오브젝트 아이디가 똑같아야만 똑 같은 시체이다.
			if (pItem->getObjectID() == m_ObjectID) 
			{
				Corpse* pCorpse = dynamic_cast<Corpse*>(pTarget);
				try 
				{
					// 시체를 존에서 삭제한다.
					Assert(pZone->getTile(x,y).getItem() == pCorpse);
					pZone->deleteItem(pCorpse , x, y);
				} 
				catch (NoSuchElementException & nsee) 
				{
					cerr << "EffectDecayCorpse::unaffect() : NoSuchElementException" << endl;
					throw Error(nsee.toString());
				}

				GCDeleteObject gcDeleteObject;
				gcDeleteObject.setObjectID(pCorpse->getObjectID());
				pZone->broadcastPacket(x, y , &gcDeleteObject);

				// 시체 자체를 삭제한다.
				SAFE_DELETE(pCorpse);
			}
		}
	}

	pTarget = NULL;

	__END_CATCH
}
コード例 #7
0
ファイル: EffectDeleteItem.cpp プロジェクト: mrktj/darkeden
//----------------------------------------------------------------------
// remove effect from target
//----------------------------------------------------------------------
void EffectDeleteItem::unaffect (Zone* pZone , ZoneCoord_t x , ZoneCoord_t y , Object* pTarget)
	throw(Error)
{
	__BEGIN_TRY

	// 올바른 좌표이어야 한다.
	//Assert(pTarget!=NULL);
	Assert(isValidZoneCoord(pZone, x, y));

	//pZone->deleteFromItemList(pTarget->getObjectID());
	//(pZone->getTile(x, y)).deleteItem();
	//pZone->deleteItem(pTarget, x, y);

	Item* pItem = NULL;

	Tile& tile = pZone->getTile(x,y);

	if (tile.hasItem() )
	{
		pItem = tile.getItem();

		if (pItem != NULL )
		{
			if (pItem->getObjectID() == m_ObjectID )
			{
				pZone->deleteItem(pItem, x, y);

				GCDeleteObject gcDO;
				gcDO.setObjectID(pTarget->getObjectID());
				pZone->broadcastPacket(x, y, &gcDO);

				SAFE_DELETE(pTarget);
			}
		}
	}

	__END_CATCH
}
コード例 #8
0
ファイル: EffectDecayItem.cpp プロジェクト: jun199004/server
//----------------------------------------------------------------------
// remove effect from target
//----------------------------------------------------------------------
void EffectDecayItem::unaffect (Zone* pZone , ZoneCoord_t x , ZoneCoord_t y , Object* pTarget)
	throw(Error)
{
	__BEGIN_TRY

	// 올바른 좌표이어야 한다.
	Assert(isValidZoneCoord(pZone, x, y));

	// TempItem 변수를 잡는다.
	Item* pTempItem = NULL;

	// 여기서는 지정 아이템이 없을 수 있으며, 또 다른 아이템이 놓여 있을 수도 있다.
	// 이 경우는 오리지널 아이템과 지금 현재 바닥에 있는 아이템을 비교하여 삭제해야 한다.
	// 없을 경우는 무시하면 된다.
	Tile & tile = pZone->getTile(x, y);

	if (tile.hasItem()) {

		pTempItem = tile.getItem();

		if (pTempItem != NULL) {
			// ObjectID가 같다는 말은 같은 아이템이란 말이다.
			//if (pTempItem->getObjectID() == m_ObjectID) {
			if (pTempItem->getObjectID() == m_ObjectID) {

				pZone->deleteItem(pTempItem , x, y);

				// 아이템이 사라졌다는 패킷을 날린다.
				GCDeleteObject gcDeleteObject;
				gcDeleteObject.setObjectID(m_ObjectID);

				pZone->broadcastPacket(x, y , &gcDeleteObject);

				if (m_bDeleteFromDB)
				{
					//ItemInfo* pItemInfo = g_pItemInfoManager->getItemInfo(pTempItem->getItemClass(), pTempItem->getItemType());
					//Assert(pItemInfo!=NULL);

					// 유니크 아이템인 경우 개수를 줄인다.
					if (pTempItem->isUnique())
					{
						// create한 아이템이 아닌 경우만 지워준다.
						if (pTempItem->getCreateType()!=Item::CREATE_TYPE_CREATE)
							UniqueItemManager::deleteItem(pTempItem->getItemClass(), pTempItem->getItemType());

						filelog("uniqueItem.txt", "[EffectDecayItem] %s", pTempItem->toString().c_str());
					}

					// ItemTraceLog 를 남긴다
					/*
					 * 존에 떨어진 아이템중 expire time인것들 모두 로그를 빼버린다.
					if (pTempItem != NULL && pTempItem->isTraceItem() )
					{
						char zoneName[15];
						sprintf(zoneName, "%4d%3d%3d", pZone->getZoneID(), x, y);
						remainTraceLog(pTempItem, zoneName, "GOD", ITEM_LOG_DELETE, DETAIL_TIMEOUT);
					}
					*/

					// 돈 로그 남기자
					if (pTempItem->getItemClass() == Item::ITEM_CLASS_MONEY )
					{
						Money* pMoney = dynamic_cast<Money*>(pTempItem);
						if (pMoney->getAmount() >= g_pVariableManager->getMoneyTraceLogLimit() )
						{
							char zoneName[15];
							sprintf(zoneName, "%4d%3d%3d", pZone->getZoneID(), x, y);
							remainMoneyTraceLog(zoneName, "GOD", ITEM_LOG_DELETE, DETAIL_TIMEOUT, pMoney->getAmount());
						}
					}

					pTempItem->destroy();
				}

				SAFE_DELETE(pTempItem);
			}
		}
	}

	pTarget = NULL;

	__END_CATCH
}
コード例 #9
0
//////////////////////////////////////////////////////////////////////////////
//
// 모터 사이클을 처리한다.
//
//////////////////////////////////////////////////////////////////////////////
void CGShopRequestSellHandler::executeMotorcycle (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);

	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);
	int         CenterX = pNPC->getX();
	int         CenterY = pNPC->getY();
	
	// 플레이어가 팔려고 하는 아이템을 가지고 있는지 검사
	Inventory* pInventory  = pPC->getInventory();
	Gold_t     playerMoney = pPC->getGold();
	Item*      pItem       = pInventory->getItemWithObjectID(ITEMOID);
	if (pItem == NULL) return sendFailPacket(pPacket, pPlayer);

	// 주위 일정 범위를 검색해서, 모터 사이클이 있는지 확인한다.
	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.hasItem())
				{
					Item* pItemOnTile = tile.getItem();
					if (pItemOnTile == NULL) continue;

					// 만일 아이템이 타일 위에 있을 경우, 모터 사이클인지 확인한다.
					if (pItemOnTile->getItemClass() == Item::ITEM_CLASS_MOTORCYCLE)
					{
						DWORD    targetID     = dynamic_cast<Key*>(pItem)->getTarget();
						ItemID_t motorcycleID = pItemOnTile->getItemID();

						if (targetID == motorcycleID)
						{
							// 모터사이클을 DB에서 삭제한다.
							pItemOnTile->destroy();

							// 플레이어의 인벤토리에서 열쇠를 제거한다.
							pInventory->deleteItem(ITEMOID);
							pItem->destroy();
							SAFE_DELETE(pItem);
							
							// 열쇠 값이 아니라, 오토바이 값을 줘야 한다.
							Price_t itemPrice = g_pPriceManager->getPrice(pItemOnTile, pNPC->getMarketCondBuy(), SHOP_RACK_NORMAL, pPC);

							// 플레이어의 돈을 늘린다.
							//pPC->setGoldEx(playerMoney+itemPrice);
							// by sigi. 2002.9.4
							pPC->increaseGoldEx(itemPrice);

							// 물건을 판 플레이어에게 GCShopSellOK를...보낸다.
							GCShopSellOK okpkt;
							okpkt.setObjectID(NPCID);
							if (!pItemOnTile->getOptionTypeList().empty()) okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_SPECIAL));
							else                                   okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_NORMAL));
							okpkt.setItemObjectID(ITEMOID);
							okpkt.setPrice(playerMoney+itemPrice);
							pPlayer->sendPacket(&okpkt);

							// 뻑킹 센터에서 박스를 삭제해 준다.
							if (g_pParkingCenter->hasMotorcycleBox(motorcycleID)) 
								g_pParkingCenter->deleteMotorcycleBox(motorcycleID);

							// NPC에게 자리가 충분하다면 플레이어가 판 아이템을 보관한다.
							// 단 스페셜 아이템만을 보관한다. 노말 아이템은 그냥 버림.
							//if (pItemOnTile->getOptionType() != 0)
							//{
							//	index = pNPC->getFirstEmptySlot(SHOP_RACK_SPECIAL);
							//	if (index < SHOP_RACK_INDEX_MAX)
							//	{
							//		pNPC->insertShopItem(SHOP_RACK_SPECIAL, index, pItemOnTile);
							//		// 스페셜 아이템을 NPC가 진열장에 추가했으므로, 상점 버전이 올라간다.
							//		pNPC->increaseShopVersion(SHOP_RACK_SPECIAL);
							//	}
							//}
							//else
							//{
							//	SAFE_DELETE(pItemOnTile);
							//}

							// 모터 사이클을 찾았으므로, 할 일이 끝났다. 
							return;
						}
					}
				}
			} // 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());
	}

	// FOR 루프를 다 돌고, 이까지 왔다는 것은 근처에 오토바이가 없다는 말이당...
	// 그러므로 모터 사이클 팔기가 실패했다는 것을 알린다.
	GCShopSellFail failpkt;
	failpkt.setObjectID(NPCID);
	pPlayer->sendPacket(&failpkt);
	
#endif

	__END_DEBUG_EX __END_CATCH
}
コード例 #10
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
}
コード例 #11
0
void EffectCureCriticalWounds::affect(Creature* pCreature)
	throw(Error)
{
	__BEGIN_TRY

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

	GCSkillToSelfOK1 _GCSkillToSelfOK1;
	GCSkillToSelfOK2 _GCSkillToSelfOK2;

	int X = pCreature->getX();
	int Y = pCreature->getY();
	Exp_t ExpUp = 0;
	bool bCured = false;

	for(int oY = -2; oY <= 2; oY++)
	for(int oX = -2; oX <= 2; oX++)
	{
		int tileX = X+oX;
		int tileY = Y+oY;

		if (isValidZoneCoord(pZone, tileX, tileY))
		{
			Tile& tile = pZone->getTile(tileX, tileY);

			if (tile.hasCreature(Creature::MOVE_MODE_WALKING ) ) 
			{
				const list<Object*>& oList = tile.getObjectList();
				for(list<Object*>::const_iterator itr = oList.begin(); itr != oList.end(); itr++) 
				{
					Object* pTarget = *itr;
					Creature* pTargetCreature = NULL;
					if (pTarget->getObjectClass() == Object::OBJECT_CLASS_CREATURE 
						&& (pTargetCreature = dynamic_cast<Creature*>(pTarget))->isSlayer()) 
					{
						Assert(pTargetCreature != NULL);
						HP_t RemainHP = 0;

						if (pTargetCreature->isSlayer() && !pTargetCreature->isFlag(Effect::EFFECT_CLASS_COMA) ) 
						{
							Slayer* pSlayer = dynamic_cast<Slayer*>(pTargetCreature);
							HP_t CurrentHP = pSlayer->getHP(ATTR_CURRENT);
							HP_t MaxHP = pSlayer->getHP(ATTR_MAX);

							if (pTargetCreature->isFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN))
							{
								ExpUp++;
								Effect* pEffect = pSlayer->findEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN);
								EffectBloodDrain * pEffectBloodDrain = dynamic_cast<EffectBloodDrain*>(pEffect);

								Assert(pEffectBloodDrain != NULL);

								if (pEffectBloodDrain->getLevel() < CriticalBloodDrainLevel ) {

									// 흡혈 아르바이트를 방지하기 위한 후유증 이펙트를 붙여준다.
									if (pSlayer->isFlag(Effect::EFFECT_CLASS_AFTERMATH))
									{
										Effect* pEffect = pSlayer->findEffect(Effect::EFFECT_CLASS_AFTERMATH);
										EffectAftermath* pEffectAftermath = dynamic_cast<EffectAftermath*>(pEffect);
										pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다.
									}
									else
									{
										EffectAftermath* pEffectAftermath = new EffectAftermath(pSlayer);
										pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다.
										pSlayer->addEffect(pEffectAftermath);
										pSlayer->setFlag(Effect::EFFECT_CLASS_AFTERMATH);
										pEffectAftermath->create(pSlayer->getName());
									}

									pEffectBloodDrain->destroy(pSlayer->getName());
									pSlayer->deleteEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN);

									bCured = true;

									SLAYER_RECORD prev;
									pSlayer->getSlayerRecord(prev);
									pSlayer->initAllStat();
									pSlayer->sendRealWearingInfo();
									pSlayer->sendModifyInfo(prev);

									GCRemoveEffect gcRemoveEffect;
									gcRemoveEffect.setObjectID(pSlayer->getObjectID());
									gcRemoveEffect.addEffectList((EffectID_t)Effect::EFFECT_CLASS_BLOOD_DRAIN);
									pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcRemoveEffect);

								}
							}

							if(CurrentHP < MaxHP ) {
								ExpUp++;
								bCured = true;

								RemainHP = min(CurrentHP + m_Point,(int)MaxHP);
								pSlayer->setHP(RemainHP, ATTR_CURRENT);

								GCModifyInformation gcMI;
								gcMI.addShortData(MODIFY_CURRENT_HP, RemainHP);
								pSlayer->getPlayer()->sendPacket(&gcMI);

								_GCSkillToSelfOK1.setSkillType(SKILL_CURE_EFFECT);
								_GCSkillToSelfOK1.setDuration(0);
								pSlayer->getPlayer()->sendPacket(&_GCSkillToSelfOK1);
							
								_GCSkillToSelfOK2.setObjectID(pSlayer->getObjectID());
								_GCSkillToSelfOK2.setSkillType(SKILL_CURE_EFFECT);
								_GCSkillToSelfOK2.setDuration(0);
								pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &_GCSkillToSelfOK2, pTargetCreature);

								Zone* pZone = pTargetCreature->getZone();
								GCStatusCurrentHP gcStatusCurrentHP;
								gcStatusCurrentHP.setObjectID(pTargetCreature->getObjectID());
								gcStatusCurrentHP.setCurrentHP(RemainHP);
								pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &gcStatusCurrentHP);
							}
						} 
					}
				}	
			}
		}	
	}

	SkillInfo * pSkillInfo = g_pSkillInfoManager->getSkillInfo(SKILL_CURE_CRITICAL_WOUNDS);

	if(pSkillInfo != NULL && bCured ) {
		SkillSlot * pSkillSlot = ((Slayer*)pCreature)->hasSkill(SKILL_CURE_CRITICAL_WOUNDS);
		if(pSkillSlot != NULL ) {
			Slayer * pCastSlayer = dynamic_cast<Slayer*>(pCreature);
			GCModifyInformation gcMI;
			SkillDomainType_t DomainType = pSkillInfo->getDomainType();
			// 경험치를 올려준다.
			shareAttrExp(pCastSlayer, ExpUp, 1 , 1 , 8, gcMI);
			increaseDomainExp(pCastSlayer, DomainType, ExpUp, gcMI);
			increaseSkillExp(pCastSlayer, DomainType, pSkillSlot, pSkillInfo, gcMI);
			pCastSlayer->getPlayer()->sendPacket(&gcMI);
		}
	}

	//cout << "EffectCureCriticalWounds " << "affect BEGIN" << endl;
	setNextTime(m_Delay);
	//cout << "EffectCureCriticalWounds " << "affect END" << endl;

	__END_CATCH
}
コード例 #12
0
ファイル: SwordOfThor.cpp プロジェクト: hillwah/darkeden
void SwordOfThor::execute(Slayer * pSlayer, ZoneCoord_t X, ZoneCoord_t Y, SkillSlot * pSkillSlot, CEffectID_t CEffectID)
throw(Error)
{
    __BEGIN_TRY

//	cout << "(x,y)=" << X << "," << Y << endl;

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

    SkillInput input(pSlayer, pSkillSlot);
    SkillOutput output;
    computeOutput(input, output);

    SIMPLE_SKILL_INPUT param;
    param.SkillType     = getSkillType();
    param.SkillDamage   = output.Damage;
    param.Delay         = output.Delay;
    param.ItemClass     = Item::ITEM_CLASS_SWORD;
    param.STRMultiplier = 8;
    param.DEXMultiplier = 1;
    param.INTMultiplier = 1;
    param.bMagicHitRoll = false;
    param.bMagicDamage  = false;
    param.bAdd          = false;
    param.bExpForTotalDamage = false;

    for (int i=-2; i<=2; ++i )
        for (int j=-2; j<=2; ++j )
        {
            param.addMask(i, j, 100);
        }

    SIMPLE_SKILL_OUTPUT result;

    // 목표위치+4방향
    /*	param.addMask(0 + dir_advance[dir][0],  0 + dir_advance[dir][1], 100);
    	param.addMask(-1 + dir_advance[dir][0], -1 + dir_advance[dir][1], 100);
    	param.addMask(0 + dir_advance[dir][0], -1 + dir_advance[dir][1], 100);
    	param.addMask(1 + dir_advance[dir][0], -1 + dir_advance[dir][1], 100);
    	param.addMask(-1 + dir_advance[dir][0],  0 + dir_advance[dir][1], 100);
    	param.addMask(1 + dir_advance[dir][0],  0 + dir_advance[dir][1], 100);
    	param.addMask(-1 + dir_advance[dir][0],  1 + dir_advance[dir][1], 100);
    	param.addMask(0 + dir_advance[dir][0],  1 + dir_advance[dir][1], 100);
    	param.addMask(1 + dir_advance[dir][0],  1 + dir_advance[dir][1], 100);*/

    g_SimpleTileMissileSkill.execute(pSlayer, X, Y, pSkillSlot, param, result);

    if (result.bSuccess )
    {
        for (int i=-2; i<=2; ++i )
            for (int j=-2; j<=2; ++j )
            {
                ZoneCoord_t tx = X+i;
                ZoneCoord_t ty = Y+j;

                if (!isValidZoneCoord(pZone, tx, ty) ) continue;
                Tile& rTile = pZone->getTile(tx, ty);
                if (!rTile.canAddEffect() ) continue;

                EffectSwordOfThor* pEffect = new EffectSwordOfThor(pZone, tx, ty);
                pEffect->setLevel(input.SkillLevel);
                pEffect->setDeadline(output.Duration);
                pZone->registerObject(pEffect);

                if (i != 0 || j != 0 ) pEffect->setBroadcastingEffect(false);
                else
                {
                    GCAddEffectToTile gcAE;
                    gcAE.setEffectID(pEffect->getSendEffectClass());
                    gcAE.setXY(tx, ty);
                    gcAE.setObjectID(pEffect->getObjectID());
                    gcAE.setDuration(output.Duration);
                    pZone->broadcastPacket(tx, ty, &gcAE);

//				cout << tx << ", " << ty << " Effect broadcast" << endl;
                }

                pZone->addEffect(pEffect);
                rTile.addEffect(pEffect);
//			cout << tx << ", " << ty << " add Effect" << endl;
            }
    }

    __END_CATCH
}
コード例 #13
0
//////////////////////////////////////////////////////////////////////////////
// 모터 사이클을 처리한다.
//////////////////////////////////////////////////////////////////////////////
void CGRequestRepairHandler::executeMotorcycle (CGRequestRepair* pPacket , Player* pPlayer)
	 throw(ProtocolException , Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

	// 패킷 정보를 뽑아낸다.
	ObjectID_t      ITEMOID     = pPacket->getObjectID();
	Creature*       pPC         = dynamic_cast<GamePlayer*>(pPlayer)->getCreature();
	Zone*           pZone       = pPC->getZone();
	Gold_t          playerMoney = 0;
	ZoneCoord_t     CenterX     = pPC->getX();
	ZoneCoord_t     CenterY     = pPC->getY();
	Item*           pItem       = NULL;
	bool            bSlayer     = false;
	bool            bVampire    = false;
	bool            bOusters    = false;
	GCNPCResponse   response;
	
	// 플레이어가 슬레이어인지 뱀파이어인지 구분.
	if (pPC->isSlayer())       bSlayer = true;
	else if (pPC->isVampire()) bVampire = true;
	else if (pPC->isOusters()) bOusters = true;
	else throw ProtocolException("CGRequestRepairHandler::execute() : Unknown player creature!");

	// 플레이어가 수리하려고 하는 아이템을 가지고 있는지 
	// 상위에서 검사를 하기 때문에, pItem이 널일리는 없다.
	if (bSlayer)
	{
		pItem       = (dynamic_cast<Slayer*>(pPC))->findItemOID(ITEMOID);
		playerMoney = (dynamic_cast<Slayer*>(pPC))->getGold();
	}
	else if (bVampire)
	{
		pItem       = (dynamic_cast<Vampire*>(pPC))->findItemOID(ITEMOID);
		playerMoney = (dynamic_cast<Vampire*>(pPC))->getGold();
	}
	else if (bOusters)
	{
		pItem       = (dynamic_cast<Ousters*>(pPC))->findItemOID(ITEMOID);
		playerMoney = (dynamic_cast<Ousters*>(pPC))->getGold();
	}

	// 주위 일정 범위를 검색해서, 모터 사이클이 있는지 확인한다.
	for (ZoneCoord_t zx=CenterX-5; zx<=CenterX+5; zx++)
	{
		for (ZoneCoord_t zy=CenterY-5; zy<=CenterY+5; zy++)
		{
			if (!isValidZoneCoord(pZone, zx, zy)) continue;

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

			if (tile.hasItem())
			{
				Item* pItemOnTile = tile.getItem();
				Assert(pItemOnTile != NULL);

				// 만일 아이템이 타일 위에 있을 경우, 모터 사이클인지 확인한다.
				if (pItemOnTile->getItemClass() == Item::ITEM_CLASS_MOTORCYCLE)
				{
					DWORD    targetID     = dynamic_cast<Key*>(pItem)->getTarget();
					ItemID_t motorcycleID = pItemOnTile->getItemID();

					if (targetID == motorcycleID)
					{
						Price_t repairPrice = g_pPriceManager->getRepairPrice(pItemOnTile);

						if (repairPrice > playerMoney)
						{
							response.setCode(NPC_RESPONSE_REPAIR_FAIL_MONEY);
							pPlayer->sendPacket(&response);
							return;
						}

						// 수리한다.
						repairItem(pItemOnTile);

						// 저장한다.
						//pItemOnTile->save(pPC->getName(), STORAGE_ZONE, pZone->getZoneID(), zx, zy);
						// item저장 최적화. by sigi. 2002.5.13
						char pField[80];
						sprintf(pField, "Durability=%d", pItemOnTile->getDurability());
						pItemOnTile->tinysave(pField);


						// 돈을 줄인다.
						//if (bSlayer) (dynamic_cast<Slayer*>(pPC))->setGoldEx(playerMoney-repairPrice);
						//else         (dynamic_cast<Vampire*>(pPC))->setGoldEx(playerMoney-repairPrice);

						// by sigi. 2002.9.4
						(dynamic_cast<PlayerCreature*>(pPC))->decreaseGoldEx(repairPrice);

						response.setCode(NPC_RESPONSE_REPAIR_OK);
						response.setParameter(playerMoney-repairPrice);
						pPlayer->sendPacket(&response);

						return;
					} // if (targetID == 
				} // if (itemclas == MOTORCYCLE
			}
		} // end of for (ZoneCoord_t zy=CenterY-5; zy<=CenterY+5; zy++)
	} // end of for (ZoneCoord_t zx=CenterX-5; zx<=CenterX+5; zx++)

	// FOR 루프를 다 돌고, 이까지 왔다는 것은 근처에 오토바이가 없다는 말이당...
	// 그러므로 모터 사이클 팔기가 실패했다는 것을 알린다.
	response.setCode(NPC_RESPONSE_REPAIR_FAIL_ITEM_NOT_EXIST);
	pPlayer->sendPacket(&response);
	
#endif

	__END_DEBUG_EX __END_CATCH
}