Example #1
0
void EffectBlazeWalk::affect(Creature* pCreature)
	throw(Error)
{
	__BEGIN_TRY

	Assert(pCreature != NULL);

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

	Creature* pAttacker = pZone->getCreature(m_UserObjectID);
	if (pAttacker == NULL )
	{
		setDeadline(0);
		return;
	}

	if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE)
		&& !pCreature->isDead()
		&& !pCreature->isFlag(Effect::EFFECT_CLASS_COMA )
		// 무적상태 체크. by sigi. 2002.9.5
		&& canAttack(pAttacker, pCreature )
	   )
	{
		GCModifyInformation gcMI, gcAttackerMI;
		setDamage(pCreature, m_Point, pAttacker, m_SkillType, &gcMI, &gcAttackerMI);

		if (pAttacker->isPC() ) computeAlignmentChange(pCreature, m_Point, pAttacker, &gcMI, &gcAttackerMI);
		if (pCreature->isPC() ) pCreature->getPlayer()->sendPacket(&gcMI);

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

			if (pSlayer != NULL )
			{
				GCModifyInformation gcMI;
				shareAttrExp(pSlayer, m_Point, 8, 1, 1, gcAttackerMI);
			}
		}

		if (pAttacker->isPC() ) pAttacker->getPlayer()->sendPacket(&gcAttackerMI);

		if (pCreature->isDead() ) setDeadline(0);
	}

	m_AttackNum--;

	if (m_AttackNum > 0 )
	{
		setNextTime(5);
	}
	else setDeadline(0);

