Beispiel #1
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
}
Beispiel #2
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
}
Beispiel #3
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
}
//////////////////////////////////////////////////////////////////////////////
// 아우스터즈 타일 핸들러
//////////////////////////////////////////////////////////////////////////////
void SummonGroundElemental::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);

		// 데미지와 지속 시간을 계산한다.
		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))
//		{
//			Tile& tile = pZone->getTile(X, Y);
//			if (tile.canAddEffect()) bTileCheck = true;
//		}

		TPOINT pt = findSuitablePosition(pZone, X, Y, Creature::MOVE_MODE_WALKING);

		if (pt.x == -1 )
		{
			bTileCheck = false;
		}
		else
		{
			bTileCheck = true;

			for (int oX = pt.x - 2 ; oX <= pt.x + 2 ; ++oX )
			for (int oY = pt.y - 2 ; oY <= pt.y + 2 ; ++oY )
			{
				if (!rect.ptInRect(oX, oY ) ) continue;
				if (pZone->getTile(oX, oY).getEffect(Effect::EFFECT_CLASS_GROUND_ELEMENTAL_AURA ) != NULL )
				{
					bTileCheck = false;
					break;
				}
			}
		}


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

			int oX, oY;
/*
HP = 200 + (S_level * 10)
Defense = 50 + (S_level * 2)
Protection = 20 + (S_level * 2)
Poison Resistance = 70% 
Acid Resistance = 60% 
Curse Resistance = 100% 
Blood Resistance = 50% 
Regen = 1 HP per 1 sec
*/
			Monster* pGroundElemental = new Monster(GROUND_ELEMENTAL_TYPE);
			pGroundElemental->setName("대지 정령");
			pGroundElemental->setHP(1000 + input.SkillLevel * 100);
			pGroundElemental->setHP(1000 + input.SkillLevel * 100, ATTR_MAX);
			pGroundElemental->setDefense(0);
			pGroundElemental->setProtection(0);
			pGroundElemental->setResist(MAGIC_DOMAIN_POISON, 0);
			pGroundElemental->setResist(MAGIC_DOMAIN_ACID, 0);
			pGroundElemental->setResist(MAGIC_DOMAIN_CURSE, 0);
			pGroundElemental->setResist(MAGIC_DOMAIN_BLOOD, 0);
			pGroundElemental->setFlag(Effect::EFFECT_CLASS_IMMUNE_TO_CURSE);
			pGroundElemental->removeFlag(Effect::EFFECT_CLASS_HIDE);
			pGroundElemental->setMoveMode(Creature::MOVE_MODE_WALKING);

			// 무뇌정령
			pGroundElemental->setBrain(NULL);

			pZone->addCreature(pGroundElemental, X, Y, 2);
			X = pGroundElemental->getX();
			Y = pGroundElemental->getY();

			//cout << pGroundElemental->toString() << " 을 " << X << ", " << Y << " 에 불러냈습니다." << endl;

			EffectGroundElemental* pCreatureEffect = new EffectGroundElemental(pGroundElemental);
			pCreatureEffect->setDeadline(output.Duration);

			pGroundElemental->setFlag(pCreatureEffect->getEffectClass());
			pGroundElemental->addEffect(pCreatureEffect);

			GCAddEffect gcAddEffect;
			gcAddEffect.setObjectID(pGroundElemental->getObjectID());
			gcAddEffect.setEffectID(pCreatureEffect->getSendEffectClass());
			pZone->broadcastPacket(X, Y, &gcAddEffect);

//			addSimpleCreatureEffect(pGroundElemental, Effect::EFFECT_CLASS_GROUND_ELEMENTAL_CENTER);

