コード例 #1
0
void CGTradeAddItemHandler::executeSlayer (CGTradeAddItem* pPacket , Player* pPlayer)
	 throw(ProtocolException , Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

	// 상위 함수에서 에러를 검사했기 때문에,
	// 여기서는 포인터가 널인지를 검사하지 않는다.
	ObjectID_t   TargetOID   = pPacket->getTargetObjectID();
	ObjectID_t   ItemOID     = pPacket->getItemObjectID();
	GamePlayer*  pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer);
	Creature*    pPC         = pGamePlayer->getCreature();
	Zone*        pZone       = pPC->getZone();
	PlayerCreature*    pTargetPC   = dynamic_cast<PlayerCreature*>(pZone->getCreature(TargetOID));

	// NoSuch제거. by sigi. 2002.5.2
	if (pTargetPC==NULL) return;

	Slayer*      pSender     = dynamic_cast<Slayer*>(pPC);

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

	// 교환 대상에 추가할 아이템의 포인터를 얻어낸다.
	CoordInven_t X, Y;
	Inventory*   pInventory = pSender->getInventory();
	Item*        pItem      = pInventory->findItemOID(ItemOID, X, Y);

	// 추가할 아이템이 없다면 당연히 더 이상 처리가 불가능
	// 추가할 아이템이 Relic이면 추가할 수 없다.
	if (pItem == NULL
	|| !canTrade(pItem ) 
	|| pSender->getStore()->hasItem(pItem)
	|| (pItem->getItemClass() == Item::ITEM_CLASS_SUB_INVENTORY && hasItemWithItemClass(pTargetPC, Item::ITEM_CLASS_SUB_INVENTORY ) )
	)
	{
		pTradeManager->cancelTrade(pPC);
		executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_ADD_ITEM);
		return;
	}

///*
//#ifdef __XMAS_EVENT_CODE__
	// 녹색 선물 상자인 경우에는, 상대방에게 적색 선물 상자가 없는지 검사한 후, 
	// 인증 패킷을 보내줘야 한다.
	if (pItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX)
	{
		PlayerCreature* pReceiver = dynamic_cast<PlayerCreature*>(pTargetPC);
		Item* pExtraSlotItem = pReceiver->getExtraInventorySlotItem();

		// 녹색 선물 상자
		if (pItem->getItemType() == 0)
		{
			// 교환 받을 사람이 이미 녹색 선물 상자를 받은 적이 있는지 체크한다. by sigi. 2002.12.16	
			FlagSet*   pFlagSet    = pReceiver->getFlagSet();
			if (pFlagSet->isOn(FLAGSET_RECEIVE_GREEN_GIFT_BOX)) 
			{
				// 적색 선물 상자는 교환 품목의 대상이 될 수 없다.
				GCTradeVerify gcTradeVerify;
				gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_FAIL);
				pPlayer->sendPacket(&gcTradeVerify);
				return;
			}

			Inventory* pTargetInventory = pReceiver->getInventory();
			if (pTargetInventory->hasRedGiftBox())
			{
				// 적색 선물 상자를 가지고 있다면 더할 수 없다. 리턴시킨다.
				GCTradeVerify gcTradeVerify;
				gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_FAIL);
				pPlayer->sendPacket(&gcTradeVerify);
				return;
			}
			else if (pExtraSlotItem != NULL)
			{
				if (pExtraSlotItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX && pExtraSlotItem->getItemType() == 1)
				{
					GCTradeVerify gcTradeVerify;
					gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_FAIL);
					pPlayer->sendPacket(&gcTradeVerify);
					return;
				}
			}
			else
			{
				// 적색 선물 상자를 가지고 있지 않다면, 걍 넘어간다.
				GCTradeVerify gcTradeVerify;
				gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_OK);
				pPlayer->sendPacket(&gcTradeVerify);
			}
		}
		// 빨간 선물 상자
		else if (pItem->getItemType() == 1)	
		{
			// 적색 선물 상자는 교환 품목의 대상이 될 수 없다.
			GCTradeVerify gcTradeVerify;
			gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_FAIL);
			pPlayer->sendPacket(&gcTradeVerify);
			return;
		}
	}
//#endif
//*/

	TradeInfo* pInfo1 = pTradeManager->getTradeInfo(pSender->getName());
	TradeInfo* pInfo2 = pTradeManager->getTradeInfo(pTargetPC->getName());

	list<Item*>      tradeList1  = pInfo1->getItemList();

	if (pItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX && pItem->getItemType() > 1 && pItem->getItemType() < 6)
	{
		for (list<Item*>::iterator itr = tradeList1.begin(); itr != tradeList1.end(); itr++)
		{
			Item* pTradeItem = (*itr);
			if (pTradeItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX && pTradeItem->getItemType() > 1 && pTradeItem->getItemType() < 6)	
			{
				GCTradeVerify gcTradeVerify;
				gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_FAIL);
				pPlayer->sendPacket(&gcTradeVerify);
				return;
			}
		}

		GCTradeVerify gcTradeVerify;
		gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_OK);
		pPlayer->sendPacket(&gcTradeVerify);
	}
	else if (pItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX && pItem->getItemType() >= 6)
	{
		GCTradeVerify gcTradeVerify;
		gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_OK);
		pPlayer->sendPacket(&gcTradeVerify);
	}


	// TradeManager에 교환 대상으로서 아이템을 더한다.
	//Assert(pInfo1->addItem(pItem));
	pInfo1->addItem(pItem);

	// 현재 OK를 누른 상태라면, 클라이언트에게 인증 패킷을 보내줘야 한다.
	if (pInfo1->getStatus() == TRADE_FINISH)
	{
        //cout << "CGTradeRemoveItem [" << pSender->getName() << "]의 상태가 TRADE_FINISH이므로, 인증 패킷을 보내준다." << endl;

		// 인증 패킷을 날려준다.
		GCTradeVerify gcTradeVerify;
		gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_WHEN_ACCEPT);
		pPlayer->sendPacket(&gcTradeVerify);
	}
    else
    {
		//cout << "CGTradeRemoveItem [" << pSender->getName() << "]의 상태가 TRADE_FINISH가 아니므로, 인증 패킷 날리지 않는다." << endl;
    }

	// 아이템을 더하거나 뺄 경우, 상태가 TRADE_FINISH라면 
	// TRADE_TRADING으로 바꿔줘야 한다.
	pInfo1->setStatus(TRADE_TRADING);
	pInfo2->setStatus(TRADE_TRADING);

	// 상대방에게 날려줄 아이템 정보를 구성한다.
	GCTradeAddItem gcTradeAddItem;
	makeGCTradeAddItemPacket(&gcTradeAddItem, pSender->getObjectID(), pItem, X, Y);

	// 상대방에게 교환할 아이템 정보를 날려준다.
	Player* pTargetPlayer = pTargetPC->getPlayer();
	pTargetPlayer->sendPacket(&gcTradeAddItem);