//cout << "EffectBlazeWalk " << "begin" << endl;
	//cout << "EffectBlazeWalk " << "end" << endl;

	__END_CATCH
}
void EffectDivineGuidance::affect(Creature* pCreature)
	throw(Error)
{
	__BEGIN_TRY

	//cout << "EffectDivineGuidance " << "begin" << endl;
	//cout << "EffectDivineGuidance " << "end" << endl;
	Assert(pCreature != NULL);

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

	Creature* pAttacker = pZone->getCreature(m_UserObjectID);

	if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE)
		&& !pCreature->isDead()
		&& !pCreature->isFlag(Effect::EFFECT_CLASS_COMA)
		// 무적상태 체크. by sigi. 2002.9.5
		&& canAttack(pAttacker, pCreature )
	   )
	{
		GCModifyInformation gcMI, gcAttackerMI;
		setDamage(pCreature, m_Point, pAttacker, SKILL_DIVINE_GUIDANCE, &gcMI, &gcAttackerMI);
		if (pCreature->isPC() ) pCreature->getPlayer()->sendPacket(&gcMI);

		if (pAttacker!=NULL) 
		{
			computeAlignmentChange(pCreature, m_Point, pAttacker, &gcMI, &gcAttackerMI);
			if (pAttacker->isPC() )
			{ 
				if (pAttacker->isSlayer() && !pCreature->isSlayer() )
				{
					Slayer* pSlayer = dynamic_cast<Slayer*>(pAttacker);

					if (pSlayer != NULL )
					{
						GCModifyInformation gcMI;
						shareAttrExp(pSlayer, m_Point, 1, 1, 8, gcAttackerMI);
					}
				}

				if (pAttacker->isPC() ) pAttacker->getPlayer()->sendPacket(&gcAttackerMI);
			}
		}

	}

	setNextTime(m_Tick);

	__END_CATCH
}
Example #3
0
Creature *ScriptFunctions::convertPC(Aurora::NWScript::Object *o) {
	Creature *pc = dynamic_cast<Creature *>(o);
	if (!pc || (pc->getID() == kObjectIDInvalid) || !pc->isPC())
		return 0;

	return pc;
}
Example #4
0
Creature *ObjectContainer::toPC(Aurora::NWScript::Object *object) {
	Creature *pc = dynamic_cast<Creature *>(object);
	if (!pc || !pc->isPC())
		return 0;

	return pc;
}
Example #5
0
//////////////////////////////////////////////////////////////////////////////
// 뱀파이어 오브젝트 핸들러
//////////////////////////////////////////////////////////////////////////////
void Death::execute(Vampire* pVampire, ObjectID_t TargetObjectID, VampireSkillSlot* pSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY
		
	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl;

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

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

		// NPC는 공격할 수 없다.
		// 저주 면역. by sigi. 2002.9.13
		// NoSuch제거. by sigi. 2002.5.2
		if (pTargetCreature==NULL
			|| pTargetCreature->isFlag(Effect::EFFECT_CLASS_IMMUNE_TO_CURSE)
			|| !canAttack(pVampire, pTargetCreature )
			|| pTargetCreature->isNPC())
		{
			executeSkillFailException(pVampire, getSkillType());
			//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl;
			return;
		}

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

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

		// Knowledge of Curse 가 있다면 hit bonus 10
		int HitBonus = 0;
		if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_CURSE ) )
		{
			RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_CURSE);
			Assert(pRankBonus != NULL);

			HitBonus = pRankBonus->getPoint();
		}

		int  RequiredMP  = decreaseConsumeMP(pVampire, pSkillInfo);
		bool bManaCheck  = hasEnoughMana(pVampire, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pSkillSlot);
		bool bRangeCheck = verifyDistance(pVampire, pTargetCreature, pSkillInfo->getRange());
		bool bHitRoll    = HitRoll::isSuccessVampireCurse(pSkillInfo->getLevel(), pTargetCreature->getResist(MAGIC_DOMAIN_CURSE));
		bool bHitRoll2   = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pSkillSlot, HitBonus);
		bool bCanHit     = canHit(pVampire, pTargetCreature, SkillType);
		bool bEffected   = pTargetCreature->isFlag(Effect::EFFECT_CLASS_DEATH);
		bool bPK         = verifyPK(pVampire, pTargetCreature);

		ZoneCoord_t targetX = pTargetCreature->getX();
		ZoneCoord_t targetY = pTargetCreature->getY();
		ZoneCoord_t myX     = pVampire->getX();
		ZoneCoord_t myY     = pVampire->getY();

		if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bHitRoll2 && bCanHit && !bEffected && bPK)
		{
			decreaseMana(pVampire, RequiredMP, _GCSkillToObjectOK1);

        	bool bCanSeeCaster = canSee(pTargetCreature, pVampire);

			SkillInput input(pVampire);
			SkillOutput output;
			computeOutput(input, output);

			// pTargetCreature가 저주마법을 반사하는 경우
			if (CheckReflection(pVampire, pTargetCreature, getSkillType()))
			{
				pTargetCreature = (Creature*)pVampire;
				TargetObjectID = pVampire->getObjectID();
			}

			Resist_t resist = pTargetCreature->getResist(MAGIC_DOMAIN_CURSE);
			if ((resist*10/3) > output.Duration ) output.Duration=0;
			else output.Duration -= resist*10/3;

			if (output.Duration < 20 ) output.Duration = 20;

			// 이펙트 오브젝트를 생성해 붙인다.
			EffectDeath* pEffect = new EffectDeath(pTargetCreature);
			pEffect->setDeadline(output.Duration);
			pEffect->setLevel(pSkillInfo->getLevel()/2);
			pEffect->setResistPenalty(output.Damage);
			pTargetCreature->addEffect(pEffect);
			pTargetCreature->setFlag(Effect::EFFECT_CLASS_DEATH);

			// 능력치를 계산해서 보내준다.
			if (pTargetCreature->isSlayer())
			{
				Slayer* pTargetSlayer = dynamic_cast<Slayer*>(pTargetCreature);

				if (bCanSeeCaster) 
				{
					SLAYER_RECORD prev;
					pTargetSlayer->getSlayerRecord(prev);
					pTargetSlayer->initAllStat();
					pTargetSlayer->addModifyInfo(prev, _GCSkillToObjectOK2);
				} 
				else 
				{
					SLAYER_RECORD prev;
					pTargetSlayer->getSlayerRecord(prev);
					pTargetSlayer->initAllStat();
					pTargetSlayer->addModifyInfo(prev, _GCSkillToObjectOK6);
				}
			}
			else if (pTargetCreature->isVampire())
			{
				Vampire* pTargetVampire = dynamic_cast<Vampire*>(pTargetCreature);
				VAMPIRE_RECORD prev;

				pTargetVampire->getVampireRecord(prev);
				pTargetVampire->initAllStat();

				if (bCanSeeCaster)
				{
					pTargetVampire->addModifyInfo(prev, _GCSkillToObjectOK2);
				}
				else
				{
					pTargetVampire->addModifyInfo(prev, _GCSkillToObjectOK6);
				}
			}
			else if (pTargetCreature->isOusters())
			{
				Ousters* pTargetOusters = dynamic_cast<Ousters*>(pTargetCreature);
				OUSTERS_RECORD prev;

				pTargetOusters->getOustersRecord(prev);
				pTargetOusters->initAllStat();

				if (bCanSeeCaster)
				{
					pTargetOusters->addModifyInfo(prev, _GCSkillToObjectOK2);
				}
				else
				{
					pTargetOusters->addModifyInfo(prev, _GCSkillToObjectOK6);
				}
			}
			else if (pTargetCreature->isMonster())
			{
				Monster* pTargetMonster = dynamic_cast<Monster*>(pTargetCreature);
				pTargetMonster->initAllStat();
			}
			else Assert(false);
								
			_GCSkillToObjectOK1.setSkillType(SkillType);
			_GCSkillToObjectOK1.setCEffectID(CEffectID);
			_GCSkillToObjectOK1.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK1.setDuration(output.Duration);
		
			_GCSkillToObjectOK2.setObjectID(pVampire->getObjectID());
			_GCSkillToObjectOK2.setSkillType(SkillType);
			_GCSkillToObjectOK2.setDuration(output.Duration);
		
			_GCSkillToObjectOK3.setObjectID(pVampire->getObjectID());
			_GCSkillToObjectOK3.setSkillType(SkillType);
			_GCSkillToObjectOK3.setTargetXY (targetX, targetY);
			
			_GCSkillToObjectOK4.setSkillType(SkillType);
			_GCSkillToObjectOK4.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK4.setDuration(output.Duration);
			
			_GCSkillToObjectOK5.setObjectID(pVampire->getObjectID());
			_GCSkillToObjectOK5.setSkillType(SkillType);
			_GCSkillToObjectOK5.setTargetObjectID (TargetObjectID);
			_GCSkillToObjectOK5.setDuration(output.Duration);
			
			_GCSkillToObjectOK6.setXY(myX, myY);
			_GCSkillToObjectOK6.setSkillType(SkillType);
			_GCSkillToObjectOK6.setDuration(output.Duration);

			if (bCanSeeCaster) // 10은 땜빵 수치다.
			{
				computeAlignmentChange(pTargetCreature, 10, pVampire, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1);
			}
			else // 10은 땜빵 수치다.
			{
				computeAlignmentChange(pTargetCreature, 10, pVampire, &_GCSkillToObjectOK6, &_GCSkillToObjectOK1);
			}
								
			list<Creature *> cList;
			cList.push_back(pTargetCreature);
			cList.push_back(pVampire);
			cList = pZone->broadcastSkillPacket(myX, myY, targetX, targetY, &_GCSkillToObjectOK5, cList);

			pZone->broadcastPacket(myX, myY, &_GCSkillToObjectOK3, cList);
			pZone->broadcastPacket(targetX, targetY, &_GCSkillToObjectOK4, cList);

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

			if (pTargetCreature->isPC()) 
			{
				Player* pTargetPlayer = pTargetCreature->getPlayer();
				if (pTargetPlayer == NULL)
				{
					//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl;
					return;
				}

				if (bCanSeeCaster) pTargetPlayer->sendPacket(&_GCSkillToObjectOK2);
				else pTargetPlayer->sendPacket(&_GCSkillToObjectOK6);
			}
			else if (pTargetCreature->isMonster())
			{
				Monster* pTargetMonster = dynamic_cast<Monster*>(pTargetCreature);
				pTargetMonster->addEnemy(pVampire);
			}

			GCAddEffect gcAddEffect;
			gcAddEffect.setObjectID(TargetObjectID);
			gcAddEffect.setEffectID(Effect::EFFECT_CLASS_DEATH);
			gcAddEffect.setDuration(output.Duration);
			pZone->broadcastPacket(targetX, targetY, &gcAddEffect);

			//cout << pTargetCreature->getName() << "에게 Death를 " << output.Duration << " duration 동안 건다." << endl;
			
			pSkillSlot->setRunTime(output.Delay);
		} 
		else 
		{
			executeSkillFailNormal(pVampire, getSkillType(), pTargetCreature);
		}
	}
	catch (Throwable & t) 
	{
		executeSkillFailException(pVampire, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl;

	__END_CATCH
}
Example #6
0
//////////////////////////////////////////////////////////////////////////////
// 슬레이어 타일 핸들러 - AR이나 SMG를 들고 있을 경우
//////////////////////////////////////////////////////////////////////////////
void MoleShot::ARSMGexecute(Slayer* pSlayer, ZoneCoord_t X, ZoneCoord_t Y, SkillSlot* pSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

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

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

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

		GCSkillToTileOK1 _GCSkillToTileOK1;
		GCSkillToTileOK2 _GCSkillToTileOK2;
		GCSkillToTileOK3 _GCSkillToTileOK3;
		GCSkillToTileOK4 _GCSkillToTileOK4;
		GCSkillToTileOK5 _GCSkillToTileOK5;

		SkillInfo*        pSkillInfo = g_pSkillInfoManager->getSkillInfo(getSkillType());
		SkillDomainType_t DomainType = pSkillInfo->getDomainType();
		Level_t 	      SkillLevel = pSkillSlot->getExpLevel();

		Item* pWeapon = pSlayer->getWearItem(Slayer::WEAR_RIGHTHAND);
		Assert(pWeapon != NULL);

		bool bIncreaseExp = pSlayer->isRealWearingEx(Slayer::WEAR_RIGHTHAND);
 
		int  RequiredMP   = (int)pSkillInfo->getConsumeMP();
		bool bManaCheck   = hasEnoughMana(pSlayer, RequiredMP);
		bool bTimeCheck   = verifyRunTime(pSkillSlot);
		bool bRangeCheck  = verifyDistance(pSlayer, X, Y, pWeapon->getRange());
		bool bBulletCheck = (getRemainBullet(pWeapon) > 0) ? true : false;

		// 총알 숫자는 무조건 떨어뜨린다.
		Bullet_t RemainBullet = 0;
		if (bBulletCheck)
		{
			decreaseBullet(pWeapon);
			// 한발쓸때마다 저장할 필요 없다. by sigi. 2002.5.9
			// pWeapon->save(pSlayer->getName(), STORAGE_GEAR, 0, Slayer::WEAR_RIGHTHAND, 0);
			RemainBullet = getRemainBullet(pWeapon);
		}

		// 데미지, 투힛 보너스, 좌표와 방향을 구한다.
		int         ToHitBonus    = 0;
		int         DamageBonus   = 0;
		int         ToHitPenalty  = 0;
		int         DamagePenalty = 0;
		ZoneCoord_t myX           = pSlayer->getX();
		ZoneCoord_t myY           = pSlayer->getY();	
		Dir_t       dir           = calcDirection(myX, myY, X, Y);
		bool        bHit          = false; // 한번이라도 맞았는가를 저장하기 위한 변수
		Damage_t    Damage        = 0;     // 마지막으로 입힌 데미지를 저장하기 위한 변수

		// AR이나 SMG일 경우에는 2부터 시작해서 4까지의 splash 데미지를 입힌다.
		int Splash = 1 + pSkillSlot->getExpLevel()/30 + 1;

		if (bManaCheck && bTimeCheck && bRangeCheck && bBulletCheck)
		{
			decreaseMana(pSlayer, RequiredMP, _GCSkillToTileOK1);

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

			// 음수 값이 돌아온다.
			ToHitPenalty  = getPercentValue(pSlayer->getToHit(), output.ToHit);

			list<Creature*> cList;
			list<Creature*> creatureList;
			getSplashVictims(pZone, X, Y, Creature::CREATURE_CLASS_MAX, creatureList, Splash);

			Level_t maxEnemyLevel = 0;
			uint EnemyNum = 0;

			list<Creature*>::iterator itr = creatureList.begin();
			for (; itr != creatureList.end(); itr++)
			{
				Creature* pTargetCreature = (*itr);
				Assert(pTargetCreature != NULL);

				ToHitBonus  = computeArmsWeaponToHitBonus(pWeapon, myX, myY, pTargetCreature->getX(), pTargetCreature->getY());
				DamageBonus = computeArmsWeaponDamageBonus(pWeapon, myX, myY, pTargetCreature->getX(), pTargetCreature->getY());

				bool bInvokerCheck   = (pTargetCreature->getObjectID() == pSlayer->getObjectID()) ? true : false;
				bool bRaceCheck      = pTargetCreature->isSlayer() || pTargetCreature->isNPC();
				bool bHitRoll        = HitRoll::isSuccess(pSlayer, pTargetCreature, ToHitPenalty + ToHitBonus);
				bool bPK             = verifyPK(pSlayer, pTargetCreature);
				bool bZoneLevelCheck = checkZoneLevelToHitTarget(pTargetCreature);

				if (pTargetCreature->isFlag(Effect::EFFECT_CLASS_NO_DAMAGE )
					|| pTargetCreature->isFlag(Effect::EFFECT_CLASS_COMA )
				)
				{
					bHitRoll = false;
				}

				if (!bInvokerCheck && !bRaceCheck && bHitRoll && bPK && bZoneLevelCheck)
				{
					bool bCriticalHit = false;

					// 데미지를 계산해서 페널티를 가한다.
					// 보너스는 멀티샷 페널티 때문에 음수가 될 수도 있다.
					Damage        = computeDamage(pSlayer, pTargetCreature, SkillLevel/5, bCriticalHit);
					DamagePenalty = getPercentValue(Damage, output.Damage);
					Damage        = max(0, Damage + DamagePenalty + DamageBonus);

					// 메인 타겟을 제외하고는, 스플래시 데미지를 입는데,
					// 스플래시 데미지는 일반 데미지의 50%다.
					if (pTargetCreature->getX() != X || pTargetCreature->getY() != Y)
					{
						Damage = Damage/2;
					}

					// 소드웨이브와는 달리 크로스 카운터 체크는 하지 않는다.
					ObjectID_t targetObjectID = pTargetCreature->getObjectID();
					cList.push_back(pTargetCreature);
					_GCSkillToTileOK1.addCListElement(targetObjectID);
					_GCSkillToTileOK2.addCListElement(targetObjectID);
					_GCSkillToTileOK5.addCListElement(targetObjectID);
							
					setDamage(pTargetCreature, Damage, pSlayer, getSkillType(), NULL, &_GCSkillToTileOK1);
					computeAlignmentChange(pTargetCreature, Damage, pSlayer, NULL, &_GCSkillToTileOK1);

					// 크리티컬 히트라면 상대방을 뒤로 물러나게 한다.
					if (bCriticalHit)
					{
						knockbackCreature(pZone, pTargetCreature, pSlayer->getX(), pSlayer->getY());
					}

					// 슬레이어가 아닐 경우에만 맞춘 걸로 간주한다.
					if (!pTargetCreature->isSlayer())
					{
						bHit = true;
						if (maxEnemyLevel < pTargetCreature->getLevel() ) maxEnemyLevel = pTargetCreature->getLevel();
						EnemyNum++;
					}
				}
			}

			if (bHit)
			{
				if (bIncreaseExp)
				{
					increaseDomainExp(pSlayer, DomainType , pSkillInfo->getPoint(), _GCSkillToTileOK1, maxEnemyLevel, EnemyNum);
					shareAttrExp(pSlayer, Damage , 1, 8, 1, _GCSkillToTileOK1);
				}
				increaseSkillExp(pSlayer, DomainType,  pSkillSlot, pSkillInfo, _GCSkillToTileOK1);
			}

			_GCSkillToTileOK1.addShortData(MODIFY_BULLET, RemainBullet);

			decreaseDurability(pSlayer, NULL, pSkillInfo, &_GCSkillToTileOK1, NULL);

			_GCSkillToTileOK1.setSkillType(getSkillType());
			_GCSkillToTileOK1.setCEffectID(CEffectID);
			_GCSkillToTileOK1.setX(X);
			_GCSkillToTileOK1.setY(Y);
			_GCSkillToTileOK1.setRange(dir);
			_GCSkillToTileOK1.setDuration(0);
		
			_GCSkillToTileOK2.setObjectID(pSlayer->getObjectID());
			_GCSkillToTileOK2.setSkillType(getSkillType());
			_GCSkillToTileOK2.setX(X);
			_GCSkillToTileOK2.setY(Y);
			_GCSkillToTileOK2.setRange(dir);
			_GCSkillToTileOK2.setDuration(0);

			_GCSkillToTileOK3.setObjectID(pSlayer->getObjectID());
			_GCSkillToTileOK3.setSkillType(getSkillType());
			_GCSkillToTileOK3.setX(X);
			_GCSkillToTileOK3.setY(Y);

			_GCSkillToTileOK4.setSkillType(getSkillType());
			_GCSkillToTileOK4.setX(X);
			_GCSkillToTileOK4.setY(Y);
			_GCSkillToTileOK4.setDuration(0);
			_GCSkillToTileOK4.setRange(dir);
		
			_GCSkillToTileOK5.setObjectID(pSlayer->getObjectID());
			_GCSkillToTileOK5.setSkillType(getSkillType());
			_GCSkillToTileOK5.setX(X);
			_GCSkillToTileOK5.setY(Y);
			_GCSkillToTileOK5.setRange(dir);
			_GCSkillToTileOK5.setDuration(0);
			
			pPlayer->sendPacket(&_GCSkillToTileOK1);
		
			// 이 기술에 의해 영향을 받는 놈들에게 패킷을 보내줘야 한다.
			for(list<Creature*>::const_iterator itr = cList.begin(); itr != cList.end(); itr++)
			{
				Creature* pTargetCreature = *itr;
				Assert(pTargetCreature != NULL);

				if (pTargetCreature->isPC())
				{
					_GCSkillToTileOK2.clearList();

					HP_t targetHP = 0;
					if (pTargetCreature->isSlayer())
					{
						targetHP = (dynamic_cast<Slayer*>(pTargetCreature))->getHP();
					}
					else if (pTargetCreature->isVampire())
					{
						targetHP = (dynamic_cast<Vampire*>(pTargetCreature))->getHP();
					}

					_GCSkillToTileOK2.addShortData(MODIFY_CURRENT_HP, targetHP);

					// 아이템의 내구력을 떨어뜨린다.
					decreaseDurability(NULL, pTargetCreature, pSkillInfo, NULL, &_GCSkillToTileOK2);

					// 패킷을 보내준다.
					Player* pPlayer = pTargetCreature->getPlayer();
					Assert(pPlayer != NULL);
					pPlayer->sendPacket(&_GCSkillToTileOK2);
				}
				else if (pTargetCreature->isMonster())
				{
					// 당근 적으로 인식한다.
					Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature);
					pMonster->addEnemy(pSlayer);
				}
			}

			cList.push_back(pSlayer);

			cList = pZone->broadcastSkillPacket(myX, myY, X, Y, &_GCSkillToTileOK5, cList);

			pZone->broadcastPacket(myX, myY,  &_GCSkillToTileOK3 , cList);
			pZone->broadcastPacket(X, Y,  &_GCSkillToTileOK4 , cList);

			pSkillSlot->setRunTime(output.Delay);
		} 
		else 
		{
			executeSkillFailNormalWithGun(pSlayer, getSkillType(), NULL, RemainBullet);
		}
	} 
	catch (Throwable & t) 
	{
		executeSkillFailException(pSlayer, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " SGexecute End" << endl;

	__END_CATCH
}
Example #7
0
//////////////////////////////////////////////////////////////////////////////
// 뱀파이어 타일 핸들러
//////////////////////////////////////////////////////////////////////////////
void IceField::execute(Ousters* pOusters, ZoneCoord_t X, ZoneCoord_t Y, OustersSkillSlot* pOustersSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

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

	Assert(pOusters != NULL);
	Assert(pOustersSkillSlot != NULL);

	try 
	{
		Player* pPlayer = pOusters->getPlayer();
		Zone* pZone = pOusters->getZone();

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

		Item* pWeapon = pOusters->getWearItem(Ousters::WEAR_RIGHTHAND);
		if (pWeapon == NULL || pWeapon->getItemClass() != Item::ITEM_CLASS_OUSTERS_WRISTLET || !pOusters->isRealWearingEx(Ousters::WEAR_RIGHTHAND))
		{
			executeSkillFailException(pOusters, pOustersSkillSlot->getSkillType());
			return;
		}

		GCSkillToTileOK1 _GCSkillToTileOK1;
		GCSkillToTileOK2 _GCSkillToTileOK2;
		GCSkillToTileOK3 _GCSkillToTileOK3;
		GCSkillToTileOK4 _GCSkillToTileOK4;
		GCSkillToTileOK5 _GCSkillToTileOK5;
		GCSkillToTileOK6 _GCSkillToTileOK6;

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

		ZoneCoord_t myX = pOusters->getX();
		ZoneCoord_t myY = pOusters->getY();

		// 이펙트의 지속시간을 계산한다.
		SkillInput input(pOusters, pOustersSkillSlot);
		SkillOutput output;
		computeOutput(input, output);

		int  RequiredMP  = (int)pSkillInfo->getConsumeMP() + pOustersSkillSlot->getExpLevel();
		bool bManaCheck  = hasEnoughMana(pOusters, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pOustersSkillSlot);
		bool bRangeCheck = verifyDistance(pOusters, X, Y, pSkillInfo->getRange());
		bool bHitRoll    = HitRoll::isSuccessMagic(pOusters, pSkillInfo, pOustersSkillSlot);
		bool bSatisfyRequire = pOusters->satisfySkillRequire(pSkillInfo);
		
		bool bTileCheck = false;
		VSRect rect(0, 0, pZone->getWidth()-1, pZone->getHeight()-1);
		if (rect.ptInRect(X, Y)) bTileCheck = true;

		if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bTileCheck && bSatisfyRequire)
		{
			decreaseMana(pOusters, RequiredMP, _GCSkillToTileOK1);

			int grade = 0;

			if (input.SkillLevel <= 10 ) grade = 0;
			else if (input.SkillLevel <= 20 ) grade = 1;
			else if (input.SkillLevel < 30 ) grade = 2;
			else grade = 3;

			list<Creature*> cList;	// denier list
			
			for (int i=0; i<m_MaskNum[grade]; i++)
			{
				POINT& pt = m_IceFieldMask[grade][i];

				int tileX = X+pt.x;
				int tileY = Y+pt.y;

				if (rect.ptInRect(tileX, tileY))
				{
					Tile& tile = pZone->getTile(tileX, tileY);
					if (tile.getEffect(Effect::EFFECT_CLASS_TRYING_POSITION) ) continue;

					// 현재 타일에다 이펙트를 추가할 수 있다면...
					if (tile.canAddEffect())
					{
						// 같은 effect가 있으면 지운다.
						Effect* pOldEffect = tile.getEffect(Effect::EFFECT_CLASS_ICE_FIELD);
						if (pOldEffect != NULL)
						{
							ObjectID_t effectID = pOldEffect->getObjectID();
							pZone->deleteEffect(effectID);// fix me
						}

						// 이펙트 클래스를 생성한다.
						EffectIceField* pEffect = new EffectIceField(pZone , tileX, tileY);
						pEffect->setCasterName(pOusters->getName());
						pEffect->setCasterID(pOusters->getObjectID());
						pEffect->setDeadline(output.Duration);
						pEffect->setDuration(output.Range);
						pEffect->setNextTime(0);
						pEffect->setTick(output.Tick);

						// Tile에 붙이는 Effect는 ObjectID를 등록받아야 한다.
						ObjectRegistry & objectregister = pZone->getObjectRegistry();
						objectregister.registerObject(pEffect);
						pZone->addEffect(pEffect);
						tile.addEffect(pEffect);

						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() || pTargetCreature->isVampire() )
								&& !checkZoneLevelToHitTarget(pTargetCreature )
							) 
							{
								cList.push_back(pTargetCreature);
								_GCSkillToTileOK2.addCListElement(pTargetCreature->getObjectID());
								_GCSkillToTileOK4.addCListElement(pTargetCreature->getObjectID());
								_GCSkillToTileOK5.addCListElement(pTargetCreature->getObjectID());

								pEffect->affect(pTargetCreature);
							}
//								pEffect->affect(pTarget);
						}
					}	
				}	
			}

			_GCSkillToTileOK1.setSkillType(SkillType);
			_GCSkillToTileOK1.setCEffectID(CEffectID);
			_GCSkillToTileOK1.setX(X);
			_GCSkillToTileOK1.setY(Y);
			_GCSkillToTileOK1.setDuration(output.Duration);
			_GCSkillToTileOK1.setRange(grade);

			_GCSkillToTileOK2.setObjectID(pOusters->getObjectID());
			_GCSkillToTileOK2.setSkillType(SkillType);
			_GCSkillToTileOK2.setX(X);
			_GCSkillToTileOK2.setY(Y);
			_GCSkillToTileOK2.setDuration(output.Duration);
			_GCSkillToTileOK2.setRange(grade);
			//_GCSkillToTileOK2.addShortData(MODIFY_VISION, ICE_FIELD_SIGHT);

			_GCSkillToTileOK3.setObjectID(pOusters->getObjectID());
			_GCSkillToTileOK3.setSkillType(SkillType);
			_GCSkillToTileOK3.setX(X);
			_GCSkillToTileOK3.setY(Y);

			_GCSkillToTileOK4.setSkillType(SkillType);
			_GCSkillToTileOK4.setX(X);
			_GCSkillToTileOK4.setY(Y);
			_GCSkillToTileOK4.setRange(grade);
			_GCSkillToTileOK4.setDuration(output.Duration);

			_GCSkillToTileOK5.setObjectID(pOusters->getObjectID());
			_GCSkillToTileOK5.setSkillType(SkillType);
			_GCSkillToTileOK5.setX(X);
			_GCSkillToTileOK5.setY(Y);
			_GCSkillToTileOK5.setRange(grade);
			_GCSkillToTileOK5.setDuration(output.Duration);

			_GCSkillToTileOK6.setOrgXY(myX, myY);
			_GCSkillToTileOK6.setSkillType(SkillType);
			_GCSkillToTileOK6.setX(X);
			_GCSkillToTileOK6.setY(Y);
			_GCSkillToTileOK6.setDuration(output.Duration);
			_GCSkillToTileOK6.setRange(grade);
			//_GCSkillToTileOK6.addShortData(MODIFY_VISION, ICE_FIELD_SIGHT);

			for(list<Creature*>::const_iterator itr = cList.begin(); itr != cList.end(); itr++)
			{
				Creature* pTargetCreature = *itr;
				if (canSee(pTargetCreature, pOusters)) pTargetCreature->getPlayer()->sendPacket(&_GCSkillToTileOK2);
				else pTargetCreature->getPlayer()->sendPacket(&_GCSkillToTileOK6);
			}

			pPlayer->sendPacket(&_GCSkillToTileOK1);

			cList.push_back(pOusters);

			list<Creature*> watcherList = pZone->getWatcherList(myX, myY, pOusters);

			// watcherList에서 cList에 속하지 않고, caster(pOusters)를 볼 수 없는 경우는
			// OK4를 보내고.. cList에 추가한다.
			for(list<Creature*>::const_iterator itr = watcherList.begin(); itr != watcherList.end(); itr++)
			{
				bool bBelong = false;
				for(list<Creature*>::const_iterator tItr = cList.begin(); tItr != cList.end(); tItr++)
					if (*itr == *tItr)
						bBelong = true;

				Creature* pWatcher = (*itr);
				if (bBelong == false && canSee(pWatcher, pOusters) == false)
				{
					//Assert(pWatcher->isPC());	// 당연 PC다.. Zone::getWatcherList는 PC만 return한다
					if (!pWatcher->isPC())
					{
						//cout << "IceField : 왓처 리스트가 PC가 아닙니다." << endl;
//						GCSkillFailed1 _GCSkillFailed1;
//						_GCSkillFailed1.setSkillType(getSkillType());
//						pOusters->getPlayer()->sendPacket(&_GCSkillFailed1);

						//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;
//						return;
						continue;
					}
					pWatcher->getPlayer()->sendPacket(&_GCSkillToTileOK4);
					cList.push_back(*itr);
				}
			}
					
			cList = pZone->broadcastSkillPacket(myX, myY, X, Y, &_GCSkillToTileOK5, cList, false);
			
			pZone->broadcastPacket(myX, myY,  &_GCSkillToTileOK3 , cList);
			
			pZone->broadcastPacket(X, Y,  &_GCSkillToTileOK4 , cList);

			pOustersSkillSlot->setRunTime(output.Delay);
		} 
		else 
		{
			executeSkillFailNormal(pOusters, getSkillType(), NULL);
		}
	} 
	catch (Throwable & t) 
	{
		executeSkillFailException(pOusters, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;

	__END_CATCH
}
Example #8
0
//////////////////////////////////////////////////////////////////////////////
// 뱀파이어 오브젝트 핸들러
//////////////////////////////////////////////////////////////////////////////
void BloodDrain::execute(Vampire* pVampire, ObjectID_t TargetObjectID)
	throw(Error)
{
	__BEGIN_TRY

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

	Assert(pVampire != NULL);

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

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

		// NPC는 공격할 수가 없다.
		// 면역 상태. by sigi. 2002.9.13
		// 무적상태 체크. by sigi.2002.9.5
		// 죽은 애는 피 빨 수 없다. by Sequoia.2003. 3. 20
		if (pTargetCreature==NULL		// NoSuch 제거. by sigi. 2002.5.2
			|| pTargetCreature->isNPC()
			|| pTargetCreature->isFlag(Effect::EFFECT_CLASS_IMMUNE_TO_BLOOD_DRAIN)
			|| !canAttack(pVampire, pTargetCreature )
			|| pTargetCreature->isFlag(Effect::EFFECT_CLASS_COMA)
			|| pTargetCreature->isDead()
		)
		{
			executeSkillFailException(pVampire, getSkillType());
			//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End(vampire)" << endl;
			return;
		}

		GCBloodDrainOK1 _GCBloodDrainOK1;
		GCBloodDrainOK2 _GCBloodDrainOK2;
		GCBloodDrainOK3 _GCBloodDrainOK3;

		Timeval CurrentTime;
		getCurrentTime(CurrentTime);

		bool bHitRoll    = HitRoll::isSuccessBloodDrain(pVampire, pTargetCreature);
		bool bCanHit     = canHit(pVampire, pTargetCreature, SKILL_BLOOD_DRAIN);
		bool bTimeCheck  = CurrentTime.tv_sec > 1 ? true : false;
		bool bRangeCheck = verifyDistance(pVampire, pTargetCreature, 2);
		bool bPK         = verifyPK(pVampire, pTargetCreature);

		if (bHitRoll && bCanHit && bTimeCheck && bRangeCheck && bPK)
		{
			// 슬레이어일 경우에만 이펙트 오브젝트를 생성한다.
			if (pTargetCreature->isSlayer())
			{
				EffectBloodDrain* pEffectBloodDrain = new EffectBloodDrain(pTargetCreature);
				pEffectBloodDrain->setLevel(pVampire->getLevel());
				pEffectBloodDrain->setDeadline(BLOODDRAIN_DURATION);	// 3일??
				pTargetCreature->addEffect(pEffectBloodDrain);
				pEffectBloodDrain->create(pTargetCreature->getName());
				_GCBloodDrainOK2.addShortData(MODIFY_EFFECT_STAT, Effect::EFFECT_CLASS_BLOOD_DRAIN);

				// 타겟이 뭐든 플래그는 건다.
				pTargetCreature->setFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN);

				Slayer* pTargetSlayer = dynamic_cast<Slayer*>(pTargetCreature);
				SLAYER_RECORD prev;
				pTargetSlayer->getSlayerRecord(prev);
				pTargetSlayer->initAllStat();
				pTargetSlayer->sendRealWearingInfo();
				pTargetSlayer->addModifyInfo(prev, _GCBloodDrainOK2);

				// 로그를 남긴다.
				//log(LOG_BLOODDRAINED, pTargetCreature->getName(), pVampire->getName());
			}
			// 아우스터즈의 경우엔..... -_-; 제한시간 없는 이펙트를 생성한다. 엄밀히 말해 제한시간이 없는 건 아니지만..
//			else if (pTargetCreature->isOusters() )
//			{
//				EffectBloodDrain* pEffectBloodDrain = new EffectBloodDrain(pTargetCreature);
//				pEffectBloodDrain->setLevel(pVampire->getLevel());
//				pTargetCreature->addEffect(pEffectBloodDrain);
//				pEffectBloodDrain->create(pTargetCreature->getName());
//				_GCBloodDrainOK2.addShortData(MODIFY_EFFECT_STAT, Effect::EFFECT_CLASS_BLOOD_DRAIN);
//
//				// 타겟이 뭐든 플래그는 건다.
//				pTargetCreature->setFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN);
//
//				Sight_t oldSight = pTargetCreature->getSight();
//				Sight_t newSight = pTargetCreature->getEffectedSight();
//
//				if (oldSight != newSight )
//				{
//					pTargetCreature->setSight(newSight);
//					pZone->updateScan(pTargetCreature, oldSight, pTargetCreature->getSight());
//					_GCBloodDrainOK2.addShortData(MODIFY_VISION, pTargetCreature->getSight());
//
//					GCChangeDarkLight gcChangeDarkLight;
//					gcChangeDarkLight.setDarkLevel(15);
//					gcChangeDarkLight.setLightLevel(newSight);
//					pTargetCreature->getPlayer()->sendPacket(&gcChangeDarkLight);
//				}
//			}

			// 타겟이 뭐든 플래그는 건다.
			pTargetCreature->setFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN);
			
			// 올릴 경험치량을 계산한다.
			Exp_t Exp = computeCreatureExp(pTargetCreature, BLOODDRAIN_EXP);

			int targetLevel = 0;
			int targetMaxHP = 0;
			// 페임을 올려준다.
			if (pTargetCreature->isSlayer()) 
			{
				//increaseFame(pVampire, Exp);
				Slayer* pTargetSlayer  = dynamic_cast<Slayer*>(pTargetCreature);
				targetLevel = pTargetSlayer->getHighestSkillDomainLevel();
				targetMaxHP = pTargetSlayer->getHP(ATTR_MAX);
			}
			else if (pTargetCreature->isVampire()) 
			{
				//increaseFame(pVampire, Exp);
				Vampire* pTargetVampire  = dynamic_cast<Vampire*>(pTargetCreature);
				targetLevel = pTargetVampire->getLevel();
				targetMaxHP = pTargetVampire->getHP(ATTR_MAX);
			}
			else if (pTargetCreature->isOusters()) 
			{
				//increaseFame(pOusters, Exp);
				Ousters* pTargetOusters  = dynamic_cast<Ousters*>(pTargetCreature);
				targetLevel = pTargetOusters->getLevel();
				targetMaxHP = pTargetOusters->getHP(ATTR_MAX);
			}
			else if (pTargetCreature->isMonster())
			{
				Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature);

				Timeval NextTurn = pMonster->getNextTurn();
				Timeval DelayTurn;
				DelayTurn.tv_sec = 4;
				DelayTurn.tv_usec = 500000;
				pMonster->addAccuDelay(DelayTurn);
				pMonster->addEnemy(pVampire);

				targetLevel = pMonster->getLevel();
				targetMaxHP = pMonster->getHP(ATTR_MAX);
			}

			shareVampExp(pVampire, Exp, _GCBloodDrainOK1);

			// 흡혈을 하게 되면 흡혈한 사람의 체력이 올라간다.
			// Mephisto이펙트가 걸려있으면 HP는 안 올라간다.
			if (!pVampire->isFlag(Effect::EFFECT_CLASS_MEPHISTO))
			{
				HP_t HealPoint = (Exp==0? computeBloodDrainHealPoint(pTargetCreature, BLOODDRAIN_EXP) : Exp);
				HP_t CurrentHP = pVampire->getHP();
				HP_t MaxHP	   = pVampire->getHP(ATTR_MAX);
				HP_t NewHP     = min((int)MaxHP , (int)CurrentHP + (int)HealPoint);

				// 은 데미지 관련 처리를 해 준다.
				Silver_t newSilverDamage = max(0, (int)pVampire->getSilverDamage()-(int)HealPoint);
				pVampire->saveSilverDamage(newSilverDamage);
				_GCBloodDrainOK1.addShortData(MODIFY_SILVER_DAMAGE, newSilverDamage);

				// 뱀파이어의 HP를 세팅한다.
				pVampire->setHP(NewHP);

				GCStatusCurrentHP gcStatusCurrentHP;
				gcStatusCurrentHP.setObjectID(pVampire->getObjectID());
				gcStatusCurrentHP.setCurrentHP(NewHP);
				pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &gcStatusCurrentHP, pVampire);

				_GCBloodDrainOK1.addShortData(MODIFY_CURRENT_HP, NewHP);
			}

			// 흡혈을 당한 애는 HP가 줄어든다.
			// 대상이 내 레벨보다 높다면.. MaxHP의 10~15% damage
			// by sigi. 2002.9.14
			int drainDamage = 0;
			int myLevel = pVampire->getLevel();

			if (targetLevel > myLevel)
			{
				drainDamage = targetMaxHP * (rand()%6+10) / 100;
			}
			else
			{
				// 레벨 5차이마다 1%씩 더~
				int damagePercent = min(30, (rand()%6+10+(myLevel-targetLevel)));
				drainDamage = targetMaxHP * damagePercent / 100;
			}
			
			if (drainDamage > 0)
			{
				//decreaseHP(pZone, pTargetCreature, drainDamage, pVampire->getObjectID()); 
				EffectDecreaseHP* pEffect = new EffectDecreaseHP(pTargetCreature);
				pEffect->setPoint(drainDamage);
				pEffect->setDeadline(20);	// 2초 후
				pEffect->setUserObjectID(pVampire->getObjectID());
				pTargetCreature->addEffect(pEffect);
				pTargetCreature->setFlag(Effect::EFFECT_CLASS_DECREASE_HP);
			}

			pVampire->getGQuestManager()->blooddrain();

			// 흡혈시에도 성향 바뀜
			// by sigi. 2002.12.16
			// EffectDecreaseHP에서 HP가 닳아서 0이 되어야하는 경우가 있어서 
			// EffectDecreaseHP::unaffect()로 옮긴다.
			//computeAlignmentChange(pTargetCreature, drainDamage, pVampire, NULL, &_GCBloodDrainOK1);

			_GCBloodDrainOK1.setObjectID(TargetObjectID);

			_GCBloodDrainOK3.setObjectID(pVampire->getObjectID());
			_GCBloodDrainOK3.setTargetObjectID (TargetObjectID);

			pPlayer->sendPacket(&_GCBloodDrainOK1);

			if (pTargetCreature != NULL && pTargetCreature->isPC()) 
			{
				Player* pTargetPlayer = pTargetCreature->getPlayer();

				if (pTargetPlayer != NULL) 
				{ 
					_GCBloodDrainOK2.setObjectID(pVampire->getObjectID());
//					_GCBloodDrainOK2.addLongData(MODIFY_DURATION, BLOODDRAIN_DURATION);
					pTargetPlayer->sendPacket(&_GCBloodDrainOK2);
				}
			}

			list<Creature *> cList;
			cList.push_back(pTargetCreature);
			cList.push_back(pVampire);
			pZone->broadcastPacket(pVampire->getX(), pVampire->getY(),  &_GCBloodDrainOK3 , cList);
		}
		else 
		{
			executeSkillFailNormal(pVampire, getSkillType(), pTargetCreature);
		}
	} 
	catch (Throwable & t) 
	{
		executeSkillFailException(pVampire, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End(vampire)" << endl;

	__END_CATCH

}
//////////////////////////////////////////////////////////////////////////////
// 
// 일반 아이템을 처리한다.
//
//////////////////////////////////////////////////////////////////////////////
void CGShopRequestSellHandler::executeNormal (CGShopRequestSell* pPacket , Player* pPlayer)
	 throw(ProtocolException , Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

	ObjectID_t      NPCID        = pPacket->getObjectID();
	ObjectID_t      ITEMOID      = pPacket->getItemObjectID();
	GamePlayer*     pGamePlayer  = dynamic_cast<GamePlayer*>(pPlayer);
	Creature*       pCreature    = pGamePlayer->getCreature();
	PlayerCreature* pPC          = dynamic_cast<PlayerCreature*>(pCreature);
	BYTE            index        = 0;
	bool            bSpecialItem = false;

	Zone* pZone = pPC->getZone();
	if (pZone == NULL) return sendFailPacket(pPacket, pPlayer);

	Creature* pNPCBase = NULL;
	/*
	try 
	{ 
		pNPCBase = pZone->getCreature(NPCID); 
	}
	catch (NoSuchElementException & nsee) 
	{ 
		pNPCBase = NULL; 
	}
	*/

	// NoSuch제거. by sigi. 2002.5.2
	pNPCBase = pZone->getCreature(NPCID); 

	if (pNPCBase == NULL || !pNPCBase->isNPC()) return sendFailPacket(pPacket, pPlayer);

	NPC* pNPC = dynamic_cast<NPC*>(pNPCBase);
	
	// 플레이어가 팔려고 하는 아이템을 가지고 있는지 검사
	Inventory* pInventory  = pPC->getInventory();
	//Gold_t     playerMoney = pPC->getGold(); 
	Item*      pItem       = pInventory->getItemWithObjectID(ITEMOID);
	ItemNum_t  itemNumber  = pItem->getNum();
	Price_t    itemPrice   = g_pPriceManager->getPrice(pItem, pNPC->getMarketCondBuy(), SHOP_RACK_NORMAL, pPC) * itemNumber;

	// 플레이어의 인벤토리에 아이템을 제거한다.
	pInventory->deleteItem(ITEMOID);
	pItem->whenPCLost(pPC);

	if (!pItem->destroy()) {
		filelog("shopDBBug.txt", "NoSuchItemInDB-destroy: %s", pItem->toString().c_str());

		throw DisconnectException("아이템 지울려는데 DB에 없다.");
	}

	// 만약 벨트라면 안에 있는 포션을 삭제해준다.
	// DB에서 지우는 것은 Belt::destroy()를 부르는 것만으로 포션까지 삭제된다.
	if (pItem->getItemClass() == Item::ITEM_CLASS_BELT) {
		Inventory* pBeltInventory = dynamic_cast<Belt*>(pItem)->getInventory();
		for (int y=0; y<pBeltInventory->getHeight(); y++) {
			for (int x=0; x<pBeltInventory->getWidth(); x++) {
				Item* pBeltItem = pBeltInventory->getItem(x, y);
				if (pBeltItem != NULL) {
					pBeltInventory->deleteItem(x, y);
					SAFE_DELETE(pBeltItem);
				}
			}
		}
	}

	// Skull 일 경우 Variable Manager 에서 머리값 배수 값으로 가격을 새로 계산한다
	if (pItem->getItemClass() == Item::ITEM_CLASS_SKULL)
		itemPrice = itemPrice * (g_pVariableManager->getHeadPriceBonus() / 100);

	// ItemTrace Log 를 남겨야 한다면 남긴다
	if (pItem != NULL && pItem->isTraceItem() )
		remainTraceLog(pItem, pCreature->getName() , pNPC->getName(), ITEM_LOG_DELETE, DETAIL_SHOPSELL);

	// 플레이어에게 물건값을 지불한다.
	// pPC->setGoldEx(playerMoney+itemPrice);
	// by sigi. 2002.9.4
	pPC->increaseGoldEx(itemPrice);

	// 플레이어가 물건 팔 때 처리할 것들을 처리한다.
	pPC->sellItem(pItem);

	if (pItem->getItemClass() == Item::ITEM_CLASS_MOON_CARD && pItem->getItemType() == 4)
		addOlympicStat(pPC, 4, (uint)(itemNumber));

	bool bClearDefaultOptionTypes = false;
	if (pItem->getItemClass() == Item::ITEM_CLASS_EVENT_ITEM && pItem->getItemType() >= 32 && pItem->getItemType() <= 36)
		bClearDefaultOptionTypes = true;

	// NPC에게 자리가 충분하다면 플레이어가 판 아이템을 보관한다.
	// 운영자 명령어로 만든 아이템은 바로 없앤다.
	// 단 스페셜 아이템만을 보관한다. 노말 아이템은 그냥 버림.
	// 퀘스트 아이템은 보관하지 않고 버린다.
	if (pNPC->getShopType()==SHOPTYPE_NORMAL &&
		pItem->getCreateType()!=Item::CREATE_TYPE_CREATE &&
		!pItem->getOptionTypeList().empty() &&
		!pItem->isTimeLimitItem()) {
		bSpecialItem = true;
		index        = pNPC->getFirstEmptySlot(SHOP_RACK_SPECIAL);

		if (index < SHOP_RACK_INDEX_MAX) {
			// 아이템을 추가한다.
			pNPC->insertShopItem(SHOP_RACK_SPECIAL, index, pItem);

			// 스페셜 아이템을 NPC가 진열장에 추가했으므로, 상점 버전이 올라간다.
			pNPC->increaseShopVersion(SHOP_RACK_SPECIAL);

			////////////////////////////////////////////////////////////////////////////
			// 근처의 플레이어들에게는 GCShopBought를...
			////////////////////////////////////////////////////////////////////////////

			int         CenterX       = pNPC->getX();
			int         CenterY       = pNPC->getY();
			Creature*   pNearCreature = NULL;
			Player*     pNearPlayer   = NULL;

			GCShopBought boughtpkt;
			boughtpkt.setObjectID(NPCID);
			if (!pItem->getOptionTypeList().empty()) {
				boughtpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_SPECIAL));
				boughtpkt.setShopType(SHOP_RACK_SPECIAL);
			} else {
				boughtpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_NORMAL));
				boughtpkt.setShopType(SHOP_RACK_NORMAL);
			}
			boughtpkt.setShopIndex(index);
			boughtpkt.setItemObjectID(ITEMOID);
			boughtpkt.setItemClass(pItem->getItemClass());
			boughtpkt.setItemType(pItem->getItemType());
			boughtpkt.setOptionType(pItem->getOptionTypeList());
			boughtpkt.setDurability(pItem->getDurability());
			boughtpkt.setSilver(pItem->getSilver());
			boughtpkt.setGrade(pItem->getGrade());
			boughtpkt.setEnchantLevel(pItem->getEnchantLevel());

			//pZone->broadcastPacket(pNPC->getX(), pNPC->getY(), &boughtpkt, pPC);

			try
			{
				for (int zx=CenterX-5; zx<=CenterX+5; zx++)
				{
					for (int zy=CenterY-5; zy<=CenterY+5; zy++)
					{
						// 바운드를 넘어가지 않는가를 체크
						if (!isValidZoneCoord(pZone, zx, zy)) continue;

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

						// 걸어다니는 크리쳐를 검색	
						if (tile.hasCreature(Creature::MOVE_MODE_WALKING))
						{
							pNearCreature = tile.getCreature(Creature::MOVE_MODE_WALKING);
							if (pNearCreature == NULL) continue;

							// 방금 물건을 판 플레이어라면 생략
							if (pNearCreature->getObjectID() == pPC->getObjectID()) continue;
							
							// 만약 플레이어라면 패킷을 보내준다.
							if (pNearCreature->isPC())
							{
								pNearPlayer = pNearCreature->getPlayer();
								if (pNearPlayer == NULL) continue;
								pNearPlayer->sendPacket(&boughtpkt);
							}
						}
						// 날아다니는 크리쳐를 검색
						if (tile.hasCreature(Creature::MOVE_MODE_FLYING))
						{
							pNearCreature = tile.getCreature(Creature::MOVE_MODE_FLYING);
							if (pNearCreature == NULL) continue;
							
							// 방금 물건을 판 플레이어라면 생략
							if (pNearCreature->getObjectID() == pPC->getObjectID()) continue;

							// 만약 플레이어라면 패킷을 보내준다.
							if (pNearCreature->isPC())
							{
								pNearPlayer = pNearCreature->getPlayer();
								if (pNearPlayer == NULL) continue;
								pNearPlayer->sendPacket(&boughtpkt);
							}
						}

					} // end of for (ZoneCoord_t zy=CenterY-5; zy<=CenterY+5; zy++)
				} // end of for (ZoneCoord_t zx=CenterX-5; zx<=CenterX+5; zx++)
			}
			catch (Throwable & t)
			{
				filelog("shopbug_packet.log", "%s", t.toString().c_str());
			}

		} // if (index < SHOP_RACK_INDEX_MAX)
		else
		{
			SAFE_DELETE(pItem);
		}
	} // if (pItem->getOptionType() != 0)
	else
	{
		bSpecialItem = false;
		SAFE_DELETE(pItem);
	}

	// 물건을 산 플레이어에게 GCShopSellOK를...보낸다.
	GCShopSellOK okpkt;
	okpkt.setObjectID(NPCID);
	if (bSpecialItem) okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_SPECIAL));
	else              okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_NORMAL));
	okpkt.setItemObjectID(ITEMOID);
	//okpkt.setPrice(playerMoney+itemPrice);
	// playerMoney + itemPrice 가 MAX_MONEY를 넘어갈 수 있다.
	// 2003.1.8 by bezz
	okpkt.setPrice(pPC->getGold());
	pPlayer->sendPacket(&okpkt);
	
	if (bClearDefaultOptionTypes )
	{
		pPC->clearDefaultOptionTypes();
		pPC->initAllStatAndSend();

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

			pSlayer->sendRealWearingInfo();
		}
		else if (pPC->isVampire() )
		{
			Vampire* pVampire = dynamic_cast<Vampire*>(pPC);
			Assert(pVampire != NULL);

			pVampire->sendRealWearingInfo();
		}
		else if (pPC->isOusters() )
		{
			Ousters* pOusters = dynamic_cast<Ousters*>(pPC);
			Assert(pOusters != NULL);

			pOusters->sendRealWearingInfo();
		}
	}

