Example #1
0
void SimpleCureSkill::execute(Slayer* pSlayer, 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();

		GCSkillToSelfOK1 _GCSkillToSelfOK1;
		GCSkillToSelfOK2 _GCSkillToSelfOK2;

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

		int  RequiredMP  = (int)pSkillInfo->getConsumeMP();
		bool bManaCheck  = hasEnoughMana(pSlayer, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pSkillSlot);
		bool bRangeCheck = checkZoneLevelToUseSkill(pSlayer);
		bool bHitRoll    = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot);
		bool bHPCheck    = false;

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

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

			uint HealPoint = param.SkillDamage;

			// 흡혈당한 상태라면 흡혈 상태를 날려준다.
			if (pEffectBloodDrain != NULL && pEffectBloodDrain->getLevel() < param.Level)
			{
				// 흡혈 아르바이트를 방지하기 위한 후유증 이펙트를 붙여준다.
				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);

				SLAYER_RECORD prev;
				pSlayer->getSlayerRecord(prev);
				pSlayer->initAllStat();
				pSlayer->sendRealWearingInfo();
				pSlayer->addModifyInfo(prev, _GCSkillToSelfOK1);

				GCRemoveEffect gcRemoveEffect;
				gcRemoveEffect.setObjectID(pSlayer->getObjectID());
				gcRemoveEffect.addEffectList((EffectID_t)Effect::EFFECT_CLASS_BLOOD_DRAIN);
				pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcRemoveEffect);
			}
		
			// HP를 세팅한다.
			HP_t CurrentHP = pSlayer->getHP(ATTR_CURRENT);
			HP_t MaxHP     = pSlayer->getHP(ATTR_MAX);

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

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

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

			// HP를 브로드캐스팅한다.
			GCStatusCurrentHP gcStatusCurrentHP;
			gcStatusCurrentHP.setObjectID(pSlayer->getObjectID());
			gcStatusCurrentHP.setCurrentHP (CurrentHP);
			pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcStatusCurrentHP);
			
			ZoneCoord_t myX = pSlayer->getX();
			ZoneCoord_t myY = pSlayer->getY();

			_GCSkillToSelfOK1.setSkillType(param.SkillType);
			_GCSkillToSelfOK1.setCEffectID(CEffectID);
			_GCSkillToSelfOK1.setDuration(0);
			
			_GCSkillToSelfOK2.setObjectID(pSlayer->getObjectID());
			_GCSkillToSelfOK2.setSkillType(param.SkillType);
			_GCSkillToSelfOK2.setDuration (0);

			// Send Packet
			pPlayer->sendPacket(&_GCSkillToSelfOK1);

			pZone->broadcastPacket(myX, myY, &_GCSkillToSelfOK2, pSlayer);

			pSkillSlot->setRunTime(param.Delay);

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

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