#endif

	__END_DEBUG_EX __END_CATCH
}
コード例 #2
0
ファイル: CGConnectHandler.cpp プロジェクト: mrktj/darkeden
//////////////////////////////////////////////////////////////////////////////
// CGConnectHandler::execute()
//
// 이 패킷은 로그인서버에서 최초로 게임 서버로 연결할 때, 또는 게임 서버에서
// 다른 게임 서버로 이동할 때, 클라이언트가 서버로 전송하는 최초의 패킷이다.
// 이때 플레이어 객체는 새로 생겨난 상태이고, 이 플레이어 객체는 IPM 에서
// 관리되는 상태이다. 
//
// 당연히 최초의 패킷으로 다른 패킷이 넘어오는 경우라면, 이것은 해킹 시도라고
// 봐도 무방하므로 이 패킷이 최초인지 검사해야 한다. 이를 위해서 플레이어 객체에
// 이전 패킷을 저장하고 있으므로, 이 값이 NULL 인지만 보면 되겠다.
//
// 잘못된 패킷이라면, ban 에 등록하고 접속을 종료한다.
//////////////////////////////////////////////////////////////////////////////
void CGConnectHandler::execute (CGConnect* pPacket , Player* pPlayer)
	 throw(ProtocolException , Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX
	__BEGIN_DEBUG
		
#ifdef __GAME_SERVER__

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

	GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer);

	// set MAC Address
	pGamePlayer->setMacAddress(pPacket->getMacAddress());

	// 이 패킷을 ConnectionInfo 객체를 갖고 온다.
	// 크래커는 키값과 캐릭터 이름을 일정 시간안에 맞춰야만 접속이 가능하다.
	try 
	{
		ConnectionInfo* pConnectionInfo = g_pConnectionInfoManager->getConnectionInfo(pGamePlayer->getSocket()->getHost());

		// 키값을 인증한다.
		if (pPacket->getKey() != pConnectionInfo->getKey())
		{
			FILELOG_INCOMING_CONNECTION("connectionError.log", "Wrong Key: [%s] %s", pConnectionInfo->getPCName().c_str(), pGamePlayer->getSocket()->getHost().c_str());
			throw InvalidProtocolException("invalid key");
		}

		// 이름을 인증한다.
		if (pPacket->getPCName() != pConnectionInfo->getPCName())
		{
			FILELOG_INCOMING_CONNECTION("connectionError.log", "Wrong PCName: [%s] %s", pConnectionInfo->getPCName().c_str(), pGamePlayer->getSocket()->getHost().c_str());
			throw InvalidProtocolException("invalid pc name");
		}

		// 일단 이름을 저장한다. 어차피 다음에 실패하면 객체를 삭제하니까 무방하다.
		pGamePlayer->setID(pConnectionInfo->getPlayerID());

		// CIM의 heartbeat가 실행되기 전에 재수좋게 접속할 가능성이 있다.
		// (타이밍이 좋으면 heartbeat 실행주기*2 안에만 접속하면 된다.)
		// 따라서, 현재 시간과 expire time 을 비교한다.
		Timeval currentTime;
		getCurrentTime(currentTime);
		if (pConnectionInfo->getExpireTime() < currentTime) 
		{
			FILELOG_INCOMING_CONNECTION("connectionError.log", "Expired: [%s] %s", pConnectionInfo->getPCName().c_str(), pGamePlayer->getSocket()->getHost().c_str());

			// 일단 삭제한다.
			g_pConnectionInfoManager->deleteConnectionInfo(pConnectionInfo->getClientIP());
			throw InvalidProtocolException("session already expired");
		}

       	// by sigi. 2002.12.7
		FILELOG_INCOMING_CONNECTION("connectionInfo.log", "Login [%s:%s] %s (%u)",
										pConnectionInfo->getPlayerID().c_str(),
										pConnectionInfo->getPCName().c_str(),
										pConnectionInfo->getClientIP().c_str(),
										pConnectionInfo->getKey());

		// 인증되었으니, ConnectionInfo 를 삭제한다.
		try {
			g_pConnectionInfoManager->deleteConnectionInfo(pConnectionInfo->getClientIP());
		} catch (NoSuchElementException& nsee)
		{
			FILELOG_INCOMING_CONNECTION("connectionInfoDelete.log", "DeleteNoSuch [%s:%s] %s (%u)",
										pConnectionInfo->getPlayerID().c_str(),
										pConnectionInfo->getPCName().c_str(),
										pConnectionInfo->getClientIP().c_str(),
										pConnectionInfo->getKey());
		}
	} 
	catch (NoSuchElementException & nsee) // 그런 IP를 가진 CI 가 없을 경우
	{ 
		FILELOG_INCOMING_CONNECTION("connectionError.log", "NoSuchConnectionInfo: %s", pGamePlayer->getSocket()->getHost().c_str());

		// 흠.. 연결 이후 CGConnect 패킷을 보내는 딜레이가 너무 길 경우
		// session 이 expire 된다. 이럴 경우에도 짜르자!
		// (예를 들어서, 최초 연결에서는 성공했으나 그다음에 디버깅 상태로
		// 들어갈 경우, CGConnect 패킷을 보낼 때쯤에는 expire 된다.)
		GCDisconnect gcDisconnect;
		gcDisconnect.setMessage(nsee.toString());

		pGamePlayer->sendPacket(&gcDisconnect);

		// 이렇게 던지면 상위 IPM::processCommands()에서 disconnect 처리한다.
		throw InvalidProtocolException(nsee.toString().c_str());
	} 
	catch (InvalidProtocolException & ipe) 
	{
		FILELOG_INCOMING_CONNECTION("connectionError.log", "%s: %s", ipe.toString().c_str(), pGamePlayer->getSocket()->getHost().c_str());
		//cout << endl << "+-----------------------+" << endl << "| Level 2 Access Denied |" << endl << "+-----------------------+" << endl << endl;

		GCDisconnect gcDisconnect;
		gcDisconnect.setMessage(ipe.toString());

		pGamePlayer->sendPacket(&gcDisconnect);

		// 이렇게 던지면 상위 IPM::processCommands()에서 disconnect 처리한다.
		throw;
	}

	//----------------------------------------------------------------------
	// 로그인 체크
	//----------------------------------------------------------------------
	Statement* pStmt   = NULL;
	Result*    pResult = NULL;
 
	// 빌링~
	PayType         payType;
	string          payPlayDate;
	uint            payPlayHours;
	uint            payPlayFlag;
	int				billingUserKey = 0;	// by sigi. 2002.11.18
	string          familyPayPlayDate;


	try
	{
		pStmt   = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement();
		pResult = pStmt->executeQuery("SELECT `PlayerID` FROM `Slayer` WHERE `Name` = '%s'",pPacket->getPCName().c_str());

	

		if (pResult->getRowCount() != 1)
		{
			StringStream msg;
			msg << "Failed to load PlayerCreature data from DB. Not 1 PlayerID (" 
				<< pPacket->getPCName().c_str() << ")";

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

			SAFE_DELETE(pStmt);
			throw ProtocolException(msg.toString().c_str());
		}

		if (pResult->next()) 
		{
			string spID = pResult->getString(1);
			if (strcasecmp(spID.c_str(), pGamePlayer->getID().c_str()) != 0) 
			{
				StringStream msg;
				msg << "Failed to load PlayerCreature data from DB. No Character(" 
					<< spID.c_str() << "!="
					<< pGamePlayer->getID().c_str() << ")";

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

				SAFE_DELETE(pStmt);
				throw ProtocolException(msg.toString().c_str());
			}
		}

		SAFE_DELETE(pStmt);

		//pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement();
		pStmt = g_pDatabaseManager->getDistConnection("PLAYER_DB")->createStatement();

#ifdef __THAILAND_SERVER__

		pResult = pStmt->executeQuery("SELECT `PlayerID`, `CurrentServerGroupID`, `LogOn`, `SpecialEventCount`, `PayType`, `PayPlayDate`, `PayPlayHours`, `PayPlayFlag`, `BillingUserKey`, `FamilyPayPlayDate`, `Birthday` FROM `Player` WHERE `PlayerID` = '%s'", pGamePlayer->getID().c_str());

#else

		pResult = pStmt->executeQuery("SELECT `PlayerID`, `CurrentServerGroupID`, `LogOn`, `SpecialEventCount`, `PayType`, `PayPlayDate`, `PayPlayHours`, `PayPlayFlag`, `BillingUserKey`, `FamilyPayPlayDate` FROM `Player` WHERE `PlayerID` = '%s'", pGamePlayer->getID().c_str());

#endif
		if (pResult->getRowCount() != 1)
		{
			StringStream msg;
			msg << "Failed to load PlayerCreature data from DB. No Player(" 
				<< pPacket->getPCName().c_str() << ")";

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

			SAFE_DELETE(pStmt);
			throw ProtocolException(msg.toString().c_str());
		}

		pResult->next();

		int i = 0;

		string          playerID = pResult->getString(++i);
		ServerGroupID_t GID      = pResult->getInt(++i);
		string          logon    = pResult->getString(++i);
		uint            scount	= pResult->getDWORD(++i);

		payType      = (PayType)pResult->getInt(++i);
		payPlayDate  = pResult->getString(++i);
		payPlayHours = pResult->getInt(++i);
		payPlayFlag  = pResult->getInt(++i);
		billingUserKey  	= pResult->getInt(++i);
		familyPayPlayDate	= pResult->getString(++i);

#ifdef __THAILAND_SERVER__
		string Birthday = pResult->getString(++i);
		pGamePlayer->setPermission(isAdultByBirthdayDate(Birthday ));
#endif

		pGamePlayer->setServerGroupID(GID);
		pGamePlayer->setSpecialEventCount(scount);
		pGamePlayer->setBillingUserKey(billingUserKey);

		if (logon != "LOGOFF")
		{
			SAFE_DELETE(pStmt);
			char str[80];
			sprintf(str, "Already connected player ID: %s, %s", playerID.c_str(), logon.c_str());
			throw ProtocolException(str);
		}

		pStmt->executeQuery("UPDATE `Player` SET `LogOn`='GAME' WHERE `PlayerID` = '%s' AND `LogOn`='LOGOFF'", playerID.c_str());

		// LogOn이 LOGOFF가 아니거나.. 등등.. by sigi. 2002.5.15
		if (pStmt->getAffectedRowCount()==0)
		{
			SAFE_DELETE(pStmt);
			char str[80];
			sprintf(str, "Already connected player ID2: %s, %s", playerID.c_str(), logon.c_str());
			throw ProtocolException(str);
		}

		string connectIP = pGamePlayer->getSocket()->getHost();

		// 빌링 by sigi. 2002.5.31
#ifdef __CONNECT_BILLING_SYSTEM__
		if (payType == PAY_TYPE_FREE )
		{
			pGamePlayer->setMetroFreePlayer();
		}
#elif defined(__PAY_SYSTEM_LOGIN__)
		if (pGamePlayer->loginPayPlay(payType, 
										payPlayDate, payPlayHours, payPlayFlag,
										connectIP, playerID))
		{
			sendPayInfo(pGamePlayer);
		}
		else
		{
			SAFE_DELETE(pStmt);
			throw ProtocolException("no pay account");
		}
// by sigi. 2002.11.18. 제한적 무료 사용자. - -; 일단 login
#elif defined(__PAY_SYSTEM_FREE_LIMIT__)
		if (pGamePlayer->loginPayPlay(payType, 
										payPlayDate, payPlayHours, payPlayFlag,
										connectIP, playerID))
		{
			sendPayInfo(pGamePlayer);
		}
#else //defined(__PAY_SYSTEM_ZONE__)
		pGamePlayer->setPayPlayValue(payType, payPlayDate, payPlayHours, payPlayFlag, familyPayPlayDate);
#endif


		SAFE_DELETE(pStmt);
	}
	catch (SQLQueryException & sqe)
	{
		SAFE_DELETE(pStmt);
		throw Error(sqe.toString());
	}

	//----------------------------------------------------------------------
	// 슬레이어 또는 뱀파이어 캐릭터를 로딩한다.
	//----------------------------------------------------------------------
	Slayer*  pSlayer  = NULL;
	Vampire* pVampire = NULL;
	Ousters* pOusters = NULL;

	bool bAlreadyConnected = false;

	//try
	//{
		if (pPacket->getPCType() == PC_SLAYER) 
		{
			pSlayer = new Slayer();
			pSlayer->setName(pPacket->getPCName());
			pSlayer->setPlayer(pGamePlayer);

			if (!pSlayer->load())
			{
				filelog("connectDB_BUG.txt", "Failed to load SLAYER(%s) data from DB", pPacket->getPCName().c_str());

				throw ProtocolException("Failed to load SLAYER data from DB");
			}

			// 유료존에서만 적용되는 아이템 때문에 밑에서 체크
			//pSlayer->loadItem();
			//Assert(pSlayer->getName() == pPacket->getPCName());
			if (pSlayer->getName() != pPacket->getPCName())
			{
				//cout << "Different Name : " << pSlayer->getName().c_str() << ", " << pPacket->getPCName().c_str() << endl;

				Assert(pSlayer->getName() == pPacket->getPCName());
			}

			pGamePlayer->setCreature(pSlayer);

			// Slayer를 TelephoneCenter에 등록한다.
			//g_pTelephoneCenter->addSlayer(pSlayer);
		
			// 주기 회복 이벤트를 플레이어 객체에 추가한다.
			// 이때 기본적으로 10초 회복을 원칙으로 한다.
			// (setDeadline의 파라미터는 0.1 초라는 데 유의할 것)
			EventRegeneration* pEventRegeneration = new EventRegeneration(pGamePlayer);
			pEventRegeneration->setDeadline(10* 10);
			pGamePlayer->addEvent(pEventRegeneration);

			// PCFinder에 추가한다.
			// PCFinder의 삭제는 ~GamePlayer()에서만 한다.
			try {
				g_pPCFinder->addCreature(pSlayer);
			} catch (DuplicatedException& de) {
				bAlreadyConnected = true;
			}

			// 이미 접속중인 경우가 아니라면.. by sigi. 2002.8.29
			if (!bAlreadyConnected)
			{
				// 길드 현재 접속 멤버 리스트에 추가한다.
				if (pSlayer->getGuildID() != 99 )
				{
					Guild* pGuild = g_pGuildManager->getGuild(pSlayer->getGuildID());
					if (pGuild != NULL )
					{
						// sharedserver로 접속을 알리고 DB 도 update 한다.
						try {
							pGuild->addCurrentMember(pSlayer->getName());

							GSGuildMemberLogOn gsGuildMemberLogOn;
							gsGuildMemberLogOn.setGuildID(pGuild->getID());
							gsGuildMemberLogOn.setName(pSlayer->getName());
							gsGuildMemberLogOn.setLogOn(true);
							gsGuildMemberLogOn.setServerID( g_pConfig->getPropertyInt("ServerID"));

							g_pSharedServerManager->sendPacket(&gsGuildMemberLogOn);

							// DB 업데이트
							BEGIN_DB
							{
								pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement();
								pStmt->executeQuery("UPDATE `GuildMember` SET `LogOn` = 1 WHERE `Name` = '%s'", pSlayer->getName().c_str());
							}
							END_DB(pStmt )

						} catch (DuplicatedException& t) {
							// 일단 무시한다. by sigi. 2002.8.29
							filelog("guildBug.log", "%s", t.toString().c_str());
						}
					}
					else
						filelog("GuildMissing.log", "[NoSuchGuild] GuildID : %d, Name : %s\n", (int)pSlayer->getGuildID(), pSlayer->getName().c_str());
				}
コード例 #3
0
void CGTradeMoneyHandler::executeSlayer (CGTradeMoney* pPacket , Player* pPlayer)
	 throw(ProtocolException , Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

	// 상위 함수에서 검사를 했기 때문에,
	// 여기서는 포인터가 널인지를 검사하지 않는다.
	ObjectID_t    TargetOID       = pPacket->getTargetObjectID();
	Gold_t        Amount          = pPacket->getAmount();
	BYTE          Code            = pPacket->getCode();
	GamePlayer*   pGamePlayer     = dynamic_cast<GamePlayer*>(pPlayer);
	Creature*     pPC             = pGamePlayer->getCreature();
	Zone*         pZone           = pPC->getZone();
	Creature*     pTargetPC       = pZone->getCreature(TargetOID); 

	// NoSuch제거. by sigi. 2002.5.2
	if (pTargetPC==NULL) return;

	Slayer*       pSender         = dynamic_cast<Slayer*>(pPC);
	Slayer*       pReceiver       = dynamic_cast<Slayer*>(pTargetPC);
	Player*       pTargetPlayer   = pTargetPC->getPlayer();
	Gold_t        finalAmount     = Amount;
	Gold_t        margin          = 0;
	GCTradeMoney  gcTradeMoney;
	GCTradeVerify gcTradeVerify;

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

	// 교환 상태가 맞는지 체크를 해봐야한다.
	TradeInfo* pInfo1 = pTradeManager->getTradeInfo(pSender->getName());
	TradeInfo* pInfo2 = pTradeManager->getTradeInfo(pReceiver->getName());

	// 인벤토리에서 돈을 덜어, 교환창에다 더한다.
	if (Code == CG_TRADE_MONEY_INCREASE)
	{
		// 교환창에다 더할 액수보다 많은 돈을 가지고 있어야 한다.
		if (pSender->getGold() >= Amount)
		{
			// 돈을 받는 쪽이 맥스를 초과하게 된다면, 일부만 넣어줘야 한다.
			// 현재 교환 예정인 돈도 더해서 계산. by sigi. 2003.1.8
			Gold_t receiverGold = pReceiver->getGold() + pInfo1->getGold();
			if (receiverGold + Amount > MAX_MONEY)
			{
				margin      = receiverGold + Amount - MAX_MONEY;
				finalAmount = finalAmount - margin;
			}

			// 인벤토리에서 돈을 빼고, 교환창에다 더한다.
			pSender->setGold(pSender->getGold() - finalAmount);
			pInfo1->setGold(pInfo1->getGold() + finalAmount);

			// 현재 OK를 누른 상태라면, 클라이언트에게 인증 패킷을 보내줘야 한다.
			if (pInfo1->getStatus() == TRADE_FINISH)
			{
				// 인증 패킷을 날려준다.
				gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_MONEY_INCREASE);
				pPlayer->sendPacket(&gcTradeVerify);
			}

			// 아이템을 더하거나 뺄 경우, 상태를 변환해줘야 한다.
			pInfo1->setStatus(TRADE_TRADING);
			pInfo2->setStatus(TRADE_TRADING);

			// 돈을 올린 당사자에게 실제로 인벤토리에서
			// 빠진 금액이 얼마인지 보내준다.
			gcTradeMoney.setTargetObjectID(TargetOID);
			gcTradeMoney.setCode(GC_TRADE_MONEY_INCREASE_RESULT);
			gcTradeMoney.setAmount(finalAmount);
			pPlayer->sendPacket(&gcTradeMoney);

			// 상대방에게 바뀐 정보를 보내준다.
			gcTradeMoney.setTargetObjectID(pSender->getObjectID());
			gcTradeMoney.setCode(GC_TRADE_MONEY_INCREASE);
			gcTradeMoney.setAmount(finalAmount);
			pTargetPlayer->sendPacket(&gcTradeMoney);
		}
		else 
		{
			pTradeManager->cancelTrade(pPC);
			executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_INCREASE_MONEY);
			return;
		}
	}
	// 교환창에서 돈을 덜어, 인벤토리에다가 더한다.
	else if (Code == CG_TRADE_MONEY_DECREASE)
	{
		// 인벤토리에다 더할 액수보다 교환창에 있는 돈이 많아야 한다.
		if (pInfo1->getGold() >= Amount)
		{
			// 돈이 맥스를 초과하게 된다면, 일부만 뺄 수 있다.
			Gold_t senderGold = pSender->getGold() + pInfo2->getGold();
			if (senderGold + Amount > MAX_MONEY)
			{
				margin      = senderGold + Amount - MAX_MONEY;
				finalAmount = finalAmount - margin;
			}
			
			// 인벤토리에다가 돈을 더하고, 교환창에서 돈을 뺀다.
			pSender->setGold(pSender->getGold() + finalAmount);
			pInfo1->setGold(pInfo1->getGold() - finalAmount);

			// 현재 OK를 누른 상태라면, 클라이언트에게 인증 패킷을 보내줘야 한다.
			if (pInfo1->getStatus() == TRADE_FINISH)
			{
				// 인증 패킷을 날려준다.
				gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_MONEY_DECREASE);
				pPlayer->sendPacket(&gcTradeVerify);
			}

			// 아이템을 더하거나 뺄 경우, 상태를 변환해줘야 한다.
			pInfo1->setStatus(TRADE_TRADING);
			pInfo2->setStatus(TRADE_TRADING);

			// 돈을 올린 당사자에게 실제로 인벤토리에다 
			// 더한 금액이 얼마인지 보내준다.
			gcTradeMoney.setTargetObjectID(TargetOID);
			gcTradeMoney.setCode(GC_TRADE_MONEY_DECREASE_RESULT);
			gcTradeMoney.setAmount(finalAmount);
			pPlayer->sendPacket(&gcTradeMoney);

			// 상대방에게 바뀐 정보를 보내준다.
			gcTradeMoney.setTargetObjectID(pSender->getObjectID());
			gcTradeMoney.setCode(GC_TRADE_MONEY_DECREASE);
			gcTradeMoney.setAmount(finalAmount);
			pTargetPlayer->sendPacket(&gcTradeMoney);
		}
		else
		{
			pTradeManager->cancelTrade(pPC);
			executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_DECREASE_MONEY);
			return;
		}
	}

