void EffectReactiveArmor::unaffect(Creature* pCreature)
	throw(Error)
{
	__BEGIN_TRY

	//cout << "EffectReactiveArmor" << "unaffect BEGIN" << endl;

	Assert(pCreature != NULL);
	Assert(pCreature->isOusters());

	// 플래그를 끈다.
	pCreature->removeFlag(Effect::EFFECT_CLASS_REACTIVE_ARMOR);

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

	Ousters* pTargetOusters = dynamic_cast<Ousters*>(pCreature);
	Assert(pTargetOusters != NULL);

	pTargetOusters->initAllStatAndSend();

	// 이펙트를 삭제하라고 알려준다.
	GCRemoveEffect gcRemoveEffect;
	gcRemoveEffect.setObjectID(pCreature->getObjectID());
	gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_REACTIVE_ARMOR);
	pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcRemoveEffect);

	//cout << "EffectReactiveArmor" << "unaffect END" << endl;

	__END_CATCH
}
Beispiel #2
0
void GroundBless::execute(Ousters* pOusters, ObjectID_t TargetObjectID,  OustersSkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error)
{
	__BEGIN_TRY
		
	//cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl;

	Assert(pOusters != NULL);
	Assert(pSkillSlot != 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, pSkillSlot->getSkillType());
			return;
		}

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

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

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

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

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

		int  RequiredMP  = (int)pSkillInfo->getConsumeMP() + pSkillSlot->getExpLevel()/2;
		bool bManaCheck  = hasEnoughMana(pOusters, RequiredMP);
		bool bTimeCheck  = verifyRunTime(pSkillSlot);
		bool bRangeCheck = verifyDistance(pOusters, pTargetCreature, pSkillInfo->getRange());
		bool bHitRoll	 = HitRoll::isSuccessMagic(pOusters, pSkillInfo, pSkillSlot);
		bool bEffected   = pTargetCreature->isFlag(Effect::EFFECT_CLASS_GROUND_BLESS);
		bool bSatisfyRequire = pOusters->satisfySkillRequire(pSkillInfo);

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

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

        	bool bCanSeeCaster = canSee(pTargetCreature, pOusters);

			// 이펙트 오브젝트를 생성해 붙인다.
			EffectGroundBless* pEffect = new EffectGroundBless(pTargetCreature);
			pEffect->setDeadline(output.Duration);
			pEffect->setBonus(output.Damage);
			pTargetCreature->addEffect(pEffect);
			pTargetCreature->setFlag(Effect::EFFECT_CLASS_GROUND_BLESS);

			Ousters* pTargetOusters = dynamic_cast<Ousters*>(pTargetCreature);
			if (pTargetOusters != NULL ) pTargetOusters->initAllStatAndSend();
							
			_GCSkillToObjectOK1.setSkillType(SkillType);
			_GCSkillToObjectOK1.setCEffectID(CEffectID);
			_GCSkillToObjectOK1.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK1.setDuration(output.Duration);
		
			_GCSkillToObjectOK2.setObjectID(pOusters->getObjectID());
			_GCSkillToObjectOK2.setSkillType(SkillType);
			_GCSkillToObjectOK2.setDuration(output.Duration);
		
			_GCSkillToObjectOK3.setObjectID(pOusters->getObjectID());
			_GCSkillToObjectOK3.setSkillType(SkillType);
			_GCSkillToObjectOK3.setTargetXY (targetX, targetY);
			
			_GCSkillToObjectOK4.setSkillType(SkillType);
			_GCSkillToObjectOK4.setTargetObjectID(TargetObjectID);
			_GCSkillToObjectOK4.setDuration(output.Duration);
			
			_GCSkillToObjectOK5.setObjectID(pOusters->getObjectID());
			_GCSkillToObjectOK5.setSkillType(SkillType);
			_GCSkillToObjectOK5.setTargetObjectID (TargetObjectID);
			_GCSkillToObjectOK5.setDuration(output.Duration);
			
			_GCSkillToObjectOK6.setXY(myX, myY);
			_GCSkillToObjectOK6.setSkillType(SkillType);
			_GCSkillToObjectOK6.setDuration(output.Duration);

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

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

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

			Player* pTargetPlayer = pTargetCreature->getPlayer();

			if (pTargetPlayer != NULL )
			{
				if (bCanSeeCaster) pTargetPlayer->sendPacket(&_GCSkillToObjectOK2);
				else pTargetPlayer->sendPacket(&_GCSkillToObjectOK6);
			}

			GCAddEffect gcAddEffect;
			gcAddEffect.setObjectID(TargetObjectID);
			gcAddEffect.setEffectID(Effect::EFFECT_CLASS_GROUND_BLESS);
			gcAddEffect.setDuration(output.Duration);
			pZone->broadcastPacket(targetX, targetY, &gcAddEffect);
			
			pSkillSlot->setRunTime(output.Delay);
		} 
		else 
		{
			executeSkillFailNormal(pOusters, getSkillType(), pTargetCreature);
		}
	}
	catch (Throwable & t) 
	{
		executeSkillFailException(pOusters, getSkillType());
	}

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

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

