Пример #1
0
void InstallMine::execute(Slayer* pSlayer, ObjectID_t, CoordInven_t X, CoordInven_t Y, CoordInven_t TargetX, CoordInven_t TargetY, SkillSlot* pSkillSlot)
throw(Error)
{
    __BEGIN_TRY

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

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

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

        GCSkillToInventoryOK1 _GCSkillToInventoryOK1;
//		GCSkillToTileOK1 _GCSkillToTileOK1;
//		GCSkillToTileOK5 _GCSkillToTileOK5;

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

        // 명중률.
        //ToHit_t ToHit = pSlayer->getToHit();

        int  RequiredMP  = (int)pSkillInfo->getConsumeMP();
        bool bManaCheck  = hasEnoughMana(pSlayer, RequiredMP);
        bool bTimeCheck  = verifyRunTime(pSkillSlot);
        bool bRangeCheck = checkZoneLevelToUseSkill(pSlayer);
        ZoneCoord_t slayerX = pSlayer->getX(), slayerY = pSlayer->getY();
        bool bInstallAction = false;

        Mine* pMine = NULL;

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

        if(bManaCheck && bTimeCheck &&bRangeCheck ) {
            // mine을 찾는다.
            Item* pItem = pInventory->getItem(X, Y);
            if(pItem != NULL && pItem->getItemClass() == Item::ITEM_CLASS_MINE)
            {
                bInstallAction = true;
                pMine = dynamic_cast<Mine*>(pItem);
            }
        }


        // 기술의 성패를 따진다.
        if (bInstallAction )
        {
            //Range_t Range = 1;

            GCSkillToInventoryOK1 _GCSkillToInventoryOK1;
//			GCSkillToInventoryOK5 _GCSkillToInventoryOK5;

            ItemInfo*       pItemInfo = g_pItemInfoManager->getItemInfo(Item::ITEM_CLASS_MINE, pMine->getItemType());

            Damage_t MinDamage = pItemInfo->getMinDamage();
            Damage_t MaxDamage = pItemInfo->getMaxDamage();

            Damage_t RealDamage = MinDamage + (max (0, ((int)MaxDamage * (int)SkillLevel / 100 ) - MinDamage ));

            Mine * pInstallMine = new Mine();
            ObjectRegistry& OR = pZone->getObjectRegistry();
            OR.registerObject(pInstallMine);

            Assert(pInstallMine != NULL);
            pInstallMine->setItemType(pMine->getItemType());
            pInstallMine->setDir(TargetX);
            pInstallMine->setDamage(RealDamage);
            pInstallMine->setInstallerName(pSlayer->getName());
            pInstallMine->setInstallerPartyID(pSlayer->getPartyID());
            pInstallMine->setFlag(Effect::EFFECT_CLASS_INSTALL);

            // 아이템 사라지는게 3분인거 때문에 지뢰도 사라졌는데..
            // 10분으로 고정. by sigi. 2002.11.3
            TPOINT pt = pZone->addItem(pInstallMine, slayerX, slayerY, true, 6000);

            // EXP up
            Exp_t Point = pSkillInfo->getPoint();

            shareAttrExp(pSlayer, 100, 1, 8, 1, _GCSkillToInventoryOK1);
            increaseDomainExp(pSlayer, SKILL_DOMAIN_GUN, Point, _GCSkillToInventoryOK1);
            increaseSkillExp(pSlayer, SKILL_DOMAIN_GUN, pSkillSlot, pSkillInfo, _GCSkillToInventoryOK1);

            decreaseMana(pSlayer, RequiredMP, _GCSkillToInventoryOK1);
            decreaseItemNum(pMine, pInventory, pSlayer->getName(), STORAGE_INVENTORY, 0, X, Y);


            _GCSkillToInventoryOK1.setObjectID(pInstallMine->getObjectID());
            _GCSkillToInventoryOK1.setSkillType(SkillType);
            _GCSkillToInventoryOK1.setCEffectID(0);
            _GCSkillToInventoryOK1.setX(X);
            _GCSkillToInventoryOK1.setY(Y);
            _GCSkillToInventoryOK1.setDuration(0);

            /*
            _GCSkillToInventoryOK5.setObjectID(pSlayer->getObjectID());
            _GCSkillToInventoryOK5.setSkillType(SkillType);
            _GCSkillToInventoryOK5.setX(X);
            _GCSkillToInventoryOK5.setY(Y);
            _GCSkillToInventoryOK5.setRange(Range);
            _GCSkillToInventoryOK5.setDuration(0);
            */

            pPlayer->sendPacket(&_GCSkillToInventoryOK1);

            // mine을 볼 수 없게 된 자들에게는 삭제
            addInstalledMine(pZone, pInstallMine, pt.x, pt.y);

//			pZone->broadcastPacket(slayerX, slayerY, &_GCSkillToInventoryOK5, pSlayer);

            //        cout << "Run Skill : " << (int)SkillType << endl;
            // Set NextTime
            pSkillSlot->setRunTime();

        }
        else
        {
            GCSkillFailed1 _GCSkillFailed1;
            GCSkillFailed2 _GCSkillFailed2;

            executeSkillFailException(pSlayer, getSkillType());
        }

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

    __END_CATCH
}
Пример #2
0
//////////////////////////////////////////////////////////////////////////////
// 슬레이어 오브젝트
//////////////////////////////////////////////////////////////////////////////
void DoubleShot::execute (Slayer* pSlayer, ObjectID_t TargetObjectID,  SkillSlot* pSkillSlot, CEffectID_t CEffectID)
	throw(Error)
{
	__BEGIN_TRY __BEGIN_DEBUG

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

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

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

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

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

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

		GCAttackArmsOK1 _GCAttackArmsOK1;
		GCAttackArmsOK2 _GCAttackArmsOK2;
		GCAttackArmsOK3 _GCAttackArmsOK3;
		GCAttackArmsOK4 _GCAttackArmsOK4;
		GCAttackArmsOK5 _GCAttackArmsOK5;

		// 들고 있는 무기가 없거나, 총 계열 무기가 아니라면 기술을 쓸 수 없다.
		// 총 계열 무기 중에서도 SG나 SR은 DoubleShot를 쓸 수가 없다.
		// SR, SG 도 이제 쓸수 있다.
		// 2003.1.14 by bezz
		Item* pWeapon = pSlayer->getWearItem(Slayer::WEAR_RIGHTHAND);
		if (pWeapon == NULL || isArmsWeapon(pWeapon) == false )
//			pWeapon->getItemClass() == Item::ITEM_CLASS_SG || 
//			pWeapon->getItemClass() == Item::ITEM_CLASS_SR)
		{
			executeSkillFailException(pSlayer, getSkillType());
			//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl;
			return;
		}

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

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

		// 페널티 값을 계산한다.
		int ToHitPenalty = getPercentValue(pSlayer->getToHit(), output.ToHit); 

		int  RequiredMP  = (int)pSkillInfo->getConsumeMP();
		bool bManaCheck   = hasEnoughMana(pSlayer, RequiredMP);
		bool bTimeCheck   = verifyRunTime(pSkillSlot);
		bool bRangeCheck  = verifyDistance(pSlayer, pTargetCreature, pWeapon->getRange());
		bool bBulletCheck = (getRemainBullet(pWeapon) > 0) ? true : false;
		bool bHitRoll     = HitRoll::isSuccess(pSlayer, pTargetCreature, ToHitPenalty);
		bool bPK          = verifyPK(pSlayer, pTargetCreature);

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

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

			_GCAttackArmsOK5.setSkillSuccess(true);
			_GCAttackArmsOK1.setSkillSuccess(true);

			bool bCriticalHit = false;

			// 데미지를 계산하고, quickfire 페널티를 가한다.
			// output.Damage가 음수이기 때문에, %값을 구해 더하면 결국 빼는 것이 된다.
			int Damage = computeDamage(pSlayer, pTargetCreature, SkillLevel/5, bCriticalHit);
			Damage += getPercentValue(Damage, output.Damage);
			Damage = max(0, Damage);

			//cout << "DoubleShotDamage:" << Damage << endl;

			// 데미지를 세팅한다.
			setDamage(pTargetCreature, Damage, pSlayer, SkillType, &_GCAttackArmsOK2, &_GCAttackArmsOK1);
			computeAlignmentChange(pTargetCreature, Damage, pSlayer, &_GCAttackArmsOK2, &_GCAttackArmsOK1);

			// 공격자와 상대의 아이템 내구성 떨어트림.
			// 밑에 있던걸 이쪽으로 옮겼다.  by sigi. 2002.5.13
			decreaseDurability(pSlayer, pTargetCreature, NULL, &_GCAttackArmsOK1, &_GCAttackArmsOK2);


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

			/*
			// 80% 확률로만 능력치가 상승한다.
			// 상대방이 슬레이어가 아닐 경우에만 경험치가 상승한다.
			if (Random(1, 100) < 80 && !pTargetCreature->isSlayer())
			{
			*/
			if(!pTargetCreature->isSlayer() ) {
				if (bIncreaseDomainExp )
				{
					shareAttrExp(pSlayer, Damage , 1, 8, 1, _GCAttackArmsOK1);
					increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCAttackArmsOK1, pTargetCreature->getLevel());
					increaseSkillExp(pSlayer, DomainType,  pSkillSlot, pSkillInfo, _GCAttackArmsOK1);
				}

				increaseAlignment(pSlayer, pTargetCreature, _GCAttackArmsOK1);
			}
			//}

			if (pTargetCreature->isPC()) 
			{
				Player* pTargetPlayer = pTargetCreature->getPlayer();
				if (pTargetPlayer != NULL) 
				{ 
					_GCAttackArmsOK2.setObjectID(pSlayer->getObjectID());
					pTargetPlayer->sendPacket(&_GCAttackArmsOK2);
				}
			} 
			else if (pTargetCreature->isMonster())
			{
				Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature);
				pMonster->addEnemy(pSlayer);
			}

			ZoneCoord_t targetX = pTargetCreature->getX();
			ZoneCoord_t targetY = pTargetCreature->getY();
			ZoneCoord_t myX     = pSlayer->getX();
			ZoneCoord_t myY     = pSlayer->getY();
			
			_GCAttackArmsOK1.setObjectID(TargetObjectID);
			_GCAttackArmsOK1.setBulletNum(RemainBullet);

			_GCAttackArmsOK3.setObjectID(pSlayer->getObjectID());
			_GCAttackArmsOK3.setTargetXY (targetX, targetY);
			
			_GCAttackArmsOK4.setTargetObjectID (TargetObjectID);
			
			_GCAttackArmsOK5.setObjectID(pSlayer->getObjectID());
			_GCAttackArmsOK5.setTargetObjectID (TargetObjectID);

			pPlayer->sendPacket(&_GCAttackArmsOK1);

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

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

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

	__END_DEBUG __END_CATCH
}