#endif

	__END_DEBUG_EX __END_CATCH
}
コード例 #4
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
}
コード例 #5
0
ファイル: ActionHeal.cpp プロジェクト: hillwah/darkeden
void ActionHeal::execute (Creature * pCreature1 , Creature * pCreature2) 
	throw(Error)
{
	__BEGIN_TRY

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

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

	// 일단 클라이언트를 위해서 OK 패킷을 함 날린다.
	GCNPCResponse okpkt;
	okpkt.setCode(NPC_RESPONSE_HEAL);
	pPlayer->sendPacket(&okpkt);

	// 죽었거나 코마 걸려있으면 안 치료해준다.
	if (pCreature2->isDead() || pCreature2->isFlag(Effect::EFFECT_CLASS_COMA ) )
	{
		return;
	}

	// 슬레이어라면...
	if (pCreature2->isSlayer())
	{
		Slayer*             pSlayer        = dynamic_cast<Slayer*>(pCreature2);
		EffectManager*      pEffectManager = pSlayer->getEffectManager();
		GCModifyInformation modifyPkt;
		GCRemoveEffect      removePkt;
		GCStatusCurrentHP   hpPkt;

		// 먼저 HP랑 MP를 풀로 채워준다.
		if (pSlayer->getHP(ATTR_CURRENT) < pSlayer->getHP(ATTR_MAX))
		{
			pSlayer->setHP(pSlayer->getHP(ATTR_MAX), ATTR_CURRENT);
			modifyPkt.addShortData(MODIFY_CURRENT_HP, pSlayer->getHP(ATTR_CURRENT));

			hpPkt.setObjectID(pSlayer->getObjectID());
			hpPkt.setCurrentHP(pSlayer->getHP(ATTR_CURRENT));
		}
		if (pSlayer->getMP(ATTR_CURRENT) < pSlayer->getMP(ATTR_MAX))
		{
			pSlayer->setMP(pSlayer->getMP(ATTR_MAX), ATTR_CURRENT);
			modifyPkt.addShortData(MODIFY_CURRENT_MP, pSlayer->getMP(ATTR_CURRENT));
		}

		// 흡혈 이펙트를 삭제한다.
		Effect* pBloodDrainEffect = pEffectManager->findEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN);
		if (pBloodDrainEffect != NULL)
		{
			// DB에서 삭제하고, 이펙트 매니저에서 삭제한다.
			pBloodDrainEffect->destroy(pSlayer->getName());
			pEffectManager->deleteEffect(pSlayer, Effect::EFFECT_CLASS_BLOOD_DRAIN);

			// 흡혈 아르바이트를 방지하기 위한 후유증 이펙트를 붙여준다.
			if (pSlayer->isFlag(Effect::EFFECT_CLASS_AFTERMATH))
			{
				Effect* pEffect = pEffectManager->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분 동안 지속된다.
				pEffectManager->addEffect(pEffectAftermath);
				pSlayer->setFlag(Effect::EFFECT_CLASS_AFTERMATH);
				pEffectAftermath->create(pSlayer->getName());
			}

			// 패킷에다 정보를 더한다.
			removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_BLOOD_DRAIN);

			// 흡혈을 치료하면 능력치가 변화하게 된다.
			SLAYER_RECORD prev;
			pSlayer->getSlayerRecord(prev);
			pSlayer->initAllStat();
			pSlayer->sendModifyInfo(prev);
			pSlayer->sendRealWearingInfo();
		}

		// 독 이펙트를 삭제한다.
		Effect* pEffectPoison = pEffectManager->findEffect(Effect::EFFECT_CLASS_POISON);
		if (pEffectPoison != NULL)
		{
			// 이펙트 매니저에서 삭제한다.
			pEffectManager->deleteEffect(pSlayer, Effect::EFFECT_CLASS_POISON);

			// 패킷에다 정보를 더한다.
			removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_POISON);
		}

		// 다크블루 포이즌 이펙트를 삭제한다.
		Effect* pEffectDarkBluePoison = pEffectManager->findEffect(Effect::EFFECT_CLASS_DARKBLUE_POISON);
		if (pEffectDarkBluePoison != NULL)
		{
			// 이펙트 매니저에서 삭제한다.
			pEffectManager->deleteEffect(pSlayer, Effect::EFFECT_CLASS_DARKBLUE_POISON);

			// 패킷에다 정보를 더한다.
			removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_DARKBLUE_POISON);
		}

		// 패킷 날려준다.
		removePkt.setObjectID(pSlayer->getObjectID());
		pPlayer->sendPacket(&modifyPkt);
		pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &removePkt);
		pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &hpPkt, pSlayer);

		//log(LOG_HEAL, pSlayer->getName(), "");
	}
	else if (pCreature2->isVampire())
	{
		Vampire*            pVampire = dynamic_cast<Vampire*>(pCreature2);
		//EffectManager*      pEffectManager = pVampire->getEffectManager();
		GCModifyInformation modifyPkt;
		GCRemoveEffect      removePkt;
		GCStatusCurrentHP   hpPkt;

		// HP 채워주고...
		if (pVampire->getHP(ATTR_CURRENT) < pVampire->getHP(ATTR_MAX))
		{
			pVampire->setHP(pVampire->getHP(ATTR_MAX), ATTR_CURRENT);
			modifyPkt.addShortData(MODIFY_CURRENT_HP, pVampire->getHP(ATTR_CURRENT));

			hpPkt.setObjectID(pVampire->getObjectID());
			hpPkt.setCurrentHP(pVampire->getHP(ATTR_CURRENT));
		}

		// 패킷 날려준다.
		removePkt.setObjectID(pVampire->getObjectID());
		pPlayer->sendPacket(&modifyPkt);
		pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &removePkt);
		pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &hpPkt, pVampire);

		//log(LOG_HEAL, pVampire->getName(), "");
	}
	else if (pCreature2->isOusters())
	{
		Ousters*             pOusters        = dynamic_cast<Ousters*>(pCreature2);
		EffectManager*      pEffectManager = pOusters->getEffectManager();
		GCModifyInformation modifyPkt;
		GCRemoveEffect      removePkt;
		GCStatusCurrentHP   hpPkt;

		// 먼저 HP랑 MP를 풀로 채워준다.
		if (pOusters->getHP(ATTR_CURRENT) < pOusters->getHP(ATTR_MAX) || pOusters->getSilverDamage() != 0 )
		{
			Silver_t prev = pOusters->getSilverDamage();

			if (prev != 0 )
			{
				pOusters->setSilverDamage(0);
				modifyPkt.addShortData(MODIFY_SILVER_DAMAGE, pOusters->getSilverDamage());
			}

			pOusters->setHP(pOusters->getHP(ATTR_MAX), ATTR_CURRENT);
			modifyPkt.addShortData(MODIFY_CURRENT_HP, pOusters->getHP(ATTR_CURRENT));

			hpPkt.setObjectID(pOusters->getObjectID());
			hpPkt.setCurrentHP(pOusters->getHP(ATTR_CURRENT));
		}
		if (pOusters->getMP(ATTR_CURRENT) < pOusters->getMP(ATTR_MAX))
		{
			pOusters->setMP(pOusters->getMP(ATTR_MAX), ATTR_CURRENT);
			modifyPkt.addShortData(MODIFY_CURRENT_MP, pOusters->getMP(ATTR_CURRENT));
		}

		// 독 이펙트를 삭제한다.
		Effect* pEffectPoison = pEffectManager->findEffect(Effect::EFFECT_CLASS_POISON);
		if (pEffectPoison != NULL)
		{
			// 이펙트 매니저에서 삭제한다.
			pEffectManager->deleteEffect(pOusters, Effect::EFFECT_CLASS_POISON);

			// 패킷에다 정보를 더한다.
			removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_POISON);
		}

		// 다크블루 포이즌 이펙트를 삭제한다.
		Effect* pEffectDarkBluePoison = pEffectManager->findEffect(Effect::EFFECT_CLASS_DARKBLUE_POISON);
		if (pEffectDarkBluePoison != NULL)
		{
			// 이펙트 매니저에서 삭제한다.
			pEffectManager->deleteEffect(pOusters, Effect::EFFECT_CLASS_DARKBLUE_POISON);

			// 패킷에다 정보를 더한다.
			removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_DARKBLUE_POISON);
		}

		// 흡혈 이펙트를 삭제한다.
		Effect* pBloodDrainEffect = pEffectManager->findEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN);
		if (pBloodDrainEffect != NULL)
		{
			pBloodDrainEffect->setDeadline(0);

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

			// 패킷에다 정보를 더한다.
			removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_BLOOD_DRAIN);
		}


		// 패킷 날려준다.
		removePkt.setObjectID(pOusters->getObjectID());
		pPlayer->sendPacket(&modifyPkt);
		pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &removePkt);
		pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &hpPkt, pOusters);

		//log(LOG_HEAL, pOusters->getName(), "");

	}
	__END_CATCH
}
コード例 #6
0
ファイル: Restore2.cpp プロジェクト: jun199004/server
//////////////////////////////////////////////////////////////////////////////
// 슬레이어 오브젝트 핸들러
//////////////////////////////////////////////////////////////////////////////
void Restore::execute(Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl;
	//cout << "Restore2 Start" << endl;

	Assert(pSlayer != NULL);
	Assert(pSkillSlot != NULL);

	try 
	{
		Player* pPlayer = pSlayer->getPlayer();
		Zone* pZone = pSlayer->getZone();
		Assert(pPlayer != NULL);
		Assert(pZone != NULL);

		Creature* pFromCreature = pZone->getCreature(TargetObjectID);

		// 뱀파이어만 건드릴 수가 있다.
		// NoSuch제거. by sigi. 2002.5.2
		if (pFromCreature==NULL
			|| !pFromCreature->isVampire())
		{
			executeSkillFailException(pSlayer, getSkillType());
			//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;
			return;
		}

		GCSkillToObjectOK1 _GCSkillToObjectOK1; // 스킬 쓴 넘에게...
		GCMorph1           _GCMorph1;           // 변신 당사자에게..
		GCMorphSlayer2     _GCMorphSlayer2;     // 변신 구경꾼들에게..

		SkillType_t SkillType  = pSkillSlot->getSkillType();
		SkillInfo*  pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType);

		bool bRangeCheck = verifyDistance(pSlayer, pFromCreature, pSkillInfo->getRange());
		bool bHitRoll    = true;

		if (bRangeCheck && bHitRoll)
		{
			//////////////////////////////////////////////////////////////////////
			// 각종 존 레벨 정보를 삭제해야 한다.
			//////////////////////////////////////////////////////////////////////

			// 파티 초대 중이라면 정보를 삭제해 준다.
			PartyInviteInfoManager* pPIIM = pZone->getPartyInviteInfoManager();
			Assert(pPIIM != NULL);
			pPIIM->cancelInvite(pFromCreature);

			// 파티 관련 정보를 삭제해 준다.
			int PartyID = pFromCreature->getPartyID();
			if (PartyID != 0)
			{
				// 먼저 로컬에서 삭제하고...
				LocalPartyManager* pLPM = pZone->getLocalPartyManager();
				Assert(pLPM != NULL);
				pLPM->deletePartyMember(PartyID, pFromCreature);

				// 글로벌에서도 삭제해 준다.
				deleteAllPartyInfo(pFromCreature);
			}

			// 트레이드 중이었다면 트레이드 관련 정보를 삭제해준다.
			TradeManager* pTM = pZone->getTradeManager();
			Assert(pTM != NULL);
			pTM->cancelTrade(pFromCreature);

			//////////////////////////////////////////////////////////////////////
			//////////////////////////////////////////////////////////////////////

			Slayer*  pNewSlayer = new Slayer;
			Vampire* pVampire   = dynamic_cast<Vampire*>(pFromCreature);

			// DB에서 혹시 남아있을 지 모르는 흡혈 정보를 삭제해준다.
			Statement* pStmt = NULL;
			BEGIN_DB
			{
				pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement();
				StringStream sql;
				sql << "DELETE FROM EffectBloodDrain WHERE OwnerID = '" + pFromCreature->getName() + "'";
				pStmt->executeQuery(sql.toString());
				SAFE_DELETE(pStmt);
			}
			END_DB(pStmt)

			pNewSlayer->setName(pFromCreature->getName());

			// 크리쳐 안의 플레이어 포인터와 플레이어 안의 크리쳐 포인터를 갱신한다.
			Player* pFromPlayer = pFromCreature->getPlayer();
			pNewSlayer->setPlayer(pFromPlayer);
			GamePlayer* pFromGamePlayer = dynamic_cast<GamePlayer*>(pFromPlayer);
			pFromGamePlayer->setCreature(pNewSlayer);

			pNewSlayer->setZone(pZone);
			pNewSlayer->load();
			pNewSlayer->setObjectID(pFromCreature->getObjectID());
			pNewSlayer->setMoveMode(Creature::MOVE_MODE_WALKING);
			
			ZoneCoord_t x    = pFromCreature->getX();
			ZoneCoord_t y    = pFromCreature->getY();
			Dir_t       dir  = pFromCreature->getDir();
			Tile&       tile = pZone->getTile(x, y);

			// 곧 pFromCreature 즉, 원래의 뱀파이어 객체는 지워질 것이므로,
			// PCFinder에 들어가 있는 값은 쓰레기 값이 될 것이다. 
			// 그러므로 뱀파이어 포인터를 지워주고, 새로운 슬레이어 포인터를 더한다.
			g_pPCFinder->deleteCreature(pFromCreature->getName());
			g_pPCFinder->addCreature(pNewSlayer);

			// 길드 현재 접속 멤버 리스트에서 삭제한다.
			if (pVampire->getGuildID() != 0 )
				g_pGuildManager->getGuild(pVampire->getGuildID() )->deleteCurrentMember(pVampire->getName());

			// 인벤토리 교체.
			Inventory* pInventory = pVampire->getInventory();
			pNewSlayer->setInventory(pInventory);
			pVampire->setInventory(NULL);

			// 보관함 교체
			pNewSlayer->deleteStash();
			pNewSlayer->setStash(pVampire->getStash());
			pNewSlayer->setStashNum(pVampire->getStashNum());
			pNewSlayer->setStashStatus(false);
			pVampire->setStash(NULL);

			/*
			// 가비지 교체
			while (true)
			{
				Item* pGarbage = pVampire->popItemFromGarbage();

				// 더 이상 없다면 브레이크...
				if (pGarbage == NULL) break;

				pNewSlayer->addItemToGarbage(pGarbage);
			}
			*/

			// 플래그 셋 교체
			pNewSlayer->deleteFlagSet();
			pNewSlayer->setFlagSet(pVampire->getFlagSet());
			pVampire->setFlagSet(NULL);

			Item* pItem = NULL;
			_TPOINT point;

			// 입고 있는 아이템들을 인벤토리 또는 바닥으로 옮긴다.
			for(int part = 0; part < (int)Vampire::VAMPIRE_WEAR_MAX; part++)
			{
				pItem = pVampire->getWearItem((Vampire::WearPart)part);
				if (pItem != NULL)
				{
					// 먼저 기어에서 삭제하고...
					pVampire->deleteWearItem((Vampire::WearPart)part);
			
					// 인벤토리에 자리가 있으면 인벤토리에 더하고...
					if (pInventory->getEmptySlot(pItem, point))
					{
						pInventory->addItem(point.x, point.y, pItem);
						pItem->save(pNewSlayer->getName(), STORAGE_INVENTORY, 0, point.x, point.y);
					}
					// 자리가 없으면 바닥에 떨어뜨린다.
					else
					{
						ZoneCoord_t ZoneX = pVampire->getX();
						ZoneCoord_t ZoneY = pVampire->getY();

						TPOINT pt;

						pt = pZone->addItem(pItem, ZoneX , ZoneY);

						if (pt.x != -1) 
						{
							pItem->save("", STORAGE_ZONE, pZone->getZoneID(), pt.x, pt.y);
						} 
						else 
						{
							pItem->destroy();
							SAFE_DELETE(pItem);
						}
					}
				}
			}

			pItem = pVampire->getExtraInventorySlotItem();
			if (pItem != NULL)
			{
				pVampire->deleteItemFromExtraInventorySlot();

				// 인벤토리에 자리가 있으면 인벤토리에 더하고...
				if (pInventory->getEmptySlot(pItem, point))
				{
					pInventory->addItem(point.x, point.y, pItem);
					pItem->save(pNewSlayer->getName(), STORAGE_INVENTORY, 0, point.x, point.y);
				}
				// 자리가 없으면 바닥에 떨어뜨린다.
				else
				{
					TPOINT pt;
					ZoneCoord_t ZoneX = pVampire->getX();
					ZoneCoord_t ZoneY = pVampire->getY();

					pt = pZone->addItem(pItem, ZoneX , ZoneY);

					if (pt.x != -1) 
					{
						pItem->save("", STORAGE_ZONE, pZone->getZoneID(), pt.x, pt.y);
					} 
					else 
					{
						pItem->destroy();
						SAFE_DELETE(pItem);
					}
				}
			}

			// 뱀파이어 가지고 있던 돈을 슬레이어로 옮겨준다.
			pNewSlayer->setGoldEx(pVampire->getGold());

			// 스킬 정보를 전송한다.
			pNewSlayer->sendSlayerSkillInfo();

			_GCMorph1.setPCInfo2(pNewSlayer->getSlayerInfo2());
			_GCMorph1.setInventoryInfo(pNewSlayer->getInventoryInfo());
			_GCMorph1.setGearInfo(pNewSlayer->getGearInfo());
			_GCMorph1.setExtraInfo(pNewSlayer->getExtraInfo());

			_GCMorphSlayer2.setSlayerInfo(pNewSlayer->getSlayerInfo3());

			pFromPlayer->sendPacket(&_GCMorph1);
			//pFromGamePlayer->deleteEvent(Event::EVENT_CLASS_REGENERATION);

			pZone->broadcastPacket(x, y, &_GCMorphSlayer2, pNewSlayer);

			// 타일 및 존에서 기존 뱀파이어를 삭제하고, 새로운 슬레이어를 더한다.
			tile.deleteCreature(pFromCreature->getObjectID());
			pZone->deletePC(pFromCreature);

			TPOINT pt = findSuitablePosition(pZone, x, y, Creature::MOVE_MODE_WALKING);
			Tile& newtile = pZone->getTile(pt.x, pt.y);

			newtile.addCreature(pNewSlayer);
			pNewSlayer->setXYDir(pt.x, pt.y, dir);

			pZone->addPC(pNewSlayer);

			pNewSlayer->tinysave("Race='SLAYER'");
			SAFE_DELETE(pFromCreature);

			// 시야 update..
			pZone->updateHiddenScan(pNewSlayer);
		
			_GCSkillToObjectOK1.setSkillType(SkillType);
			_GCSkillToObjectOK1.setCEffectID(CEffectID);
			_GCSkillToObjectOK1.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK1.setDuration(0);

			pPlayer->sendPacket(&_GCSkillToObjectOK1);

			pSkillSlot->setRunTime(0);

			EffectRestore* pEffectRestore = new EffectRestore(pNewSlayer);
			pEffectRestore->setDeadline(60*60*24*7*10); // 7일 
			pNewSlayer->addEffect(pEffectRestore);
			pNewSlayer->setFlag(Effect::EFFECT_CLASS_RESTORE);
			pEffectRestore->create(pNewSlayer->getName());
		}
		else 
		{
			executeSkillFailNormal(pSlayer, getSkillType(), pFromCreature);
		}
	} 