#ifdef __GAME_SERVER__

	ObjectID_t    ITEMOID       = pPacket->getObjectID();
	Creature*     pPC           = dynamic_cast<GamePlayer*>(pPlayer)->getCreature();
	bool          bSlayer       = false;
	bool          bVampire      = false;
	bool          bOusters      = false;
	Gold_t        playerMoney   = 0;
	Price_t       repairPrice   = 0;
	Item*         pItem         = NULL;
	Slayer*       pSlayer       = NULL;
	Vampire*      pVampire      = NULL;
	Ousters*      pOusters      = NULL;
	int           storage       = 0;
	int           X             = 0;
	int           Y             = 0;
	GCNPCResponse response;

	// 플레이어가 슬레이어인지 뱀파이어인지 구분.
	if (pPC->isSlayer())       bSlayer = true;
	else if (pPC->isVampire()) bVampire = true;
	else if (pPC->isOusters()) bOusters = true;

	// 플레이어가 수리하려고 하는 아이템을 가지고 있는지 검사
	if (bSlayer)
	{
		pSlayer     = dynamic_cast<Slayer*>(pPC);
		playerMoney = pSlayer->getGold();
		pItem       = pSlayer->findItemOID(ITEMOID, storage, X, Y);
	}
	else if (bVampire)
	{
		pVampire    = dynamic_cast<Vampire*>(pPC);
		playerMoney = pVampire->getGold();
		pItem       = pVampire->findItemOID(ITEMOID, storage, X, Y);
	}
	else if (bOusters)
	{
		pOusters    = dynamic_cast<Ousters*>(pPC);
		playerMoney = pOusters->getGold();
		pItem       = pOusters->findItemOID(ITEMOID, storage, X, Y);
	}

	// 플레이어가 수리하려고 하는 아이템을 가지고 있는지 
	// 상위에서 검사를 하기 때문에, pItem이 널일리는 없다.
	// 단, 수리할 수 없는 아이템인지를 검사한다.
	if (isRepairableItem(pItem) == false)
	{
		response.setCode(NPC_RESPONSE_REPAIR_FAIL_ITEM_TYPE);
		pPlayer->sendPacket(&response);
		return;
	}

	// 이전 내구도를 저장한다.
	Durability_t oldDurability = pItem->getDurability();

	repairPrice = g_pPriceManager->getRepairPrice(pItem);

	if (repairPrice > playerMoney)
	{
		response.setCode(NPC_RESPONSE_REPAIR_FAIL_MONEY);
		pPlayer->sendPacket(&response);
		return;
	}

	// 수리한다.
	repairItem(pItem);

	// 수리한 아이템이 기어창의 아이템이고 이전 내구도가 0 이었다면 정보를 새로 보내줘야한다.
	if (storage == STORAGE_GEAR && oldDurability == 0 )
	{
		if (bSlayer && pSlayer != NULL )
		{
			pSlayer->initAllStatAndSend();
			pSlayer->sendRealWearingInfo();
		}
		else if (bVampire && pVampire != NULL )
		{
			pVampire->initAllStatAndSend();
			pVampire->sendRealWearingInfo();
		}
		else if (bOusters && pOusters != NULL )
		{
			pOusters->initAllStatAndSend();
			pOusters->sendRealWearingInfo();
		}
	}

	// 돈을 줄인다.
	if (bSlayer)
	{
		//pSlayer->setGoldEx(playerMoney-repairPrice);
		// by sigi. 2002.9.4
		pSlayer->decreaseGoldEx(repairPrice);
		//log(LOG_REPAIR_ITEM, pSlayer->getName(), "", pItem->toString());
	}
	else if (bVampire)
	{
		// by sigi. 2002.9.4
		pVampire->decreaseGoldEx(repairPrice);
		//log(LOG_REPAIR_ITEM, pVampire->getName(), "", pItem->toString());
	}
	else if (bOusters)
	{
		// by sigi. 2002.9.4
		pOusters->decreaseGoldEx(repairPrice);
		//log(LOG_REPAIR_ITEM, pOusters->getName(), "", pItem->toString());
	}

	// 아이템을 수리했다는 정보를 DB에다가 저장해준다.
	// 단 분명히 STORAGE_STASH가 돌아올 수 있지만, 
	// 보관함에 있는 것을 수리한다는 것은 말이 안 되므로,
	// 저장하지 않는다.


	// item저장 최적화. by sigi. 2002.5.17
	if (repairPrice>0)
	{
		char pField[80];

		if (pItem->getItemClass()==Item::ITEM_CLASS_SLAYER_PORTAL_ITEM)
		{
			SlayerPortalItem* pSPItem = dynamic_cast<SlayerPortalItem*>(pItem);
			sprintf(pField, "Charge=%d", pSPItem->getCharge());
		}
		else if (pItem->getItemClass()==Item::ITEM_CLASS_OUSTERS_SUMMON_ITEM)
		{
			OustersSummonItem* pOSItem = dynamic_cast<OustersSummonItem*>(pItem);
			sprintf(pField, "Charge=%d", pOSItem->getCharge());
		}
		else
		{
			sprintf(pField, "Durability=%d", pItem->getDurability());
		}

		pItem->tinysave(pField);
	}

	/*
	// 뭐가 됐든.. durability만 바꾸면 된다.
	// 근데.. ItemObject에 Durability field가 없는 것도 있고
	// Charge를 저장해야 하는 것도 있다.
	// 그래서.. 일단은 모두 다 저장하는 save를 이용하도록 한다.
	switch (storage)
	{
		case STORAGE_INVENTORY:
		{
			pItem->save(pPC->getName(), STORAGE_INVENTORY, 0, X, Y);
		}
		break;

		case STORAGE_GEAR:
		{
			if (bSlayer) 
			{
				pItem->save(pSlayer->getName(),  STORAGE_GEAR, 0, X, 0);
			}
			else         
			{
				pItem->save(pVampire->getName(), STORAGE_GEAR, 0, X, 0);
			}
		}
		break;

		default:
			break;
	}
	*/

	// OK 패킷을 날려준다.
	response.setCode(NPC_RESPONSE_REPAIR_OK);
	response.setParameter(playerMoney-repairPrice);
	pPlayer->sendPacket(&response);