#endif

	__END_DEBUG_EX __END_CATCH
}
Example #10
0
void SimpleMissileSkill::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);


		// NPC는 공격할 수가 없다.
		// NoSuch제거. by sigi. 2002.5.2
		if (pTargetCreature==NULL
			|| !canAttack(pSlayer, pTargetCreature )
			|| pTargetCreature->isNPC())
		{
			executeSkillFailException(pSlayer, param.SkillType);
			return;
		}

		result.pTargetCreature = pTargetCreature;

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

		SkillInfo*        pSkillInfo   = g_pSkillInfoManager->getSkillInfo(param.SkillType);
		SkillDomainType_t DomainType   = pSkillInfo->getDomainType();
		SkillLevel_t      SkillLevel   = pSkillSlot->getExpLevel();
		bool              bCriticalHit = false;
		Damage_t          Damage       = 0;

		if (param.bAdd)
		{
			// 파라미터로 전달된 데미지 값이 더해지는 데미지라면, 
			// 일반 데미지를 계산 후, 데미지를 더해야 한다.
			// 파라미터로 전달된 데미지 값이 직접적으로 쓰이는 데미지라면,
			// 이 부분까지 들어오지 않으므로, 밑의 부분까지 0으로 전달된다.
			Damage += computeDamage(pSlayer, pTargetCreature, SkillLevel/5, bCriticalHit);
		}

		if (param.bMagicDamage)
		{
			// 만일 스킬 데미지가 마법 데미지라면, 마법 데미지 계산 함수를 이용해 계산을 해준다.
			Damage += computeMagicDamage(pTargetCreature, param.SkillDamage, param.SkillType);
		}
		else
		{
			Damage += param.SkillDamage;
		}

		ZoneCoord_t myX     = pSlayer->getX();
		ZoneCoord_t myY     = pSlayer->getY();
		ZoneCoord_t targetX = pTargetCreature->getX();
		ZoneCoord_t targetY = pTargetCreature->getY();
		
		int  RequiredMP  = (int)pSkillInfo->getConsumeMP();
		bool bManaCheck  = hasEnoughMana(pSlayer, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pSkillSlot);
		bool bRangeCheck = verifyDistance(pSlayer, pTargetCreature, pSkillInfo->getRange());
		bool bHitRoll    = false;
		bool bPK         = verifyPK(pSlayer, pTargetCreature);

		if (param.bMagicHitRoll)
		{
			bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot);
		}
		else
		{
			bHitRoll = HitRoll::isSuccess(pSlayer, pTargetCreature, SkillLevel/2);
		}

		if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bPK)
		{
			decreaseMana(pSlayer, RequiredMP, _GCSkillToObjectOK1);

			// 데미지를 가하고, 내구도를 떨어뜨린다.
			setDamage(pTargetCreature, Damage, pSlayer, param.SkillType, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1);
			computeAlignmentChange(pTargetCreature, Damage, pSlayer, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1);
			decreaseDurability(pSlayer, pTargetCreature, NULL, &_GCSkillToObjectOK1, &_GCSkillToObjectOK2);

			// 타겟이 슬레이어가 아닌 경우에만 경험치를 올려준다.
			if (!pTargetCreature->isSlayer())
			{
				shareAttrExp(pSlayer, Damage , param.STRMultiplier, param.DEXMultiplier, param.INTMultiplier, _GCSkillToObjectOK1);
				increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToObjectOK1, pTargetCreature->getLevel());
				increaseSkillExp(pSlayer, DomainType,  pSkillSlot, pSkillInfo, _GCSkillToObjectOK1);
				increaseAlignment(pSlayer, pTargetCreature, _GCSkillToObjectOK1);
			}

			_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.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK5.setSkillType(param.SkillType);
			_GCSkillToObjectOK5.setDuration(0);
			
			// Send Packet
			pPlayer->sendPacket(&_GCSkillToObjectOK1);
		
			if (pTargetCreature->isPC()) 
			{
				Player* pTargetPlayer = pTargetCreature->getPlayer();
				Assert(pTargetPlayer != NULL);
				pTargetPlayer->sendPacket(&_GCSkillToObjectOK2);
			} 
			else if (pTargetCreature->isMonster())
			{
				Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature);
				pMonster->addEnemy(pSlayer);
			}

			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
}
Example #11
0
//////////////////////////////////////////////////////////////////////////////
// 슬레이어 오브젝트 핸들러
//////////////////////////////////////////////////////////////////////////////
void ProtectionFromAcid::execute(Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl;

	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()
			)
		{
			executeSkillFailException(pSlayer, getSkillType());
			//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl;
			return;
		}

		GCSkillToObjectOK1 _GCSkillToObjectOK1;
		GCSkillToObjectOK2 _GCSkillToObjectOK2;
		GCSkillToObjectOK5 _GCSkillToObjectOK5;

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

		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);
		bool bEffected   = pTargetCreature->isFlag(Effect::EFFECT_CLASS_PROTECTION_FROM_ACID);

		if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected)
		{
			// 마나를 줄인다.
			decreaseMana(pSlayer, RequiredMP, _GCSkillToObjectOK1);

			// 경험치를 올려준다.
			SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType));
			Exp_t      ExpUp = 10* (Grade + 1);
			shareAttrExp(pSlayer, ExpUp, 1, 1, 8, _GCSkillToObjectOK1);
			increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToObjectOK1);
			increaseSkillExp(pSlayer, DomainType,  pSkillSlot, pSkillInfo, _GCSkillToObjectOK1);
		
			// 이펙트의 효과와 지속시간을 계산한다.
			SkillInput input(pSlayer, pSkillSlot);
			SkillOutput output;
			input.TargetType = SkillInput::TARGET_OTHER;
			computeOutput(input, output);

			// 이펙트를 생성해서 붙인다.
			EffectProtectionFromAcid* pEPFP = new EffectProtectionFromAcid (pTargetCreature);
			Assert(pEPFP != NULL);
			pEPFP->setDeadline(output.Duration);
			pEPFP->setResist(output.Damage); 
			pTargetCreature->addEffect(pEPFP);
			pTargetCreature->setFlag(Effect::EFFECT_CLASS_PROTECTION_FROM_ACID);

			if (pTargetCreature->isSlayer())
			{
				Slayer* pTargetSlayer = dynamic_cast<Slayer*>(pTargetCreature);

				SLAYER_RECORD prev;
				pTargetSlayer->getSlayerRecord(prev);
				pTargetSlayer->initAllStat();
				pTargetSlayer->addModifyInfo(prev, _GCSkillToObjectOK1);
			}
			else
			{
				Assert(false);
			}

			// 패킷을 준비해서 보낸다.
			_GCSkillToObjectOK1.setSkillType(SkillType);
			_GCSkillToObjectOK1.setCEffectID(CEffectID);
			_GCSkillToObjectOK1.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK1.setDuration(output.Duration);

			_GCSkillToObjectOK2.setObjectID(pSlayer->getObjectID());
			_GCSkillToObjectOK2.setSkillType(SkillType);
			_GCSkillToObjectOK2.setDuration (output.Duration);

			_GCSkillToObjectOK5.setObjectID(pSlayer->getObjectID());
			_GCSkillToObjectOK5.setSkillType(SkillType);
			_GCSkillToObjectOK5.setTargetObjectID (TargetObjectID);
			_GCSkillToObjectOK5.setDuration (output.Duration);

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

			if (pSlayer != pTargetCreature && pTargetCreature->isPC()) 
			{
				Player* pTargetPlayer = pTargetCreature->getPlayer();
				Assert(pTargetPlayer != NULL);
				pTargetPlayer->sendPacket(&_GCSkillToObjectOK2);
			}

			list<Creature*> cList;
			cList.push_back(pSlayer);
			cList.push_back(pTargetCreature);
		
			pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(),  &_GCSkillToObjectOK5 , cList);

			// 이펙트가 붙었다고 알려준다.
			GCAddEffect gcAddEffect;
			gcAddEffect.setObjectID(pTargetCreature->getObjectID());
			gcAddEffect.setEffectID(Effect::EFFECT_CLASS_PROTECTION_FROM_ACID);
			gcAddEffect.setDuration(output.Duration);
			pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &gcAddEffect);

			pSkillSlot->setRunTime(output.Delay);
		} 
		else 
		{
			executeSkillFailNormal(pSlayer, getSkillType(), pTargetCreature);
		}
	} 
	catch (Throwable & t) 
	{
		executeSkillFailException(pSlayer, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl;

	__END_CATCH
}
void CGAddMouseToInventoryHandler::execute(CGAddMouseToInventory* pPacket , Player* pPlayer)
	throw(ProtocolException, Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

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

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

		Creature* pCreature = pGamePlayer->getCreature();
		Assert(pCreature != NULL);
		Assert(pCreature->isPC());

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

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

		Inventory* pInventory = pPC->getInventory();
		Assert(pInventory != NULL);

		Item* pItem   = pPC->getExtraInventorySlot()->getItem();
		bool  Success = false;

		if (pItem == NULL) {
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}
        int invenID = 0;
/* Commenting the SubInventory stuff, since it's not supported by the client we use
		SubInventory* pInventoryItem = NULL;
		int invenID = 0;

		if (pPacket->getInventoryItemObjectID() != 0 )
		{
//			cout << "서브 인벤토리에 넣기 : " << pPacket->getInventoryItemObjectID() << endl;
			CoordInven_t X, Y;
			pInventoryItem = dynamic_cast<SubInventory*>(pInventory->findItemOID(pPacket->getInventoryItemObjectID(), X, Y ));

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

			if (pInventoryItem == NULL || pItem->getItemClass() == Item::ITEM_CLASS_SUB_INVENTORY || pTradeManager->hasTradeInfo(pPC->getName()) )
			{
//				cout << "근데 서브 인벤토리가 없다." <<endl;
				GCCannotAdd _GCCannotAdd;
				_GCCannotAdd.setObjectID(pPacket->getObjectID());
				pPlayer->sendPacket(&_GCCannotAdd);
				return;
			}

			pInventory = pInventoryItem->getInventory();
			invenID = pInventoryItem->getItemID();
		}
*/
		//Item::ItemClass itemClass = pItem->getItemClass();
		//ItemType_t	itemType	 = pItem->getItemType();
		ObjectID_t  itemObjectID = pItem->getObjectID();
		CoordInven_t InvenX      = pPacket->getInvenX();
		CoordInven_t InvenY      = pPacket->getInvenY();

		if (InvenX >= pInventory->getWidth() || InvenY >= pInventory->getHeight() || itemObjectID != pPacket->getObjectID() ||
			!pInventory->canAdding(InvenX, InvenY, pItem)) {
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		TPOINT pt;
		pt.x = 99;
		pt.y = 99;

		// 넣을려는 Inventory Slot의 Item을 받아온다.
		Item* pPrevItem = pInventory->searchItem(InvenX, InvenY , pItem, pt);

		// 그 장소에 아이템이 있다면
		if (pPrevItem != NULL) {
			bool bisSame = true;
			// 아이템 클래스가 같을때 숫자를 올려 주고 마우스에 있는 것은 없앤다.
			if (canStack(pItem, pPrevItem)) {
				int MaxStack = ItemMaxStack[pItem->getItemClass()];

				VolumeWidth_t  ItemWidth  = pItem->getVolumeWidth();
				VolumeHeight_t ItemHeight = pItem->getVolumeHeight();
				VolumeWidth_t  InvenWidth = pInventory->getWidth();
				VolumeWidth_t  InvenHeight= pInventory->getHeight();


				if ((InvenX + ItemWidth <= InvenWidth) && (InvenY + ItemHeight <= InvenHeight)) {
					for (int x = InvenX; x < (InvenX + ItemWidth); x++) {
						for (int y = InvenY; y < (InvenY + ItemHeight); y++) {
							if (pInventory->hasItem(x, y)) {
								if(pInventory->getItem(x,y) != pPrevItem ) {
									bisSame = false;
									break;
								}
							} else {
								bisSame = false;
								break;
							}
						}
					}
				}

				// 들어갈 아이템과 들어있는 아이템의 좌표가 꼭 일치 한다면?
				if(bisSame) {
					// 숫자가 9개를 넘으면 9개 될때까지만 Add 하고 나머지는 마우스에 달아둔다.
					if (pItem->getNum() + pPrevItem->getNum() > MaxStack) {
						ItemNum_t CurrentNum = pPrevItem->getNum();
						ItemNum_t AddNum = pItem->getNum();
						ItemNum_t NewNum = AddNum + CurrentNum - MaxStack;

						pPrevItem->setNum(MaxStack);
						pItem->setNum(NewNum);
						pInventory->increaseNum(MaxStack - CurrentNum);
						pInventory->increaseWeight(pItem->getWeight()* (MaxStack - CurrentNum));
						//pPrevItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY);
						// item저장 최적화. by sigi. 2002.5.13
						char pField[80];
						sprintf(pField, "Num=%d, Storage=%d, StorageID=%d, X=%d, Y=%d", MaxStack, STORAGE_INVENTORY, invenID, InvenX, InvenY);
						pPrevItem->tinysave(pField);

						//pItem->save(pPC->getName(), STORAGE_EXTRASLOT, 0, 0, 0);
						// item저장 최적화. by sigi. 2002.5.13
						sprintf(pField, "Num=%d, Storage=%d", NewNum, STORAGE_EXTRASLOT);
						pItem->tinysave(pField);

						Success = true;
					} else {
						pPC->deleteItemFromExtraInventorySlot();
						pPrevItem->setNum(pPrevItem->getNum() + pItem->getNum());
						pInventory->increaseNum(pItem->getNum());
						pInventory->increaseWeight(pItem->getWeight()* pItem->getNum());
						//pPrevItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY);
						// item저장 최적화. by sigi. 2002.5.13
						char pField[80];
						sprintf(pField, "Num=%d, Storage=%d, StorageID=%u, X=%d, Y=%d", pPrevItem->getNum(), STORAGE_INVENTORY, invenID, InvenX, InvenY);
						pPrevItem->tinysave(pField);

						pItem->destroy();
						SAFE_DELETE(pItem);
						Success = true;
					}

					if (g_pVariableManager->getVariable(NETMARBLE_CARD_EVENT) != 0 && pPrevItem->getItemClass() == Item::ITEM_CLASS_MOON_CARD && pPrevItem->getItemType() == 2 && pPrevItem->getNum() == 99) {
						GCNoticeEvent gcNE;
						gcNE.setCode(NOTICE_EVENT_NETMARBLE_CARD_FULL);
						pGamePlayer->sendPacket(&gcNE);
						//cout << "gcNE sent" << endl;
					}

					if (pPrevItem->getItemClass() == Item::ITEM_CLASS_LUCKY_BAG
						&& pPrevItem->getItemType() == 3
						&& pPrevItem->getNum() == 50 ) {
						GCDeleteInventoryItem gcDI;
						gcDI.setObjectID(pPrevItem->getObjectID());
						pGamePlayer->sendPacket(&gcDI);

						pInventory->deleteItem(pPrevItem->getObjectID());
						pPrevItem->destroy();
						SAFE_DELETE(pPrevItem);
						
						Item* pNewItem = g_pItemFactoryManager->createItem(Item::ITEM_CLASS_EVENT_ITEM, 28, list<OptionType_t>());
						pZone->registerObject(pNewItem);

						if (!pInventory->addItem(pt.x, pt.y, pNewItem) )
							return;

						pNewItem->create(pPC->getName(), STORAGE_INVENTORY, 0, pt.x, pt.y);

						if (pNewItem != NULL ) {
							GCCreateItem gcCI;
							makeGCCreateItem(&gcCI, pNewItem, pt.x, pt.y);
							pGamePlayer->sendPacket(&gcCI);
						}
					}

				} else {

					pInventory->deleteItem(pPrevItem->getObjectID());

					pPC->deleteItemFromExtraInventorySlot();

					pPC->addItemToExtraInventorySlot(pPrevItem);

					pInventory->addItem(InvenX , InvenY , pItem);

					//pPrevItem->save(pPC->getName(), STORAGE_EXTRASLOT, 0, 0, 0);
					// item저장 최적화. by sigi. 2002.5.13
					char pField[80];
					sprintf(pField, "Storage=%d", STORAGE_EXTRASLOT);
					pPrevItem->tinysave(pField);

					//pItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY);
					// item저장 최적화. by sigi. 2002.5.13
					sprintf(pField, "Storage=%d, StorageID=%u, X=%d, Y=%d", STORAGE_INVENTORY, invenID, InvenX, InvenY);
					pItem->tinysave(pField);


					Success = true;
				}
			} 
			else {// 아이템 클래스가 다르거나, 쌓이는 아이템이 아니라면.
				pInventory->deleteItem(pPrevItem->getObjectID());

				pPC->deleteItemFromExtraInventorySlot();

				pPC->addItemToExtraInventorySlot(pPrevItem);

				pInventory->addItem(InvenX , InvenY , pItem);

				//pPrevItem->save(pPC->getName(), STORAGE_EXTRASLOT, 0, 0, 0);
				// item저장 최적화. by sigi. 2002.5.13
				char pField[80];
				sprintf(pField, "Storage=%d", STORAGE_EXTRASLOT);
				pPrevItem->tinysave(pField);

				//pItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY);
				// item저장 최적화. by sigi. 2002.5.13
				sprintf(pField, "Storage=%d, StorageID=%u, X=%d, Y=%d", STORAGE_INVENTORY, invenID, InvenX, InvenY);
				pItem->tinysave(pField);


				Success = true;
			}
		} else { // 그 장소에 아이템이 없다면.
			//cout << "prevItem is NULL" << endl;

			// Inventory에 특정 아이템을 넣는다.
			pInventory->addItem(InvenX , InvenY , pItem);

			// 넣기에 성공하면 마우스에 달려있는 아이템을 없앤다.
			pPC->deleteItemFromExtraInventorySlot();

			//pItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY);
			// item저장 최적화. by sigi. 2002.5.13
			char pField[80];
			sprintf(pField, "Storage=%d, StorageID=%u, X=%d, Y=%d", STORAGE_INVENTORY, invenID, InvenX, InvenY);
			pItem->tinysave(pField);


			Success = true;
		}

		if (Success) {
			TradeManager* pTradeManager = pZone->getTradeManager();
			TradeInfo* pInfo = pTradeManager->getTradeInfo(pCreature->getName());
			if (pInfo != NULL && pInfo->getStatus() == TRADE_FINISH) {
				GCTradeVerify gcTradeVerify;
				gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_MOUSE_TO_INVENTORY_OK);
				pPlayer->sendPacket(&gcTradeVerify);
			}

			// 트리 조각일 경우
			if (pItem != NULL && pItem->getItemClass() == Item::ITEM_CLASS_EVENT_TREE) {
				ItemType_t itemtype = pItem->getItemType();

				// 크리스마스 트리 조각이면
				if (itemtype <= 11) {
					// 크리스마스 트리 조각이 맞춰지는지 본다.
					TPOINT pt = checkEventPuzzle(pPC, InvenX, InvenY, 0);
					if (pt.x != -1 && pt.y != -1 )
					{
						// 맞춰진 트리 조각을 지운다.
						deleteInventoryItem(pInventory, pt.x, pt.y, pt.x + 2, pt.y + 3);

						// 트리를 생성한다.
						list<OptionType_t> optionType;
						Item* pTreeItem = g_pItemFactoryManager->createItem(Item::ITEM_CLASS_EVENT_TREE, 12, optionType);
						pZone->getObjectRegistry().registerObject(pTreeItem);
						pInventory->addItem(pt.x, pt.y, pTreeItem);
						pTreeItem->create(pPC->getName(), STORAGE_INVENTORY, invenID, pt.x, pt.y);

						// 클라이언트에 트리가 만들어졌다는 걸 알린다.
						GCCreateItem gcCreateItem;
						makeGCCreateItem(&gcCreateItem, pTreeItem, pt.x, pt.y);
						pGamePlayer->sendPacket(&gcCreateItem);
					}
				}
				// 크리스마스 트리 조각이면
				else if (itemtype > 12 && itemtype <= 24) {
					// 크리스마스 트리 조각이 맞춰지는지 본다.
					TPOINT pt = checkEventPuzzle(pPC, InvenX, InvenY, 13);
					if (pt.x != -1 && pt.y != -1) {
						// 맞춰진 트리 조각을 지운다.
						deleteInventoryItem(pInventory, pt.x, pt.y, pt.x + 2, pt.y + 3);

						// 트리를 생성한다.
						list<OptionType_t> optionType;
						Item* pTreeItem = g_pItemFactoryManager->createItem(Item::ITEM_CLASS_EVENT_TREE, 25, optionType);
						pTreeItem->setQuestItem();
						pZone->getObjectRegistry().registerObject(pTreeItem);
						pInventory->addItem(pt.x, pt.y, pTreeItem);
						pTreeItem->create(pPC->getName(), STORAGE_INVENTORY, invenID, pt.x, pt.y);

						// 클라이언트에 트리가 만들어졌다는 걸 알린다.
						GCCreateItem gcCreateItem;
						makeGCCreateItem(&gcCreateItem, pTreeItem, pt.x, pt.y);
						pGamePlayer->sendPacket(&gcCreateItem);
					}
				}
				// 크리스마스 트리 조각이면
				else if (itemtype > 28 && itemtype <= 40) {
					// 크리스마스 트리 조각이 맞춰지는지 본다.
					TPOINT pt = checkEventPuzzle(pPC, InvenX, InvenY, 29);
					if (pt.x != -1 && pt.y != -1) {
						// 맞춰진 트리 조각을 지운다.
						deleteInventoryItem(pInventory, pt.x, pt.y, pt.x + 2, pt.y + 3);

						// 트리를 생성한다.
						list<OptionType_t> optionType;
						Item* pTreeItem = g_pItemFactoryManager->createItem(Item::ITEM_CLASS_EVENT_TREE, 41, optionType);
						pTreeItem->setQuestItem();
						pZone->getObjectRegistry().registerObject(pTreeItem);
						pInventory->addItem(pt.x, pt.y, pTreeItem);
						pTreeItem->create(pPC->getName(), STORAGE_INVENTORY, invenID, pt.x, pt.y);

						// 클라이언트에 트리가 만들어졌다는 걸 알린다.
						GCCreateItem gcCreateItem;
						makeGCCreateItem(&gcCreateItem, pTreeItem, pt.x, pt.y);
						pGamePlayer->sendPacket(&gcCreateItem);
					}
				}
			}
		} else {
			//cout << "cannot add" << endl;
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
		}
	} catch (Throwable & t) {}

#endif	// __GAME_SERVER__

    __END_DEBUG_EX __END_CATCH

}
Example #13
0
//////////////////////////////////////////////////////////////////////////////
// 뱀파이어 타일 핸들러
//////////////////////////////////////////////////////////////////////////////
void RefusalEther::execute(Ousters* pOusters, ZoneCoord_t X, ZoneCoord_t Y, OustersSkillSlot* pOustersSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

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

	Assert(pOusters != NULL);
	Assert(pOustersSkillSlot != NULL);

	BYTE Grade = 0;
	if (pOustersSkillSlot->getExpLevel() < 15 ) Grade = 0;
	else if (pOustersSkillSlot->getExpLevel() < 30 ) Grade = 1;
	else Grade = 2;

	try 
	{
		Player* pPlayer = pOusters->getPlayer();
		Zone* pZone = pOusters->getZone();

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

		Item* pWeapon = pOusters->getWearItem(Ousters::WEAR_RIGHTHAND);
		if (pWeapon == NULL || pWeapon->getItemClass() != Item::ITEM_CLASS_OUSTERS_WRISTLET || !pOusters->isRealWearingEx(Ousters::WEAR_RIGHTHAND))
		{
			executeSkillFailException(pOusters, pOustersSkillSlot->getSkillType(), Grade);
			return;
		}

		GCSkillToTileOK1 _GCSkillToTileOK1;
		GCSkillToTileOK2 _GCSkillToTileOK2;
		GCSkillToTileOK3 _GCSkillToTileOK3;
		GCSkillToTileOK4 _GCSkillToTileOK4;
		GCSkillToTileOK5 _GCSkillToTileOK5;
		GCSkillToTileOK6 _GCSkillToTileOK6;

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

		ZoneCoord_t myX = pOusters->getX();
		ZoneCoord_t myY = pOusters->getY();

		// 이펙트의 지속시간을 계산한다.
		SkillInput input(pOusters, pOustersSkillSlot);
		SkillOutput output;
		computeOutput(input, output);

		int  RequiredMP  = (int)pSkillInfo->getConsumeMP() + pOustersSkillSlot->getExpLevel()/3;
		bool bManaCheck  = hasEnoughMana(pOusters, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pOustersSkillSlot);
		bool bRangeCheck = verifyDistance(pOusters, X, Y, pSkillInfo->getRange());
		bool bHitRoll    = HitRoll::isSuccessMagic(pOusters, pSkillInfo, pOustersSkillSlot);
		bool bSatisfyRequire = pOusters->satisfySkillRequire(pSkillInfo);
		
		bool bTileCheck = false;
		VSRect rect(0, 0, pZone->getWidth()-1, pZone->getHeight()-1);
		if (rect.ptInRect(X, Y)) bTileCheck = true;

		if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bTileCheck && bSatisfyRequire)
		{
			decreaseMana(pOusters, RequiredMP, _GCSkillToTileOK1);
			list<Creature*> cList;

			for (int ox = X-output.Range; ox <= X+output.Range; ++ox )
			for (int oy = Y-output.Range; oy <= Y+output.Range; ++oy )
			{
				if (!rect.ptInRect(ox,oy) ) continue;

				Tile& rTile = pZone->getTile(ox,oy);
				EffectDarkness* pEffect = dynamic_cast<EffectDarkness*>(rTile.getEffect(Effect::EFFECT_CLASS_DARKNESS));
				int ratio = 0;

				if (pEffect != NULL )
				{
					if (input.SkillLevel <= 15 )
					{
						ratio = (int)(pOusters->getLevel() + (input.SkillLevel * 8.0 / 3.0 ) - pEffect->getLevel());
					}
					else
					{
						ratio = (int)(pOusters->getLevel() + 20 + (input.SkillLevel * 4.0 / 3.0 ) - pEffect->getLevel());
						if (input.SkillLevel == 30 ) ratio = (int)(ratio * 1.1);
					}

					ratio = max(20, ratio);
				}
				else
				{
					continue;
				}

				bool bHitRoll2	= (rand()%100) < ratio;

				if (bHitRoll2)
				{
					pZone->deleteEffect(pEffect->getObjectID());
					
					Creature* pTargetCreature = NULL;
					if (rTile.hasCreature(Creature::MOVE_MODE_WALKING))
						pTargetCreature = rTile.getCreature(Creature::MOVE_MODE_WALKING);

					GCDeleteEffectFromTile gcDeleteEffectFromTile;
					gcDeleteEffectFromTile.setXY(ox, oy);
					gcDeleteEffectFromTile.setObjectID(pEffect->getObjectID());
					gcDeleteEffectFromTile.setEffectID(Effect::EFFECT_CLASS_DARKNESS);
					pZone->broadcastPacket(ox, oy, &gcDeleteEffectFromTile);

					if (pTargetCreature != NULL && pTargetCreature->isPC() && pTargetCreature->getObjectID() != pOusters->getObjectID() )
						cList.push_back(pTargetCreature);
				}
			}

			_GCSkillToTileOK1.setSkillType(SkillType);
			_GCSkillToTileOK1.setCEffectID(CEffectID);
			_GCSkillToTileOK1.setX(X);
			_GCSkillToTileOK1.setY(Y);
			_GCSkillToTileOK1.setDuration(output.Duration);
			_GCSkillToTileOK1.setRange(0);
			_GCSkillToTileOK1.setGrade(Grade);

			_GCSkillToTileOK2.setObjectID(pOusters->getObjectID());
			_GCSkillToTileOK2.setSkillType(SkillType);
			_GCSkillToTileOK2.setX(X);
			_GCSkillToTileOK2.setY(Y);
			_GCSkillToTileOK2.setDuration(output.Duration);
			_GCSkillToTileOK2.setRange(0);
			//_GCSkillToTileOK2.addShortData(MODIFY_VISION, ICE_FIELD_SIGHT);
			_GCSkillToTileOK2.setGrade(Grade);

			_GCSkillToTileOK3.setObjectID(pOusters->getObjectID());
			_GCSkillToTileOK3.setSkillType(SkillType);
			_GCSkillToTileOK3.setX(X);
			_GCSkillToTileOK3.setY(Y);
			_GCSkillToTileOK3.setGrade(Grade);

			_GCSkillToTileOK4.setSkillType(SkillType);
			_GCSkillToTileOK4.setX(X);
			_GCSkillToTileOK4.setY(Y);
			_GCSkillToTileOK4.setRange(0);
			_GCSkillToTileOK4.setDuration(output.Duration);
			_GCSkillToTileOK4.setGrade(Grade);

			_GCSkillToTileOK5.setObjectID(pOusters->getObjectID());
			_GCSkillToTileOK5.setSkillType(SkillType);
			_GCSkillToTileOK5.setX(X);
			_GCSkillToTileOK5.setY(Y);
			_GCSkillToTileOK5.setRange(0);
			_GCSkillToTileOK5.setDuration(output.Duration);
			_GCSkillToTileOK5.setGrade(Grade);

			_GCSkillToTileOK6.setOrgXY(myX, myY);
			_GCSkillToTileOK6.setSkillType(SkillType);
			_GCSkillToTileOK6.setX(X);
			_GCSkillToTileOK6.setY(Y);
			_GCSkillToTileOK6.setDuration(output.Duration);
			_GCSkillToTileOK6.setRange(0);
			//_GCSkillToTileOK6.addShortData(MODIFY_VISION, ICE_FIELD_SIGHT);
			_GCSkillToTileOK6.setGrade(Grade);

			pPlayer->sendPacket(&_GCSkillToTileOK1);

			list<Creature*>::iterator itr = cList.begin();
			list<Creature*>::iterator endItr = cList.end();

			for (; itr != endItr ; ++itr )
			{
				if ((*itr)->isPC() )
				{
					(*itr)->getPlayer()->sendPacket(&_GCSkillToTileOK2);
				}
			}

			cList.push_back(pOusters);

			cList = pZone->broadcastSkillPacket(myX, myY, X, Y, &_GCSkillToTileOK5, cList, false);
			
			pZone->broadcastPacket(myX, myY,  &_GCSkillToTileOK3 , cList);

			pZone->broadcastPacket(X, Y,  &_GCSkillToTileOK4 , cList);

			pOustersSkillSlot->setRunTime(output.Delay);
		}
		else
		{
			executeSkillFailNormal(pOusters, getSkillType(), NULL, Grade);
		}
	} 
	catch (Throwable & t) 
	{
		executeSkillFailException(pOusters, getSkillType(), Grade);
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;

	__END_CATCH
}
Example #14
0
//////////////////////////////////////////////////////////////////////
//
// ThunderFlash::execute()
//
//////////////////////////////////////////////////////////////////////
void ThunderFlash::execute(Slayer* pSlayer, ZoneCoord_t X, ZoneCoord_t Y, SkillSlot* pSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " begin" << endl;

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

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

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

		// 무장하고 있는 무기가 널이거나, SWORD가 아니라면 사용할 수 없다.
		Item* pItem = pSlayer->getWearItem(Slayer::WEAR_RIGHTHAND);
		if (pItem == NULL || pItem->getItemClass() != Item::ITEM_CLASS_SWORD)
		{
			executeSkillFailException(pSlayer, getSkillType());
			//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end" << endl;
			return;
		}

		bool bIncreaseExp = pSlayer->isRealWearingEx(Slayer::WEAR_RIGHTHAND);

		GCSkillToTileOK1 _GCSkillToTileOK1;
		GCSkillToTileOK2 _GCSkillToTileOK2;
		GCSkillToTileOK5 _GCSkillToTileOK5;

		SkillType_t       SkillType  = pSkillSlot->getSkillType();
		SkillInfo*        pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType);
		SkillDomainType_t DomainType = pSkillInfo->getDomainType();
		SkillLevel_t      SkillLevel = pSkillSlot->getExpLevel();

		int  RequiredMP  = (int)pSkillInfo->getConsumeMP();
		bool bManaCheck  = hasEnoughMana(pSlayer, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pSkillSlot);
		bool bRangeCheck = verifyDistance(pSlayer, X, Y, pSkillInfo->getRange());

		// 마나가 있어야 하고, 시간과 거리 체크에 성공하고,
		if (bManaCheck && bTimeCheck && bRangeCheck)
		{
			// MP를 떨어뜨린다.
			decreaseMana(pSlayer, RequiredMP, _GCSkillToTileOK1);

			// 좌표와 방향을 구한다.
			ZoneCoord_t myX = pSlayer->getX();
			ZoneCoord_t myY = pSlayer->getY();	
			Dir_t       dir = calcDirection(myX, myY, X, Y);

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

			Damage_t SkillDamage = output.Damage;
			Damage_t Damage      = 0;
			bool     bHit        = false;

			Level_t maxEnemyLevel = 0;
			uint EnemyNum = 0;

			VSRect rect(1, 1, pZone->getWidth()-2, pZone->getHeight()-2);

			list<Creature*> cList;

			for (int count=0; count<4; count++)
			{
				int tileX = X + m_pThunderFlashMask[count].x;
				int tileY = Y + m_pThunderFlashMask[count].y;

				// 현재 타일이 존 내부이고, 안전지대가 아니라면, 맞을 확률이 있다.
				if (rect.ptInRect(tileX, tileY))
				{
					// 타일을 받아온다.
					Tile& tile = pZone->getTile(tileX, tileY);

					list<Creature*> targetList;
					if (tile.hasCreature(Creature::MOVE_MODE_WALKING))
					{
						Creature* pCreature = tile.getCreature(Creature::MOVE_MODE_WALKING);
						targetList.push_back(pCreature);
					}

					list<Creature*>::iterator itr = targetList.begin();
					for(; itr != targetList.end(); itr++)
					{
						Creature* pTargetCreature = (*itr);
						Assert(pTargetCreature != NULL);

						bool bMoveModeCheck  = (pTargetCreature->getMoveMode() == Creature::MOVE_MODE_WALKING) ? true : false;
						bool bHitRoll        = HitRoll::isSuccess(pSlayer, pTargetCreature, SkillLevel/2);
						//bool bCanHit        = canHit(pSlayer, pTargetCreature, SkillType);
						bool bCanHit         = true;
						bool bPK             = verifyPK(pSlayer, pTargetCreature);
						bool bRaceCheck      = pTargetCreature->isSlayer() || pTargetCreature->isNPC();
						bool bZoneLevelCheck = checkZoneLevelToHitTarget(pTargetCreature);

						if (bMoveModeCheck && bHitRoll && bCanHit && bPK && !bRaceCheck && bZoneLevelCheck)
						{
							CheckCrossCounter(pSlayer, pTargetCreature, Damage, pSkillInfo->getRange());

							bool bCriticalHit = false;

							Damage = computeDamage(pSlayer, pTargetCreature, SkillLevel/5, bCriticalHit) + SkillDamage;

							ObjectID_t targetObjectID = pTargetCreature->getObjectID();
							cList.push_back(pTargetCreature);

							_GCSkillToTileOK1.addCListElement(targetObjectID);
							_GCSkillToTileOK2.addCListElement(targetObjectID);
							_GCSkillToTileOK5.addCListElement(targetObjectID);

							// 일단 맞는 놈이 받을 패킷은 널 상태로 한 채로, 데미지를 준다.
							setDamage(pTargetCreature, Damage, pSlayer, SkillType, NULL, &_GCSkillToTileOK1);
							computeAlignmentChange(pTargetCreature, Damage, pSlayer, NULL, &_GCSkillToTileOK1);
							increaseAlignment(pSlayer, pTargetCreature, _GCSkillToTileOK1);

							// 크리티컬 히트라면 상대방을 뒤로 물러나게 한다.
							if (bCriticalHit)
							{
								knockbackCreature(pZone, pTargetCreature, pSlayer->getX(), pSlayer->getY());
							}

							// 슬레이어가 아닐 경우에만 맞은 것으로 간주한다.
							if (!pTargetCreature->isSlayer())
							{
								bHit = true;
								if (maxEnemyLevel < pTargetCreature->getLevel() ) maxEnemyLevel = pTargetCreature->getLevel();
								EnemyNum++;
							}
						}
					} //for (; itr != objectList.end(); itr++) 
				} // if (rect.ptInRect(tileX, tileY) && ...
			} // for (int count=0; count<3; count++)

			if (bHit)
			{
				if (bIncreaseExp)
				{
					shareAttrExp(pSlayer, Damage , 8, 1, 1, _GCSkillToTileOK1);
					increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToTileOK1, maxEnemyLevel, EnemyNum);
					increaseSkillExp(pSlayer, DomainType,  pSkillSlot, pSkillInfo, _GCSkillToTileOK1);
				}
			}

			// 공격자 아이템 내구성 떨어트림.
			decreaseDurability(pSlayer, NULL, pSkillInfo, &_GCSkillToTileOK1, NULL);

			_GCSkillToTileOK1.setSkillType(SkillType);
			_GCSkillToTileOK1.setCEffectID(CEffectID);
			_GCSkillToTileOK1.setX(X);
			_GCSkillToTileOK1.setY(Y);
			_GCSkillToTileOK1.setRange(dir);
			_GCSkillToTileOK1.setDuration(0);
		
			_GCSkillToTileOK2.setObjectID(pSlayer->getObjectID());
			_GCSkillToTileOK2.setSkillType(SkillType);
			_GCSkillToTileOK2.setX(X);
			_GCSkillToTileOK2.setY(Y);
			_GCSkillToTileOK2.setRange(dir);
			_GCSkillToTileOK2.setDuration(0);
		
			_GCSkillToTileOK5.setObjectID(pSlayer->getObjectID());
			_GCSkillToTileOK5.setSkillType(SkillType);
			_GCSkillToTileOK5.setX(X);
			_GCSkillToTileOK5.setY(Y);
			_GCSkillToTileOK5.setRange(dir);
			_GCSkillToTileOK5.setDuration(0);
		
			pPlayer->sendPacket(&_GCSkillToTileOK1);
		
			// 이 기술에 의해 영향을 받는 놈들에게 패킷을 보내줘야 한다.
			for (list<Creature*>::const_iterator itr = cList.begin(); itr != cList.end(); itr++)
			{
				Creature * pTargetCreature = *itr;
				Assert(pTargetCreature != NULL);

				if (pTargetCreature->isPC())
				{
					_GCSkillToTileOK2.clearList();

					// HP의 변경사항을 패킷에다 기록한다.
					HP_t targetHP = 0;
					if (pTargetCreature->isSlayer()) targetHP = (dynamic_cast<Slayer*>(pTargetCreature))->getHP(ATTR_CURRENT);
					else if (pTargetCreature->isVampire()) targetHP = (dynamic_cast<Vampire*>(pTargetCreature))->getHP(ATTR_CURRENT);
					_GCSkillToTileOK2.addShortData(MODIFY_CURRENT_HP, targetHP);

					// 아이템의 내구력을 떨어뜨린다.
					decreaseDurability(NULL, pTargetCreature, pSkillInfo, NULL, &_GCSkillToTileOK2);

					// 패킷을 보내준다.
					pTargetCreature->getPlayer()->sendPacket(&_GCSkillToTileOK2);
				}
				else if (pTargetCreature->isMonster())
				{
					// 당근 적으로 인식한다.
					Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature);
					pMonster->addEnemy(pSlayer);
				}
			}

			cList.push_back(pSlayer);

			pZone->broadcastPacket(myX, myY, &_GCSkillToTileOK5 , cList);

			// set Next Run Time
			pSkillSlot->setRunTime(output.Delay);
		} 
		else 
		{
			executeSkillFailNormal(pSlayer, getSkillType(), NULL);
		}
	} 
	catch (Throwable & t) 
	{
		executeSkillFailException(pSlayer, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end" << endl;

	__END_CATCH
}
Example #15
0
//////////////////////////////////////////////////////////////////////////////
// 슬레이어 오브젝트 핸들러
//////////////////////////////////////////////////////////////////////////////
void Liberty::execute(Ousters* pOusters, ObjectID_t TargetObjectID, OustersSkillSlot* pOustersSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl;

	Assert(pOusters != NULL);
	Assert(pOustersSkillSlot != NULL);

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

		Item* pWeapon = pOusters->getWearItem(Ousters::WEAR_RIGHTHAND);
		if (pWeapon == NULL || pWeapon->getItemClass() != Item::ITEM_CLASS_OUSTERS_WRISTLET || !pOusters->isRealWearingEx(Ousters::WEAR_RIGHTHAND))
		{
			executeSkillFailException(pOusters, pOustersSkillSlot->getSkillType());
			return;
		}

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

		// NoSuch제거. by sigi. 2002.5.2
		if (pTargetCreature==NULL
			|| !pTargetCreature->isOusters())
		{
			executeSkillFailException(pOusters, getSkillType());
			//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl;
			return;
		}

		Ousters* pTargetOusters = dynamic_cast<Ousters*>(pTargetCreature);

		GCSkillToObjectOK1 _GCSkillToObjectOK1;
		GCSkillToObjectOK2 _GCSkillToObjectOK2;
		GCSkillToObjectOK5 _GCSkillToObjectOK5;

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

		int  RequiredMP  = (int)pSkillInfo->getConsumeMP() +  pOustersSkillSlot->getExpLevel()/3;
		bool bManaCheck  = hasEnoughMana(pOusters, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pOustersSkillSlot);
		bool bRangeCheck = verifyDistance(pOusters, pTargetCreature, pSkillInfo->getRange()) && canHit(pOusters, pTargetCreature, SkillType, pOustersSkillSlot->getExpLevel());
		bool bHitRoll    = HitRoll::isSuccessMagic(pOusters, pSkillInfo, pOustersSkillSlot);
		bool bSatisfyRequire	= pOusters->satisfySkillRequire(pSkillInfo);
		bool bHPCheck	= pTargetOusters->isFlag(Effect::EFFECT_CLASS_PARALYZE);

		int Ratio = 0;
		EffectParalyze* pEffect = dynamic_cast<EffectParalyze*>(pTargetOusters->findEffect(Effect::EFFECT_CLASS_PARALYZE ));
		if (pEffect != NULL )
		{
			if (pOustersSkillSlot->getExpLevel() <= 15 )
			{
				Ratio = (int)((pOusters->getLevel() + (pOustersSkillSlot->getExpLevel() * 8.0 / 3.0 ) ) - pEffect->getLevel());
			}
			else
			{
				Ratio = (int)((pOusters->getLevel() + 20 + (pOustersSkillSlot->getExpLevel() * 4.0 / 3.0 ) ) - pEffect->getLevel());
				if (pOustersSkillSlot->getExpLevel() == 30 ) Ratio = (int)(Ratio * 1.1);
			}
		}

		bool bHitRoll2 = (rand()%100) < Ratio;

		if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bHitRoll2 && bSatisfyRequire && bHPCheck)
		{
			// 마나를 줄인다.
			decreaseMana(pOusters, RequiredMP, _GCSkillToObjectOK1);

			// 이펙트의 효과와 지속시간을 계산한다.
			SkillInput input(pOusters, pOustersSkillSlot);
			SkillOutput output;
			input.TargetType = SkillInput::TARGET_OTHER;
			computeOutput(input, output);

			pEffect->setDeadline(0);

			// 패킷을 준비해서 보낸다.
			_GCSkillToObjectOK1.setSkillType(SkillType);
			_GCSkillToObjectOK1.setCEffectID(CEffectID);
			_GCSkillToObjectOK1.setTargetObjectID(TargetObjectID);

			_GCSkillToObjectOK2.setObjectID(pOusters->getObjectID());
			_GCSkillToObjectOK2.setSkillType(SkillType);

			_GCSkillToObjectOK5.setObjectID(pOusters->getObjectID());
			_GCSkillToObjectOK5.setSkillType(SkillType);
			_GCSkillToObjectOK5.setTargetObjectID (TargetObjectID);

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

			if (pOusters != pTargetCreature && pTargetCreature->isPC()) 
			{
				Player* pTargetPlayer = pTargetCreature->getPlayer();
				Assert(pTargetPlayer != NULL);
				pTargetPlayer->sendPacket(&_GCSkillToObjectOK2);
			}

			list<Creature*> cList;
			cList.push_back(pOusters);
			cList.push_back(pTargetCreature);
		
			pZone->broadcastPacket(pOusters->getX(), pOusters->getY(),  &_GCSkillToObjectOK5 , cList);

			pOustersSkillSlot->setRunTime(output.Delay);
		} 
		else 
		{
			executeSkillFailNormal(pOusters, getSkillType(), pTargetCreature);
		}
	} 
	catch (Throwable & t) 
	{
		executeSkillFailException(pOusters, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl;

	__END_CATCH
}
Example #16
0
void Flare::execute(Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

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

	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);

		// NPC이거나, 슬레이어에게는 Flare를 쓸 수가 없다.
		// NoSuch제거. by sigi. 2002.5.2
		if (pTargetCreature==NULL
			|| pTargetCreature->isNPC() || pTargetCreature->isSlayer())
		{
			executeSkillFailException(pSlayer, getSkillType());
			//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;
			return;
		}

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

		SkillType_t       SkillType  = pSkillSlot->getSkillType();
		SkillInfo*        pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType);
		SkillDomainType_t DomainType = pSkillInfo->getDomainType();
		SkillLevel_t      SkillLevel = pSkillSlot->getExpLevel();

		int  RequiredMP  = (int)pSkillInfo->getConsumeMP();
		bool bManaCheck  = hasEnoughMana(pSlayer, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pSkillSlot);
		bool bRangeCheck = verifyDistance(pSlayer, pTargetCreature, pSkillInfo->getRange());
		bool bHitRoll    = HitRoll::isSuccessFlare(pTargetCreature, SkillLevel) && canAttack(pSlayer, pTargetCreature);
		bool bEffected   = pTargetCreature->isFlag(Effect::EFFECT_CLASS_FLARE);

		//if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected)
		if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected && pTargetCreature->getCompetence() == 3)
		{
			decreaseMana(pSlayer, RequiredMP, _GCSkillToObjectOK1);

			// 지속 시간을 계산한다.
			SkillInput input(pSlayer, pSkillSlot);
			SkillOutput output;
			computeOutput(input, output);

			// 이펙트 클래스를 만들어 붙인다.
			EffectFlare* pEffect = new EffectFlare(pTargetCreature);
			//pEffect->setOldSight(13);
			pEffect->setOldSight(pTargetCreature->getSight());
			// 제거할때 level체크하기 위햇서.by sigi. 2002.6.21
			pEffect->setLevel(pSkillInfo->getLevel());	
			pEffect->setDeadline(output.Duration);
			pTargetCreature->setFlag(Effect::EFFECT_CLASS_FLARE);
			pTargetCreature->addEffect(pEffect);

			// 이펙트를 적용시킨다. 
			pEffect->affect(pTargetCreature);

			// 경험치를 올린다.
			SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType));
			Exp_t ExpUp = 10* (Grade + 1);
			shareAttrExp(pSlayer, ExpUp, 1, 1, 8, _GCSkillToObjectOK1);
        	increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToObjectOK1);
			increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToObjectOK1);

			// 패킷을 준비한다.
			ZoneCoord_t targetX = pTargetCreature->getX();
			ZoneCoord_t targetY = pTargetCreature->getY();
			ZoneCoord_t myX     = pSlayer->getX();
			ZoneCoord_t myY     = pSlayer->getY();

			_GCSkillToObjectOK1.setSkillType(SkillType);
			_GCSkillToObjectOK1.setCEffectID(CEffectID);

			_GCSkillToObjectOK1.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK1.setDuration(0);
		
			_GCSkillToObjectOK2.setObjectID(pSlayer->getObjectID());
			_GCSkillToObjectOK2.setSkillType(SkillType);
			_GCSkillToObjectOK2.addShortData(MODIFY_VISION, FLARE_SIGHT);
			_GCSkillToObjectOK2.setDuration(0);
		
			_GCSkillToObjectOK3.setObjectID(pSlayer->getObjectID());
			_GCSkillToObjectOK3.setSkillType(SkillType);
			_GCSkillToObjectOK3.setTargetXY (targetX, targetY);
			
			_GCSkillToObjectOK4.setSkillType(SkillType);
			_GCSkillToObjectOK4.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK4.setDuration(0);
			
			_GCSkillToObjectOK5.setObjectID(pSlayer->getObjectID());
			_GCSkillToObjectOK5.setSkillType(SkillType);
			_GCSkillToObjectOK5.setTargetObjectID (TargetObjectID);
			_GCSkillToObjectOK5.setDuration(0);

			list<Creature *> cList;
			cList.push_back(pTargetCreature);
			cList.push_back(pSlayer);
			cList = pZone->broadcastSkillPacket(myX, myY, targetX, targetY, &_GCSkillToObjectOK5, cList);
			pZone->broadcastPacket(myX, myY, &_GCSkillToObjectOK3, cList);
			pZone->broadcastPacket(targetX, targetY, &_GCSkillToObjectOK4, cList);

			pPlayer->sendPacket(&_GCSkillToObjectOK1);

			if (pTargetCreature->isPC()) 
			{
				Player* pTargetPlayer = pTargetCreature->getPlayer();
				Assert(pTargetPlayer != NULL);
				pTargetPlayer->sendPacket(&_GCSkillToObjectOK2);
			} 
			else 
			{
				Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature);
				pMonster->addEnemy(pSlayer);
			}
		
			GCAddEffect gcAddEffect;
			gcAddEffect.setObjectID(TargetObjectID);
			gcAddEffect.setEffectID(Effect::EFFECT_CLASS_FLARE);
			gcAddEffect.setDuration(output.Duration);
			pZone->broadcastPacket(targetX, targetY, &gcAddEffect);
			
			pSkillSlot->setRunTime(output.Delay);
		} 
		else 
		{
			executeSkillFailNormal(pSlayer, getSkillType(), pTargetCreature);
		}
	} 
	catch (Throwable & t) 
	{
		executeSkillFailException(pSlayer, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;

	__END_CATCH
}
Example #17
0
//////////////////////////////////////////////////////////////////////////////
// 슬레이어 타일 핸들러
//////////////////////////////////////////////////////////////////////////////
void MagicElusion::execute(Slayer* pSlayer, ZoneCoord_t X, ZoneCoord_t Y, SkillSlot* pSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

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

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

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

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

		GCSkillToTileOK1 _GCSkillToTileOK1;
		GCSkillToTileOK2 _GCSkillToTileOK2;
		GCSkillToTileOK3 _GCSkillToTileOK3;
		GCSkillToTileOK4 _GCSkillToTileOK4;
		GCSkillToTileOK5 _GCSkillToTileOK5;
		GCSkillToTileOK6 _GCSkillToTileOK6;

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

		ZoneCoord_t myX = pSlayer->getX();
		ZoneCoord_t myY = pSlayer->getY();

		int  RequiredMP  = (int)pSkillInfo->getConsumeMP();
		bool bManaCheck  = hasEnoughMana(pSlayer, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pSkillSlot);
		bool bRangeCheck = verifyDistance(pSlayer, X, Y, pSkillInfo->getRange()) && checkZoneLevelToUseSkill(pSlayer);
		bool bHitRoll    = HitRoll::isSuccessMagicElusion(pSlayer);
		
		bool bTileCheck = false;
		VSRect rect(0, 0, pZone->getWidth()-1, pZone->getHeight()-1);
		if (rect.ptInRect(X, Y)) bTileCheck = true;

		// 이펙트의 지속시간을 계산한다.
		SkillInput input(pSlayer, pSkillSlot);
		SkillOutput output;
		computeOutput(input, output);


		if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bTileCheck)
		{
			decreaseMana(pSlayer, RequiredMP, _GCSkillToTileOK1);

			Range_t    Range    = 2;

			int oX, oY;
			
			list<Creature*> cList;	// denier list
			
			ObjectRegistry & objectregister = pZone->getObjectRegistry();

			// 일단 이미 sanctuary가 있는지 검색한다.
			for(oY = -1; oY <= 1; oY++)
			for(oX = -1; oX <= 1; oX++)
			{
				int tileX = X+oX;
				int tileY = Y+oY;
				if (rect.ptInRect(tileX, tileY))
				{
					Tile& tile = pZone->getTile(tileX, tileY);

					if (tile.canAddEffect())
					{
						Effect* pOldEffect = tile.getEffect(Effect::EFFECT_CLASS_MAGIC_ELUSION);

						// 이미 있다면
						// 기술 실패다.
						if (pOldEffect != NULL)
						{
							executeSkillFailNormal(pSlayer, getSkillType(), NULL);

							return;
						}
					}
					else
					{
						executeSkillFailNormal(pSlayer, getSkillType(), NULL);
						return;
					}
				}
			}

			for(oY = -1; oY <= 1; oY++)
			for(oX = -1; oX <= 1; oX++)
			{
				int tileX = X+oX;
				int tileY = Y+oY;
				if (rect.ptInRect(tileX, tileY))
				{
					Tile& tile = pZone->getTile(tileX, tileY);

					// 이펙트 클래스를 생성한다.
					EffectMagicElusion* pEffect = new EffectMagicElusion(pZone , tileX, tileY);
					pEffect->setDeadline(output.Duration);

					// Tile에 붙이는 Effect는 ObjectID를 등록받아야 한다.
					objectregister.registerObject(pEffect);
					pZone->addEffect(pEffect);
					tile.addEffect(pEffect);

					if (oX==0 && oY==0)
					{
						pEffect->setBroadcastingEffect(true);
						GCAddEffectToTile gcAddEffectToTile;
						gcAddEffectToTile.setEffectID(pEffect->getEffectClass());
						gcAddEffectToTile.setObjectID(pEffect->getObjectID());
						gcAddEffectToTile.setXY(X, Y);
						gcAddEffectToTile.setDuration(output.Duration);

						pZone->broadcastPacket(X, Y, &gcAddEffectToTile, pSlayer);
					}
					else
					{
						// 가운데 이펙트가 아니면 브로드캐스팅해주지 않는다.
						pEffect->setBroadcastingEffect(false);
					}

					const list<Object*>& oList = tile.getObjectList();
					for(list<Object*>::const_iterator itr = oList.begin(); itr != oList.end(); itr++) 
					{
						Object* pTarget = *itr;
						if (pTarget->getObjectClass() == Object::OBJECT_CLASS_CREATURE )
						{
							Creature* pCreature = dynamic_cast<Creature*>(pTarget);
							Assert(pCreature != NULL);
							
							if (pCreature->isVampire() )
							{
								Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);
								Assert(pVampire != NULL);

								GCModifyInformation gcMI;
								::setDamage(pVampire, output.Damage, pSlayer, pSkillSlot->getSkillType(), &gcMI);

								pVampire->getPlayer()->sendPacket(&gcMI);
								cList.push_back(pCreature);
							}
							else if (pCreature->isMonster() )
							{
								::setDamage(pCreature, output.Damage, pSlayer, pSkillSlot->getSkillType());
							}
						}
					}
				}
			}

			_GCSkillToTileOK1.setSkillType(SkillType);
			_GCSkillToTileOK1.setCEffectID(CEffectID);
			_GCSkillToTileOK1.setX(X);
			_GCSkillToTileOK1.setY(Y);
			_GCSkillToTileOK1.setDuration(output.Duration);
			_GCSkillToTileOK1.setRange(Range);

			_GCSkillToTileOK2.setObjectID(pSlayer->getObjectID());
			_GCSkillToTileOK2.setSkillType(SkillType);
			_GCSkillToTileOK2.setX(X);
			_GCSkillToTileOK2.setY(Y);
			_GCSkillToTileOK2.setDuration(output.Duration);
			_GCSkillToTileOK2.setRange(Range);

			_GCSkillToTileOK3.setObjectID(pSlayer->getObjectID());
			_GCSkillToTileOK3.setSkillType(SkillType);
			_GCSkillToTileOK3.setX(X);
			_GCSkillToTileOK3.setY(Y);

			_GCSkillToTileOK4.setSkillType(SkillType);
			_GCSkillToTileOK4.setX(X);
			_GCSkillToTileOK4.setY(Y);
			_GCSkillToTileOK4.setRange(Range);
			_GCSkillToTileOK4.setDuration(output.Duration);

			_GCSkillToTileOK5.setObjectID(pSlayer->getObjectID());
			_GCSkillToTileOK5.setSkillType(SkillType);
			_GCSkillToTileOK5.setX(X);
			_GCSkillToTileOK5.setY(Y);
			_GCSkillToTileOK5.setRange(Range);
			_GCSkillToTileOK5.setDuration(output.Duration);

			_GCSkillToTileOK6.setOrgXY(myX, myY);
			_GCSkillToTileOK6.setSkillType(SkillType);
			_GCSkillToTileOK6.setX(X);
			_GCSkillToTileOK6.setY(Y);
			_GCSkillToTileOK6.setDuration(output.Duration);
			_GCSkillToTileOK6.setRange(Range);

			for(list<Creature*>::const_iterator itr = cList.begin(); itr != cList.end(); itr++)
			{
				Creature* pTargetCreature = *itr;
				if (canSee(pTargetCreature, pSlayer)) pTargetCreature->getPlayer()->sendPacket(&_GCSkillToTileOK2);
				else pTargetCreature->getPlayer()->sendPacket(&_GCSkillToTileOK6);
			}

			pPlayer->sendPacket(&_GCSkillToTileOK1);

			cList.push_back(pSlayer);

			list<Creature*> watcherList = pZone->getWatcherList(myX, myY, pSlayer);

			// watcherList에서 cList에 속하지 않고, caster(pSlayer)를 볼 수 없는 경우는
			// OK4를 보내고.. cList에 추가한다.
			for(list<Creature*>::const_iterator itr = watcherList.begin(); itr != watcherList.end(); itr++)
			{
				bool bBelong = false;
				for(list<Creature*>::const_iterator tItr = cList.begin(); tItr != cList.end(); tItr++)
					if (*itr == *tItr)
						bBelong = true;

				Creature* pWatcher = (*itr);
				if (bBelong == false && canSee(pWatcher, pSlayer) == false)
				{
					//Assert(pWatcher->isPC());	// 당연 PC다.. Zone::getWatcherList는 PC만 return한다
					if (pWatcher->isPC())
					{
						pWatcher->getPlayer()->sendPacket(&_GCSkillToTileOK4);
						cList.push_back(*itr);
					}
				}
			}

			cList = pZone->broadcastSkillPacket(myX, myY, X, Y, &_GCSkillToTileOK5, cList, false);

			pZone->broadcastPacket(myX, myY,  &_GCSkillToTileOK3 , cList);

			pZone->broadcastPacket(X, Y,  &_GCSkillToTileOK4 , cList);
		} 
		else 
		{
			executeSkillFailNormal(pSlayer, getSkillType(), NULL);
		}

		if (bTimeCheck ) pSkillSlot->setRunTime(output.Delay);
	} 
	catch (Throwable & t) 
	{
		executeSkillFailException(pSlayer, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;


	__END_CATCH
}
Example #18
0
//////////////////////////////////////////////////////////////////////////////
// 슬레이어 오브젝트 핸들러
//////////////////////////////////////////////////////////////////////////////
void RemoveCurse::execute(Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

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

	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, getSkillType());
			//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;
			return;
		}

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

		SkillType_t       SkillType  = pSkillSlot->getSkillType();
		SkillInfo*        pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType);
		SkillDomainType_t DomainType = pSkillInfo->getDomainType();
		// by sigi. 2002.12.3
		SkillLevel_t      SkillLevel = pSlayer->getINT()/2; //pSkillSlot->getExpLevel();

		bool bDoom      = false;
		bool bParalyze  = false;
		bool bSeduction = false;
		// by sigi. 2002.12.3
		//bool bHallucination = false;
		bool bDeath = false;
		bool bEffected  = false; // 아무 저주나 걸려 있으면 켠다.

		EffectDoom*      pEffectDoom     = NULL;
		EffectParalyze*  pEffectParalyze = NULL;
		EffectSeduction* pEffectSeduction = NULL;
		// by sigi. 2002.12.3
		//EffectHallucination* pEffectHallucination = NULL;
		EffectDeath* pEffectDeath = NULL;

		if (pTargetCreature->isEffect(Effect::EFFECT_CLASS_DOOM)) 
		{
			pEffectDoom = (EffectDoom*)pTargetCreature->findEffect(Effect::EFFECT_CLASS_DOOM);
			Assert(pEffectDoom != NULL);

			bDoom = HitRoll::isSuccessRemoveCurse(45, SkillLevel, 20, pEffectDoom->getLevel()/4);
			bEffected = true;
		}
		if (pTargetCreature->isEffect(Effect::EFFECT_CLASS_PARALYZE)) 
		{
			pEffectParalyze = (EffectParalyze*)pTargetCreature->findEffect(Effect::EFFECT_CLASS_PARALYZE);
			Assert(pEffectParalyze != NULL);

			bParalyze = HitRoll::isSuccessRemoveCurse(45, SkillLevel, 10, pEffectParalyze->getLevel()/4);
			bEffected = true;
		}
		if (pTargetCreature->isEffect(Effect::EFFECT_CLASS_SEDUCTION)) 
		{
			pEffectSeduction = (EffectSeduction*)pTargetCreature->findEffect(Effect::EFFECT_CLASS_SEDUCTION);
			Assert(pEffectSeduction != NULL);

			bSeduction = HitRoll::isSuccessRemoveCurse(45, SkillLevel, 30, pEffectSeduction->getLevel()/4);
			bEffected = true;
		}
		// by sigi. 2002.12.3