コード例 #7
0
ファイル: EventMorph.cpp プロジェクト: jun199004/server
void EventMorph::activate () 
	throw(Error)
{
	__BEGIN_TRY
	__BEGIN_DEBUG

	Assert(m_pGamePlayer != NULL);

	Creature* pFromCreature = m_pGamePlayer->getCreature();
	Assert(pFromCreature->isSlayer());

	if (m_pGamePlayer->getPlayerStatus() != GPS_NORMAL)
	{
		// 플레이어의 상태가 WAITING_FOR_CG_READY인데, morph가 
		// activate되어 밑의 존에서 크리쳐를 지우는 부분에서 에러가 throw되어
		// 서버가 죽는 버그가 있었다. 정확히 어떻게 해서 CG_READY상태에서
		// 이벤트가 activate되는지는 모르겠으나, GamePlayer의 
		// EventManager 자체를 GPS_NORMAL일 때만 돌아가게 하면,
		// Resurrect가 되지 않으니 주의하길 바란다. 결국 GamePlayer 내부에서
		// 체크를 하기가 곤란하기 때문에 이 부분에서, 처리한다.
		StringStream msg;
		msg << "EventMorph::activate() : GamePlayer의 상태가 GPS_NORMAL이 아닙니다."
			<< "PlayerID[" << m_pGamePlayer->getID() << "]"
			<< "CreatureName[" << pFromCreature->getName() << "]";

		filelog("EventMorphError.log", "%s", msg.toString().c_str());
		return;
	}

	pFromCreature->removeFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN);
	Zone* pZone = pFromCreature->getZone();

	// 만일 Restore 이펙트가 걸려있다면 변신이 되지 않는다.
	if (pFromCreature->isFlag(Effect::EFFECT_CLASS_RESTORE))
	{
		return;
	}

	dropRelicToZone(pFromCreature);
	dropFlagToZone(pFromCreature);
	dropSweeperToZone(pFromCreature);

	//////////////////////////////////////////////////////////////////////
	// 각종 존 레벨 정보를 삭제해야 한다.
	//////////////////////////////////////////////////////////////////////
	
	// 파티 초대 중이라면 정보를 삭제해 준다.
	PartyInviteInfoManager* pPIIM = pZone->getPartyInviteInfoManager();
	Assert(pPIIM != NULL);
	pPIIM->cancelInvite(pFromCreature);

	// 파티 관련 정보를 삭제해 준다.
	uint PartyID = pFromCreature->getPartyID();
	if (PartyID != 0)
	{
		// 먼저 로컬에서 삭제하고...
		LocalPartyManager* pLPM = pZone->getLocalPartyManager();
		Assert(pLPM != NULL);
		pLPM->deletePartyMember(PartyID, pFromCreature);

		// 글로벌에서도 삭제해 준다.
		deleteAllPartyInfo(pFromCreature);
	}

	// 트레이드 중이었다면 트레이드 관련 정보를 삭제해준다.
	TradeManager* pTM = pZone->getTradeManager();
	Assert(pTM != NULL);
	pTM->cancelTrade(pFromCreature);

	//////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////

	Vampire* pVampire = new Vampire();
	
	GCMorph1 gcEventMorph1;	// 변신 당사자에게..
	GCMorphVampire2 gcEventMorphVampire2;	// 변신 구경꾼들에게..
		
	pVampire->setName(pFromCreature->getName());

	ObjectID_t fromObjectID = pFromCreature->getObjectID();
	pVampire->setObjectID(fromObjectID);

	Player* pPlayer = pFromCreature->getPlayer();
	dynamic_cast<GamePlayer*>(pPlayer)->setCreature(pVampire);
	pVampire->setPlayer(pPlayer);
	pVampire->setZone(pZone);
	pVampire->load();

	Coord_t x = pFromCreature->getX(), y = pFromCreature->getY();
	Dir_t dir = pFromCreature->getDir();
	pVampire->setXYDir(x, y, dir);
	pVampire->setMoveMode(pFromCreature->getMoveMode());
	
	// slayer to vampire
	Slayer* pSlayer = dynamic_cast<Slayer*>(pFromCreature);

	// 뱀파이어로 변신할때 Creature Pointer가 달라지므로...
	// 원래 등록 되어있던 포인터는 개가 된다...
	// 따라서 새로운 Creature Pointer를 등록해줘야 한다.
	g_pPCFinder->deleteCreature(pFromCreature->getName());
	g_pPCFinder->addCreature(pVampire);

	// 길드 현재 접속 리스트에서 삭제한다.
	if (pSlayer->getGuildID() != 99 )
	{
		Guild* pGuild = g_pGuildManager->getGuild(pSlayer->getGuildID());
		if (pGuild != NULL )
		{
			pGuild->deleteCurrentMember(pSlayer->getName());

			GSGuildMemberLogOn gsGuildMemberLogOn;
			gsGuildMemberLogOn.setGuildID(pGuild->getID());
			gsGuildMemberLogOn.setName(pSlayer->getName());
			gsGuildMemberLogOn.setLogOn(false);

			g_pSharedServerManager->sendPacket(&gsGuildMemberLogOn);
			
			Statement* pStmt = NULL;
			// 디비에 업데이트 한다.
			BEGIN_DB
			{
				pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement();
				pStmt->executeQuery("UPDATE GuildMember SET LogOn = 0 WHERE Name = '%s'", pSlayer->getName().c_str());
			}
			END_DB(pStmt)
		}
コード例 #8
0
ファイル: SimpleCureSkill.cpp プロジェクト: jun199004/server
void SimpleCureSkill::execute(Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, 
	const SIMPLE_SKILL_INPUT& param, SIMPLE_SKILL_OUTPUT& result,
	CEffectID_t CEffectID) 
	throw(Error)
{
	__BEGIN_TRY

	Assert(pSlayer != NULL);
	Assert(pSkillSlot != NULL);

	try 
	{
		Player* pPlayer = pSlayer->getPlayer();
		Zone* pZone = pSlayer->getZone();
		Assert(pPlayer != NULL);
		Assert(pZone != NULL);

		Creature* pTargetCreature = pZone->getCreature(TargetObjectID);
		//Assert(pTargetCreature != NULL);

		// 슬레이어 외에는 치료할 수가 없다.
		// NoSuch제거. by sigi. 2002.5.2
		if (pTargetCreature==NULL
			|| pTargetCreature->isSlayer() == false)
		{
			executeSkillFailException(pSlayer, param.SkillType);
			return;
		}

		GCSkillToObjectOK1 _GCSkillToObjectOK1;
		GCSkillToObjectOK2 _GCSkillToObjectOK2;
		GCSkillToObjectOK3 _GCSkillToObjectOK3;
		GCSkillToObjectOK4 _GCSkillToObjectOK4;
		GCSkillToObjectOK5 _GCSkillToObjectOK5;

		SkillInfo*        pSkillInfo = g_pSkillInfoManager->getSkillInfo(param.SkillType);
		SkillDomainType_t DomainType = pSkillInfo->getDomainType();

		bool bHPCheck = false;

		// 체력이 닳거나, 흡혈을 당한 상태여야 한다.
		Slayer* pTargetSlayer = dynamic_cast<Slayer*>(pTargetCreature);
		Assert(pTargetSlayer != NULL);

		EffectBloodDrain* pEffectBloodDrain = NULL;

		if (pTargetSlayer->getHP(ATTR_CURRENT) < pTargetSlayer->getHP(ATTR_MAX))
		{
			bHPCheck = true;
		}
		if (pTargetSlayer->isFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN))
		{
			Effect* pEffect = pTargetSlayer->findEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN);
			pEffectBloodDrain = dynamic_cast<EffectBloodDrain*>(pEffect);
			Assert(pEffectBloodDrain != NULL);

			if (pEffectBloodDrain->getLevel() < param.Level) bHPCheck = true;
		}

		int  RequiredMP  = (int)pSkillInfo->getConsumeMP();
		bool bManaCheck  = hasEnoughMana(pSlayer, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pSkillSlot);
		bool bRangeCheck = verifyDistance(pSlayer, pTargetCreature, pSkillInfo->getRange());
		bool bHitRoll    = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot);

		if (bHPCheck && bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && pTargetCreature->isAlive())
		{
			decreaseMana(pSlayer, RequiredMP, _GCSkillToObjectOK1);

			uint HealPoint = param.SkillDamage;

			// 흡혈당한 상태라면 흡혈 상태를 날려준다.
			if (pEffectBloodDrain != NULL && pEffectBloodDrain->getLevel() < param.Level)
			{
				// 흡혈 아르바이트를 방지하기 위한 후유증 이펙트를 붙여준다.
				if (pTargetSlayer->isFlag(Effect::EFFECT_CLASS_AFTERMATH))
				{
					Effect* pEffect = pTargetSlayer->findEffect(Effect::EFFECT_CLASS_AFTERMATH);
					EffectAftermath* pEffectAftermath = dynamic_cast<EffectAftermath*>(pEffect);
					pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다.
				}
				else
				{
					EffectAftermath* pEffectAftermath = new EffectAftermath(pTargetSlayer);
					pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다.
					pTargetSlayer->addEffect(pEffectAftermath);
					pTargetSlayer->setFlag(Effect::EFFECT_CLASS_AFTERMATH);
					pEffectAftermath->create(pTargetSlayer->getName());
				}


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

				SLAYER_RECORD prev;
				pTargetSlayer->getSlayerRecord(prev);
				pTargetSlayer->initAllStat();
				pTargetSlayer->sendRealWearingInfo();
				pTargetSlayer->addModifyInfo(prev, _GCSkillToObjectOK2);

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

			// 다른 사람을 치료한다.
			HP_t CurrentHP = pTargetSlayer->getHP(ATTR_CURRENT);
			HP_t MaxHP     = pTargetSlayer->getHP(ATTR_MAX);

			// 실제 회복 수치를 계산한다.
			int RealHealPoint = 0;
			if(CurrentHP + HealPoint <= MaxHP ) {
				RealHealPoint = max((unsigned int)0, HealPoint);
			} else {
				RealHealPoint = max(0, MaxHP - CurrentHP);
			}

			// 경험치를 올려준다.
			shareAttrExp(pSlayer, HealPoint , param.STRMultiplier, param.DEXMultiplier, param.INTMultiplier, _GCSkillToObjectOK1);
			increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToObjectOK1);
			increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToObjectOK1);

			CurrentHP = min((int)(MaxHP), (int)(CurrentHP + HealPoint));
			pTargetSlayer->setHP(CurrentHP, ATTR_CURRENT);
		
			// 치료가 되었으니 HP를 브로드캐스팅한다.
			GCStatusCurrentHP gcStatusCurrentHP;
			gcStatusCurrentHP.setObjectID(TargetObjectID);
			gcStatusCurrentHP.setCurrentHP (CurrentHP);
			pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &gcStatusCurrentHP);

			_GCSkillToObjectOK2.addShortData(MODIFY_CURRENT_HP, CurrentHP);
			
			ZoneCoord_t myX     = pSlayer->getX();
			ZoneCoord_t myY     = pSlayer->getY();
			ZoneCoord_t targetX = pTargetCreature->getX();
			ZoneCoord_t targetY = pTargetCreature->getY();

			_GCSkillToObjectOK1.setSkillType(param.SkillType);
			_GCSkillToObjectOK1.setCEffectID(CEffectID);
			_GCSkillToObjectOK1.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK1.setDuration(0);

			_GCSkillToObjectOK2.setObjectID(pSlayer->getObjectID());
			_GCSkillToObjectOK2.setSkillType(param.SkillType);
			_GCSkillToObjectOK2.setDuration (0);

			_GCSkillToObjectOK3.setObjectID(pSlayer->getObjectID());
			_GCSkillToObjectOK3.setSkillType(param.SkillType);
			_GCSkillToObjectOK3.setTargetXY(targetX, targetY);

			_GCSkillToObjectOK4.setSkillType(param.SkillType);
			_GCSkillToObjectOK4.setTargetObjectID(TargetObjectID);
			
			_GCSkillToObjectOK5.setObjectID(pSlayer->getObjectID());
			_GCSkillToObjectOK5.setSkillType(param.SkillType);
			_GCSkillToObjectOK5.setTargetObjectID (TargetObjectID);
			_GCSkillToObjectOK5.setDuration (0);

			pPlayer->sendPacket(&_GCSkillToObjectOK1);

			if (pTargetCreature->isPC()) 
			{
				Player* pTargetPlayer = pTargetCreature->getPlayer();
				Assert(pTargetPlayer != NULL);
				pTargetPlayer->sendPacket(&_GCSkillToObjectOK2);
			}
			
			list<Creature*> cList;
			cList.push_back(pSlayer);
			cList.push_back(pTargetCreature);

			cList = pZone->broadcastSkillPacket(myX, myY, targetX, targetY, &_GCSkillToObjectOK5, cList);

			pZone->broadcastPacket(myX, myY,  &_GCSkillToObjectOK3 , cList);
			pZone->broadcastPacket(targetX, targetY,  &_GCSkillToObjectOK4 , cList);
			
			pSkillSlot->setRunTime(param.Delay);

			result.bSuccess = true;
		} 
		else 
		{
			executeSkillFailNormal(pSlayer, param.SkillType, pTargetCreature);
		}
	} 
	catch(Throwable & t)  
	{
		executeSkillFailException(pSlayer, param.SkillType);
	}

	__END_CATCH
}