#endif

	__END_DEBUG_EX __END_CATCH
}
//////////////////////////////////////////////////////////////////////////////
// 모든 아이템 수리하기
//////////////////////////////////////////////////////////////////////////////
void CGRequestRepairHandler::executeAll(CGRequestRepair* pPacket , Player* pPlayer)
	 throw(ProtocolException , Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

	Creature*     pPC         = dynamic_cast<GamePlayer*>(pPlayer)->getCreature();
	Price_t       repairPrice = 0;
	GCNPCResponse response;

	bool bSendRealWearingInfo = false;

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

		// 모든 아이템을 합한 수리비를 계산한다.
		for (int i=0; i<Slayer::WEAR_MAX; i++)
		{
			Item* pItem = pSlayer->getWearItem((Slayer::WearPart)i);
			if (pItem != NULL)
			{
				if (i == Slayer::WEAR_RIGHTHAND && isTwohandWeapon(pItem))
				{
					// 오른손이고, 현재 들고 있는 무기가 양손 무기라면...
					// 수리 가격에 포함시킬 필요가 없다.
				}
				else
				{
					repairPrice += g_pPriceManager->getRepairPrice(pItem);
				}
			}
		}

		// 돈이 모자라다면 리턴한다.
		if (pSlayer->getGold() < repairPrice)
		{
			response.setCode(NPC_RESPONSE_REPAIR_FAIL_MONEY);
			pPlayer->sendPacket(&response);
			return;
		}

		// 각각의 아이템을 수리하고, DB에 저장한다.
		char pField[80];

		for (int i=0; i<Slayer::WEAR_MAX; i++)
		{
			Item* pItem = pSlayer->getWearItem((Slayer::WearPart)i);
			if (pItem != NULL)
			{
				if (i == Slayer::WEAR_RIGHTHAND && isTwohandWeapon(pItem))
				{
					// 오른손이고, 현재 들고 있는 무기가 양손 무기라면...
					// 수리할 필요가 없다.
				}
				else if (isRepairableItem(pItem ) )
				{
					Durability_t oldDurability = pItem->getDurability();
					repairItem(pItem);
					if (pItem->getDurability() != oldDurability)
					{
						// DB 쿼리를 줄이기 위해서
						// 내구도의 변화가 생긴 경우에만 세이브한다.
						//pItem->save(pSlayer->getName(), STORAGE_GEAR, 0, i, 0);
						// item저장 최적화. by sigi. 2002.5.13
						sprintf(pField, "Durability=%d", pItem->getDurability());
						pItem->tinysave(pField);
					}

					if (oldDurability == 0 )
						bSendRealWearingInfo = true;
				}
			}
		}

		// 돈을 줄이고...
		//pSlayer->setGoldEx(pSlayer->getGold() - repairPrice);

		// by sigi.2002.9.4
		pSlayer->decreaseGoldEx(repairPrice);

		// 로그를 남긴다.
		//log(LOG_REPAIR_ITEM, pSlayer->getName(), "", "ALL");

		// OK 패킷을 날려준다.
		response.setCode(NPC_RESPONSE_REPAIR_OK);
		response.setParameter(pSlayer->getGold());
		pPlayer->sendPacket(&response);
	}
	else if (pPC->isVampire())
	{
		Vampire* pVampire = dynamic_cast<Vampire*>(pPC);

		// 모든 아이템을 합한 수리비를 계산한다.
		for (int i=0; i<Vampire::VAMPIRE_WEAR_MAX; i++)
		{
			Item* pItem = pVampire->getWearItem((Vampire::WearPart)i);
			if (pItem != NULL) 
			{
				if (i == Vampire::WEAR_RIGHTHAND && isTwohandWeapon(pItem))
				{
					// 양손무기는 한쪽만 수리한다.
				}
				else
				{
					repairPrice += g_pPriceManager->getRepairPrice(pItem);
				}
			}
		}

		// 돈이 모자라다면 리턴한다.
		if (pVampire->getGold() < repairPrice)
		{
			response.setCode(NPC_RESPONSE_REPAIR_FAIL_MONEY);
			pPlayer->sendPacket(&response);
			return;
		}
 
		// 각각의 아이템을 수리하고, DB에 저장한다.
		char pField[80];

		for (int i=0; i<Vampire::VAMPIRE_WEAR_MAX; i++)
		{
			Item* pItem = pVampire->getWearItem((Vampire::WearPart)i);
			if (pItem != NULL)
			{
				if (i == Vampire::WEAR_RIGHTHAND && isTwohandWeapon(pItem))
				{
					// 양손무기는 한쪽만 수리한다.
				}
				else
				{
					Durability_t oldDurability = pItem->getDurability();
					repairItem(pItem);
					if (pItem->getDurability() != oldDurability)
					{
						// DB 쿼리를 줄이기 위해서
						// 내구도의 변화가 생긴 경우에만 세이브한다.
						//pItem->save(pVampire->getName(), STORAGE_GEAR, 0, i, 0);
						// item저장 최적화. by sigi. 2002.5.13
						sprintf(pField, "Durability=%d", pItem->getDurability());
						pItem->tinysave(pField);

					}

					if (oldDurability == 0 )
						bSendRealWearingInfo = true;
				}
			}
		}

		// 돈을 줄이고...
		//pVampire->setGoldEx(pVampire->getGold() - repairPrice);
		// by sigi.2002.9.4
		pVampire->decreaseGoldEx(repairPrice);

		// 로그를 남긴다.
		//log(LOG_REPAIR_ITEM, pVampire->getName(), "", "ALL");

		// OK 패킷을 날려준다.
		response.setCode(NPC_RESPONSE_REPAIR_OK);
		response.setParameter(pVampire->getGold());
		pPlayer->sendPacket(&response);
	}
	else if (pPC->isOusters())
	{
		Ousters* pOusters = dynamic_cast<Ousters*>(pPC);

		// 모든 아이템을 합한 수리비를 계산한다.
		for (int i=0; i<Ousters::OUSTERS_WEAR_MAX; i++)
		{
			Item* pItem = pOusters->getWearItem((Ousters::WearPart)i);
			if (pItem != NULL) 
			{
				if (i == Ousters::WEAR_RIGHTHAND && isTwohandWeapon(pItem))
				{
					// 양손무기는 한쪽만 수리한다.
				}
				else
				{
					repairPrice += g_pPriceManager->getRepairPrice(pItem);
				}
			}
		}

		// 돈이 모자라다면 리턴한다.
		if (pOusters->getGold() < repairPrice)
		{
			response.setCode(NPC_RESPONSE_REPAIR_FAIL_MONEY);
			pPlayer->sendPacket(&response);
			return;
		}
 
		// 각각의 아이템을 수리하고, DB에 저장한다.
		char pField[80];

		for (int i=0; i<Ousters::OUSTERS_WEAR_MAX; i++)
		{
			Item* pItem = pOusters->getWearItem((Ousters::WearPart)i);
			if (pItem != NULL)
			{
				if (i == Ousters::WEAR_RIGHTHAND && isTwohandWeapon(pItem))
				{
					// 양손무기는 한쪽만 수리한다.
				}
				else
				{
					Durability_t oldDurability = pItem->getDurability();
					repairItem(pItem);
					if (pItem->getDurability() != oldDurability)
					{
						// DB 쿼리를 줄이기 위해서
						// 내구도의 변화가 생긴 경우에만 세이브한다.
						//pItem->save(pOusters->getName(), STORAGE_GEAR, 0, i, 0);
						// item저장 최적화. by sigi. 2002.5.13
						sprintf(pField, "Durability=%d", pItem->getDurability());
						pItem->tinysave(pField);
					}

					if (oldDurability == 0 )
						bSendRealWearingInfo = true;
				}
			}
		}

		// 돈을 줄이고...
		//pOusters->setGoldEx(pOusters->getGold() - repairPrice);
		// by sigi.2002.9.4
		pOusters->decreaseGoldEx(repairPrice);

		// 로그를 남긴다.
		//log(LOG_REPAIR_ITEM, pOusters->getName(), "", "ALL");

		// OK 패킷을 날려준다.
		response.setCode(NPC_RESPONSE_REPAIR_OK);
		response.setParameter(pOusters->getGold());
		pPlayer->sendPacket(&response);
	}

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

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

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

			pOusters->initAllStatAndSend();
			pOusters->sendRealWearingInfo();
		}
	}

#endif

	__END_DEBUG_EX __END_CATCH
}