//		if (pTargetCreature->isEffect(Effect::EFFECT_CLASS_HALLUCINATION)) 
//		{
//			pEffectHallucination = (EffectHallucination*)pTargetCreature->findEffect(Effect::EFFECT_CLASS_HALLUCINATION);
////			Assert(pEffectHallucination != NULL);
//
//			bHallucination = HitRoll::isSuccessRemoveCurse(45, SkillLevel, 40, pEffectHallucination->getLevel()/4);
//			bEffected = true;
//		}
		if (pTargetCreature->isEffect(Effect::EFFECT_CLASS_DEATH)) 
		{
			pEffectDeath = (EffectDeath*)pTargetCreature->findEffect(Effect::EFFECT_CLASS_DEATH);
			Assert(pEffectDeath != NULL);

			bDeath = HitRoll::isSuccessRemoveCurse(45, SkillLevel, 50, pEffectDeath->getLevel()/4);
			bEffected = true;
		}

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

		// 마나가 있고, 시간이 됐고, 거리가 적당하며,
		// 저주가 하나라도 걸려있어야 한다.
		if (bManaCheck && bTimeCheck && bRangeCheck && bEffected)
		{
			decreaseMana(pSlayer, RequiredMP, _GCSkillToObjectOK1);

			SkillInput input(pSlayer, pSkillSlot);
			SkillOutput output;
			computeOutput(input, output);
		
			// 각각의 저주를 삭제하고,
			// 패킷에다 이펙트 삭제하라고 더한다.
			GCRemoveEffect gcRemoveEffect;
			gcRemoveEffect.setObjectID(pTargetCreature->getObjectID());

			if (bDoom)
			{
				pEffectDoom->setDeadline(0);
				pTargetCreature->removeFlag(Effect::EFFECT_CLASS_DOOM);
				gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_DOOM);
			}
			if (bParalyze)
			{
				pEffectParalyze->setDeadline(0);
				pTargetCreature->removeFlag(Effect::EFFECT_CLASS_PARALYZE);
				gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_PARALYZE);
			}
			if (bSeduction)
			{
				pEffectSeduction->setDeadline(0);
				pTargetCreature->removeFlag(Effect::EFFECT_CLASS_SEDUCTION);
				gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_SEDUCTION);
			}
			// by sigi. 2002.12.3
