Example #1
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
}
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
}
Example #3
0
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
}
void EffectBloodyWallBlocked::affect()
	throw(Error)
{
	__BEGIN_TRY

	//cout << "EffectBloodyWallBlocked" << "affect BEGIN" << endl;
	
	Assert(m_pZone != NULL);

	// 현재 이펙트가 붙어있는 타일을 받아온다.
    Tile& tile = m_pZone->getTile(m_X, m_Y);

	HP_t CurrentHP = 0;
	HP_t RemainHP  = 0;

	// 타일 안에 존재하는 오브젝트들을 검색한다.
    const list<Object*>& oList = tile.getObjectList();
	list<Object*>::const_iterator itr = oList.begin();
    for (; itr != oList.end(); itr++) 
	{
		Assert(*itr != NULL);

		Object* pObject = *itr;
		Assert(pObject != NULL);

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

			// 무적상태 체크. by sigi. 2002.9.5
			// 산 면역. by sigi. 2002.9.13
			if (!canAttack(NULL, pCreature )
				|| pCreature->isFlag(Effect::EFFECT_CLASS_IMMUNE_TO_BLOOD_DRAIN)
				|| pCreature->isFlag(Effect::EFFECT_CLASS_COMA)
				|| pCreature->isDead())
			{
				continue;
			}

			int AcidDamage = computeMagicDamage(pCreature, m_Damage, SKILL_BLOODY_WALL);

			if (pCreature->getMoveMode() != Creature::MOVE_MODE_FLYING)
			{
				if (pCreature->isSlayer()) 
				{
					Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature);

					CurrentHP = pSlayer->getHP(ATTR_CURRENT);
					RemainHP  = max(0, CurrentHP -(int)AcidDamage);

					pSlayer->setHP(RemainHP, ATTR_CURRENT);

					GCModifyInformation gcMI;
					gcMI.addShortData(MODIFY_CURRENT_HP, pSlayer->getHP(ATTR_CURRENT));

					Player* pPlayer = pSlayer->getPlayer();
					Assert(pPlayer != NULL);
					pPlayer->sendPacket(&gcMI);

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

					CurrentHP = pVampire->getHP(ATTR_CURRENT);
					RemainHP  = max(0, CurrentHP -(int)AcidDamage);

					pVampire->setHP(RemainHP, ATTR_CURRENT);

					GCModifyInformation gcMI;
					gcMI.addShortData(MODIFY_CURRENT_HP, pVampire->getHP(ATTR_CURRENT));

					Player* pPlayer = pVampire->getPlayer();
					Assert(pPlayer != NULL);
					pPlayer->sendPacket(&gcMI);

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

					CurrentHP = pOusters->getHP(ATTR_CURRENT);
					RemainHP  = max(0, CurrentHP -(int)AcidDamage);

					pOusters->setHP(RemainHP, ATTR_CURRENT);

					GCModifyInformation gcMI;
					gcMI.addShortData(MODIFY_CURRENT_HP, pOusters->getHP(ATTR_CURRENT));

					Player* pPlayer = pOusters->getPlayer();
					Assert(pPlayer != NULL);
					pPlayer->sendPacket(&gcMI);

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

					CurrentHP = pMonster->getHP(ATTR_CURRENT);
					RemainHP  = max(0, CurrentHP -(int)AcidDamage);

					pMonster->setHP(RemainHP, ATTR_CURRENT);

					if(m_CasterName != "" ) {
						// 시전자의 데미지를 추가해 준다.
						// 맞는 놈이 몬스터이고, 공격자가 사람이라면,
						// 데미지에 따라서 변하는 우선권 테이블을 갱신해 주어야 한다.
						pMonster->addPrecedence(m_CasterName, m_PartyID, AcidDamage);
						pMonster->setLastHitCreatureClass(Creature::CREATURE_CLASS_VAMPIRE);
					}

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


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

					if (pAttacker!=NULL)
					{ 
						affectKillCount(pAttacker, pCreature);
					}
				}
			}
		}
	}
	
	// 한번만..
	//setNextTime(m_Tick);

	//cout << "EffectBloodyWallBlocked" << "affect END" << endl;

	__END_CATCH 
}
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
}