void giveMemberReward(PlayerCreature* pPC, uint type )
{
    Exp_t exp = ExpRewardTable[pPC->getRace()][pPC->getLevel()];
    Gold_t gold = GoldRewardTable[pPC->getRace()][type];

    pPC->increaseGoldEx(gold);
    GCModifyInformation gcMI;
    gcMI.addLongData(MODIFY_GOLD, pPC->getGold());

    if (pPC->isSlayer() )
    {
        Slayer* pSlayer = dynamic_cast<Slayer*>(pPC);
        increaseDomainExp(pSlayer, pSlayer->getHighestSkillDomain(), exp, gcMI);
        pSlayer->getPlayer()->sendPacket(&gcMI);
    }
    else if (pPC->isVampire() )
    {
        Vampire* pVampire = dynamic_cast<Vampire*>(pPC);
        increaseVampExp(pVampire, exp, gcMI);
        pVampire->getPlayer()->sendPacket(&gcMI);
    }
    else if (pPC->isOusters() )
    {
        GCModifyInformation gcMI;
        Ousters* pOusters = dynamic_cast<Ousters*>(pPC);
        increaseOustersExp(pOusters, exp, gcMI);
    }
}
예제 #2
0
void CGSelectWayPointHandler::execute(CGSelectWayPoint* pPacket , Player* pPlayer) throw(Error) {
	__BEGIN_TRY __BEGIN_DEBUG_EX

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

	static map<Level_t,Price_t> sPriceMap;

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

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

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

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

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

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

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

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

			if (!canEnterBeginnerZone(pCreature)) return;

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

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

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

					pGamePlayer->sendPacket(&gcSystemMessage);

					return;
				}
			}
#endif

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

					pGamePlayer->sendPacket (&gcSystemMessage);

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

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

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

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

		bool bCancel = false;

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

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

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

					//return;
				}

				try {

					if (!bCancel) {

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

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

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

								pGamePlayer->sendPacket (&gcSystemMessage);

								bCancel = true;
							}
						}
#endif

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

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

								GCNoticeEvent gcNoticeEvent;

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

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

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

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

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

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

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

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

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