//			for (int i = 0; i < m_MaskIndex[Grade]; ++i )
			for (oX = X - 2 ; oX <= X + 2 ; ++oX )
			for (oY = Y - 2 ; oY <= Y + 2 ; ++oY )
			{
//				oX = m_ElementalMask[Grade][i].x;
//				oY = m_ElementalMask[Grade][i].y;

				if (!rect.ptInRect(oX, oY)) continue;
				if (oX == X && oY == Y ) continue;

				Tile&   tile  = pZone->getTile(oX, oY);
				if (!tile.canAddEffect()) continue;

				if (tile.getEffect(Effect::EFFECT_CLASS_TRYING_POSITION) ) continue;
				
				// 같은 이펙트가 이미 존재한다면 삭제한다.
				Effect* pOldEffect = tile.getEffect(Effect::EFFECT_CLASS_GROUND_ELEMENTAL_AURA);
				if (pOldEffect != NULL)
				{
					ObjectID_t effectID = pOldEffect->getObjectID();
					pZone->deleteEffect(effectID);
				}

				// 이펙트 오브젝트를 생성한다.
				EffectSummonGroundElemental* pEffect = new EffectSummonGroundElemental(pZone, oX, oY);
				pEffect->setDeadline(output.Duration);

				// 타일에 붙은 이펙트는 OID를 받아야 한다.
				ObjectRegistry & objectregister = pZone->getObjectRegistry();
				objectregister.registerObject(pEffect);
			
				// 존 및 타일에다가 이펙트를 추가한다.
				pZone->addEffect(pEffect);	
				tile.addEffect(pEffect);

				GCAddEffectToTile gcAddEffect;
				gcAddEffect.setXY(oX, oY);
				gcAddEffect.setEffectID(pEffect->getSendEffectClass());
				gcAddEffect.setObjectID(pEffect->getObjectID());
				gcAddEffect.setDuration(output.Duration);

				pZone->broadcastPacket(oX, oY, &gcAddEffect);
			}

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

			_GCSkillToTileOK1.setSkillType(SkillType);
			_GCSkillToTileOK1.setCEffectID(CEffectID);
			_GCSkillToTileOK1.setX(X);
			_GCSkillToTileOK1.setY(Y);
			_GCSkillToTileOK1.setDuration(output.Duration);
			_GCSkillToTileOK1.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.setDuration(output.Duration);
			_GCSkillToTileOK4.setGrade(Grade);
		
			_GCSkillToTileOK5.setObjectID(pOusters->getObjectID());
			_GCSkillToTileOK5.setSkillType(SkillType);
			_GCSkillToTileOK5.setX(X);
			_GCSkillToTileOK5.setY(Y);
			_GCSkillToTileOK5.setDuration(output.Duration);
			_GCSkillToTileOK5.setGrade(Grade);

			pPlayer->sendPacket(&_GCSkillToTileOK1);
		
			list<Creature*> cList;
			cList.push_back(pOusters);

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

			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 << t.toString() << endl;
	}

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

	__END_CATCH
}
Beispiel #5
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
}
Beispiel #6
0
//////////////////////////////////////////////////////////////////////////////
// 뱀파이어 타일 핸들러
//  뱀파이어가 Energy Drop Skill을 Tile에 사용했을때 사용하는 Handler
//////////////////////////////////////////////////////////////////////////////
void EnergyDrop::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;

	EffectEnergyDrop * pEffect = NULL;
	EffectEnergyDrop * pEffect2 = 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);
		SkillDomainType_t DomainType = pSkillInfo->getDomainType();

		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());
		bool bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot);


		bool bTileCheck = false;

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

		if(rect.ptInRect(X, Y))
		{
			Tile& tile = pZone->getTile(X, Y);
			if (tile.canAddEffect()) bTileCheck = true;
		}


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

			// calculate damage and duration time
			SkillInput input(pSlayer, pSkillSlot);
			SkillOutput output;
			computeOutput(input, output);

			// Holy Smashing 이 있다면 데미지 10% 증가
			if (pSlayer->hasRankBonus(RankBonus::RANK_BONUS_HOLY_SMASHING ) )
			{
				RankBonus* pRankBonus = pSlayer->getRankBonus(RankBonus::RANK_BONUS_HOLY_SMASHING);
				Assert(pRankBonus != NULL);

				output.Damage += pRankBonus->getPoint();
			}

			Range_t Range = 3;

			// 기존에 같은 이펙트가 타일에 있다면 지우고 새로 설정한다.
			Tile& tile = pZone->getTile(X, Y);
			Effect* pOldEffect = tile.getEffect(Effect::EFFECT_CLASS_ENERGY_DROP);
			if(pOldEffect != NULL)
			{
				ObjectID_t effectID = pOldEffect->getObjectID();
				pZone->deleteEffect(effectID);
			}

			// 이펙트 오브젝트를 생성해서 타일에 붙인다. 
			//cout << "make EffectObject to Tile" << X << " " << Y << endl;
			pEffect = new EffectEnergyDrop(pZone, X, Y);

			pEffect->setUserObjectID(pSlayer->getObjectID());