//			if (bHallucination)
//			{
//				pEffectHallucination->setDeadline(0);
//				pTargetCreature->removeFlag(Effect::EFFECT_CLASS_HALLUCINATION);
//				gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_HALLUCINATION);
//			}
			if (bDeath)
			{
				pEffectDeath->setDeadline(0);
				pTargetCreature->removeFlag(Effect::EFFECT_CLASS_DEATH);
				gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_DEATH);
			}

			// 경험치를 올린다.
			SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType));
			Exp_t ExpUp = 10*(Grade+1);
			shareAttrExp(pSlayer, ExpUp, 1, 1, 8, _GCSkillToObjectOK1);
			increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToObjectOK1);
			increaseSkillExp(pSlayer, DomainType,  pSkillSlot, pSkillInfo, _GCSkillToObjectOK1);

			// 패킷을 만들어 보낸다.
			ZoneCoord_t myX     = pSlayer->getX();
			ZoneCoord_t myY     = pSlayer->getY();
			ZoneCoord_t targetX = pTargetCreature->getX();
			ZoneCoord_t targetY = pTargetCreature->getY();

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

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

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

			_GCSkillToObjectOK4.setSkillType(SkillType);
			_GCSkillToObjectOK4.setTargetObjectID(TargetObjectID);

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

			pPlayer->sendPacket(&_GCSkillToObjectOK1);

			if (pTargetCreature->isPC()) 
			{
				Player* pTargetPlayer = pTargetCreature->getPlayer();
				pTargetPlayer->sendPacket(&_GCSkillToObjectOK2);
			}

			pZone->broadcastPacket(targetX, targetY, &gcRemoveEffect);

			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(output.Delay);
		} 
		else 
		{
			executeSkillFailNormal(pSlayer, getSkillType(), pTargetCreature);
		}
	} 
	catch(Throwable & t)  
	{
		executeSkillFailException(pSlayer, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;

	__END_CATCH
}
void EffectPlasmaRocketLauncher::affect(Creature* pCreature)
	throw(Error)
{
	__BEGIN_TRY
	__BEGIN_DEBUG

	Assert(pCreature != NULL);

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

	Creature* pAttacker = pZone->getCreature(m_UserObjectID);

	VSRect rect(0, 0, pZone->getWidth()-1, pZone->getHeight()-1);

	int cX = pCreature->getX();
	int cY = pCreature->getY();
	
	for(int x = -1; x <= 1; x++)
	{
		for(int y= -1; y <= 1; y++)
		{
			int X = cX + x;
			int Y = cY + y;

			if(!rect.ptInRect(X, Y)) continue;
			Tile& tile = pZone->getTile(X, Y);
			
			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* pCreature2 = dynamic_cast<Creature*>(pObject);
					Assert(pCreature2 != NULL);

					if (pCreature2 != pCreature && pCreature2->isSlayer() ) continue;
	
					if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE)
						&& !pCreature2->isDead()
						&& !pCreature2->isFlag(Effect::EFFECT_CLASS_COMA)
						// 무적상태 체크. by sigi. 2002.9.5
						&& canAttack(pAttacker, pCreature2 )
					   )
					{
						GCModifyInformation gcMI, gcAttackerMI;
						setDamage(pCreature2, m_Point, pAttacker, SKILL_PLASMA_ROCKET_LAUNCHER, &gcMI, &gcAttackerMI);
						if (pCreature2->isPC() ) pCreature2->getPlayer()->sendPacket(&gcMI);

						if (pAttacker!=NULL) 
						{
							computeAlignmentChange(pCreature2, m_Point, pAttacker, &gcMI, &gcAttackerMI);
							if (pAttacker->isPC() )
							{ 
								if (pAttacker->isSlayer() && !pCreature2->isSlayer() )
								{
									Slayer* pSlayer = dynamic_cast<Slayer*>(pAttacker);

									if (pSlayer != NULL )
									{
										GCModifyInformation gcMI;
										shareAttrExp(pSlayer, m_Point, 1, 8, 1, gcAttackerMI);
									}
								}

								if (pAttacker->isPC() ) pAttacker->getPlayer()->sendPacket(&gcAttackerMI);
							}
						}
					}

				}
				
			}
		}
	}

	setDeadline(0);

	__END_DEBUG
	__END_CATCH
}
Example #20
0
//////////////////////////////////////////////////////////////////////////////
// 뱀파이어 타일 핸들러
//////////////////////////////////////////////////////////////////////////////
void BloodyBreaker::execute(Vampire* pVampire, ZoneCoord_t X, ZoneCoord_t Y, VampireSkillSlot* pVampireSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl;
	SkillType_t SkillType = getSkillType();

	// Knowledge of Blood 가 있다면 hit bonus 10
	int HitBonus = 0;
	if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_BLOOD ) )
	{
		RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_BLOOD);
		Assert(pRankBonus != NULL);

		HitBonus = pRankBonus->getPoint();
	}

	try 
	{
		SkillInput input(pVampire);
		SkillOutput output;
		computeOutput(input, output);

		Dir_t	Dir		= getDirectionToPosition(pVampire->getX(), pVampire->getY(), X, Y);

		// 강제로 knockback시킬 확률
//		bool bForceKnockback = rand()%100 < output.ToHit;

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

		VSRect rect(1, 1, pZone->getWidth()-2, pZone->getHeight()-2);
		if (!rect.ptInRect(X, Y ))
		{
			executeSkillFailException(pVampire, SkillType);
			return;
		}


		GCSkillToTileOK1 _GCSkillToTileOK1;
		GCSkillToTileOK2 _GCSkillToTileOK2;
//		GCSkillToTileOK3 _GCSkillToTileOK3;
//		GCSkillToTileOK4 _GCSkillToTileOK4;
		GCSkillToTileOK5 _GCSkillToTileOK5;
//		GCSkillToTileOK6 _GCSkillToTileOK6;

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

		int  RequiredMP  = decreaseConsumeMP(pVampire, pSkillInfo);
		bool bManaCheck  = hasEnoughMana(pVampire, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pVampireSkillSlot);
		bool bRangeCheck = verifyDistance(pVampire, X, Y, pSkillInfo->getRange());

		if (bManaCheck && bTimeCheck && bRangeCheck )
		{
			// 마나를 떨어뜨린다.
			decreaseMana(pVampire, RequiredMP, _GCSkillToTileOK1);

			// 좌표와 방향을 구한다.
			ZoneCoord_t myX          = pVampire->getX();
			ZoneCoord_t myY          = pVampire->getY();
			Dir_t       dir          = calcDirection(myX, myY, X, Y);

			list<Creature*> cList;

			// knockback 때문에 recursive 하게 데미지를 먹는 경우가 있다.
			// 그래서 제일 먼쪽에 있는 마스크부터 체크한다.
			for (int i = 21; i >= 0; i-- )
			{
				int tileX   = myX + m_pBloodyBreakerMask[Dir][i].x;
				int tileY   = myY + m_pBloodyBreakerMask[Dir][i].y;

				// 현재 타일이 존 내부이고, 안전지대가 아니라면 맞을 가능성이 있다.
				if (rect.ptInRect(tileX, tileY))
				{
					// 타일을 받아온다.
					Tile& tile = pZone->getTile(tileX, tileY);

					list<Creature*> targetList;
					if (tile.hasCreature(Creature::MOVE_MODE_WALKING))
					{
						Creature* pCreature = tile.getCreature(Creature::MOVE_MODE_WALKING);
						targetList.push_back(pCreature);
					}
					if (tile.hasCreature(Creature::MOVE_MODE_FLYING))
					{
						Creature* pCreature = tile.getCreature(Creature::MOVE_MODE_FLYING);
						targetList.push_back(pCreature);
					}
					if (tile.hasCreature(Creature::MOVE_MODE_BURROWING))
					{
						Creature* pCreature = tile.getCreature(Creature::MOVE_MODE_BURROWING);
						targetList.push_back(pCreature);
					}

					list<Creature*>::iterator itr = targetList.begin();
					for(; itr != targetList.end(); itr++)
					{
						Creature* pTargetCreature = (*itr);
						Assert(pTargetCreature != NULL);

						if (!canAttack(pVampire, pTargetCreature )
							|| pTargetCreature->isFlag(Effect::EFFECT_CLASS_COMA) )
						{
							continue;
						}

						if (pTargetCreature != pVampire)
						{
							bool bPK             = verifyPK(pVampire, pTargetCreature);
							bool bRaceCheck      = pTargetCreature->isSlayer() || pTargetCreature->isMonster() || pTargetCreature->isOusters();
							bool bZoneLevelCheck = checkZoneLevelToHitTarget(pTargetCreature);
							bool bHitRoll        = false;//HitRoll::isSuccessMagic(pVampire, pSkillInfo, pVampireSkillSlot, HitBonus);

							int EnemyLevel = 0;

							if (pTargetCreature->isSlayer() )
							{
								Slayer* pSlayer = dynamic_cast<Slayer*>(pTargetCreature);
								EnemyLevel = pSlayer->getHighestSkillDomainLevel();
							}
							else if (pTargetCreature->isOusters() )
							{
								Ousters* pOusters = dynamic_cast<Ousters*>(pTargetCreature);
								EnemyLevel = pOusters->getLevel();
							}
							else if (pTargetCreature->isMonster() )
							{
								Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature);
								EnemyLevel = pMonster->getLevel();
							}

							// min : 20, max : 100
							int hitRatio = max(20, 50 + pVampire->getLevel() - EnemyLevel + HitBonus);
							bHitRoll = (rand()%100) < hitRatio;

							if (bPK && bRaceCheck && bZoneLevelCheck && bHitRoll)
							{
								Damage_t Damage = 0;
								bool bForceKnockback = rand() & 1;

								Damage += computeMagicDamage(pTargetCreature, output.Damage, SkillType, true, pVampire);

								ObjectID_t targetObjectID = pTargetCreature->getObjectID();
								cList.push_back(pTargetCreature);

								_GCSkillToTileOK1.addCListElement(targetObjectID);
								_GCSkillToTileOK2.addCListElement(targetObjectID);
								_GCSkillToTileOK5.addCListElement(targetObjectID);

								// 일단 맞는 놈이 받을 패킷은 널 상태로 한 채로, 데미지를 준다.
								setDamage(pTargetCreature, Damage, pVampire, SkillType, NULL, &_GCSkillToTileOK1);
								computeAlignmentChange(pTargetCreature, Damage, pVampire, NULL, &_GCSkillToTileOK1);

								increaseAlignment(pVampire, pTargetCreature, _GCSkillToTileOK1);

								// 크리티컬 히트라면 상대방을 뒤로 물러나게 한다.
								if (bForceKnockback)
								{
									knockbackCreature(pZone, pTargetCreature, pVampire->getX(), pVampire->getY());
								}

								if (pTargetCreature->isDead())
								{
									int exp = computeCreatureExp(pTargetCreature, KILL_EXP);
									shareVampExp(pVampire, exp, _GCSkillToTileOK1);
								}
							}
						}
					}
				}
			}


			// 공격자의 아이템 내구성을 떨어뜨린다.
			decreaseDurability(pVampire, NULL, pSkillInfo, &_GCSkillToTileOK1, NULL);

			_GCSkillToTileOK1.setSkillType(SkillType);
			_GCSkillToTileOK1.setCEffectID(0);
			_GCSkillToTileOK1.setX(X);
			_GCSkillToTileOK1.setY(Y);
			_GCSkillToTileOK1.setRange(dir);
			_GCSkillToTileOK1.setDuration(0);

			_GCSkillToTileOK2.setObjectID(pVampire->getObjectID());
			_GCSkillToTileOK2.setSkillType(SkillType);
			_GCSkillToTileOK2.setX(X);
			_GCSkillToTileOK2.setY(Y);
			_GCSkillToTileOK2.setRange(dir);
			_GCSkillToTileOK2.setDuration(0);

			_GCSkillToTileOK5.setObjectID(pVampire->getObjectID());
			_GCSkillToTileOK5.setSkillType(SkillType);
			_GCSkillToTileOK5.setX(X);
			_GCSkillToTileOK5.setY(Y);
			_GCSkillToTileOK5.setRange(dir);
			_GCSkillToTileOK5.setDuration(0);

			pPlayer->sendPacket(&_GCSkillToTileOK1);

			// 이 기술에 의해 영향을 받는 놈들에게 패킷을 보내줘야 한다.
			for (list<Creature*>::const_iterator itr = cList.begin(); itr != cList.end(); itr++)
			{
				Creature * pTargetCreature = *itr;
				Assert(pTargetCreature != NULL);

				if (pTargetCreature->isPC())
				{
					_GCSkillToTileOK2.clearList();

					// HP의 변경사항을 패킷에다 기록한다.
					HP_t targetHP = 0;
					if (pTargetCreature->isSlayer())
					{
						targetHP = (dynamic_cast<Slayer*>(pTargetCreature))->getHP(ATTR_CURRENT);
					}
					else if (pTargetCreature->isVampire())
					{
						targetHP = (dynamic_cast<Vampire*>(pTargetCreature))->getHP(ATTR_CURRENT);
					}
					else if (pTargetCreature->isOusters())
					{
						targetHP = (dynamic_cast<Ousters*>(pTargetCreature))->getHP(ATTR_CURRENT);
					}

					_GCSkillToTileOK2.addShortData(MODIFY_CURRENT_HP, targetHP);

					// 아이템의 내구력을 떨어뜨린다.
					decreaseDurability(NULL, pTargetCreature, pSkillInfo, NULL, &_GCSkillToTileOK2);

					// 패킷을 보내준다.
					pTargetCreature->getPlayer()->sendPacket(&_GCSkillToTileOK2);
				}
				else if (pTargetCreature->isMonster())
				{
					// 당근 적으로 인식한다.
					Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature);
					pMonster->addEnemy(pVampire);
				}
			}

			cList.push_back(pVampire);

			pZone->broadcastPacket(myX, myY, &_GCSkillToTileOK5 , cList);

			// set Next Run Time
			pVampireSkillSlot->setRunTime(output.Delay);
		}
		else 
		{
			executeSkillFailNormal(pVampire, SkillType, NULL);
		}
	}
	catch (Throwable & t) 
	{
		executeSkillFailException(pVampire, SkillType);
	}