#endif	// __GAME_SERVER__
		
	__END_DEBUG_EX __END_CATCH
}
예제 #3
0
void EffectAlignmentRecovery::affect(Creature* pCreature)
	throw(Error)
{
	__BEGIN_TRY

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

	Timeval CurrentTime;
	getCurrentTime(CurrentTime);

	GCModifyInformation gcModifyInformation;

	Alignment_t CurrentAlignment = 0;
	Alignment_t NewAlignment = 0;

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

		if (m_Period != 0) 
		{
			// 플레그 걸귀
			pSlayer->setFlag(Effect::EFFECT_CLASS_ALIGNMENT_RECOVERY);

			// 한 턴에 얼마나 회복 시킬 것인가.
			CurrentAlignment = pSlayer->getAlignment();
			NewAlignment     = min(10000, (int)(CurrentAlignment + m_AlignmentQuantity));

			pSlayer->setAlignment(NewAlignment);

			gcModifyInformation.addLongData(MODIFY_ALIGNMENT, NewAlignment);
			pSlayer->getPlayer()->sendPacket(&gcModifyInformation);

			WORD AlignmentSaveCount = pSlayer->getAlignmentSaveCount();
			if (AlignmentSaveCount > ALIGNMENT_SAVE_PERIOD)
			{
				StringStream msg;
				msg << "Alignment = " << NewAlignment;
				pSlayer->tinysave(msg.toString());
				AlignmentSaveCount = 0;
			}
			else AlignmentSaveCount++;
			pSlayer->setAlignmentSaveCount(AlignmentSaveCount);
		} 
		else 
		{
			// unaffect하면서 패킷이 날아갈 테니까....
			setDeadline(0);
		}

		m_Period--;
	}
	else if (pCreature->isVampire())
	{

		Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);
		Assert(pVampire != NULL);

		if (m_Period != 0) 
		{
			// 플레그 걸귀
			pVampire->setFlag(Effect::EFFECT_CLASS_ALIGNMENT_RECOVERY);

			// 한 턴에 얼마나 회복 시킬 것인가.
			CurrentAlignment = pVampire->getAlignment();
			NewAlignment     = min(10000, CurrentAlignment + m_AlignmentQuantity);

			pVampire->setAlignment(NewAlignment);

			gcModifyInformation.addLongData(MODIFY_ALIGNMENT, NewAlignment);
			pVampire->getPlayer()->sendPacket(&gcModifyInformation);

			WORD AlignmentSaveCount = pVampire->getAlignmentSaveCount();
			if (AlignmentSaveCount > ALIGNMENT_SAVE_PERIOD)
			{
				StringStream msg;
				msg << "Alignment = " << NewAlignment;
				pVampire->tinysave(msg.toString());
				AlignmentSaveCount = 0;
			}
			else AlignmentSaveCount++;
			pVampire->setAlignmentSaveCount(AlignmentSaveCount);
		} 
		else
		{
			// unaffect하면서 패킷이 날아갈 테니까....
			setDeadline(0);
		}

		m_Period--;
	}
	else if (pCreature->isOusters())
	{

		Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);
		Assert(pOusters != NULL);

		if (m_Period != 0) 
		{
			// 플레그 걸귀
			pOusters->setFlag(Effect::EFFECT_CLASS_ALIGNMENT_RECOVERY);

			// 한 턴에 얼마나 회복 시킬 것인가.
			CurrentAlignment = pOusters->getAlignment();
			NewAlignment     = min(10000, CurrentAlignment + m_AlignmentQuantity);

			pOusters->setAlignment(NewAlignment);

			gcModifyInformation.addLongData(MODIFY_ALIGNMENT, NewAlignment);
			pOusters->getPlayer()->sendPacket(&gcModifyInformation);

			WORD AlignmentSaveCount = pOusters->getAlignmentSaveCount();
			if (AlignmentSaveCount > ALIGNMENT_SAVE_PERIOD)
			{
				StringStream msg;
				msg << "Alignment = " << NewAlignment;
				pOusters->tinysave(msg.toString());
				AlignmentSaveCount = 0;
			}
			else AlignmentSaveCount++;
			pOusters->setAlignmentSaveCount(AlignmentSaveCount);
		} 
		else
		{
			// unaffect하면서 패킷이 날아갈 테니까....
			setDeadline(0);
		}

		m_Period--;
	}
	else
	{
		return;	// 큰 의미는 없지만..
	}

	// 성향 단계가 바뀌면 다른 사람들에게도 알려줘야 한다.  by sigi. 2002.12.28

	Alignment beforeAlignment = g_pAlignmentManager->getAlignmentType(CurrentAlignment);
	Alignment afterAlignment = g_pAlignmentManager->getAlignmentType(NewAlignment);

	if (beforeAlignment!=afterAlignment)
	{
		GCOtherModifyInfo gcOtherModifyInfo;
		gcOtherModifyInfo.setObjectID(pCreature->getObjectID());
		gcOtherModifyInfo.addShortData(MODIFY_ALIGNMENT, NewAlignment);

		Zone* pZone = pCreature->getZone();	// 2003.1.10
		Assert(pZone!=NULL);
		
		pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcOtherModifyInfo, pCreature);
	}

	__END_CATCH
}
예제 #4
0
void EffectDecreaseHP::unaffect(Creature* pCreature)
	throw(Error)
{
	__BEGIN_TRY
	__BEGIN_DEBUG

	Assert(pCreature != NULL);

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

	pCreature->removeFlag(Effect::EFFECT_CLASS_DECREASE_HP);

	Damage_t decreaseHP = m_Point;

	if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE)
		&& !pCreature->isDead()
		&& !pCreature->isFlag(Effect::EFFECT_CLASS_COMA)
		// 무적상태 체크. by sigi. 2002.9.5
		&& canAttack(NULL, pCreature )
	   )
	{
		if (pCreature->isSlayer())
		{
			Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature);

			HP_t CurrentHP = pSlayer->getHP(ATTR_CURRENT);

			if (CurrentHP > 0)
			{
				HP_t RemainHP  = max(0, CurrentHP -(int)decreaseHP);

				pSlayer->setHP(RemainHP, ATTR_CURRENT);

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

				// 변한 HP를 브로드캐스팅해준다.
				GCStatusCurrentHP pkt;
				pkt.setObjectID(pSlayer->getObjectID());
				pkt.setCurrentHP(RemainHP);
				pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &pkt);
			}
		}
		else if (pCreature->isVampire())
		{
			Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);

			HP_t CurrentHP = pVampire->getHP(ATTR_CURRENT);

			if (CurrentHP > 0)
			{
				HP_t RemainHP  = max(0, CurrentHP -(int)decreaseHP);

				pVampire->setHP(RemainHP, ATTR_CURRENT);

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

				// 공격(흡혈) 당하는 경우에는 공격자의 성향이 바뀜 by sigi. 2002.12.27
				Creature* pAttacker = pZone->getCreature(m_UserObjectID);
				if (pAttacker!=NULL && pAttacker->isVampire())
				{
					Vampire* pAttackVampire = dynamic_cast<Vampire*>(pAttacker);

					GCModifyInformation gcAttackerMI;
					computeAlignmentChange(pVampire, decreaseHP, pAttackVampire, NULL, &gcAttackerMI);

					// 뭔가 변한 정보가 있다면 보내준다.
					if (gcAttackerMI.getShortCount()+gcAttackerMI.getLongCount() > 0)
					{
						pAttackVampire->getPlayer()->sendPacket(&gcAttackerMI);
					}
				}

				// 변한 HP를 브로드캐스팅해준다.
				GCStatusCurrentHP pkt;
				pkt.setObjectID(pVampire->getObjectID());
				pkt.setCurrentHP(RemainHP);
				pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &pkt);
			}
		}
		else if (pCreature->isOusters())
		{
			Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);

			HP_t CurrentHP = pOusters->getHP(ATTR_CURRENT);

			if (CurrentHP > 0)
			{
				HP_t RemainHP  = max(0, CurrentHP -(int)decreaseHP);

				pOusters->setHP(RemainHP, ATTR_CURRENT);

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

				// 공격(흡혈) 당하는 경우에는 공격자의 성향이 바뀜 by sigi. 2002.12.27
				Creature* pAttacker = pZone->getCreature(m_UserObjectID);
				if (pAttacker!=NULL && pAttacker->isOusters())
				{
					Ousters* pAttackOusters = dynamic_cast<Ousters*>(pAttacker);

					GCModifyInformation gcAttackerMI;
					computeAlignmentChange(pOusters, decreaseHP, pAttackOusters, NULL, &gcAttackerMI);

					// 뭔가 변한 정보가 있다면 보내준다.
					if (gcAttackerMI.getShortCount()+gcAttackerMI.getLongCount() > 0)
					{
						pAttackOusters->getPlayer()->sendPacket(&gcAttackerMI);
					}
				}

				// 변한 HP를 브로드캐스팅해준다.
				GCStatusCurrentHP pkt;
				pkt.setObjectID(pOusters->getObjectID());
				pkt.setCurrentHP(RemainHP);
				pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &pkt);
			}
		}
		else if (pCreature->isMonster())
		{
			Monster* pMonster = dynamic_cast<Monster*>(pCreature);

			HP_t CurrentHP = pMonster->getHP(ATTR_CURRENT);

			if (CurrentHP > 0)
			{
				HP_t RemainHP  = max(0, CurrentHP -(int)decreaseHP);

				pMonster->setHP(RemainHP, ATTR_CURRENT);

				// 변한 HP를 브로드캐스팅해준다.
				GCStatusCurrentHP pkt;
				pkt.setObjectID(pMonster->getObjectID());
				pkt.setCurrentHP(RemainHP);
				pZone->broadcastPacket(pMonster->getX(), pMonster->getY(), &pkt);

				if (RemainHP == 0 )
				{
					Creature* pAttacker = pZone->getCreature(m_UserObjectID);
					if (pAttacker != NULL && pAttacker->isVampire() )
					{
						Vampire* pAttackVampire = dynamic_cast<Vampire*>(pAttacker);

						GCModifyInformation gcMI;
						increaseAlignment(pAttackVampire, pCreature, gcMI);

						if (gcMI.getShortCount() > 0 || gcMI.getLongCount() > 0 )
							pAttackVampire->getPlayer()->sendPacket(&gcMI);
					}
				}
			}
		}


		// m_CasterName이 pCreature를 죽인 경우의 KillCount 처리
		// by sigi. 2002.9.9
		if (pCreature->isDead())
		{
			Creature* pAttacker = pZone->getCreature(m_UserObjectID);

			if (pAttacker!=NULL)
			{ 
				if (pAttacker->isVampire())
				{
					Vampire* pVampire = dynamic_cast<Vampire*>(pAttacker);
					// 죽일때 경험치를 준다.
					GCModifyInformation mi;

					int exp = computeCreatureExp(pCreature, KILL_EXP);
					shareVampExp(pVampire, exp, mi);

					if (pCreature->isMonster() )
					{
						increaseFame(pVampire, decreaseHP);
						mi.addLongData(MODIFY_FAME, pVampire->getFame());
					}

					pAttacker->getPlayer()->sendPacket(&mi);
				}
				else if (pAttacker->isOusters() )
				{
					Ousters* pOusters = dynamic_cast<Ousters*>(pAttacker);
					GCModifyInformation mi;
					int exp = computeCreatureExp(pCreature, 100);
					shareOustersExp(pOusters, exp, mi);

					if (pCreature->isMonster() )
					{
						increaseFame(pOusters, decreaseHP);
						mi.addLongData(MODIFY_FAME, pOusters->getFame());
					}
				}

				affectKillCount(pAttacker, pCreature);
			}
		}
	}

	__END_DEBUG
	__END_CATCH
}
예제 #5
0
void EffectAlignmentRecovery::unaffect(Creature* pCreature)
	throw(Error)
{
	__BEGIN_TRY

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

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

		if (m_Period != 0) 
		{
			// 한 턴에 얼마나 회복 시킬 것인가.
			Alignment_t CurrentAlignment = pSlayer->getAlignment();
			Alignment_t NewAlignment     = min(10000, (int)(CurrentAlignment + m_AlignmentQuantity* m_Period));

			pSlayer->setAlignment(NewAlignment);

			WORD AlignmentSaveCount = pSlayer->getAlignmentSaveCount();
			if (AlignmentSaveCount == 10)
			{
				StringStream msg;
				msg << "Alignment = " << NewAlignment;
				pSlayer->tinysave(msg.toString());

				AlignmentSaveCount = 0;
			}
			else AlignmentSaveCount++;
			pSlayer->setAlignmentSaveCount(AlignmentSaveCount);
		} 

		// 현재 Alignment를 브로드캐스팅한다.
		// 이제 회복이 끝났나는 것을 알리도록 한다.
		// 자신에게 먼저
		GCModifyInformation gcModifyInformation;
		gcModifyInformation.addLongData(MODIFY_ALIGNMENT, pSlayer->getAlignment());
		pSlayer->getPlayer()->sendPacket(&gcModifyInformation);

		// 주변사람에게도 무언가를 날려줘야 한다.
		// 패킷을 새로 만들어야겠지..
		pSlayer->removeFlag(Effect::EFFECT_CLASS_ALIGNMENT_RECOVERY);
	}
	else if (pCreature->isVampire())
	{
		Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);

		//Zone* pZone = pVampire->getZone();

		if (m_Period != 0) 
		{
			// 한 턴에 얼마나 회복 시킬 것인가.
			Alignment_t CurrentAlignment = pVampire->getAlignment();
			Alignment_t NewAlignment     = min(10000, (int)(CurrentAlignment + m_AlignmentQuantity* m_Period));

			WORD AlignmentSaveCount = pVampire->getAlignmentSaveCount();
			if (AlignmentSaveCount == 10)
			{
				StringStream msg;
				msg << "Alignment = " << NewAlignment;
				pVampire->tinysave(msg.toString());

				AlignmentSaveCount = 0;
			}
			else AlignmentSaveCount++;
			pVampire->setAlignmentSaveCount(AlignmentSaveCount);
		} 

		// 현재 Alignment를 브로드캐스팅한다.
		// 이제 회복이 끝났나는 것을 알리도록 한다.
		// 자신에게 먼저
		GCModifyInformation gcModifyInformation;
		gcModifyInformation.addLongData(MODIFY_ALIGNMENT, pVampire->getAlignment());
		pVampire->getPlayer()->sendPacket(&gcModifyInformation);

		// 주변사람에게도..
		pVampire->removeFlag(Effect::EFFECT_CLASS_ALIGNMENT_RECOVERY);
	}
	else if (pCreature->isOusters())
	{
		Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);

		//Zone* pZone = pOusters->getZone();

		if (m_Period != 0) 
		{
			// 한 턴에 얼마나 회복 시킬 것인가.
			Alignment_t CurrentAlignment = pOusters->getAlignment();
			Alignment_t NewAlignment     = min(10000, (int)(CurrentAlignment + m_AlignmentQuantity* m_Period));

			WORD AlignmentSaveCount = pOusters->getAlignmentSaveCount();
			if (AlignmentSaveCount == 10)
			{
				StringStream msg;
				msg << "Alignment = " << NewAlignment;
				pOusters->tinysave(msg.toString());

				AlignmentSaveCount = 0;
			}
			else AlignmentSaveCount++;
			pOusters->setAlignmentSaveCount(AlignmentSaveCount);
		} 

		// 현재 Alignment를 브로드캐스팅한다.
		// 이제 회복이 끝났나는 것을 알리도록 한다.
		// 자신에게 먼저
		GCModifyInformation gcModifyInformation;
		gcModifyInformation.addLongData(MODIFY_ALIGNMENT, pOusters->getAlignment());
		pOusters->getPlayer()->sendPacket(&gcModifyInformation);

		// 주변사람에게도..
		pOusters->removeFlag(Effect::EFFECT_CLASS_ALIGNMENT_RECOVERY);
	}

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