//			pEffect->setCasterName(pSlayer->getName());
//			pEffect->setPartyID(pSlayer->getPartyID());
			pEffect->setDeadline(output.Duration);
			pEffect->setNextTime(0);
			pEffect->setTick(output.Tick);
			pEffect->setDamage(output.Damage);
			pEffect->setLevel(pSkillInfo->getLevel()/2);

			//
			//ObjectRegistry& objectregister = pZone->getObjectRegistry();
			//objectregister.registerObject(pEffect);

			//
			//
			//pZone->addEffect(pEffect);
			//tile.addEffect(pEffect);
			// 이펙트 오브젝트를 생성해서 타일에 붙인다. 
			pEffect2 = new EffectEnergyDrop(pZone, X, Y);
			pEffect2->setUserObjectID(pSlayer->getObjectID());
			pEffect2->setDeadline(output.Duration);
			pEffect2->setNextTime(0);
			pEffect2->setTick(output.Tick);
			pEffect2->setDamage(output.Damage * 30 / 100);
			pEffect2->setLevel(pSkillInfo->getLevel()/2);

			// 이펙트 범위내의 모든 Creature에게 effect를 붙여준다.
			// Slayer가 기술을 사용한 경우 같은 Slayer에게는
			// 해당하지 않는다.
			bool bEffected = false;
			bool bHit = false;

			Creature* pTargetCreature;

			list<Creature*> cList;
			cList.push_back(pSlayer);

			int oX, oY;

			Level_t maxEnemyLevel = 0;
			uint EnemyNum = 0;

			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);
		    	if (!tile.canAddEffect()) continue; 

				pTargetCreature = NULL;
				if(tile.hasCreature(Creature::MOVE_MODE_WALKING))
					pTargetCreature = tile.getCreature(Creature::MOVE_MODE_WALKING);

				EffectEnergyDrop * pTempEffect = NULL;

				if(oX == 2 || oX == -2 || oY == 2 || oY == -2 ) pTempEffect = pEffect2;
				else pTempEffect = pEffect;

				if(pTargetCreature != NULL && canAttack(pSlayer, pTargetCreature ))
				{
					if(pTargetCreature->isVampire()||pTargetCreature->isOusters())
					{
						if(pTempEffect->affectCreature(pTargetCreature, false) == true)
						{
							//cout << "EnergyDrop to Slayer Success" << endl;
							Player* pTargetPlayer = pTargetCreature->getPlayer();
							bEffected = true;

							bHit = true;

							if (maxEnemyLevel < pTargetCreature->getLevel() ) maxEnemyLevel = pTargetCreature->getLevel();
							EnemyNum++;

							bool bCanSee = canSee(pTargetCreature, pSlayer);

							_GCSkillToTileOK1.addCListElement(pTargetCreature->getObjectID());
							_GCSkillToTileOK4.addCListElement(pTargetCreature->getObjectID());
							_GCSkillToTileOK5.addCListElement(pTargetCreature->getObjectID());

							cList.push_back(pTargetCreature);

							if (bCanSee)
							{
								// 공격을 당한 사람에게 
								_GCSkillToTileOK2.setObjectID(pSlayer->getObjectID());
								_GCSkillToTileOK2.setSkillType(SkillType);
								_GCSkillToTileOK2.setX(X);
								_GCSkillToTileOK2.setY(Y);
								_GCSkillToTileOK2.setDuration(output.Duration);
								_GCSkillToTileOK2.setRange(Range);
								pTargetPlayer->sendPacket(&_GCSkillToTileOK2);
							}
						}
						else
						{
							//cout << "EnergyDrop to Vampire fail" << endl;
						}
					}
					else if(pTargetCreature->isMonster())
					{
						if(pTempEffect->affectCreature(pTargetCreature, false) == true)
						{
							//cout << "EnergyDrop to Monster Success" << endl;
							bHit = true;

							if (maxEnemyLevel < pTargetCreature->getLevel() ) maxEnemyLevel = pTargetCreature->getLevel();
							EnemyNum++;

							Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature);
							pMonster->addEnemy(pSlayer);

							// 마지막 때린 애가 슬레이어라고 설정한다. by sigi. 2002.6.21
							pMonster->setLastHitCreatureClass(Creature::CREATURE_CLASS_SLAYER);
						}
						else
						{
							//cout << "EnergyDrop to Monster Falis" << endl;
						}

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

			if(bHit)
			{
				//cout << "Skill Succesfully Attacked(" << output.Damage << ")" << endl;
				shareAttrExp(pSlayer, output.Damage, 1, 1, 8, _GCSkillToTileOK1);
				increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToTileOK1, maxEnemyLevel, EnemyNum);
				increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToTileOK1);
			}

			// 기술을 사용한 사람들에게
			_GCSkillToTileOK1.setSkillType(SkillType);
			_GCSkillToTileOK1.setCEffectID(CEffectID);
			_GCSkillToTileOK1.setX(X);
			_GCSkillToTileOK1.setY(Y);
			_GCSkillToTileOK1.setDuration(output.Duration);
			_GCSkillToTileOK1.setRange(Range);
		
			// 기술을 쓴 사람만 볼 수 있는 사람들에게
			_GCSkillToTileOK3.setSkillType(SkillType);
			_GCSkillToTileOK3.setX(X);
			_GCSkillToTileOK3.setY(Y);
			//_GCSkillToTileOK3.setDuration(output.Duration);
			//_GCSkillToTileOK3.setRange(Range);

			// 기술을 당한 사람만 볼 수 있는 사람들에게
			_GCSkillToTileOK4.setSkillType(SkillType);
			_GCSkillToTileOK4.setX(X);
			_GCSkillToTileOK4.setY(Y);
			_GCSkillToTileOK4.setDuration(output.Duration);
			_GCSkillToTileOK4.setRange(Range);

			//기술을 쓴 사람과 당한 사람을 모두 볼 수 있는 사람들에게
			_GCSkillToTileOK5.setObjectID(pSlayer->getObjectID());
			_GCSkillToTileOK5.setSkillType(SkillType);
			_GCSkillToTileOK5.setX(X);
			_GCSkillToTileOK5.setY(Y);
			_GCSkillToTileOK5.setDuration(output.Duration);
			_GCSkillToTileOK5.setRange(Range);
	
			// 기술을 사용한 사람에게 packet 전달
			pPlayer->sendPacket(&_GCSkillToTileOK1);

			// 기술을 쓸 사람과 당한 사람을 모두 볼 수 있는 사람들에게 broadcasing
			// broadcasting후 5번OK를 받은 사람을 기록한다.
			// 여기에 기록된 사람은 차후 broadcasting에서 제외된다.
			cList = pZone->broadcastSkillPacket(myX, myY, X, Y, &_GCSkillToTileOK5, cList);
			
			// 기술을 쓴 사람을 볼 수 있는 사람들에게 broadcasting
			pZone->broadcastPacket(myX, myY, &_GCSkillToTileOK3, cList);

			// 기술을 당한 사람을 볼 수 있는 사람들에게 broadcasting
			pZone->broadcastPacket(X, Y, &_GCSkillToTileOK4, cList);

			// 기술 delay setting
			pSkillSlot->setRunTime(output.Delay);

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

		SAFE_DELETE(pEffect);
		SAFE_DELETE(pEffect2);
	}
	catch(Throwable& t)
	{
		SAFE_DELETE(pEffect);
		SAFE_DELETE(pEffect2);
		executeSkillFailException(pSlayer, getSkillType());
	}

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

	__END_CATCH
}
Beispiel #7
0
//////////////////////////////////////////////////////////////////////////////
// 몬스터 타일 핸들러
//////////////////////////////////////////////////////////////////////////////
void EnergyDrop::execute(Monster* pMonster, ZoneCoord_t X, ZoneCoord_t Y)
	throw(Error)
{
	__BEGIN_TRY

	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl;
	EffectEnergyDrop * pEffect = NULL;
	EffectEnergyDrop * pEffect2 = NULL;

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

		Assert(pZone != NULL);

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

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

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

		bool bRangeCheck = verifyDistance(pMonster, X, Y, pSkillInfo->getRange());
		bool bHitRoll = HitRoll::isSuccessMagic(pMonster, pSkillInfo);


		bool bTileCheck = false;

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

		if(rect.ptInRect(X, Y))
		{
			Tile& tile = pZone->getTile(X, Y);
			if (tile.canAddEffect()) bTileCheck = true;
		}

		if (bRangeCheck && bHitRoll && bTileCheck)
		{
			// calculate damage and duration time
			SkillInput input(pMonster);
			SkillOutput output;
			computeOutput(input, output);

			Range_t Range = 3;

			// 기존에 같은 이펙트가 타일에 있다면 지우고 새로 설정한다.
			Tile& tile = pZone->getTile(X, Y);
			Effect* pOldEffect = tile.getEffect(Effect::EFFECT_CLASS_ENERGY_DROP);
			if(pOldEffect != NULL)
			{
				ObjectID_t effectID = pOldEffect->getObjectID();
				pZone->deleteEffect(effectID);
			}

			// 이펙트 오브젝트를 생성해서 타일에 붙인다. 
			pEffect = new EffectEnergyDrop(pZone, X, Y);
			pEffect->setDeadline(output.Duration);
			pEffect->setNextTime(0);
			pEffect->setTick(output.Tick);
			pEffect->setDamage(output.Damage);
			pEffect->setLevel(pSkillInfo->getLevel()/2);

			//
			//ObjectRegistry& objectregister = pZone->getObjectRegistry();
			//objectregister.registerObject(pEffect);

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

			// 이펙트 오브젝트를 생성해서 타일에 붙인다. 
			pEffect2 = new EffectEnergyDrop(pZone, X, Y);
			pEffect2->setDeadline(output.Duration);
			pEffect2->setNextTime(0);
			pEffect2->setTick(output.Tick);
			pEffect2->setDamage(output.Damage * 30 / 100);
			pEffect2->setLevel(pSkillInfo->getLevel()/2);


			// 이펙트 범위내의 모든 Creature에게 effect를 붙여준다.
			// Slayer가 기술을 사용한 경우 같은 Slayer에게는
			// 해당하지 않는다.
			bool bEffected = false;
			Creature* pTargetCreature;


			list<Creature*> cList;
			cList.push_back(pMonster);

			int oX, oY;

			for(oX = -2; oX <= 2; oX++)
			for(oY = -2; oY <= 2; oY++)
			{
				int tileX = X+oX;
				int tileY = Y+oY;

				EffectEnergyDrop * pTempEffect = NULL;

				if(oX == 2 || oX == -2 || oY == 2 || oY == -2 ) pTempEffect = pEffect2;
				else pTempEffect = pEffect;

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

				Tile& tile = pZone->getTile(tileX, tileY);

				if (!tile.canAddEffect()) continue;

				pTargetCreature = NULL;
				if(tile.hasCreature(Creature::MOVE_MODE_WALKING))
					pTargetCreature = tile.getCreature(Creature::MOVE_MODE_WALKING);

				if(pTargetCreature != NULL)
				{
					if(pTargetCreature->isPC())
					{
						if(pTempEffect->affectCreature(pTargetCreature, false) == true)
						{
							Player* pTargetPlayer = pTargetCreature->getPlayer();
							bEffected = true;

							bool bCanSee = canSee(pTargetCreature, pMonster);

							_GCSkillToTileOK1.addCListElement(pTargetCreature->getObjectID());
							_GCSkillToTileOK4.addCListElement(pTargetCreature->getObjectID());
							_GCSkillToTileOK5.addCListElement(pTargetCreature->getObjectID());

							cList.push_back(pTargetCreature);

							if (bCanSee)
							{
								// 공격을 당한 사람에게 
								_GCSkillToTileOK2.setObjectID(pMonster->getObjectID());
								_GCSkillToTileOK2.setSkillType(SkillType);
								_GCSkillToTileOK2.setX(X);
								_GCSkillToTileOK2.setY(Y);
								_GCSkillToTileOK2.setDuration(output.Duration);
								_GCSkillToTileOK2.setRange(Range);
								pTargetPlayer->sendPacket(&_GCSkillToTileOK2);
							}
						}
					}
				} // if(pTargetCreature!= NULL)
			}

			// 기술을 쓴 사람만 볼 수 있는 사람들에게
			_GCSkillToTileOK3.setSkillType(SkillType);
			_GCSkillToTileOK3.setX(myX);
			_GCSkillToTileOK3.setY(myY);
			//_GCSkillToTileOK3.setDuration(output.Duration);
			//_GCSkillToTileOK3.setRange(Range);

			// 기술을 당한 사람만 볼 수 있는 사람들에게
			_GCSkillToTileOK4.setSkillType(SkillType);
			_GCSkillToTileOK4.setX(X);
			_GCSkillToTileOK4.setY(Y);
			_GCSkillToTileOK4.setDuration(output.Duration);
			_GCSkillToTileOK4.setRange(Range);

			//기술을 쓴 사람과 당한 사람을 모두 볼 수 있는 사람들에게
			_GCSkillToTileOK5.setObjectID(pMonster->getObjectID());
			_GCSkillToTileOK5.setSkillType(SkillType);
			_GCSkillToTileOK5.setX(X);
			_GCSkillToTileOK5.setY(Y);
			_GCSkillToTileOK5.setDuration(output.Duration);
			_GCSkillToTileOK5.setRange(Range);
	
			// 기술을 쓸 사람과 당한 사람을 모두 볼 수 있는 사람들에게 broadcasing
			cList = pZone->broadcastSkillPacket(myX, myY, X, Y, &_GCSkillToTileOK5, cList);
			
			// 기술을 쓴 사람을 볼 수 있는 사람들에게 broadcasting
			pZone->broadcastPacket(myX, myY, &_GCSkillToTileOK3, cList);

			// 기술을 당한 사람을 볼 수 있는 사람들에게 broadcasting
			pZone->broadcastPacket(X, Y, &_GCSkillToTileOK4, cList);


		}
		else
		{
			executeSkillFailNormal(pMonster, getSkillType(), NULL);
		}
		SAFE_DELETE(pEffect);
		SAFE_DELETE(pEffect2);
	}
	catch(Throwable& t)
	{
		SAFE_DELETE(pEffect);
		SAFE_DELETE(pEffect2);
		executeSkillFailException(pMonster, getSkillType());
	}


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

	__END_CATCH
}
Beispiel #8
0
//////////////////////////////////////////////////////////////////////////////
// 아우스터즈 타일 핸들러
//////////////////////////////////////////////////////////////////////////////
void Prominence::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);

		// 데미지와 지속 시간을 계산한다.
		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, output.Range);
		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))
		{
			Tile& tile = pZone->getTile(X, Y);
			if (tile.canAddEffect()) bTileCheck = true;
		}

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

			int oX, oY;

			for (oX = X - 1 ; oX <= X + 1 ; ++oX )
			for (oY = Y - 1 ; oY <= Y + 1 ; ++oY )
			{
				if (!rect.ptInRect(oX, oY)) continue;

				Tile&   tile  = pZone->getTile(oX, oY);
				if (!tile.canAddEffect()) continue;

				// 머시 그라운드 있음 추가 못한당.
				if (tile.getEffect(Effect::EFFECT_CLASS_MERCY_GROUND) != NULL ) continue;
				if (tile.getEffect(Effect::EFFECT_CLASS_TRYING_POSITION) ) continue;
				
				// 같은 이펙트가 이미 존재한다면 삭제한다.
				Effect* pOldEffect = tile.getEffect(Effect::EFFECT_CLASS_PROMINENCE);
				if (pOldEffect != NULL)
				{
					ObjectID_t effectID = pOldEffect->getObjectID();
					pZone->deleteEffect(effectID);
				}

				checkMine(pZone, oX, oY);
				
				// 이펙트 오브젝트를 생성한다.
				EffectProminence* pEffect = new EffectProminence(pZone, oX, oY);
				pEffect->setUserObjectID(pOusters->getObjectID());
				pEffect->setDeadline(output.Duration);
				pEffect->setNextTime(0);
				pEffect->setTick(output.Tick);

				pEffect->setDamage(output.Damage);
				pEffect->setLevel(pOustersSkillSlot->getExpLevel());

				if (Grade > 0 )
				{
					if (Grade == 1 ) pEffect->setSendEffectClass(Effect::EFFECT_CLASS_PROMINENCE_2);
					else pEffect->setSendEffectClass(Effect::EFFECT_CLASS_PROMINENCE_3);
				}

				// 타일에 붙은 이펙트는 OID를 받아야 한다.
				ObjectRegistry & objectregister = pZone->getObjectRegistry();
				objectregister.registerObject(pEffect);
			
				// 존 및 타일에다가 이펙트를 추가한다.
				pZone->addEffect(pEffect);	
				tile.addEffect(pEffect);

				GCAddEffectToTile gcAddEffect;
				gcAddEffect.setXY(oX, oY);
				gcAddEffect.setEffectID(pEffect->getSendEffectClass());
				gcAddEffect.setObjectID(pEffect->getObjectID());
				gcAddEffect.setDuration(output.Duration);

				pZone->broadcastPacket(oX, oY, &gcAddEffect, pOusters);
			}

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

			_GCSkillToTileOK1.setSkillType(SkillType);
			_GCSkillToTileOK1.setCEffectID(CEffectID);
			_GCSkillToTileOK1.setX(X);
			_GCSkillToTileOK1.setY(Y);
			_GCSkillToTileOK1.setDuration(output.Duration);
			_GCSkillToTileOK1.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.setDuration(output.Duration);
			_GCSkillToTileOK4.setGrade(Grade);
		
			_GCSkillToTileOK5.setObjectID(pOusters->getObjectID());
			_GCSkillToTileOK5.setSkillType(SkillType);
			_GCSkillToTileOK5.setX(X);
			_GCSkillToTileOK5.setY(Y);
			_GCSkillToTileOK5.setDuration(output.Duration);
			_GCSkillToTileOK5.setGrade(Grade);

			pPlayer->sendPacket(&_GCSkillToTileOK1);
		
			list<Creature*> cList;
			cList.push_back(pOusters);

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

			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 << t.toString() << endl;
	}

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

	__END_CATCH
}
Beispiel #9
0
//////////////////////////////////////////////////////////////////////////////
// 뱀파이어 타일 핸들러
//////////////////////////////////////////////////////////////////////////////
void Darkness::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 Innate 가 있다면 hit bonus 10
        int HitBonus = 0;
        if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_INNATE ) )
        {
            RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_INNATE);
            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 bSlayerSafeZone = pZone->getZoneLevel(X, Y ) & SLAYER_SAFE_ZONE;

        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 && !bSlayerSafeZone)
        {
            decreaseMana(pVampire, RequiredMP, _GCSkillToTileOK1);

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

            // Wisdom of Darkness 이 있다면 지속시간 30% 증가
            if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_WISDOM_OF_DARKNESS ) )
            {
                RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_WISDOM_OF_DARKNESS);
                Assert(pRankBonus != NULL);

                output.Duration += getPercentValue(output.Duration, pRankBonus->getPoint());
            }

            Range_t    Range    = 3;

            int oX, oY;

            list<Creature*> cList;	// denier list

            int edge = 1;

            // Wide Darkness 이 있다면 범위가 5*5 로 수정. skill type 을 수정한다.
            if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_WIDE_DARKNESS ) )
            {
                RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_WIDE_DARKNESS);
                Assert(pRankBonus != NULL);

                Range = pRankBonus->getPoint();
                edge = (pRankBonus->getPoint() - 1 ) / 2;

                SkillType = SKILL_DARKNESS_WIDE;
            }

