예제 #1
0
//////////////////////////////////////////////////////////////////////////////
// 뱀파이어 셀프 핸들러
//////////////////////////////////////////////////////////////////////////////
void SummonCasket::execute(Vampire* pVampire, VampireSkillSlot* pSkillSlot, CEffectID_t CEffectID)
throw(Error)
{
    __BEGIN_TRY

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

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

    //cout << "SummonCasket try.." << endl;

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

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

        if (!pVampire->isVampire()
                && !pVampire->isMonster())
        {
            executeSkillFailNormal(pVampire, getSkillType(), NULL);
            return;
        }


        GCSkillToSelfOK1 _GCSkillToSelfOK1;
        GCSkillToSelfOK3 _GCSkillToSelfOK3;

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

        ZoneCoord_t x = pVampire->getX();
        ZoneCoord_t y = pVampire->getY();

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

            HitBonus = pRankBonus->getPoint();
        }

        int  RequiredMP     = decreaseConsumeMP(pVampire, pSkillInfo);
        bool bManaCheck     = hasEnoughMana(pVampire, RequiredMP);
        bool bTimeCheck     = verifyRunTime(pSkillSlot);
        bool bRangeCheck    = checkZoneLevelToUseSkill(pVampire);
        bool bHitRoll       = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pSkillSlot, HitBonus);
        bool bTileCheck     = canBurrow(pZone, x, y);
        bool bMoveModeCheck = pVampire->isWalking();
        bool bEffected      = pVampire->isFlag(Effect::EFFECT_CLASS_CASKET);

        if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bTileCheck && bMoveModeCheck && !bEffected)
        {
            //cout << "SummonCasket Success" << endl;

            decreaseMana(pVampire, RequiredMP, _GCSkillToSelfOK1);

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


            // 뱀파이어를 땅 위에서 삭제하기 이전에 기술 패킷들을 날린다.
            _GCSkillToSelfOK1.setSkillType(SkillType);
            _GCSkillToSelfOK1.setCEffectID(CEffectID);
            _GCSkillToSelfOK1.setDuration(output.Duration);

            _GCSkillToSelfOK3.setXY(x, y);
            _GCSkillToSelfOK3.setSkillType(SkillType);
            _GCSkillToSelfOK3.setDuration(output.Duration);

            pPlayer->sendPacket(&_GCSkillToSelfOK1);
            pZone->broadcastPacket(x, y, &_GCSkillToSelfOK3, pVampire);

            //---------------------------------------------------------------
            // 기존의 지속 마법 효과를 제거한다.
            //---------------------------------------------------------------
            EffectManager* pEffectManager = pVampire->getEffectManager();
            Assert(pEffectManager!=NULL);

            Effect* pCheckEffect = NULL;

            // 사용자의 level을 구한다.
            int userLevel = pVampire->getLevel();

            Effect::EffectClass effectClass;

            // EFFECT_CLASS_FLARE
            effectClass = Effect::EFFECT_CLASS_FLARE;
            pCheckEffect = pEffectManager->findEffect(effectClass);
            if (pCheckEffect!=NULL)
            {
                int level =	(dynamic_cast<EffectFlare*>(pCheckEffect))->getLevel();

                if (level < userLevel)
                {
                    pEffectManager->deleteEffect(effectClass);
                    pVampire->removeFlag(effectClass);
                }
            }

            // EFFECT_CLASS_DOOM
            effectClass = Effect::EFFECT_CLASS_DOOM;
            pCheckEffect = pEffectManager->findEffect(effectClass);
            if (pCheckEffect!=NULL)
            {
                int level =	(dynamic_cast<EffectDoom*>(pCheckEffect))->getLevel();

                if (level < userLevel)
                {
                    pEffectManager->deleteEffect(effectClass);
                    pVampire->removeFlag(effectClass);
                }
            }

            // EFFECT_CLASS_SEDUCTION
            effectClass = Effect::EFFECT_CLASS_SEDUCTION;
            pCheckEffect = pEffectManager->findEffect(effectClass);
            if (pCheckEffect!=NULL)
            {
                int level =	(dynamic_cast<EffectSeduction*>(pCheckEffect))->getLevel();

                if (level < userLevel)
                    pEffectManager->deleteEffect(effectClass);
                pVampire->removeFlag(effectClass);
            }


            //---------------------------------------------------------------
            // 이펙트 오브젝트를 생성해 붙인다.
            //---------------------------------------------------------------
            EffectSummonCasket* pEffect = new EffectSummonCasket(pVampire);
            pEffect->setDeadline(99999999);
            pEffect->setType(0);
            pVampire->addEffect(pEffect);
            pVampire->setFlag(Effect::EFFECT_CLASS_CASKET);

            // SUMMON CASKET 에 의해 변하는 능력치가 변한다.. 2002.12.13  by bezz.
            VAMPIRE_RECORD prev;

            pVampire->getVampireRecord(prev);
            pVampire->initAllStat();
            pVampire->sendRealWearingInfo();
            pVampire->sendModifyInfo(prev);

            GCAddEffect gcAddEffect;
            gcAddEffect.setObjectID(pVampire->getObjectID());
            gcAddEffect.setEffectID(Effect::EFFECT_CLASS_CASKET);
            gcAddEffect.setDuration(output.Duration);
            pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &gcAddEffect, pVampire);

            pSkillSlot->setRunTime();
        }
        else
        {
            //cout << "SummonCasket Failed" << endl;
            executeSkillFailNormal(pVampire, getSkillType(), NULL);
        }
    }
    catch(Throwable & t)
    {
        //cout << "SummonCasket Failed2" << endl;
        executeSkillFailException(pVampire, getSkillType());
    }

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

    __END_CATCH

}
예제 #2
0
void ActionHeal::execute (Creature * pCreature1 , Creature * pCreature2) 
	throw(Error)
{
	__BEGIN_TRY

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

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

	// 일단 클라이언트를 위해서 OK 패킷을 함 날린다.
	GCNPCResponse okpkt;
	okpkt.setCode(NPC_RESPONSE_HEAL);
	pPlayer->sendPacket(&okpkt);

	// 죽었거나 코마 걸려있으면 안 치료해준다.
	if (pCreature2->isDead() || pCreature2->isFlag(Effect::EFFECT_CLASS_COMA ) )
	{
		return;
	}

	// 슬레이어라면...
	if (pCreature2->isSlayer())
	{
		Slayer*             pSlayer        = dynamic_cast<Slayer*>(pCreature2);
		EffectManager*      pEffectManager = pSlayer->getEffectManager();
		GCModifyInformation modifyPkt;
		GCRemoveEffect      removePkt;
		GCStatusCurrentHP   hpPkt;

		// 먼저 HP랑 MP를 풀로 채워준다.
		if (pSlayer->getHP(ATTR_CURRENT) < pSlayer->getHP(ATTR_MAX))
		{
			pSlayer->setHP(pSlayer->getHP(ATTR_MAX), ATTR_CURRENT);
			modifyPkt.addShortData(MODIFY_CURRENT_HP, pSlayer->getHP(ATTR_CURRENT));

			hpPkt.setObjectID(pSlayer->getObjectID());
			hpPkt.setCurrentHP(pSlayer->getHP(ATTR_CURRENT));
		}
		if (pSlayer->getMP(ATTR_CURRENT) < pSlayer->getMP(ATTR_MAX))
		{
			pSlayer->setMP(pSlayer->getMP(ATTR_MAX), ATTR_CURRENT);
			modifyPkt.addShortData(MODIFY_CURRENT_MP, pSlayer->getMP(ATTR_CURRENT));
		}

		// 흡혈 이펙트를 삭제한다.
		Effect* pBloodDrainEffect = pEffectManager->findEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN);
		if (pBloodDrainEffect != NULL)
		{
			// DB에서 삭제하고, 이펙트 매니저에서 삭제한다.
			pBloodDrainEffect->destroy(pSlayer->getName());
			pEffectManager->deleteEffect(pSlayer, Effect::EFFECT_CLASS_BLOOD_DRAIN);

			// 흡혈 아르바이트를 방지하기 위한 후유증 이펙트를 붙여준다.
			if (pSlayer->isFlag(Effect::EFFECT_CLASS_AFTERMATH))
			{
				Effect* pEffect = pEffectManager->findEffect(Effect::EFFECT_CLASS_AFTERMATH);
				EffectAftermath* pEffectAftermath = dynamic_cast<EffectAftermath*>(pEffect);
				pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다.
			}
			else
			{
				EffectAftermath* pEffectAftermath = new EffectAftermath(pSlayer);
				pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다.
				pEffectManager->addEffect(pEffectAftermath);
				pSlayer->setFlag(Effect::EFFECT_CLASS_AFTERMATH);
				pEffectAftermath->create(pSlayer->getName());
			}

			// 패킷에다 정보를 더한다.
			removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_BLOOD_DRAIN);

			// 흡혈을 치료하면 능력치가 변화하게 된다.
			SLAYER_RECORD prev;
			pSlayer->getSlayerRecord(prev);
			pSlayer->initAllStat();
			pSlayer->sendModifyInfo(prev);
			pSlayer->sendRealWearingInfo();
		}

		// 독 이펙트를 삭제한다.
		Effect* pEffectPoison = pEffectManager->findEffect(Effect::EFFECT_CLASS_POISON);
		if (pEffectPoison != NULL)
		{
			// 이펙트 매니저에서 삭제한다.
			pEffectManager->deleteEffect(pSlayer, Effect::EFFECT_CLASS_POISON);

			// 패킷에다 정보를 더한다.
			removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_POISON);
		}

		// 다크블루 포이즌 이펙트를 삭제한다.
		Effect* pEffectDarkBluePoison = pEffectManager->findEffect(Effect::EFFECT_CLASS_DARKBLUE_POISON);
		if (pEffectDarkBluePoison != NULL)
		{
			// 이펙트 매니저에서 삭제한다.
			pEffectManager->deleteEffect(pSlayer, Effect::EFFECT_CLASS_DARKBLUE_POISON);

			// 패킷에다 정보를 더한다.
			removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_DARKBLUE_POISON);
		}

		// 패킷 날려준다.
		removePkt.setObjectID(pSlayer->getObjectID());
		pPlayer->sendPacket(&modifyPkt);
		pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &removePkt);
		pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &hpPkt, pSlayer);

		//log(LOG_HEAL, pSlayer->getName(), "");
	}
	else if (pCreature2->isVampire())
	{
		Vampire*            pVampire = dynamic_cast<Vampire*>(pCreature2);
		//EffectManager*      pEffectManager = pVampire->getEffectManager();
		GCModifyInformation modifyPkt;
		GCRemoveEffect      removePkt;
		GCStatusCurrentHP   hpPkt;

		// HP 채워주고...
		if (pVampire->getHP(ATTR_CURRENT) < pVampire->getHP(ATTR_MAX))
		{
			pVampire->setHP(pVampire->getHP(ATTR_MAX), ATTR_CURRENT);
			modifyPkt.addShortData(MODIFY_CURRENT_HP, pVampire->getHP(ATTR_CURRENT));

			hpPkt.setObjectID(pVampire->getObjectID());
			hpPkt.setCurrentHP(pVampire->getHP(ATTR_CURRENT));
		}

		// 패킷 날려준다.
		removePkt.setObjectID(pVampire->getObjectID());
		pPlayer->sendPacket(&modifyPkt);
		pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &removePkt);
		pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &hpPkt, pVampire);

		//log(LOG_HEAL, pVampire->getName(), "");
	}
	else if (pCreature2->isOusters())
	{
		Ousters*             pOusters        = dynamic_cast<Ousters*>(pCreature2);
		EffectManager*      pEffectManager = pOusters->getEffectManager();
		GCModifyInformation modifyPkt;
		GCRemoveEffect      removePkt;
		GCStatusCurrentHP   hpPkt;

		// 먼저 HP랑 MP를 풀로 채워준다.
		if (pOusters->getHP(ATTR_CURRENT) < pOusters->getHP(ATTR_MAX) || pOusters->getSilverDamage() != 0 )
		{
			Silver_t prev = pOusters->getSilverDamage();

			if (prev != 0 )
			{
				pOusters->setSilverDamage(0);
				modifyPkt.addShortData(MODIFY_SILVER_DAMAGE, pOusters->getSilverDamage());
			}

			pOusters->setHP(pOusters->getHP(ATTR_MAX), ATTR_CURRENT);
			modifyPkt.addShortData(MODIFY_CURRENT_HP, pOusters->getHP(ATTR_CURRENT));

			hpPkt.setObjectID(pOusters->getObjectID());
			hpPkt.setCurrentHP(pOusters->getHP(ATTR_CURRENT));
		}
		if (pOusters->getMP(ATTR_CURRENT) < pOusters->getMP(ATTR_MAX))
		{
			pOusters->setMP(pOusters->getMP(ATTR_MAX), ATTR_CURRENT);
			modifyPkt.addShortData(MODIFY_CURRENT_MP, pOusters->getMP(ATTR_CURRENT));
		}

		// 독 이펙트를 삭제한다.
		Effect* pEffectPoison = pEffectManager->findEffect(Effect::EFFECT_CLASS_POISON);
		if (pEffectPoison != NULL)
		{
			// 이펙트 매니저에서 삭제한다.
			pEffectManager->deleteEffect(pOusters, Effect::EFFECT_CLASS_POISON);

			// 패킷에다 정보를 더한다.
			removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_POISON);
		}

		// 다크블루 포이즌 이펙트를 삭제한다.
		Effect* pEffectDarkBluePoison = pEffectManager->findEffect(Effect::EFFECT_CLASS_DARKBLUE_POISON);
		if (pEffectDarkBluePoison != NULL)
		{
			// 이펙트 매니저에서 삭제한다.
			pEffectManager->deleteEffect(pOusters, Effect::EFFECT_CLASS_DARKBLUE_POISON);

			// 패킷에다 정보를 더한다.
			removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_DARKBLUE_POISON);
		}

		// 흡혈 이펙트를 삭제한다.
		Effect* pBloodDrainEffect = pEffectManager->findEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN);
		if (pBloodDrainEffect != NULL)
		{
			pBloodDrainEffect->setDeadline(0);

			// 흡혈 아르바이트를 방지하기 위한 후유증 이펙트를 붙여준다.
			if (pOusters->isFlag(Effect::EFFECT_CLASS_AFTERMATH))
			{
				Effect* pEffect = pEffectManager->findEffect(Effect::EFFECT_CLASS_AFTERMATH);
				EffectAftermath* pEffectAftermath = dynamic_cast<EffectAftermath*>(pEffect);
				pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다.
			}
			else
			{
				EffectAftermath* pEffectAftermath = new EffectAftermath(pOusters);
				pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다.
				pEffectManager->addEffect(pEffectAftermath);
				pOusters->setFlag(Effect::EFFECT_CLASS_AFTERMATH);
				pEffectAftermath->create(pOusters->getName());
			}

			// 패킷에다 정보를 더한다.
			removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_BLOOD_DRAIN);
		}


		// 패킷 날려준다.
		removePkt.setObjectID(pOusters->getObjectID());
		pPlayer->sendPacket(&modifyPkt);
		pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &removePkt);
		pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &hpPkt, pOusters);

		//log(LOG_HEAL, pOusters->getName(), "");

	}
	__END_CATCH
}