//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl;

	__END_CATCH
}
Example #21
0
void SimpleMissileSkill::execute(
	Vampire* pVampire, ObjectID_t TargetObjectID, VampireSkillSlot* pVampireSkillSlot, 
	const SIMPLE_SKILL_INPUT& param, SIMPLE_SKILL_OUTPUT& result, 
	CEffectID_t CEffectID, int HitBonus) 
	throw(Error)
{
	__BEGIN_TRY

	Assert(pVampire != NULL);
	Assert(pVampireSkillSlot != NULL);

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

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

		// NPC는 공격할 수가 없다.
		// NoSuch제거. by sigi. 2002.5.2
		if (pTargetCreature==NULL
			|| !canAttack(pVampire, pTargetCreature )
			|| pTargetCreature->isNPC())
		{
			executeSkillFailException(pVampire, param.SkillType);
			return;
		}

		result.pTargetCreature = pTargetCreature;

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

		SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(param.SkillType);
		bool       bCriticalHit = false;
		Damage_t   Damage       = 0;

		if (param.bAdd)
		{
			// 파라미터로 전달된 데미지 값이 더해지는 데미지라면, 
			// 일반 데미지를 계산 후, 데미지를 더해야 한다.
			// 파라미터로 전달된 데미지 값이 직접적으로 쓰이는 데미지라면,
			// 이 부분까지 들어오지 않으므로, 밑의 부분까지 0으로 전달된다.
			Damage += computeDamage(pVampire, pTargetCreature, 0, bCriticalHit);
		}

		if (param.bMagicDamage)
		{
			// 만일 스킬 데미지가 마법 데미지라면, 마법 데미지 계산 함수를 이용해 계산을 해준다.
			Damage += computeMagicDamage(pTargetCreature, param.SkillDamage, param.SkillType, true, pVampire);
		}
		else
		{
			Damage += param.SkillDamage;
		}

		int  RequiredMP  = decreaseConsumeMP(pVampire, pSkillInfo);
		bool bManaCheck  = hasEnoughMana(pVampire, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pVampireSkillSlot);
		bool bRangeCheck = verifyDistance(pVampire, pTargetCreature, pSkillInfo->getRange());
		bool bHitRoll    = false;
		bool bCanHit     = canHit(pVampire, pTargetCreature, param.SkillType);
		bool bPK         = verifyPK(pVampire, pTargetCreature);

		if (param.bMagicHitRoll)
		{
			bHitRoll = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pVampireSkillSlot, HitBonus);
		}
		else
		{
			bHitRoll = HitRoll::isSuccess(pVampire, pTargetCreature);
		}

		ZoneCoord_t vampX   = pVampire->getX();
		ZoneCoord_t vampY   = pVampire->getY();
		ZoneCoord_t targetX = pTargetCreature->getX();
		ZoneCoord_t targetY = pTargetCreature->getY();

		if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bCanHit && bPK)
		{
			decreaseMana(pVampire, RequiredMP, _GCSkillToObjectOK1);

			bool bCanSeeCaster = canSee(pTargetCreature, pVampire);

			// 데미지를 가하고, 아이템 내구도를 떨어뜨린다.
			if (bCanSeeCaster) 
			{
				setDamage(pTargetCreature, Damage, pVampire, param.SkillType, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1);
				computeAlignmentChange(pTargetCreature, Damage, pVampire, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1);
				decreaseDurability(pVampire, pTargetCreature, pSkillInfo, &_GCSkillToObjectOK1, &_GCSkillToObjectOK2);
			}
			else
			{
				setDamage(pTargetCreature, Damage, pVampire, param.SkillType, &_GCSkillToObjectOK6, &_GCSkillToObjectOK1);
				computeAlignmentChange(pTargetCreature, Damage, pVampire, &_GCSkillToObjectOK6, &_GCSkillToObjectOK1);
				decreaseDurability(pVampire, pTargetCreature, pSkillInfo, &_GCSkillToObjectOK1, &_GCSkillToObjectOK6);
			}

			// 상대가 죽었다면 경험치를 좀 올려준다.
			if (pTargetCreature->isDead())
			{
				int exp = computeCreatureExp(pTargetCreature, KILL_EXP);
				shareVampExp(pVampire, exp, _GCSkillToObjectOK1);
			}

			increaseAlignment(pVampire, pTargetCreature, _GCSkillToObjectOK1);

			_GCSkillToObjectOK1.setSkillType(param.SkillType);
			_GCSkillToObjectOK1.setCEffectID(CEffectID);
			_GCSkillToObjectOK1.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK1.setDuration(0);
		
			_GCSkillToObjectOK2.setObjectID(pVampire->getObjectID());
			_GCSkillToObjectOK2.setSkillType(param.SkillType);
			_GCSkillToObjectOK2.setDuration(0);
			
			_GCSkillToObjectOK3.setObjectID(pVampire->getObjectID());
			_GCSkillToObjectOK3.setSkillType(param.SkillType);
			_GCSkillToObjectOK3.setTargetXY(targetX, targetY);
		
			_GCSkillToObjectOK4.setSkillType(param.SkillType);
			_GCSkillToObjectOK4.setTargetObjectID(TargetObjectID);

			_GCSkillToObjectOK5.setObjectID(pVampire->getObjectID());
			_GCSkillToObjectOK5.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK5.setSkillType(param.SkillType);
			
			_GCSkillToObjectOK6.setXY(vampX, vampY);
			_GCSkillToObjectOK6.setSkillType(param.SkillType);
			_GCSkillToObjectOK6.setDuration(0);

			pPlayer->sendPacket(&_GCSkillToObjectOK1);
		
			Player* pTargetPlayer = NULL;
			if (pTargetCreature->isPC()) 
			{
				pTargetPlayer = pTargetCreature->getPlayer();
				Assert(pTargetPlayer != NULL);
				if (bCanSeeCaster) pTargetPlayer->sendPacket(&_GCSkillToObjectOK2);
				else pTargetPlayer->sendPacket(&_GCSkillToObjectOK6);
			} 
			else 
			{
				Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature);
				pMonster->addEnemy(pVampire);
			}

			list<Creature*> cList;
			cList.push_back(pVampire);
			cList.push_back(pTargetCreature);

			cList = pZone->broadcastSkillPacket(vampX, vampY, targetX, targetY, &_GCSkillToObjectOK5, cList);
			
			pZone->broadcastPacket(vampX, vampY,  &_GCSkillToObjectOK3 , cList);
			pZone->broadcastPacket(targetX, targetY,  &_GCSkillToObjectOK4 , cList);

			pVampireSkillSlot->setRunTime(param.Delay);

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

	__END_CATCH
}
//----------------------------------------------------------------------
// 
// SGModifyGuildOKHandler::execute()
// 
//----------------------------------------------------------------------
void SGModifyGuildOKHandler::execute (SGModifyGuildOK* pPacket )
	 throw(ProtocolException , Error )
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

	Guild* pGuild = g_pGuildManager->getGuild(pPacket->getGuildID());
	Assert(pGuild != NULL);

	if (pGuild->getState() == Guild::GUILD_STATE_WAIT && pPacket->getGuildState() == Guild::GUILD_STATE_ACTIVE )
	{
		/////////////////////////////////////////////////////////////
		// 존 추가
		/////////////////////////////////////////////////////////////
/*		if (pGuild->getServerGroupID() == g_pConfig->getPropertyInt("ServerID" ) )
		{
			// 이 게임 서버에 길드 아지트를 만든다.

			//////////////
			// Zone Info
			//////////////
			ZoneInfo* pZoneInfo = new ZoneInfo();
			pZoneInfo->setZoneID(pGuild->getZoneID());
			pZoneInfo->setZoneGroupID(2);
			pZoneInfo->setZoneType("NPC_SHOP");
			pZoneInfo->setZoneLevel(0);
			pZoneInfo->setZoneAccessMode("PUBLIC");
			pZoneInfo->setZoneOwnerID("");
			pZoneInfo->setPayPlay("");
			if (pGuild->getRace() == Guild::GUILD_RACE_SLAYER )
			{
				pZoneInfo->setSMPFilename("team_hdqrs.smp");
				pZoneInfo->setSSIFilename("team_hdqrs.ssi");
				string Name = "team - " + pGuild->getName();
				pZoneInfo->setFullName(Name);
				pZoneInfo->setShortName(Name);
			}
			else if (pGuild->getRace() == Guild::GUILD_RACE_VAMPIRE )
			{
				pZoneInfo->setSMPFilename("clan_hdqrs.smp");
				pZoneInfo->setSSIFilename("clan_hdqrs.ssi");
				string Name = "clan - " + pGuild->getName();
				pZoneInfo->setFullName(Name);
				pZoneInfo->setShortName(Name);
			}

			g_pZoneInfoManager->addZoneInfo(pZoneInfo);
			
			/////////
			// Zone
			/////////
			Zone* pZone = new Zone(pGuild->getZoneID());
			Assert(pZone != NULL);

			ZoneGroup* pZoneGroup = g_pZoneGroupManager->getZoneGroup(2);
			Assert(pZoneGroup != NULL);

			pZone->setZoneGroup(pZoneGroup);
			pZoneGroup->addZone(pZone);
			pZone->init();
		}
*/

		// 정식 길드로 변경
		pGuild->setState(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);

				// 길드 아이디를 바꿔준다.
				pPlayerCreature->setGuildID(pGuild->getID());

				// 클라이언트에 길드 아이디가 바꼈음을 알려준다.
				GCModifyGuildMemberInfo gcModifyGuildMemberInfo;
				gcModifyGuildMemberInfo.setGuildID(pGuild->getID());
				gcModifyGuildMemberInfo.setGuildName(pGuild->getName());
				gcModifyGuildMemberInfo.setGuildMemberRank(pGuildMember->getRank());
				pPlayer->sendPacket(&gcModifyGuildMemberInfo);

				// 주위에 알린다.
				Zone* pZone = pCreature->getZone();
				Assert(pZone != NULL);

				GCOtherModifyInfo gcOtherModifyInfo;
				gcOtherModifyInfo.setObjectID(pCreature->getObjectID());
				gcOtherModifyInfo.addShortData(MODIFY_GUILDID, pPlayerCreature->getGuildID());

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

				// 정식 길드가 되었음을 알림
				Statement* pStmt = NULL;
				Result* pResult = NULL;

				BEGIN_DB
				{
					pStmt = g_pDatabaseManager->getConnection("DARKEDEN" )->createStatement();
					pResult = pStmt->executeQuery("SELECT Message FROM Messages WHERE Receiver = '%s'", pGuildMember->getName().c_str());

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

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

					SAFE_DELETE(pStmt);
				}
				END_DB(pStmt)
			}

			__LEAVE_CRITICAL_SECTION((*g_pPCFinder))
		}