#ifndef __OLD_GUILD_WAR__

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

	SYSTEM_RETURN_IF_NOT(SYSTEM_GUILD_WAR);

	GCNPCResponse gcNPCResponse;

	PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2);
	GuildID_t guildID = pPC->getGuildID();

	if (!g_pVariableManager->isWarActive() || !g_pVariableManager->isActiveGuildWar() )
	{
		gcNPCResponse.setCode(NPC_RESPONSE_WAR_UNAVAILABLE);
		pPC->getPlayer()->sendPacket(&gcNPCResponse);
		return;
	}

	if (!g_pGuildManager->isGuildMaster(guildID, pPC ) )
	{
		gcNPCResponse.setCode(NPC_RESPONSE_NOT_GUILD_MASTER);
		pPC->getPlayer()->sendPacket(&gcNPCResponse);
		return;
	}

	Gold_t warRegistrationFee = g_pVariableManager->getVariable(WAR_REGISTRATION_FEE);
	if (pPC->getGold() < warRegistrationFee )
	{
		gcNPCResponse.setCode(NPC_RESPONSE_NOT_ENOUGH_MONEY);
		pPC->getPlayer()->sendPacket(&gcNPCResponse);
		return;
	}

	Zone* pZone = getZoneByZoneID(m_ZoneID);
	Assert(pZone != NULL);
	Assert(pZone->isCastle());

	WarScheduler* pWarScheduler = pZone->getWarScheduler();
	Assert(pWarScheduler != NULL);

	/* 성을 소유했어도 전쟁 신청이 되도록 수정함 (자기 성에는 신청 못하겠지 -_-;;)
	// 이미 성을 소유한 길드인가?
	if (g_pGuildManager->hasCastle(guildID ) )
	{
		gcNPCResponse.setCode(NPC_RESPONSE_ALREADY_HAS_CASTLE);
		pPC->getPlayer()->sendPacket(&gcNPCResponse);
		return;
	}
	*/