//			map<int, uint> canAddMap;

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

//					if (canAddMap[normalizeCoord_DARKNESS(oX, oY, edge )] == 1 ) continue;

                        if (tile.hasItem() )
                        {
                            Item* pItem = tile.getItem();
                            if (pItem != NULL && pItem->getItemClass() == Item::ITEM_CLASS_CORPSE && pItem->getItemType() == MONSTER_CORPSE )
                            {
                                MonsterCorpse* pMonsterCorpse = dynamic_cast<MonsterCorpse*>(pItem);
                                if (g_pFlagManager->isFlagPole(pMonsterCorpse ) )
                                {
//								canAddMap[normalizeCoord_DARKNESS(oX+1, oY, edge )] = 1;
//								canAddMap[normalizeCoord_DARKNESS(oX+1, oY+1, edge )] = 1;
//								canAddMap[normalizeCoord_DARKNESS(oX, oY+1, edge )] = 1;
                                    continue;
                                }
                            }
                        }

                        if (tile.getEffect(Effect::EFFECT_CLASS_TRYING_POSITION ) != NULL ) continue;

                        // 현재 타일에다 이펙트를 추가할 수 있다면...
                        if (tile.canAddEffect())
                        {
                            // 머시 그라운드 있음 추가 못한당.
                            if (tile.getEffect(Effect::EFFECT_CLASS_MERCY_GROUND) != NULL ) continue;
                            if (tile.getEffect(Effect::EFFECT_CLASS_DARKNESS_FORBIDDEN) != NULL ) continue;

                            // 같은 effect가 있으면 지운다.
                            Effect* pOldEffect = tile.getEffect(Effect::EFFECT_CLASS_DARKNESS);
                            if (pOldEffect != NULL)
                            {
                                ObjectID_t effectID = pOldEffect->getObjectID();
                                pZone->deleteEffect(effectID);// fix me
                            }

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

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

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

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

            _GCSkillToTileOK2.setObjectID(pVampire->getObjectID());
            _GCSkillToTileOK2.setSkillType(SkillType);
            _GCSkillToTileOK2.setX(X);
            _GCSkillToTileOK2.setY(Y);
            _GCSkillToTileOK2.setDuration(output.Duration);
            _GCSkillToTileOK2.setRange(Range);
            //_GCSkillToTileOK2.addShortData(MODIFY_VISION, DARKNESS_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(Range);
            _GCSkillToTileOK4.setDuration(output.Duration);

            _GCSkillToTileOK5.setObjectID(pVampire->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);
            //_GCSkillToTileOK6.addShortData(MODIFY_VISION, DARKNESS_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 << "Darkness : 왓처 리스트가 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
}
Beispiel #10
0
//////////////////////////////////////////////////////////////////////////////
// 몬스터 셀프 핸들러
//////////////////////////////////////////////////////////////////////////////
void Darkness::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_DARKNESS;
        SkillInfo*  pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType);

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

        bool bRangeCheck = verifyDistance(pMonster, X, Y, pSkillInfo->getRange());
        bool bHitRoll    = 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;

            int oX, oY;

            list<Creature*> cList;	// denier list

            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.hasItem() )
                        {
                            Item* pItem = tile.getItem();
                            if (pItem != NULL && pItem->getItemClass() == Item::ITEM_CLASS_CORPSE && pItem->getItemType() == MONSTER_CORPSE )
                            {
                                MonsterCorpse* pMonsterCorpse = dynamic_cast<MonsterCorpse*>(pItem);
                                if (g_pFlagManager->isFlagPole(pMonsterCorpse ) ) continue;
                            }
                        }

                        // 현재 타일에다 이펙트를 추가할 수 있다면...
                        if (tile.canAddEffect())
                        {
                            // 머시 그라운드 있음 추가 못한당.
                            if (tile.getEffect(Effect::EFFECT_CLASS_MERCY_GROUND) != NULL ) continue;

                            // 같은 effect가 있으면 지운다.
                            Effect* pOldEffect = tile.getEffect(Effect::EFFECT_CLASS_DARKNESS);
                            if (pOldEffect != NULL)
                            {
                                ObjectID_t effectID = pOldEffect->getObjectID();
                                pZone->deleteEffect(effectID);// fix me
                            }

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

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

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

            _GCSkillToTileOK2.setObjectID(pMonster->getObjectID());
            _GCSkillToTileOK2.setSkillType(SkillType);
            _GCSkillToTileOK2.setX(X);
            _GCSkillToTileOK2.setY(Y);
            _GCSkillToTileOK2.setDuration(output.Duration);
            _GCSkillToTileOK2.setRange(Range);
            //_GCSkillToTileOK2.addShortData(MODIFY_VISION, DARKNESS_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(Range);
            _GCSkillToTileOK4.setDuration(output.Duration);

            _GCSkillToTileOK5.setObjectID(pMonster->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);
            //_GCSkillToTileOK6.addShortData(MODIFY_VISION, DARKNESS_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
}