Example #23
0
void SimpleMissileSkill::execute(
	Ousters* pOusters, ObjectID_t TargetObjectID, OustersSkillSlot* pOustersSkillSlot, 
	const SIMPLE_SKILL_INPUT& param, SIMPLE_SKILL_OUTPUT& result, 
	CEffectID_t CEffectID, int HitBonus) 
	throw(Error)
{
	__BEGIN_TRY

	Assert(pOusters != NULL);
	Assert(pOustersSkillSlot != NULL);

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

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

		// NPC는 공격할 수가 없다.
		// NoSuch제거. by sigi. 2002.5.2
		if (pTargetCreature==NULL
			|| !canAttack(pOusters, pTargetCreature )
			|| pTargetCreature->isNPC()
			)
		{
			executeSkillFailException(pOusters, param.SkillType, param.Grade);
			return;
		}

		result.pTargetCreature = pTargetCreature;

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

		if (param.ItemClass != Item::ITEM_CLASS_MAX)
		{
			Item* pItem = pOusters->getWearItem(Ousters::WEAR_RIGHTHAND);
			if (pItem == NULL || pItem->getItemClass() != param.ItemClass || !pOusters->isRealWearingEx(Ousters::WEAR_RIGHTHAND))
			{
				executeSkillFailException(pOusters, param.SkillType, param.Grade);
				return;
			}
		}

		SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(param.SkillType);
		bool       bCriticalHit = false;
		Damage_t   Damage       = 0;

		if (param.bAdd)
		{
			// 파라미터로 전달된 데미지 값이 더해지는 데미지라면, 
			// 일반 데미지를 계산 후, 데미지를 더해야 한다.
			// 파라미터로 전달된 데미지 값이 직접적으로 쓰이는 데미지라면,
			// 이 부분까지 들어오지 않으므로, 밑의 부분까지 0으로 전달된다.
			Damage += computeDamage(pOusters, pTargetCreature, 0, bCriticalHit);
		}

		if (param.bMagicDamage)
		{
			// 만일 스킬 데미지가 마법 데미지라면, 마법 데미지 계산 함수를 이용해 계산을 해준다.
//			Damage += computeMagicDamage(pTargetCreature, param.SkillDamage, param.SkillType, true);
			Damage += computeOustersMagicDamage(pOusters, pTargetCreature, param.SkillDamage, param.SkillType);
		}
		else
		{
			Damage += param.SkillDamage;
		}

		computeCriticalBonus(pOusters, param.SkillType, Damage, bCriticalHit);

		int  RequiredMP         = (int)pSkillInfo->getConsumeMP();
		bool bManaCheck         = hasEnoughMana(pOusters, RequiredMP);
		bool bTimeCheck         = verifyRunTime(pOustersSkillSlot);
		bool bRangeCheck        = verifyDistance(pOusters, pTargetCreature, pSkillInfo->getRange());
		bool bHitRoll           = false;
		bool bCanHit            = canHit(pOusters, pTargetCreature, param.SkillType);
		bool bPK                = verifyPK(pOusters, pTargetCreature);
		bool bSatisfyRequire	= pOusters->satisfySkillRequire(pSkillInfo);

		if (param.bMagicHitRoll)
		{
			bHitRoll = HitRoll::isSuccessMagic(pOusters, pSkillInfo, pOustersSkillSlot, HitBonus);
		}
		else 
		{
			bHitRoll = HitRoll::isSuccess(pOusters, pTargetCreature);
		}

		ZoneCoord_t X   = pOusters->getX();
		ZoneCoord_t Y   = pOusters->getY();
		ZoneCoord_t targetX = pTargetCreature->getX();
		ZoneCoord_t targetY = pTargetCreature->getY();

		if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bCanHit && bPK && bSatisfyRequire )
		{
            decreaseMana(pOusters, RequiredMP, _GCSkillToObjectOK1);

			bool bCanSeeCaster = canSee(pTargetCreature, pOusters);
			if (bCanSeeCaster) 
			{
				setDamage(pTargetCreature, Damage, pOusters, param.SkillType, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1);
				computeAlignmentChange(pTargetCreature, Damage, pOusters, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1);
				decreaseDurability(pOusters, pTargetCreature, pSkillInfo, &_GCSkillToObjectOK1, &_GCSkillToObjectOK2);
			}
			else
			{
				setDamage(pTargetCreature, Damage, pOusters, param.SkillType, &_GCSkillToObjectOK6, &_GCSkillToObjectOK1);
				computeAlignmentChange(pTargetCreature, Damage, pOusters, &_GCSkillToObjectOK6, &_GCSkillToObjectOK1);
				decreaseDurability(pOusters, pTargetCreature, pSkillInfo, &_GCSkillToObjectOK1, &_GCSkillToObjectOK6);
			}

			if (pTargetCreature->isDead())
			{
				int exp = computeCreatureExp(pTargetCreature, 100, pOusters);
				shareOustersExp(pOusters, exp, _GCSkillToObjectOK1);
			}

			increaseAlignment(pOusters, pTargetCreature, _GCSkillToObjectOK1);

			_GCSkillToObjectOK1.setSkillType(param.SkillType);
			_GCSkillToObjectOK1.setCEffectID(CEffectID);
			_GCSkillToObjectOK1.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK1.setDuration(0);
			_GCSkillToObjectOK1.setGrade(param.Grade);
		
			_GCSkillToObjectOK2.setObjectID(pOusters->getObjectID());
			_GCSkillToObjectOK2.setSkillType(param.SkillType);
			_GCSkillToObjectOK2.setDuration(0);
			_GCSkillToObjectOK2.setGrade(param.Grade);
			
			_GCSkillToObjectOK3.setObjectID(pOusters->getObjectID());
			_GCSkillToObjectOK3.setSkillType(param.SkillType);
			_GCSkillToObjectOK3.setTargetXY(targetX, targetY);
			_GCSkillToObjectOK3.setGrade(param.Grade);
		
			_GCSkillToObjectOK4.setSkillType(param.SkillType);
			_GCSkillToObjectOK4.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK4.setGrade(param.Grade);

			_GCSkillToObjectOK5.setObjectID(pOusters->getObjectID());
			_GCSkillToObjectOK5.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK5.setSkillType(param.SkillType);
			_GCSkillToObjectOK5.setGrade(param.Grade);
			
			_GCSkillToObjectOK6.setXY(X, Y);
			_GCSkillToObjectOK6.setSkillType(param.SkillType);
			_GCSkillToObjectOK6.setDuration(0);
			_GCSkillToObjectOK6.setGrade(param.Grade);

			pPlayer->sendPacket(&_GCSkillToObjectOK1);
		
			Player* pTargetPlayer = NULL;
			if (pTargetCreature->isPC()) 
			{
				pTargetPlayer = pTargetCreature->getPlayer();
				Assert(pTargetPlayer != NULL);
				if (bCanSeeCaster) pTargetPlayer->sendPacket(&_GCSkillToObjectOK2);
				else pTargetPlayer->sendPacket(&_GCSkillToObjectOK6);
			} 
			else 
			{
				Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature);
				pMonster->addEnemy(pOusters);
			}

			list<Creature*> cList;
			cList.push_back(pOusters);
			cList.push_back(pTargetCreature);

			cList = pZone->broadcastSkillPacket(X, Y, targetX, targetY, &_GCSkillToObjectOK5, cList);
			
			pZone->broadcastPacket(X, Y,  &_GCSkillToObjectOK3 , cList);
			pZone->broadcastPacket(targetX, targetY,  &_GCSkillToObjectOK4 , cList);

			pOustersSkillSlot->setRunTime(param.Delay);

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


	__END_CATCH
}
Example #24
0
//////////////////////////////////////////////////////////////////////////////
// 뱀파이어 타일 핸들러
//////////////////////////////////////////////////////////////////////////////
void BloodyWall::execute(Vampire* pVampire, ZoneCoord_t X, ZoneCoord_t Y, VampireSkillSlot* pVampireSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

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

	Assert(pVampire != NULL);
	Assert(pVampireSkillSlot != NULL);

	try 
	{
		Player* pPlayer = pVampire->getPlayer();
		Zone* pZone = pVampire->getZone();

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

		GCSkillToTileOK1 _GCSkillToTileOK1;
		GCSkillToTileOK2 _GCSkillToTileOK2;
		GCSkillToTileOK3 _GCSkillToTileOK3;
		GCSkillToTileOK4 _GCSkillToTileOK4;
		GCSkillToTileOK5 _GCSkillToTileOK5;
		GCSkillToTileOK6 _GCSkillToTileOK6;

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

		ZoneCoord_t myX = pVampire->getX();
		ZoneCoord_t myY = pVampire->getY();

		// Knowledge of Blood 가 있다면 hit bonus 10
		int HitBonus = 0;
		if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_BLOOD ) )
		{
			RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_BLOOD);
			Assert(pRankBonus != NULL);

			HitBonus = pRankBonus->getPoint();
		}

		int  RequiredMP  = decreaseConsumeMP(pVampire, pSkillInfo);
		bool bManaCheck  = hasEnoughMana(pVampire, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pVampireSkillSlot);
		bool bRangeCheck = verifyDistance(pVampire, X, Y, pSkillInfo->getRange());
		bool bHitRoll    = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pVampireSkillSlot, HitBonus);
		
		bool bTileCheck = false;
		VSRect rect(0, 0, pZone->getWidth()-1, pZone->getHeight()-1);
		if (rect.ptInRect(X, Y)) bTileCheck = true;

		if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bTileCheck)
		{
			decreaseMana(pVampire, RequiredMP, _GCSkillToTileOK1);

			// 이펙트의 지속시간을 계산한다.
			SkillInput input(pVampire);
			SkillOutput output;
			computeOutput(input, output);

			Dir_t 	   Dir		= getDirectionToPosition(myX, myY, X, Y);

			list<Creature*> cList;	// denier list
			
			for (int i=0; i<5; i++)
			{
				POINT& pt = m_BloodyWallMask[Dir][i];

				int tileX = X+pt.x;
				int tileY = Y+pt.y;

				if (rect.ptInRect(tileX, tileY))
				{
					Tile& tile = pZone->getTile(tileX, tileY);
					if (tile.getEffect(Effect::EFFECT_CLASS_TRYING_POSITION )!=NULL ) continue;

					// 현재 타일에다 이펙트를 추가할 수 있다면...
					if (tile.canAddEffect())
					{
						// 같은 effect가 있으면 지운다.
						Effect* pOldEffect = tile.getEffect(Effect::EFFECT_CLASS_BLOODY_WALL);
						if (pOldEffect != NULL)
						{
							ObjectID_t effectID = pOldEffect->getObjectID();
							pZone->deleteEffect(effectID);// fix me
						}
					
						// 이펙트 클래스를 생성한다.
						EffectBloodyWall* pEffect = new EffectBloodyWall(pZone , tileX, tileY);
						pEffect->setCasterName(pVampire->getName());
						pEffect->setCasterID(pVampire->getObjectID());
						pEffect->setClan(Creature::CREATURE_CLASS_VAMPIRE, pVampire->getClanType());
						pEffect->setDamage(output.Damage);
						pEffect->setDeadline(output.Duration);
						pEffect->setLevel(pVampire->getINT());
						pEffect->setNextTime(0);
						pEffect->setTick(output.Tick);

						// Tile에 붙이는 Effect는 ObjectID를 등록받아야 한다.
						ObjectRegistry & objectregister = pZone->getObjectRegistry();
						objectregister.registerObject(pEffect);
						pZone->addEffect(pEffect);
						tile.addEffect(pEffect);

						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() || pTargetCreature->isOusters() )
								&& !checkZoneLevelToHitTarget(pTargetCreature )
							) 
							{
								cList.push_back(pTargetCreature);
								_GCSkillToTileOK2.addCListElement(pTargetCreature->getObjectID());
								_GCSkillToTileOK4.addCListElement(pTargetCreature->getObjectID());
								_GCSkillToTileOK5.addCListElement(pTargetCreature->getObjectID());

								pEffect->affect(pTargetCreature);
							}
//								pEffect->affect(pTarget);
						}
					}	
				}	
			}

			_GCSkillToTileOK1.setSkillType(SkillType);
			_GCSkillToTileOK1.setCEffectID(CEffectID);
			_GCSkillToTileOK1.setX(X);
			_GCSkillToTileOK1.setY(Y);
			_GCSkillToTileOK1.setDuration(output.Duration);
			_GCSkillToTileOK1.setRange(Dir);

			_GCSkillToTileOK2.setObjectID(pVampire->getObjectID());
			_GCSkillToTileOK2.setSkillType(SkillType);
			_GCSkillToTileOK2.setX(X);
			_GCSkillToTileOK2.setY(Y);
			_GCSkillToTileOK2.setDuration(output.Duration);
			_GCSkillToTileOK2.setRange(Dir);
			//_GCSkillToTileOK2.addShortData(MODIFY_VISION, BLOODY_WALL_SIGHT);

			_GCSkillToTileOK3.setObjectID(pVampire->getObjectID());
			_GCSkillToTileOK3.setSkillType(SkillType);
			_GCSkillToTileOK3.setX(X);
			_GCSkillToTileOK3.setY(Y);

			_GCSkillToTileOK4.setSkillType(SkillType);
			_GCSkillToTileOK4.setX(X);
			_GCSkillToTileOK4.setY(Y);
			_GCSkillToTileOK4.setRange(Dir);
			_GCSkillToTileOK4.setDuration(output.Duration);

			_GCSkillToTileOK5.setObjectID(pVampire->getObjectID());
			_GCSkillToTileOK5.setSkillType(SkillType);
			_GCSkillToTileOK5.setX(X);
			_GCSkillToTileOK5.setY(Y);
			_GCSkillToTileOK5.setRange(Dir);
			_GCSkillToTileOK5.setDuration(output.Duration);

			_GCSkillToTileOK6.setOrgXY(myX, myY);
			_GCSkillToTileOK6.setSkillType(SkillType);
			_GCSkillToTileOK6.setX(X);
			_GCSkillToTileOK6.setY(Y);
			_GCSkillToTileOK6.setDuration(output.Duration);
			_GCSkillToTileOK6.setRange(Dir);
			//_GCSkillToTileOK6.addShortData(MODIFY_VISION, BLOODY_WALL_SIGHT);

			for(list<Creature*>::const_iterator itr = cList.begin(); itr != cList.end(); itr++)
			{
				Creature* pTargetCreature = *itr;
				if (canSee(pTargetCreature, pVampire)) pTargetCreature->getPlayer()->sendPacket(&_GCSkillToTileOK2);
				else pTargetCreature->getPlayer()->sendPacket(&_GCSkillToTileOK6);
			}

			pPlayer->sendPacket(&_GCSkillToTileOK1);

			cList.push_back(pVampire);

			list<Creature*> watcherList = pZone->getWatcherList(myX, myY, pVampire);

			// watcherList에서 cList에 속하지 않고, caster(pVampire)를 볼 수 없는 경우는
			// OK4를 보내고.. cList에 추가한다.
			for(list<Creature*>::const_iterator itr = watcherList.begin(); itr != watcherList.end(); itr++)
			{
				bool bBelong = false;
				for(list<Creature*>::const_iterator tItr = cList.begin(); tItr != cList.end(); tItr++)
					if (*itr == *tItr)
						bBelong = true;

				Creature* pWatcher = (*itr);
				if (bBelong == false && canSee(pWatcher, pVampire) == false)
				{
					//Assert(pWatcher->isPC());	// 당연 PC다.. Zone::getWatcherList는 PC만 return한다
					if (!pWatcher->isPC())
					{
						//cout << "BloodyWall : 왓처 리스트가 PC가 아닙니다." << endl;
						GCSkillFailed1 _GCSkillFailed1;
						_GCSkillFailed1.setSkillType(getSkillType());
						pVampire->getPlayer()->sendPacket(&_GCSkillFailed1);

						//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;
						return;
					}
					pWatcher->getPlayer()->sendPacket(&_GCSkillToTileOK4);
					cList.push_back(*itr);
				}
			}
					
			cList = pZone->broadcastSkillPacket(myX, myY, X, Y, &_GCSkillToTileOK5, cList, false);
			
			pZone->broadcastPacket(myX, myY,  &_GCSkillToTileOK3 , cList);
			
			pZone->broadcastPacket(X, Y,  &_GCSkillToTileOK4 , cList);

			pVampireSkillSlot->setRunTime(output.Delay);
		} 
		else 
		{
			executeSkillFailNormal(pVampire, getSkillType(), NULL);
		}
	} 
	catch (Throwable & t) 
	{
		executeSkillFailException(pVampire, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;

	__END_CATCH
}
Example #25
0
//////////////////////////////////////////////////////////////////////////////
// 클라이언트가 CGLogout 패킷을 보내면, 게임 서버는 크리처를 존에서 삭제하고,
// 크리처와 아이템 정보를 DB에 저장한 후, 접속을 종료한다.
//////////////////////////////////////////////////////////////////////////////
void CGLogoutHandler::execute (CGLogout* pPacket , Player* pPlayer)
	 throw(ProtocolException , Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

//	Assert(pPacket != NULL);
	Assert(pPlayer != NULL);
	
	// 새로그인 구조에서는 Logout을 하면 대기 상태로 나가야 한다.
	// Logout 패킷을 받으면 플레이어를 IncomingPlayerManager로 보낸다.
	GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer);

	//cout << "CGLogoutHandler: " << pGamePlayer->getID() << endl;

	Creature* pCreature = pGamePlayer->getCreature();

	Assert(pCreature != NULL);

	Zone* pZone = pCreature->getZone();

	Assert(pZone != NULL);


	// 나는 나간다 라고 로그를 남긴다.
	pGamePlayer->logLoginoutDateTime();

    try 
	{
		// 로그아웃할때 성물, 피의 성서 조각을 떨어뜨린다.
//		bool bSendPacket = false;
//		dropRelicToZone(pCreature, bSendPacket);

		if (pCreature->isPLAYER() && g_pPKZoneInfoManager->isPKZone(pCreature->getZoneID() ) )
		{
			g_pPKZoneInfoManager->leavePKZone(pCreature->getZoneID());
		}

		if (g_pConfig->hasKey("Hardcore") && g_pConfig->getPropertyInt("Hardcore")!=0 && pPacket==NULL )
		{
		}
		else
		{
			// 크리처의 정보를 저장한다.
			pCreature->save();

			if (pCreature->isSlayer() )
			{
				Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature);
				pSlayer->tinysave("LastPlayDate=now()");
			}
			else if (pCreature->isVampire() )
			{
				Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);
				pVampire->tinysave("LastPlayDate=now()");
			}
			else if (pCreature->isOusters() )
			{
				Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);
				pOusters->tinysave("LastPlayDate=now()");
			}

			//////////////////////////////////////////////////////////////
			// 플레이어가 COMA상태(현재 죽은 상태)라면 로그아웃시 자동으로
			// 부활위치로 캐릭터를 이동시킨다.
			// Login/Logout의 반복으로 부활기술을 사용하지 못하게 함
			//
			// Creature의 정보를 먼저 DB에 업데이트한 후 새로 업데이트를 한다.
			//////////////////////////////////////////////////////////////

			// 이터니티를 한번 쓴 상태로 로그아웃하면 부활 위치로 날라간다.
			if (pCreature->isFlag(Effect::EFFECT_CLASS_COMA) || pCreature->isFlag(Effect::EFFECT_CLASS_ETERNITY))
			{
				//cout << "COMA 상태에서 로그아웃했음" << endl;

				ZoneID_t  ZoneID = 0;
				ZoneCoord_t ZoneX = 0;
				ZoneCoord_t ZoneY = 0;
				ZONE_COORD ResurrectCoord;

				if (pCreature->isPC() )
				{
					PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature);

					g_pResurrectLocationManager->getPosition(pPC, ResurrectCoord);

					ZoneID = ResurrectCoord.id;
					ZoneX  = ResurrectCoord.x;
					ZoneY  = ResurrectCoord.y;

					char pField[80];
					sprintf(pField, "ZoneID=%d, XCoord=%d, YCoord=%d, CurrentHP=HP", ZoneID, ZoneX, ZoneY);

					if (pPC->isSlayer() )
					{
						Slayer* pSlayer = dynamic_cast<Slayer*>(pPC);
						pSlayer->tinysave(pField);
					}
					else if (pPC->isVampire() )
					{
						Vampire* pVampire = dynamic_cast<Vampire*>(pPC);
						pVampire->tinysave(pField);
					}
					else if (pPC->isOusters() )
					{
						Ousters* pOusters = dynamic_cast<Ousters*>(pPC);
						pOusters->tinysave(pField);
					}
				}
			}

			// 포스 스크롤이 켜져 있으면 로그아웃하면저 저장한다.
			if (pCreature->isFlag(Effect::EFFECT_CLASS_BEHEMOTH_FORCE_SCROLL) )
			{
				Effect* pEffect = pCreature->findEffect(Effect::EFFECT_CLASS_BEHEMOTH_FORCE_SCROLL);
				pEffect->save(pCreature->getName());
			}
			if (pCreature->isFlag(Effect::EFFECT_CLASS_SAFE_FORCE_SCROLL) )
			{
				Effect* pEffect = pCreature->findEffect(Effect::EFFECT_CLASS_SAFE_FORCE_SCROLL);
				pEffect->save(pCreature->getName());
			}
			if (pCreature->isFlag(Effect::EFFECT_CLASS_CARNELIAN_FORCE_SCROLL) )
			{
				Effect* pEffect = pCreature->findEffect(Effect::EFFECT_CLASS_CARNELIAN_FORCE_SCROLL);
				pEffect->save(pCreature->getName());
			}
/*
			if(pCreature->isSlayer())
			{
				Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature);
				Assert(pSlayer != NULL);

				if (g_pResurrectLocationManager->getSlayerPosition(pSlayer->getResurrectZoneID(), ResurrectCoord))
				{
					ZoneID = ResurrectCoord.id;
					ZoneX  = ResurrectCoord.x;
					ZoneY  = ResurrectCoord.y;
				}
				else
				{
					if (g_pResurrectLocationManager->getSlayerPosition(pSlayer->getZone()->getZoneID(), ResurrectCoord))
					{
						ZoneID = ResurrectCoord.id;
						ZoneX  = ResurrectCoord.x;
						ZoneY  = ResurrectCoord.y;
					}
					else
					{
						throw Error("Critical Error: ResurrectInfo is not established");
					}
				}

				char pField[80];
				sprintf(pField, "ZoneID=%d, XCoord=%d, YCoord=%d, CurrentHP=HP", ZoneID, ZoneX, ZoneY);
				pSlayer->tinysave(pField);
			}
			else if(pCreature->isVampire())
			{
				Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);
				Assert(pVampire != NULL);

				if (g_pResurrectLocationManager->getVampirePosition(pVampire->getResurrectZoneID(), ResurrectCoord))
				{
					ZoneID = ResurrectCoord.id;
					ZoneX  = ResurrectCoord.x;
					ZoneY  = ResurrectCoord.y;
				}
				else
				{
					if (g_pResurrectLocationManager->getVampirePosition(pVampire->getZone()->getZoneID(), ResurrectCoord))
					{
						ZoneID = ResurrectCoord.id;
						ZoneX  = ResurrectCoord.x;
						ZoneY  = ResurrectCoord.y;
					}
					else
					{
						throw Error("Critical Error: ResurrectInfo is not established");
					}
				}
				// 이제 정보를 저장한다.
				char pField[80];
				sprintf(pField, "ZoneID=%d, XCoord=%d, YCoord=%d, CurrentHP=HP", ZoneID, ZoneX, ZoneY);
				pVampire->tinysave(pField);
			}
*/
		}


		//
		// 이제, 존에서 PC를 삭제한다.
		//
		// *CAUTION*
		//
		// pCreature의 좌표가 실제로 pCreature가 존재하는 타일의 좌표와 같아야 한다.
		// 따라서, 이 메쏘드를 호출하기 전에 좌표를 잘 바꿔놔야 한당..
		//
		pZone->deleteCreature(pCreature , pCreature->getX() , pCreature->getY());

		////cout << "PC deleted from Zone >> ";

		// 존그룹의 ZPM에서 플레이어를 삭제한다.
		// ZonePlayerManager의 ProcessCommand 안에서 지우는 것이므로 반드시 NoBlocked 으로 지워야 한다.
		pZone->getZoneGroup()->getZonePlayerManager()->deletePlayer(pGamePlayer->getSocket()->getSOCKET());

		// IPM으로 플레이어를 옮긴다.
		//g_pIncomingPlayerManager->pushPlayer(pGamePlayer);

		// Core의 구조를 바꾸면서 쓰레드로 부터 독립적으로 행하기 위하여 뒤에 한꺼번에 처리하기 위해서
		// OutList로 넣는다.
		pZone->getZoneGroup()->getZonePlayerManager()->pushOutPlayer(pGamePlayer);

		////cout << "Move PC to IPM >> ";
	} 
	catch (NoSuchElementException & nsee) 
	{
		throw DisconnectException();
	}

	// 로그인 서버로 GLIncomingConnection을 보낸다.
	// PlayerName과 ClientIP를 같이 실어서 보낸다.
	/*
	GLIncomingConnection glIncomingConnection;
	glIncomingConnection.setPlayerID(pGamePlayer->getID());
	glIncomingConnection.setClientIP(pGamePlayer->getSocket()->getHost());

	if (g_pConfig->getProperty("User") == "excel96")
		g_pLoginServerManager->sendPacket("211.117.52.12" , g_pConfig->getPropertyInt("LoginServerUDPPort"), &glIncomingConnection);
	else if (g_pConfig->getProperty("User") == "elcastle")
		g_pLoginServerManager->sendPacket("211.117.52.12" , g_pConfig->getPropertyInt("LoginServerUDPPort"), &glIncomingConnection);
	else if (g_pConfig->getProperty("User") == "elca")
		g_pLoginServerManager->sendPacket("211.117.52.12" , g_pConfig->getPropertyInt("LoginServerUDPPort"), &glIncomingConnection);
	*/

	pGamePlayer->setPlayerStatus(GPS_AFTER_SENDING_GL_INCOMING_CONNECTION);