//	ServerID_t serverID;
//	ZoneID_t zoneID;
//	bool bHasCastle = g_pGuildManager->hasCastle(guildID , serverID , zoneID);

//	if (bHasCastle && serverID == g_pConfig->getPropertyInt("ServerID" ) && zoneID == m_ZoneID )

	CastleInfo* pCastleInfo = g_pCastleInfoManager->getCastleInfo(m_ZoneID);
	GuildID_t ownerGuildID = pCastleInfo->getGuildID();

	if (guildID == ownerGuildID )
	{
		gcNPCResponse.setCode(NPC_RESPONSE_ALREADY_HAS_CASTLE);
		pPC->getPlayer()->sendPacket(&gcNPCResponse);
		return;
	}

	// 이미 전쟁 신청을 했는가?
	if (g_pGuildManager->hasWarSchedule(guildID ) )
	{
		gcNPCResponse.setCode(NPC_RESPONSE_WAR_ALREADY_REGISTERED);
		pPC->getPlayer()->sendPacket(&gcNPCResponse);
		return;
	}

	// 전쟁 스케쥴이 다 찼는가?
/*	if (!pWarScheduler->canAddWar(WAR_GUILD ) )
	{
		gcNPCResponse.setCode(NPC_RESPONSE_WAR_SCHEDULE_FULL);
		pPC->getPlayer()->sendPacket(&gcNPCResponse);
		return;
	}

	GuildWar* pWar = new GuildWar(m_ZoneID, guildID, War::WAR_STATE_WAIT);

	pWar->setRegistrationFee(warRegistrationFee);

	if (!pWarScheduler->addWar(pWar ) )
	{
		gcNPCResponse.setCode(NPC_RESPONSE_WAR_SCHEDULE_FULL);
		pPC->getPlayer()->sendPacket(&gcNPCResponse);

		SAFE_DELETE(pWar);
		return;
	}*/

	Schedule* pNextSchedule = pWarScheduler->getRecentSchedule();

	Work* pNextWork = NULL;
	if (pNextSchedule != NULL ) pNextWork = pNextSchedule->getWork();

	SiegeWar* pNextWar = dynamic_cast<SiegeWar*>(pNextWork);

	if (pNextWar == NULL )
	{
		pNextWar = new SiegeWar(m_ZoneID, War::WAR_STATE_WAIT);
		pNextWar->addRegistrationFee(warRegistrationFee);
		pNextWar->addChallengerGuild(guildID);

		if (!pWarScheduler->addWar(pNextWar ) )
		{
			gcNPCResponse.setCode(NPC_RESPONSE_WAR_SCHEDULE_FULL);
			pPC->getPlayer()->sendPacket(&gcNPCResponse);

			SAFE_DELETE(pNextWar);
			return;
		}
	}
	else if (pNextWar->getChallengerGuildCount() < 5 )
	{
		WarSchedule* pNextWarSchedule = dynamic_cast<WarSchedule*>(pNextSchedule);
		Assert(pNextWarSchedule != NULL);

		pNextWar->addRegistrationFee(warRegistrationFee);
		pNextWar->addChallengerGuild(guildID);
		pNextWarSchedule->save();
	}
	else
	{
		gcNPCResponse.setCode(NPC_RESPONSE_WAR_SCHEDULE_FULL);
		pPC->getPlayer()->sendPacket(&gcNPCResponse);

//		SAFE_DELETE(pNextWar);
		return;
	}

	pPC->decreaseGoldEx(warRegistrationFee);

	GCModifyInformation gcMI;
	gcMI.addLongData(MODIFY_GOLD, pPC->getGold());
	pPC->getPlayer()->sendPacket(&gcMI);

	gcNPCResponse.setCode(NPC_RESPONSE_WAR_REGISTRATION_OK);
	pPC->getPlayer()->sendPacket(&gcNPCResponse);
	return;

#endif

	__END_CATCH
}
예제 #7
0
//----------------------------------------------------------------------
// 
// SGDeleteGuildOKHandler::execute()
// 
//----------------------------------------------------------------------
void SGDeleteGuildOKHandler::execute (SGDeleteGuildOK* pPacket )
	 throw(ProtocolException , Error )
{
	__BEGIN_TRY

#ifdef __GAME_SERVER__

	// 길드 아지트에 있는 멤버를 warp 시킨다.
	// 길드 아지트를 삭제한다.
	// 멤버 warp와 길드 아지트 삭제 시 다른 쓰레드에서 ZoneGroup Thread 내부에서 일어나게 해야 별탈이 없을 듯 하다.
	// 일단은 걍 둔다. Portal 이 막히므로 다시 들어갈 수 없을 것이다.
	
	Assert(pPacket != NULL);

	// 길드를 가져온다.
	Guild* pGuild = g_pGuildManager->getGuild(pPacket->getGuildID());
	try { Assert(pGuild != NULL); } catch (Throwable& ) { return; }


	// 길드 활동 중인 상태에서의 해체인지 대기 중인 상태에서의 해체인지 구별한다.
	if (pGuild->getState() == Guild::GUILD_STATE_ACTIVE )
	{
		HashMapGuildMember& Members = pGuild->getMembers();
		HashMapGuildMemberItor itr = Members.begin();

		for (; itr != Members.end(); itr++ )
		{
			GuildMember* pGuildMember = itr->second;

			// 접속해 있으면
			__ENTER_CRITICAL_SECTION((*g_pPCFinder))

			Creature* pCreature = g_pPCFinder->getCreature_LOCKED(pGuildMember->getName());
			if (pCreature != NULL && pCreature->isPC() )
			{
				Player* pPlayer = pCreature->getPlayer();
				Assert(pPlayer != NULL);

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

				// Slayer, Vampire 의 길드 아이디를 바꾼다.
				if (pPlayerCreature->isSlayer() )
				{
					pPlayerCreature->setGuildID(99);		// 슬레이어 가입안한 상태의 길드 ID

					// 클라이언트에 길드 아이디가 바꼈음을 알린다.
					GCModifyGuildMemberInfo gcModifyGuildMemberInfo;
					gcModifyGuildMemberInfo.setGuildID(pPlayerCreature->getGuildID());
					gcModifyGuildMemberInfo.setGuildName("");
					gcModifyGuildMemberInfo.setGuildMemberRank(GuildMember::GUILDMEMBER_RANK_DENY);
					pPlayer->sendPacket(&gcModifyGuildMemberInfo);
				}
				else if (pPlayerCreature->isVampire() )
				{
					pPlayerCreature->setGuildID(0);		// 뱀파이어 가입안한 상태의 길드 ID

					// 클라이언트에 길드 아이디가 바꼈음을 알린다.
					GCModifyGuildMemberInfo gcModifyGuildMemberInfo;
					gcModifyGuildMemberInfo.setGuildID(pPlayerCreature->getGuildID());
					gcModifyGuildMemberInfo.setGuildName("");
					gcModifyGuildMemberInfo.setGuildMemberRank(GuildMember::GUILDMEMBER_RANK_DENY);
					pPlayer->sendPacket(&gcModifyGuildMemberInfo);
				}
				else if (pPlayerCreature->isOusters() )
				{
					pPlayerCreature->setGuildID(66);		// 아우스터즈 가입안한 상태의 길드 ID

					// 클라이언트에 길드 아이디가 바꼈음을 알린다.
					GCModifyGuildMemberInfo gcModifyGuildMemberInfo;
					gcModifyGuildMemberInfo.setGuildID(pPlayerCreature->getGuildID());
					gcModifyGuildMemberInfo.setGuildName("");
					gcModifyGuildMemberInfo.setGuildMemberRank(GuildMember::GUILDMEMBER_RANK_DENY);
					pPlayer->sendPacket(&gcModifyGuildMemberInfo);
				}

				// 주위에 클라이언트에 길드 아이디가 바꼈음을 알린다.
				GCOtherModifyInfo gcOtherModifyInfo;
				gcOtherModifyInfo.setObjectID(pCreature->getObjectID());
				gcOtherModifyInfo.addShortData(MODIFY_GUILDID, pPlayerCreature->getGuildID());

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

				pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcOtherModifyInfo, pCreature);
			}

			__LEAVE_CRITICAL_SECTION((*g_pPCFinder))

			// Guild Member 객체를 삭제한다.
			SAFE_DELETE(pGuildMember);
		}

		// 길드 멤버 맵을 삭제한다.
		Members.clear();

		// 길드 매니저에서 길드를 삭제한다.
		g_pGuildManager->deleteGuild(pGuild->getID());

		// 길드 객체를 삭제한다.
		SAFE_DELETE(pGuild);
	}
	else if (pGuild->getState() == Guild::GUILD_STATE_WAIT )
	{
		HashMapGuildMember& Members = pGuild->getMembers();
		HashMapGuildMemberItor itr = Members.begin();

		Statement* pStmt = NULL;
		Result* pResult = NULL;

		BEGIN_DB
		{
			pStmt = g_pDatabaseManager->getConnection("DARKEDEN" )->createStatement();
			
			for (; itr != Members.end(); itr++ )
			{
				GuildMember* pGuildMember = itr->second;

				// 접속해 있으면
				__ENTER_CRITICAL_SECTION((*g_pPCFinder))

				Creature* pCreature = g_pPCFinder->getCreature_LOCKED(pGuildMember->getName());
				if (pCreature != NULL && pCreature->isPC() )
				{
					Player* pPlayer = pCreature->getPlayer();
					Assert(pPlayer != NULL);

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

					// 등록비를 환불한다.
					Gold_t Gold = pPlayerCreature->getGold();
					if (pGuildMember->getRank() == GuildMember::GUILDMEMBER_RANK_MASTER )
					{
						Gold = min((uint64_t)(Gold + RETURN_SLAYER_MASTER_GOLD), (uint64_t)2000000000);
					}
					else if (pGuildMember->getRank() == GuildMember::GUILDMEMBER_RANK_SUBMASTER )
					{
						Gold = min((uint64_t)(Gold + RETURN_SLAYER_SUBMASTER_GOLD), (uint64_t)2000000000);
					}

					pPlayerCreature->setGoldEx(Gold);

					GCModifyInformation gcModifyInformation;
					gcModifyInformation.addLongData(MODIFY_GOLD, Gold);
					pPlayer->sendPacket(&gcModifyInformation);

					// 메시지를 보낸다.
					pResult = pStmt->executeQuery("SELECT Message FROM Messages WHERE Receiver = '%s'", pCreature->getName().c_str());

					while (pResult->next() )
					{
						GCSystemMessage message;
						message.setMessage(pResult->getString(1));
						pPlayer->sendPacket(&message);
					}

					pStmt->executeQuery("DELETE FROM Messages WHERE Receiver = '%s'", pCreature->getName().c_str());
				}

				__LEAVE_CRITICAL_SECTION((*g_pPCFinder))

				// 길드 멤버 객체를 삭제한다.
				SAFE_DELETE(pGuildMember);
			}

			// 길드 멤버 해쉬 맵을 지운다.
			Members.clear();

			// 길드 매니저에서 길드를 삭제한다.
			g_pGuildManager->deleteGuild(pGuild->getID());
			GuildUnionManager::Instance().removeMasterGuild(pGuild->getID());

			// 길드 객체를 삭제한다.
			SAFE_DELETE(pGuild);

			SAFE_DELETE(pStmt);
		}
		END_DB(pStmt)
	}