#endif

	__END_DEBUG_EX __END_CATCH
}
Example #26
0
//////////////////////////////////////////////////////////////////////////////
// 몬스터 셀프 핸들러
//////////////////////////////////////////////////////////////////////////////
void BloodyWall::execute(Monster* pMonster, ZoneCoord_t X, ZoneCoord_t Y)
	throw(Error)
{
	__BEGIN_TRY

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

	Assert(pMonster != NULL);

	try 
	{
		Zone* pZone = pMonster->getZone();

		Assert(pZone != NULL);

		GCSkillToTileOK2 _GCSkillToTileOK2;
		GCSkillToTileOK3 _GCSkillToTileOK3;
		GCSkillToTileOK4 _GCSkillToTileOK4;
		GCSkillToTileOK5 _GCSkillToTileOK5;
		GCSkillToTileOK6 _GCSkillToTileOK6;

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

		ZoneCoord_t myX = pMonster->getX();
		ZoneCoord_t myY = pMonster->getY();

		// 마스터는 무조건~~
		bool bRangeCheck = pMonster->isMaster()
#ifdef __UNDERWORLD__
			|| pMonster->isUnderworld() || pMonster->getMonsterType() == 599
#endif
							|| verifyDistance(pMonster, X, Y, pSkillInfo->getRange());

		bool bHitRoll    = pMonster->isMaster() 
#ifdef __UNDERWORLD__
			|| pMonster->isUnderworld() || pMonster->getMonsterType() == 599
#endif
							|| HitRoll::isSuccessMagic(pMonster, pSkillInfo);
		
		bool bTileCheck = false;
		VSRect rect(0, 0, pZone->getWidth()-1, pZone->getHeight()-1);
		if (rect.ptInRect(X, Y)) bTileCheck = true;

		if (bRangeCheck && bHitRoll && bTileCheck)
		{
			// 이펙트의 지속시간을 계산한다.
			SkillInput input(pMonster);
			SkillOutput output;
			computeOutput(input, output);

			//Range_t    Range    = 3;
			Dir_t 	   Dir		= getDirectionToPosition(myX, myY, X, Y);

			list<Creature*> cList;	// denier list

			for (int i=0; i<5; i++)
			{
				POINT& pt = m_BloodyWallMask[Dir][i];

				int tileX = X+pt.x;
				int tileY = Y+pt.y;

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

					// 현재 타일에다 이펙트를 추가할 수 있다면...
					if (tile.canAddEffect())
					{
						// 같은 effect가 있으면 지운다.
						Effect* pOldEffect = tile.getEffect(Effect::EFFECT_CLASS_BLOODY_WALL);
						if (pOldEffect != NULL)
						{
							ObjectID_t effectID = pOldEffect->getObjectID();
							pZone->deleteEffect(effectID);// fix me
						}
					
						// 이펙트 클래스를 생성한다.
						EffectBloodyWall* pEffect = new EffectBloodyWall(pZone , tileX, tileY);
						pEffect->setCasterName(pMonster->getName());
						pEffect->setCasterID(pMonster->getObjectID());
						pEffect->setClan(Creature::CREATURE_CLASS_MONSTER, pMonster->getClanType());
						pEffect->setDamage(output.Damage);
						pEffect->setDeadline(output.Duration);
						pEffect->setLevel(pMonster->getINT());
						pEffect->setNextTime(0);
						pEffect->setTick(output.Tick);

						// Tile에 붙이는 Effect는 ObjectID를 등록받아야 한다.
						ObjectRegistry & objectregister = pZone->getObjectRegistry();
						objectregister.registerObject(pEffect);

						pZone->addEffect(pEffect);
						tile.addEffect(pEffect);

						GCAddEffectToTile gcAE;
						gcAE.setObjectID(pEffect->getObjectID());
						gcAE.setEffectID(pEffect->getSendEffectClass());
						gcAE.setDuration(output.Duration);
						gcAE.setXY(tileX, tileY);
						pZone->broadcastPacket(tileX, tileY, &gcAE);

						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() || pTargetCreature->isOusters() )
							) 
							{
								cList.push_back(pTargetCreature);
								_GCSkillToTileOK2.addCListElement(pTargetCreature->getObjectID());
								_GCSkillToTileOK4.addCListElement(pTargetCreature->getObjectID());
								_GCSkillToTileOK5.addCListElement(pTargetCreature->getObjectID());
								
								pEffect->affect(pTargetCreature);
							}

							//pEffect->affectObject(pTarget, false);
						}
					}	
				}	
			}

			_GCSkillToTileOK2.setObjectID(pMonster->getObjectID());
			_GCSkillToTileOK2.setSkillType(SkillType);
			_GCSkillToTileOK2.setX(X);
			_GCSkillToTileOK2.setY(Y);
			_GCSkillToTileOK2.setDuration(output.Duration);
			_GCSkillToTileOK2.setRange(Dir);
			//_GCSkillToTileOK2.addShortData(MODIFY_VISION, BLOODY_WALL_SIGHT);

			_GCSkillToTileOK3.setObjectID(pMonster->getObjectID());
			_GCSkillToTileOK3.setSkillType(SkillType);
			_GCSkillToTileOK3.setX(X);
			_GCSkillToTileOK3.setY(Y);

			_GCSkillToTileOK4.setSkillType(SkillType);
			_GCSkillToTileOK4.setX(X);
			_GCSkillToTileOK4.setY(Y);
			_GCSkillToTileOK4.setRange(Dir);
			_GCSkillToTileOK4.setDuration(output.Duration);

			_GCSkillToTileOK5.setObjectID(pMonster->getObjectID());
			_GCSkillToTileOK5.setSkillType(SkillType);
			_GCSkillToTileOK5.setX(X);
			_GCSkillToTileOK5.setY(Y);
			_GCSkillToTileOK5.setRange(Dir);
			_GCSkillToTileOK5.setDuration(output.Duration);

			_GCSkillToTileOK6.setOrgXY(myX, myY);
			_GCSkillToTileOK6.setSkillType(SkillType);
			_GCSkillToTileOK6.setX(X);
			_GCSkillToTileOK6.setY(Y);
			_GCSkillToTileOK6.setDuration(output.Duration);
			_GCSkillToTileOK6.setRange(Dir);
			//_GCSkillToTileOK6.addShortData(MODIFY_VISION, BLOODY_WALL_SIGHT);

			for(list<Creature*>::const_iterator itr = cList.begin(); itr != cList.end(); itr++)
			{
				Creature* pTargetCreature = *itr;
				if (canSee(pTargetCreature, pMonster)) pTargetCreature->getPlayer()->sendPacket(&_GCSkillToTileOK2);
				else pTargetCreature->getPlayer()->sendPacket(&_GCSkillToTileOK6);
			}

			cList.push_back(pMonster);

			list<Creature*> watcherList = pZone->getWatcherList(myX, myY, pMonster);

			// watcherList에서 cList에 속하지 않고, caster(pMonster)를 볼 수 없는 경우는
			// OK4를 보내고.. cList에 추가한다.
			for(list<Creature*>::const_iterator itr = watcherList.begin(); itr != watcherList.end(); itr++)
			{
				bool bBelong = false;
				for(list<Creature*>::const_iterator tItr = cList.begin(); tItr != cList.end(); tItr++)
					if (*itr == *tItr)
						bBelong = true;

				Creature* pWatcher = (*itr);
				if (bBelong == false && canSee(pWatcher, pMonster) == false)
				{
					//Assert(pWatcher->isPC());	// 당연 PC다.. Zone::getWatcherList는 PC만 return한다
					if (!pWatcher->isPC())
					{
						//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;
						return;
					}

					pWatcher->getPlayer()->sendPacket(&_GCSkillToTileOK4);
					cList.push_back(*itr);
				}
			}
					
			cList = pZone->broadcastSkillPacket(myX, myY, X, Y, &_GCSkillToTileOK5, cList, false);
			
			pZone->broadcastPacket(myX, myY,  &_GCSkillToTileOK3 , cList);
			
			pZone->broadcastPacket(X, Y,  &_GCSkillToTileOK4 , cList);
		} 
		else 
		{
			executeSkillFailNormal(pMonster, getSkillType(), NULL);
		}
	} 
	catch (Throwable & t) 
	{
		executeSkillFailException(pMonster, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;

	__END_CATCH
}
Example #27
0
//////////////////////////////////////////////////////////////////////
//
// Visible::execute()
//
//////////////////////////////////////////////////////////////////////
void Visible::execute(Slayer * pSlayer, ZoneCoord_t X, ZoneCoord_t Y, SkillSlot * pSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

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

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

	try 
	{
		// Player를 받아온다.
		Player * pPlayer = pSlayer->getPlayer();

		// Zone을 받아온다.
		Zone * pZone = pSlayer->getZone();

		SkillType_t SkillType = pSkillSlot->getSkillType();

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

		// 기술의 레벨을 받아온다.
		//SkillLevel_t SkillLevel = pSkillSlot->getExpLevel();

		//SkillDomainType_t DomainType = pSkillInfo->getDomainType();

        VSRect rect(0, 0, pZone->getWidth()-1, pZone->getHeight()-1);

		int  RequiredMP  = (int)pSkillInfo->getConsumeMP();
		bool bManaCheck  = hasEnoughMana(pSlayer, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pSkillSlot);
		bool bRangeCheck = verifyDistance(pSlayer, X, Y, pSkillInfo->getRange());
		bool bHit       = false;

		// 기술성공률 검증.
		if (bManaCheck && bTimeCheck && bRangeCheck)
		{

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

			GCSkillToTileOK1 _GCSkillToTileOK1;
			GCSkillToTileOK2 _GCSkillToTileOK2;
			GCSkillToTileOK3 _GCSkillToTileOK3;
			GCSkillToTileOK4 _GCSkillToTileOK4;
			GCSkillToTileOK5 _GCSkillToTileOK5;

			Coord_t myX = pSlayer->getX(), myY = pSlayer->getY();
	        Dir_t       dir           = calcDirection(myX, myY, X, Y);

			list<Creature*> cList;
			int oX, oY;
			for(oX = -2; oX <= 2; oX++)
			for(oY = -2; oY <= 2; oY++)
			{
				int tileX = X+oX;
				int tileY = Y+oY;

				if (!rect.ptInRect(tileX, tileY)) continue;

				Tile& tile = pZone->getTile(tileX, tileY);
				Creature * pTargetCreature = NULL;
				if(tile.hasCreature(Creature::MOVE_MODE_WALKING)) pTargetCreature = tile.getCreature(Creature::MOVE_MODE_WALKING);

				if(pTargetCreature != NULL)
				{
					if(pTargetCreature->isPC())
					{
						bool bHitRoll    = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot);
						bool bEffected   = pTargetCreature->isFlag(Effect::EFFECT_CLASS_INVISIBILITY);

						if(bHitRoll && bEffected ) {
							// 주위에 GCAddXXX를 보내고, effect manager에서 effect를 삭제하고, GCRemoveEffect를 보낸다.
							addVisibleCreature(pZone, pTargetCreature, true);

							_GCSkillToTileOK2.setObjectID(pSlayer->getObjectID());
							_GCSkillToTileOK2.setSkillType(SkillType);
							_GCSkillToTileOK2.setX(X);
							_GCSkillToTileOK2.setY(Y);
							_GCSkillToTileOK2.setRange(dir);
							_GCSkillToTileOK2.setDuration(0);

							Player * pTargetPlayer = pTargetCreature->getPlayer();
							Assert(pTargetPlayer != NULL);
							pTargetPlayer->sendPacket(&_GCSkillToTileOK2);

							cList.push_back(pTargetCreature);

							bHit = true;
						}

					}
				} // if(pTargetCreature!= NULL)
			}

			decreaseMana(pSlayer, RequiredMP, _GCSkillToTileOK1);

			SkillDomainType_t DomainType = pSkillInfo->getDomainType();
			// EXP UP!
			Exp_t Point = pSkillInfo->getPoint();

			if(bHit ) {
				shareAttrExp(pSlayer, Point, 1, 1, 8, _GCSkillToTileOK1);
				increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToTileOK1);
				increaseSkillExp(pSlayer, DomainType,  pSkillSlot, pSkillInfo, _GCSkillToTileOK1);
				
			}
			_GCSkillToTileOK1.setSkillType(SkillType);
			_GCSkillToTileOK1.setCEffectID(CEffectID);
			_GCSkillToTileOK1.setX(X);
			_GCSkillToTileOK1.setY(Y);
			_GCSkillToTileOK1.setRange(dir);
			_GCSkillToTileOK1.setDuration(0);
		
			_GCSkillToTileOK3.setObjectID(pSlayer->getObjectID());
			_GCSkillToTileOK3.setSkillType(SkillType);
			_GCSkillToTileOK3.setX(X);
			_GCSkillToTileOK3.setY(Y);

			_GCSkillToTileOK4.setSkillType(SkillType);
			_GCSkillToTileOK4.setX(X);
			_GCSkillToTileOK4.setY(Y);
			_GCSkillToTileOK4.setDuration(0);
			_GCSkillToTileOK4.setRange(dir);
		
			_GCSkillToTileOK5.setObjectID(pSlayer->getObjectID());
			_GCSkillToTileOK5.setSkillType(SkillType);
			_GCSkillToTileOK5.setX(X);
			_GCSkillToTileOK5.setY(Y);
			_GCSkillToTileOK5.setRange(dir);
			_GCSkillToTileOK5.setDuration(0);
	
			// Send Packet
			pPlayer->sendPacket(&_GCSkillToTileOK1);

			cList.push_back(pSlayer);

			cList = pZone->broadcastSkillPacket(myX, myY, X, Y, &_GCSkillToTileOK5, cList);

			pZone->broadcastPacket(myX, myY,  &_GCSkillToTileOK3 , cList);
			pZone->broadcastPacket(X , Y ,  &_GCSkillToTileOK4 , cList);

			pSkillSlot->setRunTime(output.Delay);
		} 
		else 
		{
			executeSkillFailNormal(pSlayer, getSkillType(), NULL);
		}
	} 
	catch(Throwable & t)  
	{
		executeSkillFailException(pSlayer, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;

	__END_CATCH
}
Example #28
0
//////////////////////////////////////////////////////////////////////////////
// 아우스터즈 오브젝트 핸들러
//////////////////////////////////////////////////////////////////////////////
void ChargingAttack::execute(Ousters * pOusters, ObjectID_t TargetObjectID, OustersSkillSlot * pOustersSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY

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

	Assert(pOusters != NULL);
	Assert(pOustersSkillSlot != NULL);

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

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

		// NoSuch제거. by sigi. 2002.5.2
		// NPC는 공격할 수가 없다.
		if (pTargetCreature==NULL
			|| pTargetCreature->isNPC())
		{
			executeSkillFailException(pOusters, getSkillType());
			//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;
			return;
		}

		// 무장하고 있는 무기가 널이거나, 검이 아니라면 기술을 사용할 수 없다.
		Item* pItem = pOusters->getWearItem(Ousters::WEAR_RIGHTHAND);
		if (pItem == NULL)
		{
			executeSkillFailException(pOusters, getSkillType());
			//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;
			return;
		}

		GCSkillToObjectOK1 _GCSkillToObjectOK1;
		GCSkillToObjectOK2 _GCSkillToObjectOK2;

		SkillType_t       SkillType  = pOustersSkillSlot->getSkillType();
		SkillInfo*        pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType);
		SkillLevel_t      SkillLevel = pOustersSkillSlot->getExpLevel();

		SkillInput input(pOusters, pOustersSkillSlot);
		SkillOutput output;
		computeOutput(input, output);

		int  RequiredMP  = (int)pSkillInfo->getConsumeMP();
		bool bManaCheck  = hasEnoughMana(pOusters, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pOustersSkillSlot);
		bool bRangeCheck = verifyDistance(pOusters, pTargetCreature, output.Range);
		bool bHitRoll    = HitRoll::isSuccess(pOusters, pTargetCreature, SkillLevel/2);
		bool bCanHit     = canHit(pOusters, pTargetCreature, SkillType) && canAttack(pOusters, pTargetCreature);
		bool bPK         = verifyPK(pOusters, pTargetCreature);
		bool bEffected	 = pOusters->hasRelicItem() 
							|| pOusters->isFlag(Effect::EFFECT_CLASS_HAS_FLAG)
							|| pOusters->isFlag(Effect::EFFECT_CLASS_HAS_SWEEPER);

		if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bCanHit && bPK && !bEffected )
		{
			// 빠르게 PC를 움직여준다.
			if (pZone->moveFastPC(pOusters, pOusters->getX(), pOusters->getY(), pTargetCreature->getX(), pTargetCreature->getY(), getSkillType())) 
			{
				decreaseMana(pOusters, RequiredMP, _GCSkillToObjectOK1);

				bool bCriticalHit = false;

				// 데미지를 준다.
				Damage_t Damage = computeDamage(pOusters, pTargetCreature, 0, bCriticalHit) + output.Damage;
				setDamage(pTargetCreature, Damage, pOusters, SkillType, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1);
				computeAlignmentChange(pTargetCreature, Damage, pOusters, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1);
				decreaseDurability(pOusters, pTargetCreature, pSkillInfo, &_GCSkillToObjectOK1, &_GCSkillToObjectOK2);

				// 크리티컬 히트라면 상대방을 뒤로 물러나게 한다.
				if (bCriticalHit)
				{
					knockbackCreature(pZone, pTargetCreature, pOusters->getX(), pOusters->getY());
				}

				if (pTargetCreature->isDead())
				{
					int exp = computeCreatureExp(pTargetCreature, 100, pOusters);
					shareOustersExp(pOusters, exp, _GCSkillToObjectOK1);
				}

				// 패킷을 준비하고 보낸다.
				_GCSkillToObjectOK1.setSkillType(SkillType);
				_GCSkillToObjectOK1.setCEffectID(CEffectID);
				_GCSkillToObjectOK1.setTargetObjectID(TargetObjectID);
				_GCSkillToObjectOK1.setDuration(0);

				pPlayer->sendPacket(&_GCSkillToObjectOK1);
				_GCSkillToObjectOK2.setObjectID(pOusters->getObjectID());
				_GCSkillToObjectOK2.setSkillType(SkillType);
				_GCSkillToObjectOK2.setDuration(0);

				if (pTargetCreature->isPC()) 
				{
					Player* pTargetPlayer = pTargetCreature->getPlayer();
					Assert(pTargetPlayer != NULL);
					pTargetPlayer->sendPacket(&_GCSkillToObjectOK2);
				} 
				else 
				{
					Monster * pMonster = dynamic_cast<Monster*>(pTargetCreature);
					pMonster->addEnemy(pOusters);
				}

				pOustersSkillSlot->setRunTime(output.Delay);

			} 
			else 
			{
				executeSkillFailNormal(pOusters, getSkillType(), pTargetCreature);
			}
		} 
		else 
		{
			executeSkillFailNormal(pOusters, getSkillType(), pTargetCreature);
		}
	} 
	catch (Throwable & t) 
	{
		executeSkillFailException(pOusters, getSkillType());
	}

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;

	__END_CATCH
}
void CGTradeAddItemHandler::execute (CGTradeAddItem* pPacket , Player* pPlayer)
	 throw(ProtocolException , Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

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

	ObjectID_t  TargetOID   = pPacket->getTargetObjectID();
	GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer);

	Creature* pPC = pGamePlayer->getCreature();
	Assert(pPC != NULL);

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

	TradeManager* pTradeManager = pZone->getTradeManager();
	Assert(pTradeManager != NULL);
	
	// 교환을 원하는 상대방을 존에서 찾아본다.
	Creature* pTargetPC = NULL;
	/*
	try 
	{ 
		pTargetPC = pZone->getCreature(TargetOID); 
	}
	catch (NoSuchElementException) 
	{ 
		pTargetPC = NULL; 
	}
	*/

	// NoSuch제거. by sigi. 2002.5.2
	pTargetPC = pZone->getCreature(TargetOID); 

	// 교환 상대가 없다면 에러다.
	if (pTargetPC == NULL)
	{
		pTradeManager->cancelTrade(pPC);
		executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_TARGET_NOT_EXIST);
		return;
	}

	// 교환 상대가 사람이 아니거나, 같은 종족이 아니라면 에러다.
	if (!pTargetPC->isPC() || !isSameRace(pTargetPC, pPC))
	{
		pTradeManager->cancelTrade(pPC);
		executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_RACE_DIFFER);
		return;
	}

    // 둘 다 안전 지대에 있는지 체크를 한다.
	if (!isInSafeZone(pPC) || !isInSafeZone(pTargetPC))
	{
		pTradeManager->cancelTrade(pPC);
		executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_NOT_SAFE);
		return;
	}

	// 오토바이를 타고 있다면 에러다.
	if (pPC->isSlayer() && pTargetPC->isSlayer())
	{
		Slayer* pSlayer1 = dynamic_cast<Slayer*>(pPC);
		Slayer* pSlayer2 = dynamic_cast<Slayer*>(pTargetPC);

		if (pSlayer1->hasRideMotorcycle() || pSlayer2->hasRideMotorcycle())
		{
			pTradeManager->cancelTrade(pPC);
			executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_MOTORCYCLE);
			return;
		}
	}

	if (pPC->isOusters() && pTargetPC->isOusters())
	{
		Ousters* pOusters1 = dynamic_cast<Ousters*>(pPC);
		Ousters* pOusters2 = dynamic_cast<Ousters*>(pTargetPC);

		if (pOusters1->isFlag(Effect::EFFECT_CLASS_SUMMON_SYLPH) 
			|| pOusters2->isFlag(Effect::EFFECT_CLASS_SUMMON_SYLPH) )
		{
			pTradeManager->cancelTrade(pPC);
			executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_MOTORCYCLE);
			return;
		}
	}

	// 둘이서 교환을 하고 있는 상태가 아니라면 에러다.
	if (!pTradeManager->isTrading(pPC, pTargetPC))
	{
		pTradeManager->cancelTrade(pPC);
		executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_NOT_TRADING);
		return;
	}

	if (pPC->isSlayer()) executeSlayer(pPacket, pPlayer);
	else if (pPC->isVampire()) executeVampire(pPacket, pPlayer);
	else if (pPC->isOusters()) executeOusters(pPacket, pPlayer);
	else throw ProtocolException("CGTradeAddItemHandler::execute() : 알 수 없는 플레이어 크리쳐");

#endif

	__END_DEBUG_EX __END_CATCH
}
Example #30
0
//////////////////////////////////////////////////////////////////////////////
// 뱀파이어 오브젝트 핸들러
//////////////////////////////////////////////////////////////////////////////
void WildWolf::execute(Vampire* pVampire, ObjectID_t TargetObjectID, VampireSkillSlot* pVampireSkillSlot, CEffectID_t CEffectID)
throw(Error)
{
    __BEGIN_TRY

    Assert(pVampire != NULL);
    Assert(pVampireSkillSlot != NULL);

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

        Creature* pTargetCreature = pZone->getCreature(TargetObjectID);
        //Assert(pTargetCreature != NULL);
        if (pTargetCreature==NULL )
        {
            Item* pTargetItem = pZone->getItem(TargetObjectID);
            if (pTargetItem == NULL || pTargetItem->getItemClass() != Item::ITEM_CLASS_CORPSE )
            {
                executeSkillFailException(pVampire, getSkillType());
                return;
            }

            eatCorpse(pVampire, pTargetItem, pVampireSkillSlot);
            return;
        }

        // NPC는 공격할 수가 없다.
        // NoSuch제거. by sigi. 2002.5.2
        if (!canAttack(pVampire, pTargetCreature )
                || pTargetCreature->isNPC() )
        {
            executeSkillFailException(pVampire, getSkillType());
            return;
        }

        if (pTargetCreature->isFlag(Effect::EFFECT_CLASS_COMA ) )
        {
            eatComaCreature(pVampire, pTargetCreature);
            return;
        }

        GCSkillToObjectOK1 _GCSkillToObjectOK1;
        GCSkillToObjectOK2 _GCSkillToObjectOK2;
        GCSkillToObjectOK5 _GCSkillToObjectOK5;

        SkillType_t       SkillType  = pVampireSkillSlot->getSkillType();
        SkillInfo*        pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType);
        Range_t			  Range		 = pSkillInfo->getRange();

        int  RequiredMP         = decreaseConsumeMP(pVampire, pSkillInfo);
        bool bManaCheck         = hasEnoughMana(pVampire, RequiredMP);
        bool bTimeCheck         = verifyRunTime(pVampireSkillSlot);
        bool bRangeCheck        = verifyDistance(pVampire, pTargetCreature, Range);
        bool bHitRoll           = HitRoll::isSuccess(pVampire, pTargetCreature);
        bool bCanHit            = canHit(pVampire, pTargetCreature, getSkillType());
        bool bPK                = verifyPK(pVampire, pTargetCreature);

        if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bCanHit && bPK)
        {
            SkillInput input(pVampire);
            SkillOutput output;
            computeOutput(input, output);

            Damage_t Damage = output.Damage;
            bool bCriticalHit = false;
            Damage += computeDamage(pVampire, pTargetCreature, 0, bCriticalHit);

            // 마나를 깍는다.
            decreaseMana(pVampire, RequiredMP, _GCSkillToObjectOK1);

            EffectSetAfire* pEffect = new EffectSetAfire(pTargetCreature);
            pEffect->setDamage(Damage);
            pEffect->setTick(3);
            pEffect->setNextTime(3);
            pEffect->setTimes(3);
            pEffect->setCasterOID(pVampire->getObjectID());
            pTargetCreature->addEffect(pEffect);

            increaseAlignment(pVampire, pTargetCreature, _GCSkillToObjectOK1);

            // 패킷을 보낸다.
            _GCSkillToObjectOK1.setSkillType(getSkillType());
            _GCSkillToObjectOK1.setCEffectID(CEffectID);
            _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID);
            _GCSkillToObjectOK1.setDuration(0);

            _GCSkillToObjectOK2.setObjectID(pVampire->getObjectID());
            _GCSkillToObjectOK2.setSkillType(getSkillType());
            _GCSkillToObjectOK2.setDuration(0);

            _GCSkillToObjectOK5.setObjectID(pVampire->getObjectID());
            _GCSkillToObjectOK5.setTargetObjectID(TargetObjectID);
            _GCSkillToObjectOK5.setSkillType(getSkillType());

            pPlayer->sendPacket(&_GCSkillToObjectOK1);

            Player* pTargetPlayer = NULL;

            if (pTargetCreature->isPC())
            {
                pTargetPlayer = pTargetCreature->getPlayer();
                Assert(pTargetPlayer != NULL);
                pTargetPlayer->sendPacket(&_GCSkillToObjectOK2);
            }
            else
            {
                Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature);
                pMonster->addEnemy(pVampire);
            }

            list<Creature*> cList;
            cList.push_back(pVampire);
            cList.push_back(pTargetCreature);

            cList = pZone->broadcastSkillPacket(pVampire->getX(), pVampire->getY(),
                                                pTargetCreature->getX(), pTargetCreature->getY(), &_GCSkillToObjectOK5, cList);

            pVampireSkillSlot->setRunTime(output.Delay);
        }
        else
        {
            executeSkillFailNormal(pVampire, getSkillType(), pTargetCreature);
        }
    }
    catch(Throwable & t)
    {
        executeSkillFailException(pVampire, getSkillType());
    }

    __END_CATCH
}