예제 #8
0
void CGDownSkillHandler::execute (CGDownSkill* pPacket , Player* pPlayer)
throw(ProtocolException, Error)
{
    __BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

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

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

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

    SkillType_t targetSkillType = pPacket->getSkillType();

    GCDownSkillFailed failpkt;
    failpkt.setSkillType(targetSkillType);

    if (!pPC->isOusters() )
    {
        failpkt.setDesc(NOT_OUSTERS);
        pPlayer->sendPacket(&failpkt);

        return;
    }

    Ousters* pOusters = dynamic_cast<Ousters*>(pPC);
    Assert(pOusters != NULL);
    OustersSkillSlot* pTargetSkillSlot = pOusters->getSkill(targetSkillType);

    if (pTargetSkillSlot == NULL )
    {
        failpkt.setDesc(HAVE_NOT_SKILL);
        pPlayer->sendPacket(&failpkt);
        return;
    }

    SkillInfo* pTargetSkillInfo = NULL;

    try
    {
        pTargetSkillInfo = g_pSkillInfoManager->getSkillInfo(targetSkillType);
    }
    catch(Exception& e)
    {
        failpkt.setDesc(INVALID_SKILL);
        pPlayer->sendPacket(&failpkt);

        return;
    }

    if (pTargetSkillSlot->getExpLevel() <= 1 )
    {
        if (!pTargetSkillInfo->canDelete() )
        {
            failpkt.setDesc(TOO_LOW);
            pPlayer->sendPacket(&failpkt);
            return;
        }

        list<SkillType_t>& rRequiredSkills = pTargetSkillInfo->getRequiredSkills();
        list<SkillType_t>::iterator itr = rRequiredSkills.begin();

        for (; itr != rRequiredSkills.end(); ++itr )
        {
            if (pOusters->hasSkill(*itr) != NULL )
            {
                bool canDrop = false;
                SkillInfo* pFollowingSkillInfo = g_pSkillInfoManager->getSkillInfo(*itr);
                list<SkillType_t>& rRequireSkills = pFollowingSkillInfo->getRequireSkills();
                list<SkillType_t>::iterator itr2 = rRequireSkills.begin();
                for (; itr2 != rRequireSkills.end(); ++itr2 )
                {
                    if ((*itr2) != targetSkillType && pOusters->hasSkill(*itr2) != NULL )
                    {
                        SkillInfo* pAlternativeSkillInfo = g_pSkillInfoManager->getSkillInfo(*itr2);
                        if (getSkillMapID((ElementalDomain)pAlternativeSkillInfo->getElementalDomain()) == getSkillMapID((ElementalDomain)pTargetSkillInfo->getElementalDomain()) )
                            canDrop = true;
                    }
                }

                if (!canDrop )
                {
                    failpkt.setDesc(CANNOT_DROP_SKILL);
                    pPlayer->sendPacket(&failpkt);
                    return;
                }
            }
        }
    }

    /*	if (pTargetSkillSlot->getExpLevel() >= 30 )
    	{
    		failpkt.setDesc(TOO_HIGH);
    		pPlayer->sendPacket(&failpkt);
    		return;
    	}*/

    Assert(pTargetSkillInfo != NULL);

    int backPoint = pTargetSkillInfo->getLevelUpPoint();
    Price_t downPrice = (int)(backPoint * pow(pOusters->getLevel(),1.3) * 200);

    if (pTargetSkillSlot->getExpLevel() <= 1 )
    {
        downPrice *= 5;
        if (downPrice == 0 ) downPrice = 1000000;
    }

    if (pOusters->getGold() < downPrice )
    {
        failpkt.setDesc(NOT_ENOUGH_MONEY);
        pPlayer->sendPacket(&failpkt);

        return;
    }

    pOusters->decreaseGoldEx(downPrice);
    pTargetSkillSlot->setExpLevel(pTargetSkillSlot->getExpLevel() - 1);
    pTargetSkillSlot->save();
    if (pTargetSkillSlot->getExpLevel() <= 0 )
    {
        pTargetSkillSlot->destroy(pOusters->getName());
        backPoint = pTargetSkillInfo->getSkillPoint();
        pOusters->removeSkill(targetSkillType);
    }

    pOusters->setSkillBonus(pOusters->getSkillBonus() + backPoint);
    char query[50];
    sprintf(query, "SkillBonus=%d", pOusters->getSkillBonus());
    pOusters->tinysave(query);

    GCDownSkillOK okpkt;
    okpkt.setSkillType(targetSkillType);
    pPlayer->sendPacket(&okpkt);

    GCModifyInformation gcMI;
    gcMI.addLongData(MODIFY_GOLD, pOusters->getGold());
    gcMI.addShortData(MODIFY_SKILL_BONUS_POINT, pOusters->getSkillBonus());

    switch (targetSkillType )
    {
    case SKILL_HIDE_SIGHT:
    {
        OUSTERS_RECORD prev;
        pOusters->getOustersRecord(prev);
        pOusters->initAllStat();
        pOusters->sendRealWearingInfo();
        pOusters->addModifyInfo(prev, gcMI);
    }
    break;

    default :
        break;
    }

    pPlayer->sendPacket(&gcMI);

#endif	// __GAME_SERVER__

    __END_DEBUG_EX __END_CATCH
}
//----------------------------------------------------------------------
//
// SGAddGuildMemberOKHandler::execute()
//
//----------------------------------------------------------------------
void SGAddGuildMemberOKHandler::execute (SGAddGuildMemberOK* pPacket )
throw(ProtocolException , Error )
{
    __BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

    // 길드 멤버 object 를 만든다.
    GuildMember* pGuildMember = new GuildMember();
    pGuildMember->setGuildID(pPacket->getGuildID());
    pGuildMember->setName(pPacket->getName());
    pGuildMember->setRank(pPacket->getGuildMemberRank());

    // 길드에 추가한다.
    Guild* pGuild = g_pGuildManager->getGuild(pGuildMember->getGuildID());
    pGuild->addMember(pGuildMember);

    // 멤버에게 메세지를 보낸다.
    __ENTER_CRITICAL_SECTION((*g_pPCFinder))

    Creature* pCreature = g_pPCFinder->getCreature_LOCKED(pGuildMember->getName());
    if (pCreature != NULL && pCreature->isPC() )
    {
        Player* pPlayer = pCreature->getPlayer();
        Assert(pPlayer != NULL);

        if (pGuildMember->getRank() == GuildMember::GUILDMEMBER_RANK_MASTER ||
                pGuildMember->getRank() == GuildMember::GUILDMEMBER_RANK_SUBMASTER )		// 길드마스터나 서브마스터일 경우
        {
            PlayerCreature* pPlayerCreature = dynamic_cast<PlayerCreature*>(pCreature);
            Assert(pPlayerCreature != NULL);

            Gold_t Fee;
            if (pGuildMember->getRank() == GuildMember::GUILDMEMBER_RANK_MASTER )
                Fee = REQUIRE_SLAYER_MASTER_GOLD;
            else if (pGuildMember->getRank() == GuildMember::GUILDMEMBER_RANK_SUBMASTER )
                Fee = REQUIRE_SLAYER_SUBMASTER_GOLD;
            else
                Fee = 0;

            Gold_t CurMoney = pPlayerCreature->getGold();
            if (CurMoney < Fee )
            {
                // 큰일났군
                CurMoney = 0;
            }
            else
                CurMoney -= Fee;

            pPlayerCreature->setGoldEx(CurMoney);

            if (Fee != 0 )
            {
                GCModifyInformation gcModifyInformation;
                gcModifyInformation.addLongData(MODIFY_GOLD, CurMoney);

                // 바뀐정보를 클라이언트에 보내준다.
                pPlayer->sendPacket(&gcModifyInformation);
            }

            // 길드 가입 메시지를 보여준다.
            GCSystemMessage gcSystemMessage;
            if (pGuild->getRace() == Guild::GUILD_RACE_SLAYER )
                gcSystemMessage.setMessage(g_pStringPool->getString(STRID_TEAM_JOIN_ACCEPTED ));
            else if (pGuild->getRace() == Guild::GUILD_RACE_VAMPIRE )
                gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CLAN_JOIN_ACCEPTED ));
            else if (pGuild->getRace() == Guild::GUILD_RACE_OUSTERS )
                gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CLAN_JOIN_ACCEPTED ));
            pPlayer->sendPacket(&gcSystemMessage);

        }
        else if (pGuildMember->getRank() == GuildMember::GUILDMEMBER_RANK_WAIT )
        {
            // 길드 가입 신청 메시지를 보낸다.
            GCSystemMessage gcSystemMessage;
            if (pGuild->getRace() == Guild::GUILD_RACE_SLAYER )
                gcSystemMessage.setMessage(g_pStringPool->getString(STRID_TEAM_JOIN_TRY ));
            else if (pGuild->getRace() == Guild::GUILD_RACE_VAMPIRE )
                gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CLAN_JOIN_TRY ));
            else if (pGuild->getRace() == Guild::GUILD_RACE_OUSTERS )
                gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CLAN_JOIN_TRY ));

            pPlayer->sendPacket(&gcSystemMessage);
        }
    }
    else
    {
        // 접속이 안되어 있다.

        // 마스터나 서브마스터일 경우
        // DB 에서 돈을 까도록 한다.
        if ((pGuildMember->getRank() == GuildMember::GUILDMEMBER_RANK_MASTER ||
                pGuildMember->getRank() == GuildMember::GUILDMEMBER_RANK_SUBMASTER )		// 길드마스터나 서브마스터일 경우
                && pPacket->getServerGroupID() == g_pConfig->getPropertyInt("ServerID" ) )		// 이 게임 서버에서 추가한 길드원인가?
        {
            Gold_t Fee;
            if (pGuildMember->getRank() == GuildMember::GUILDMEMBER_RANK_MASTER )
                Fee = REQUIRE_SLAYER_MASTER_GOLD;
            else if (pGuildMember->getRank() == GuildMember::GUILDMEMBER_RANK_SUBMASTER )
                Fee = REQUIRE_SLAYER_SUBMASTER_GOLD;
            else
                Fee = 0;

            string table = "";
            if (pGuild->getRace() == Guild::GUILD_RACE_SLAYER )
            {
                table = "Slayer";
            }
            else if (pGuild->getRace() == Guild::GUILD_RACE_VAMPIRE )
            {
                table = "Vampire";
            }
            else if (pGuild->getRace() == Guild::GUILD_RACE_OUSTERS )
            {
                table = "Ousters";
            }

            if (table != "" && Fee != 0 )
            {
                Statement* pStmt = NULL;

                BEGIN_DB
                {
                    pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement();
                    pStmt->executeQuery("UPDATE %s SET Gold = IF (%u > Gold , 0, Gold - %u ) WHERE Name = '%s'",
                    table.c_str(), Fee, Fee, pGuildMember->getName().c_str());
                }
                END_DB(pStmt)
            }
        }