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 ActionStashOpen::execute (Creature * pCreature1 , Creature * pCreature2) 
	throw(Error)
{
	__BEGIN_TRY 

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

	// 만일 플레이어가 아직 이 존에서 보관함에 관련된 OID를
	// 할당받지 않았다면 여기서 할당해 준다.
	if (pCreature2->isSlayer())
	{
		Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature2);
		if (!pSlayer->getStashStatus()) pSlayer->registerStash();
	}
	else if (pCreature2->isVampire())
	{
		Vampire* pVampire = dynamic_cast<Vampire*>(pCreature2);
		if (!pVampire->getStashStatus()) pVampire->registerStash();
	}
	else if (pCreature2->isOusters())
	{
		Ousters* pOusters = dynamic_cast<Ousters*>(pCreature2);
		if (!pOusters->getStashStatus()) pOusters->registerStash();
	}

	GCNPCResponse okpkt;
	okpkt.setCode(NPC_RESPONSE_INTERFACE_STASHOPEN);
	pCreature2->getPlayer()->sendPacket(&okpkt);

	__END_CATCH
}
Beispiel #3
0
void EffectComa::unaffect(Creature* pDeadCreature)
	throw(Error)
{
	__BEGIN_TRY

	Assert(pDeadCreature != NULL);
	//Assert(pDeadCreature->isDead());

	// 이펙트 플래그를 삭제해준다.
	pDeadCreature->removeFlag(Effect::EFFECT_CLASS_COMA);
	// 날아오면 강제로 죽이는 코드를 집어넣는다.
	if (pDeadCreature->isSlayer()) {
		Slayer* pSlayer = dynamic_cast<Slayer*>(pDeadCreature);
		pSlayer->setHP(0, ATTR_CURRENT);
	}
	else if (pDeadCreature->isVampire()) {
		Vampire* pVampire = dynamic_cast<Vampire*>(pDeadCreature);
		pVampire->setHP(0, ATTR_CURRENT);
	}
	else if (pDeadCreature->isOusters())
	{
		Ousters* pOusters = dynamic_cast<Ousters*>(pDeadCreature);
		pOusters->setHP(0, ATTR_CURRENT);
	}

	__END_CATCH
}
Beispiel #4
0
// Mysterious Item 가격
// itemClass와 pCreature의 능력치에 따라서 가격이 달라진다.
Price_t PriceManager::getMysteriousPrice(Item::ItemClass itemClass, Creature* pCreature) const
{
	int multiplier = 1;

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

		Attr_t CSTR = pSlayer->getSTR(ATTR_BASIC);
		Attr_t CDEX = pSlayer->getDEX(ATTR_BASIC);
		Attr_t CINT = pSlayer->getINT(ATTR_BASIC);
		Attr_t CSUM = CSTR + CDEX + CINT;

		// 0~20 사이
		multiplier = CSUM / 15;
	}
	else if (pCreature->isVampire())
	{
		Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);

		Level_t CLevel = pVampire->getLevel();

		// 0~20 사이
		multiplier = CLevel / 5;
	}
	else if (pCreature->isOusters())
	{
		Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);

		Level_t CLevel = pOusters->getLevel();

		// 0~20 사이
		multiplier = CLevel / 5;
	}

	// 1~20사이
	multiplier = max(1, multiplier);

	// 가격 평균을 알아온다.
	InfoClassManager* pInfoClass = g_pItemInfoManager->getInfoManager(itemClass);
	Assert(pInfoClass!=NULL);

	// 가격 평균 * 능력치 비율?
	int finalPrice = (int)pInfoClass->getAveragePrice() * multiplier;

	// Blood Bible 보너스 적용
	if (pCreature->isPC() )
	{
		PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature);
		int ratio = pPC->getGamblePriceRatio();
		if (ratio != 0 )
		{
			// ratio 값은 마이너스 값이다.
			finalPrice += getPercentValue(finalPrice, ratio);
		}
	}

	return finalPrice;
}
bool EventQuestLootingInfo::isTargetMonster(PlayerCreature* pPC, Monster* pMonster ) const
{
	if (pPC->getRace() == m_Race )
	{
		QuestID_t qID;
		if (!pPC->getQuestManager()->hasEventQuest(m_QuestLevel, qID ) ) return false;

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

			qGrade = pSlayer->getQuestGrade();
		}
		else if (pPC->isVampire() )
		{
			Vampire* pVampire = dynamic_cast<Vampire*>(pPC);

			qGrade = pVampire->getLevel();
		}
		else if (pPC->isOusters() )
		{
			Ousters* pOusters = dynamic_cast<Ousters*>(pPC);

			qGrade = pOusters->getLevel();
		}
		else
		{
			//cout << "³Í¹¹³Ä!" << endl;
			qGrade = 0;
		}

		if (qGrade < m_MinGrade || qGrade > m_MaxGrade ) return false;

		if (m_Type == LOOTING_ZONE || m_Type == LOOTING_BOTH )
		{
			if (pMonster->getZoneID() != m_LootingZoneID ) return false;
		}

		if (m_Type == LOOTING_MONSTER || m_Type == LOOTING_BOTH )
		{
			if (pMonster->getMonsterType() != m_LootingMonsterType ) return false;
		}

		return true;
	}
	else
	{
		return false;
	}
}
GQuestElement::ResultType GQuestAdvanceClassElement::checkCondition(PlayerCreature* pPC ) const
{
	if (pPC->getLevel() != 150 ) return FAIL;
	Exp_t advExp = 0;
	if (pPC->isSlayer() )
	{
		Slayer* pSlayer = dynamic_cast<Slayer*>(pPC);
		SkillDomainType_t domain = pSlayer->getHighestSkillDomain();
		DomainInfo* pDomainInfo = g_pSkillDomainInfoManager->getDomainInfo((SkillDomain)domain, pPC->getLevel());
		if (pDomainInfo == NULL ) return FAIL;
		Exp_t goalExp = pDomainInfo->getGoalExp();
		Exp_t currentExp = goalExp - pSlayer->getGoalExp(domain);

		advExp = (Exp_t)(currentExp * 0.0688933574);
	}
	else if (pPC->isVampire() )
	{
		Vampire* pVampire = dynamic_cast<Vampire*>(pPC);
		VampEXPInfo* pExpInfo = g_pVampEXPInfoManager->getVampEXPInfo(pVampire->getLevel());
		if (pExpInfo == NULL ) return FAIL;
		Exp_t goalExp = pExpInfo->getGoalExp();
		Exp_t currentExp = goalExp - pVampire->getGoalExp();

		advExp = currentExp / 100;
	}
	else if (pPC->isOusters() )
	{
		Ousters* pOusters = dynamic_cast<Ousters*>(pPC);
		OustersEXPInfo* pExpInfo = g_pOustersEXPInfoManager->getOustersEXPInfo(pOusters->getLevel());
		if (pExpInfo == NULL ) return FAIL;
		Exp_t goalExp = pExpInfo->getGoalExp();
		Exp_t currentExp = goalExp - pOusters->getGoalExp();

		advExp = currentExp / 100;
	}

	advExp = min((int)advExp, 18496191);
	// ÇϵåÄÚµù -_-
	pPC->increaseAdvancementClassExp(advExp, false);

	return OK;
}
void DynamicZoneSlayerMirrorOfAbyss::killPC()
{
	Assert(m_pZone != NULL);

    // PC 를 죽인다.
    map<ObjectID_t, Creature*>::const_iterator itr = m_pZone->getPCManager()->getCreatures().begin();
    map<ObjectID_t, Creature*>::const_iterator endItr = m_pZone->getPCManager()->getCreatures().end();

    for (; itr != endItr; ++itr )
    {
        Assert(itr->second != NULL);

        if (itr->second->isPC() )
        {
            PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(itr->second);
            Assert(pPC != NULL);

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

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

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

				pOusters->setHP(0);
			}
        }
    }
}
////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionSetResurrectZone::execute (Creature * pCreature1 , Creature * pCreature2) 
	throw(Error)
{
	__BEGIN_TRY

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

	// 일단 클라이언트를 위해서 OK 패킷을 함 날린다.
	GCNPCResponse okpkt;
	Player* pPlayer = pCreature2->getPlayer();
	Assert(pPlayer != NULL);
	pPlayer->sendPacket(&okpkt);

	if (pCreature2->isSlayer())
	{
		Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature2);
		pSlayer->setResurrectZoneIDEx(m_ZoneID);
	}
	else if (pCreature2->isVampire())
	{
		Vampire* pVampire = dynamic_cast<Vampire*>(pCreature2);
		pVampire->setResurrectZoneIDEx(m_ZoneID);
	}
	else if (pCreature2->isOusters())
	{
		Ousters* pOusters = dynamic_cast<Ousters*>(pCreature2);
		pOusters->setResurrectZoneIDEx(m_ZoneID);
	}

	GCSystemMessage msg;
	msg.setMessage(g_pStringPool->getString(STRID_SET_RESURRECTION_POSITION ));
	pPlayer->sendPacket(&msg);

	__END_CATCH
}
Beispiel #9
0
void EffectEvade::unaffect(Creature* pCreature)
	throw(Error)
{
	__BEGIN_TRY

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

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

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

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

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

	OUSTERS_RECORD prev;

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

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

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

	__END_CATCH
}
Beispiel #10
0
void EffectDecreaseHP::unaffect(Creature* pCreature)
	throw(Error)
{
	__BEGIN_TRY
	__BEGIN_DEBUG

	Assert(pCreature != NULL);

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

	pCreature->removeFlag(Effect::EFFECT_CLASS_DECREASE_HP);

	Damage_t decreaseHP = m_Point;

	if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE)
		&& !pCreature->isDead()
		&& !pCreature->isFlag(Effect::EFFECT_CLASS_COMA)
		// 무적상태 체크. by sigi. 2002.9.5
		&& canAttack(NULL, pCreature )
	   )
	{
		if (pCreature->isSlayer())
		{
			Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature);

			HP_t CurrentHP = pSlayer->getHP(ATTR_CURRENT);

			if (CurrentHP > 0)
			{
				HP_t RemainHP  = max(0, CurrentHP -(int)decreaseHP);

				pSlayer->setHP(RemainHP, ATTR_CURRENT);

				GCModifyInformation gcMI;
				gcMI.addShortData(MODIFY_CURRENT_HP, RemainHP);
				pSlayer->getPlayer()->sendPacket(&gcMI);

				// 변한 HP를 브로드캐스팅해준다.
				GCStatusCurrentHP pkt;
				pkt.setObjectID(pSlayer->getObjectID());
				pkt.setCurrentHP(RemainHP);
				pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &pkt);
			}
		}
		else if (pCreature->isVampire())
		{
			Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);

			HP_t CurrentHP = pVampire->getHP(ATTR_CURRENT);

			if (CurrentHP > 0)
			{
				HP_t RemainHP  = max(0, CurrentHP -(int)decreaseHP);

				pVampire->setHP(RemainHP, ATTR_CURRENT);

				GCModifyInformation gcMI;
				gcMI.addShortData(MODIFY_CURRENT_HP, RemainHP);
				pVampire->getPlayer()->sendPacket(&gcMI);

				// 공격(흡혈) 당하는 경우에는 공격자의 성향이 바뀜 by sigi. 2002.12.27
				Creature* pAttacker = pZone->getCreature(m_UserObjectID);
				if (pAttacker!=NULL && pAttacker->isVampire())
				{
					Vampire* pAttackVampire = dynamic_cast<Vampire*>(pAttacker);

					GCModifyInformation gcAttackerMI;
					computeAlignmentChange(pVampire, decreaseHP, pAttackVampire, NULL, &gcAttackerMI);

					// 뭔가 변한 정보가 있다면 보내준다.
					if (gcAttackerMI.getShortCount()+gcAttackerMI.getLongCount() > 0)
					{
						pAttackVampire->getPlayer()->sendPacket(&gcAttackerMI);
					}
				}

				// 변한 HP를 브로드캐스팅해준다.
				GCStatusCurrentHP pkt;
				pkt.setObjectID(pVampire->getObjectID());
				pkt.setCurrentHP(RemainHP);
				pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &pkt);
			}
		}
		else if (pCreature->isOusters())
		{
			Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);

			HP_t CurrentHP = pOusters->getHP(ATTR_CURRENT);

			if (CurrentHP > 0)
			{
				HP_t RemainHP  = max(0, CurrentHP -(int)decreaseHP);

				pOusters->setHP(RemainHP, ATTR_CURRENT);

				GCModifyInformation gcMI;
				gcMI.addShortData(MODIFY_CURRENT_HP, RemainHP);
				pOusters->getPlayer()->sendPacket(&gcMI);

				// 공격(흡혈) 당하는 경우에는 공격자의 성향이 바뀜 by sigi. 2002.12.27
				Creature* pAttacker = pZone->getCreature(m_UserObjectID);
				if (pAttacker!=NULL && pAttacker->isOusters())
				{
					Ousters* pAttackOusters = dynamic_cast<Ousters*>(pAttacker);

					GCModifyInformation gcAttackerMI;
					computeAlignmentChange(pOusters, decreaseHP, pAttackOusters, NULL, &gcAttackerMI);

					// 뭔가 변한 정보가 있다면 보내준다.
					if (gcAttackerMI.getShortCount()+gcAttackerMI.getLongCount() > 0)
					{
						pAttackOusters->getPlayer()->sendPacket(&gcAttackerMI);
					}
				}

				// 변한 HP를 브로드캐스팅해준다.
				GCStatusCurrentHP pkt;
				pkt.setObjectID(pOusters->getObjectID());
				pkt.setCurrentHP(RemainHP);
				pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &pkt);
			}
		}
		else if (pCreature->isMonster())
		{
			Monster* pMonster = dynamic_cast<Monster*>(pCreature);

			HP_t CurrentHP = pMonster->getHP(ATTR_CURRENT);

			if (CurrentHP > 0)
			{
				HP_t RemainHP  = max(0, CurrentHP -(int)decreaseHP);

				pMonster->setHP(RemainHP, ATTR_CURRENT);

				// 변한 HP를 브로드캐스팅해준다.
				GCStatusCurrentHP pkt;
				pkt.setObjectID(pMonster->getObjectID());
				pkt.setCurrentHP(RemainHP);
				pZone->broadcastPacket(pMonster->getX(), pMonster->getY(), &pkt);

				if (RemainHP == 0 )
				{
					Creature* pAttacker = pZone->getCreature(m_UserObjectID);
					if (pAttacker != NULL && pAttacker->isVampire() )
					{
						Vampire* pAttackVampire = dynamic_cast<Vampire*>(pAttacker);

						GCModifyInformation gcMI;
						increaseAlignment(pAttackVampire, pCreature, gcMI);

						if (gcMI.getShortCount() > 0 || gcMI.getLongCount() > 0 )
							pAttackVampire->getPlayer()->sendPacket(&gcMI);
					}
				}
			}
		}


		// m_CasterName이 pCreature를 죽인 경우의 KillCount 처리
		// by sigi. 2002.9.9
		if (pCreature->isDead())
		{
			Creature* pAttacker = pZone->getCreature(m_UserObjectID);

			if (pAttacker!=NULL)
			{ 
				if (pAttacker->isVampire())
				{
					Vampire* pVampire = dynamic_cast<Vampire*>(pAttacker);
					// 죽일때 경험치를 준다.
					GCModifyInformation mi;

					int exp = computeCreatureExp(pCreature, KILL_EXP);
					shareVampExp(pVampire, exp, mi);

					if (pCreature->isMonster() )
					{
						increaseFame(pVampire, decreaseHP);
						mi.addLongData(MODIFY_FAME, pVampire->getFame());
					}

					pAttacker->getPlayer()->sendPacket(&mi);
				}
				else if (pAttacker->isOusters() )
				{
					Ousters* pOusters = dynamic_cast<Ousters*>(pAttacker);
					GCModifyInformation mi;
					int exp = computeCreatureExp(pCreature, 100);
					shareOustersExp(pOusters, exp, mi);

					if (pCreature->isMonster() )
					{
						increaseFame(pOusters, decreaseHP);
						mi.addLongData(MODIFY_FAME, pOusters->getFame());
					}
				}

				affectKillCount(pAttacker, pCreature);
			}
		}
	}

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

#ifdef __GAME_SERVER__

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

			pOusters->sendRealWearingInfo();
		}
	}

#endif

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

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

	Timeval CurrentTime;
	getCurrentTime(CurrentTime);

	GCModifyInformation gcModifyInformation;

	Alignment_t CurrentAlignment = 0;
	Alignment_t NewAlignment = 0;

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

		if (m_Period != 0) 
		{
			// 플레그 걸귀
			pSlayer->setFlag(Effect::EFFECT_CLASS_ALIGNMENT_RECOVERY);

			// 한 턴에 얼마나 회복 시킬 것인가.
			CurrentAlignment = pSlayer->getAlignment();
			NewAlignment     = min(10000, (int)(CurrentAlignment + m_AlignmentQuantity));

			pSlayer->setAlignment(NewAlignment);

			gcModifyInformation.addLongData(MODIFY_ALIGNMENT, NewAlignment);
			pSlayer->getPlayer()->sendPacket(&gcModifyInformation);

			WORD AlignmentSaveCount = pSlayer->getAlignmentSaveCount();
			if (AlignmentSaveCount > ALIGNMENT_SAVE_PERIOD)
			{
				StringStream msg;
				msg << "Alignment = " << NewAlignment;
				pSlayer->tinysave(msg.toString());
				AlignmentSaveCount = 0;
			}
			else AlignmentSaveCount++;
			pSlayer->setAlignmentSaveCount(AlignmentSaveCount);
		} 
		else 
		{
			// unaffect하면서 패킷이 날아갈 테니까....
			setDeadline(0);
		}

		m_Period--;
	}
	else if (pCreature->isVampire())
	{

		Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);
		Assert(pVampire != NULL);

		if (m_Period != 0) 
		{
			// 플레그 걸귀
			pVampire->setFlag(Effect::EFFECT_CLASS_ALIGNMENT_RECOVERY);

			// 한 턴에 얼마나 회복 시킬 것인가.
			CurrentAlignment = pVampire->getAlignment();
			NewAlignment     = min(10000, CurrentAlignment + m_AlignmentQuantity);

			pVampire->setAlignment(NewAlignment);

			gcModifyInformation.addLongData(MODIFY_ALIGNMENT, NewAlignment);
			pVampire->getPlayer()->sendPacket(&gcModifyInformation);

			WORD AlignmentSaveCount = pVampire->getAlignmentSaveCount();
			if (AlignmentSaveCount > ALIGNMENT_SAVE_PERIOD)
			{
				StringStream msg;
				msg << "Alignment = " << NewAlignment;
				pVampire->tinysave(msg.toString());
				AlignmentSaveCount = 0;
			}
			else AlignmentSaveCount++;
			pVampire->setAlignmentSaveCount(AlignmentSaveCount);
		} 
		else
		{
			// unaffect하면서 패킷이 날아갈 테니까....
			setDeadline(0);
		}

		m_Period--;
	}
	else if (pCreature->isOusters())
	{

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

		if (m_Period != 0) 
		{
			// 플레그 걸귀
			pOusters->setFlag(Effect::EFFECT_CLASS_ALIGNMENT_RECOVERY);

			// 한 턴에 얼마나 회복 시킬 것인가.
			CurrentAlignment = pOusters->getAlignment();
			NewAlignment     = min(10000, CurrentAlignment + m_AlignmentQuantity);

			pOusters->setAlignment(NewAlignment);

			gcModifyInformation.addLongData(MODIFY_ALIGNMENT, NewAlignment);
			pOusters->getPlayer()->sendPacket(&gcModifyInformation);

			WORD AlignmentSaveCount = pOusters->getAlignmentSaveCount();
			if (AlignmentSaveCount > ALIGNMENT_SAVE_PERIOD)
			{
				StringStream msg;
				msg << "Alignment = " << NewAlignment;
				pOusters->tinysave(msg.toString());
				AlignmentSaveCount = 0;
			}
			else AlignmentSaveCount++;
			pOusters->setAlignmentSaveCount(AlignmentSaveCount);
		} 
		else
		{
			// unaffect하면서 패킷이 날아갈 테니까....
			setDeadline(0);
		}

		m_Period--;
	}
	else
	{
		return;	// 큰 의미는 없지만..
	}

	// 성향 단계가 바뀌면 다른 사람들에게도 알려줘야 한다.  by sigi. 2002.12.28

	Alignment beforeAlignment = g_pAlignmentManager->getAlignmentType(CurrentAlignment);
	Alignment afterAlignment = g_pAlignmentManager->getAlignmentType(NewAlignment);

	if (beforeAlignment!=afterAlignment)
	{
		GCOtherModifyInfo gcOtherModifyInfo;
		gcOtherModifyInfo.setObjectID(pCreature->getObjectID());
		gcOtherModifyInfo.addShortData(MODIFY_ALIGNMENT, NewAlignment);

		Zone* pZone = pCreature->getZone();	// 2003.1.10
		Assert(pZone!=NULL);
		
		pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcOtherModifyInfo, pCreature);
	}

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

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

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

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

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

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

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

			HitBonus = pRankBonus->getPoint();
		}

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

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

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

        	bool bCanSeeCaster = canSee(pTargetCreature, pVampire);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#ifdef __GAME_SERVER__

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

	GamePlayer*    pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer);
	Creature*      pCreature   = pGamePlayer->getCreature();
	bool           Success     = false;

	if (pCreature->isSlayer())
	{
		Slayer*        pSlayer    = dynamic_cast<Slayer*>(pCreature);
		InventorySlot* pExtraSlot = pSlayer->getExtraInventorySlot();
		Item*          pItem      = pExtraSlot->getItem();

		if (pItem == NULL)
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		ObjectID_t      ItemObjectID = pItem->getObjectID();
		SlotID_t        SlotID       = pPacket->getSlotID();
		Item::ItemClass IClass       = pItem->getItemClass();

		// 아이템의 ObjectID가 일치하는지 체크한다.
		if (ItemObjectID != pPacket->getObjectID()) 
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		// 벨트를 입고 있지 않다면 벨트에다 아이템을 더할 수가 없다.
		if (!pSlayer->isWear(Slayer::WEAR_BELT))
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		// 포션도 아니고, 탄창도 아니라면 더할 수가 없지.
		if (IClass != Item::ITEM_CLASS_POTION && IClass != Item::ITEM_CLASS_MAGAZINE && IClass != Item::ITEM_CLASS_EVENT_ETC && IClass != Item::ITEM_CLASS_KEY)
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}
		if (IClass == Item::ITEM_CLASS_EVENT_ETC && pItem->getItemType() < 14 )
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		Item*      pBelt          = pSlayer->getWearItem(Slayer::WEAR_BELT);
		Inventory* pBeltInventory = ((Belt*)pBelt)->getInventory();

		if (pBeltInventory->canAdding(SlotID, 0,  pItem)) 
		{
			// 현재 벨트에 있는 Item을 받아온다.
			Item* pPrevItem = pBeltInventory->getItem(SlotID, 0);

			// 지정한 자리에 아이템이 있다면...
			if (pPrevItem != NULL)
			{
				// 아이템이 완전히 같은 아이템이라면...
				if (isStackable(pItem) && isSameItem(pItem, pPrevItem))
				{
					int MaxStack = ItemMaxStack[pItem->getItemClass()];

					if (pItem->getNum() + pPrevItem->getNum() > MaxStack) 
					{
						ItemNum_t CurrentNum = pPrevItem->getNum();
						ItemNum_t AddNum     = pItem->getNum();
						ItemNum_t NewNum	 = AddNum + CurrentNum - MaxStack;

						pPrevItem->setNum(MaxStack);
						pItem->setNum(NewNum);
						pBeltInventory->increaseNum(MaxStack - CurrentNum);
						pBeltInventory->increaseWeight(pItem->getWeight()* (MaxStack - CurrentNum));
						//pPrevItem->save(pSlayer->getName(), STORAGE_BELT, pBelt->getItemID(), SlotID, 0);
						// item저장 최적화. by sigi. 2002.5.13
						char pField[80];
						sprintf(pField, "Num=%d, Storage=%d, StorageID=%lu, X=%d", MaxStack, STORAGE_BELT, pBelt->getItemID(), SlotID);
						pPrevItem->tinysave(pField);

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


						Success = true;
					} 
					else // 숫자가 9개를 넘지 않을 때.
					{
						pSlayer->deleteItemFromExtraInventorySlot();
						pPrevItem->setNum(pPrevItem->getNum() + pItem->getNum());
						pBeltInventory->increaseNum(pItem->getNum());
						pBeltInventory->increaseWeight(pItem->getWeight()* pItem->getNum());
						//pPrevItem->save(pSlayer->getName(), STORAGE_BELT , pBelt->getItemID(), SlotID, 0);
						// item저장 최적화. by sigi. 2002.5.13
						char pField[80];
						sprintf(pField, "Num=%d, Storage=%d, StorageID=%lu, X=%d", pPrevItem->getNum(), STORAGE_BELT, pBelt->getItemID(), SlotID);
						pPrevItem->tinysave(pField);

						pItem->destroy();
						SAFE_DELETE(pItem);
						Success = true;
					}
				} 
				else // 클래스랑 타입이 같지 않을때
				{
					// 마우스에 달려있는 아이템과 벨트에 있는 아이템을 제거한다.
					pSlayer->deleteItemFromExtraInventorySlot();
					pBeltInventory->deleteItem(pPrevItem->getObjectID());

					// 둘의 위치를 바꿔 준다.
					pSlayer->addItemToExtraInventorySlot(pPrevItem);
					pBeltInventory->addItem(SlotID , 0 , pItem);

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

					//pItem->save(pSlayer->getName(), STORAGE_BELT , pBelt->getItemID(), SlotID, 0);
					// item저장 최적화. by sigi. 2002.5.13
					sprintf(pField, "Storage=%d, StorageID=%lu, X=%d", STORAGE_BELT, pBelt->getItemID(), SlotID);
					pItem->tinysave(pField);


					Success = true;
				}
			} 
			else // 슬랏에 아무런 기존의 아이템이 없을때.
			{
				// Inventory에 특정 아이템을 넣는다.
				pBeltInventory->addItem(SlotID, 0 , pItem);

				// 넣기에 성공하면 마우스에 달려있는 아이템을 없앤다.
				pSlayer->deleteItemFromExtraInventorySlot();
				//pItem->save(pSlayer->getName(), STORAGE_BELT, pBelt->getItemID(), SlotID, 0);
				// item저장 최적화. by sigi. 2002.5.13
				char pField[80];
				sprintf(pField, "Storage=%d, StorageID=%lu, X=%d", STORAGE_BELT, pBelt->getItemID(), SlotID);
				pItem->tinysave(pField);

				Success = true;
			}
		} // end of if (pBeltInventory->canAdding(SlotID, 0,  pItem)) 
	} // if (pCreature->isSlayer())
	else if (pCreature->isOusters())
	{
		Ousters*        pOusters  = dynamic_cast<Ousters*>(pCreature);
		InventorySlot* pExtraSlot = pOusters->getExtraInventorySlot();
		Item*          pItem      = pExtraSlot->getItem();

		if (pItem == NULL)
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		ObjectID_t      ItemObjectID = pItem->getObjectID();
		SlotID_t        SlotID       = pPacket->getSlotID();
		Item::ItemClass IClass       = pItem->getItemClass();

		// 아이템의 ObjectID가 일치하는지 체크한다.
		if (ItemObjectID != pPacket->getObjectID()) 
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		Ousters::WearPart part = (SlotID > 2 ? Ousters::WEAR_ARMSBAND2 : Ousters::WEAR_ARMSBAND1);
		if (SlotID > 2 ) SlotID -= 3;

		// 해당 암스밴드가 없다
		if (!pOusters->isWear(part)) 
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		// 푸파도 아니고, 콤포스메이도 아니라면 더할 수가 없지.
		if (IClass != Item::ITEM_CLASS_PUPA && IClass != Item::ITEM_CLASS_COMPOS_MEI && IClass != Item::ITEM_CLASS_EVENT_ETC )
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		if (IClass == Item::ITEM_CLASS_EVENT_ETC && pItem->getItemType() < 14 )
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
			return;
		}

		Item*      pArmsband          = pOusters->getWearItem(part);
		Inventory* pArmsbandInventory = ((OustersArmsband*)pArmsband)->getInventory();

		if (pArmsbandInventory->canAdding(SlotID, 0,  pItem)) 
		{
			// 현재 벨트에 있는 Item을 받아온다.
			Item* pPrevItem = pArmsbandInventory->getItem(SlotID, 0);

			// 지정한 자리에 아이템이 있다면...
			if (pPrevItem != NULL)
			{
				// 아이템이 완전히 같은 아이템이라면...
				if (isSameItem(pItem, pPrevItem))
				{
					int MaxStack = ItemMaxStack[pItem->getItemClass()];

					if (pItem->getNum() + pPrevItem->getNum() > MaxStack) 
					{
						ItemNum_t CurrentNum = pPrevItem->getNum();
						ItemNum_t AddNum     = pItem->getNum();
						ItemNum_t NewNum	 = AddNum + CurrentNum - MaxStack;

						pPrevItem->setNum(MaxStack);
						pItem->setNum(NewNum);
						pArmsbandInventory->increaseNum(MaxStack - CurrentNum);
						pArmsbandInventory->increaseWeight(pItem->getWeight()* (MaxStack - CurrentNum));
						//pPrevItem->save(pOusters->getName(), STORAGE_BELT, pArmsband->getItemID(), SlotID, 0);
						// item저장 최적화. by sigi. 2002.5.13
						char pField[80];
						sprintf(pField, "Num=%d, Storage=%d, StorageID=%lu, X=%d", MaxStack, STORAGE_BELT, pArmsband->getItemID(), SlotID);
						pPrevItem->tinysave(pField);

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


						Success = true;
					} 
					else // 숫자가 9개를 넘지 않을 때.
					{
						pOusters->deleteItemFromExtraInventorySlot();
						pPrevItem->setNum(pPrevItem->getNum() + pItem->getNum());
						pArmsbandInventory->increaseNum(pItem->getNum());
						pArmsbandInventory->increaseWeight(pItem->getWeight()* pItem->getNum());
						//pPrevItem->save(pOusters->getName(), STORAGE_BELT , pArmsband->getItemID(), SlotID, 0);
						// item저장 최적화. by sigi. 2002.5.13
						char pField[80];
						sprintf(pField, "Num=%d, Storage=%d, StorageID=%lu, X=%d", pPrevItem->getNum(), STORAGE_BELT, pArmsband->getItemID(), SlotID);
						pPrevItem->tinysave(pField);

						pItem->destroy();
						SAFE_DELETE(pItem);
						Success = true;
					}
				} 
				else // 클래스랑 타입이 같지 않을때
				{
					// 마우스에 달려있는 아이템과 벨트에 있는 아이템을 제거한다.
					pOusters->deleteItemFromExtraInventorySlot();
					pArmsbandInventory->deleteItem(pPrevItem->getObjectID());

					// 둘의 위치를 바꿔 준다.
					pOusters->addItemToExtraInventorySlot(pPrevItem);
					pArmsbandInventory->addItem(SlotID , 0 , pItem);

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

					//pItem->save(pOusters->getName(), STORAGE_BELT , pArmsband->getItemID(), SlotID, 0);
					// item저장 최적화. by sigi. 2002.5.13
					sprintf(pField, "Storage=%d, StorageID=%lu, X=%d", STORAGE_BELT, pArmsband->getItemID(), SlotID);
					pItem->tinysave(pField);


					Success = true;
				}
			} 
			else // 슬랏에 아무런 기존의 아이템이 없을때.
			{
				// Inventory에 특정 아이템을 넣는다.
				pArmsbandInventory->addItem(SlotID, 0 , pItem);

				// 넣기에 성공하면 마우스에 달려있는 아이템을 없앤다.
				pOusters->deleteItemFromExtraInventorySlot();
				//pItem->save(pOusters->getName(), STORAGE_BELT, pArmsband->getItemID(), SlotID, 0);
				// item저장 최적화. by sigi. 2002.5.13
				char pField[80];
				sprintf(pField, "Storage=%d, StorageID=%lu, X=%d", STORAGE_BELT, pArmsband->getItemID(), SlotID);
				pItem->tinysave(pField);

				Success = true;
			}
		} // end of if (pArmsbandInventory->canAdding(SlotID, 0,  pItem)) 
	} // if (pCreature->isOusters())

	// QuickSlot에 넣는 것을 실패 하였을때 실패 패킷을 날린다.
	if (!Success) 
	{
		GCCannotAdd _GCCannotAdd;
		_GCCannotAdd.setObjectID(pPacket->getObjectID());
		pPlayer->sendPacket(&_GCCannotAdd);
	}

#endif	// __GAME_SERVER__

    __END_DEBUG_EX __END_CATCH

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

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

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

		if (m_Period != 0) 
		{
			// 한 턴에 얼마나 회복 시킬 것인가.
			Alignment_t CurrentAlignment = pSlayer->getAlignment();
			Alignment_t NewAlignment     = min(10000, (int)(CurrentAlignment + m_AlignmentQuantity* m_Period));

			pSlayer->setAlignment(NewAlignment);

			WORD AlignmentSaveCount = pSlayer->getAlignmentSaveCount();
			if (AlignmentSaveCount == 10)
			{
				StringStream msg;
				msg << "Alignment = " << NewAlignment;
				pSlayer->tinysave(msg.toString());

				AlignmentSaveCount = 0;
			}
			else AlignmentSaveCount++;
			pSlayer->setAlignmentSaveCount(AlignmentSaveCount);
		} 

		// 현재 Alignment를 브로드캐스팅한다.
		// 이제 회복이 끝났나는 것을 알리도록 한다.
		// 자신에게 먼저
		GCModifyInformation gcModifyInformation;
		gcModifyInformation.addLongData(MODIFY_ALIGNMENT, pSlayer->getAlignment());
		pSlayer->getPlayer()->sendPacket(&gcModifyInformation);

		// 주변사람에게도 무언가를 날려줘야 한다.
		// 패킷을 새로 만들어야겠지..
		pSlayer->removeFlag(Effect::EFFECT_CLASS_ALIGNMENT_RECOVERY);
	}
	else if (pCreature->isVampire())
	{
		Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);

		//Zone* pZone = pVampire->getZone();

		if (m_Period != 0) 
		{
			// 한 턴에 얼마나 회복 시킬 것인가.
			Alignment_t CurrentAlignment = pVampire->getAlignment();
			Alignment_t NewAlignment     = min(10000, (int)(CurrentAlignment + m_AlignmentQuantity* m_Period));

			WORD AlignmentSaveCount = pVampire->getAlignmentSaveCount();
			if (AlignmentSaveCount == 10)
			{
				StringStream msg;
				msg << "Alignment = " << NewAlignment;
				pVampire->tinysave(msg.toString());

				AlignmentSaveCount = 0;
			}
			else AlignmentSaveCount++;
			pVampire->setAlignmentSaveCount(AlignmentSaveCount);
		} 

		// 현재 Alignment를 브로드캐스팅한다.
		// 이제 회복이 끝났나는 것을 알리도록 한다.
		// 자신에게 먼저
		GCModifyInformation gcModifyInformation;
		gcModifyInformation.addLongData(MODIFY_ALIGNMENT, pVampire->getAlignment());
		pVampire->getPlayer()->sendPacket(&gcModifyInformation);

		// 주변사람에게도..
		pVampire->removeFlag(Effect::EFFECT_CLASS_ALIGNMENT_RECOVERY);
	}
	else if (pCreature->isOusters())
	{
		Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);

		//Zone* pZone = pOusters->getZone();

		if (m_Period != 0) 
		{
			// 한 턴에 얼마나 회복 시킬 것인가.
			Alignment_t CurrentAlignment = pOusters->getAlignment();
			Alignment_t NewAlignment     = min(10000, (int)(CurrentAlignment + m_AlignmentQuantity* m_Period));

			WORD AlignmentSaveCount = pOusters->getAlignmentSaveCount();
			if (AlignmentSaveCount == 10)
			{
				StringStream msg;
				msg << "Alignment = " << NewAlignment;
				pOusters->tinysave(msg.toString());

				AlignmentSaveCount = 0;
			}
			else AlignmentSaveCount++;
			pOusters->setAlignmentSaveCount(AlignmentSaveCount);
		} 

		// 현재 Alignment를 브로드캐스팅한다.
		// 이제 회복이 끝났나는 것을 알리도록 한다.
		// 자신에게 먼저
		GCModifyInformation gcModifyInformation;
		gcModifyInformation.addLongData(MODIFY_ALIGNMENT, pOusters->getAlignment());
		pOusters->getPlayer()->sendPacket(&gcModifyInformation);

		// 주변사람에게도..
		pOusters->removeFlag(Effect::EFFECT_CLASS_ALIGNMENT_RECOVERY);
	}

	__END_CATCH
}
Beispiel #16
0
void EffectPoison::affect(Creature* pCreature)
	throw(Error)
{
	__BEGIN_TRY

	//cout << "EffectPoison " << "begin" << endl;

	Assert(pCreature != NULL);

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

	// 스킬 사용자를 가져온다.
	// !! 이미 존을 나갔을 수 있으므로 NULL이 될 수 있다.
	// by bezz. 2003.1.4
	Creature* pCastCreature = pZone->getCreature(m_UserObjectID);

	// EffectPoison이 크리쳐에게 걸리게 되는 경우에는 현재로서는 
	// GreenPoison에 의해 타일 위에 생긴 
	// EffectGreenPoison 위를 플레이어가 지나갈 때 뿐이다.
	// EffectGreenPoison 내부에서 저항을 고려해서 데미지를 세팅한 다음
	// EffectPoison을 붙이므로, 내부에서 한번 더 계산하면 안된다.
	//Damage_t PoisonDamage = computeMagicDamage(pCreature, m_Point, MAGIC_DOMAIN_POISON, m_Level);
	Damage_t PoisonDamage = m_Point;

	if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE)
		// 무적상태 체크. by sigi. 2002.9.5
		&& canAttack(pCastCreature, pCreature )
		)
	{
		if (pCreature->isSlayer())
		{
			Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature);

			GCModifyInformation gcMI;
			::setDamage(pSlayer, PoisonDamage, pCastCreature, SKILL_GREEN_POISON, &gcMI);
			pSlayer->getPlayer()->sendPacket(&gcMI);
		}
		else if (pCreature->isVampire())
		{
			Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);

			GCModifyInformation gcMI;
			::setDamage(pVampire, PoisonDamage, pCastCreature, SKILL_GREEN_POISON, &gcMI);
			pVampire->getPlayer()->sendPacket(&gcMI);
		}
		else if (pCreature->isOusters())
		{
			Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);

			GCModifyInformation gcMI;
			::setDamage(pOusters, PoisonDamage, pCastCreature, SKILL_GREEN_POISON, &gcMI);
			pOusters->getPlayer()->sendPacket(&gcMI);
		}
		else if (pCreature->isMonster())
		{
			Monster* pMonster = dynamic_cast<Monster*>(pCreature);

			::setDamage(pMonster, PoisonDamage, pCastCreature, SKILL_GREEN_POISON);
		}

		// m_CasterName이 pCreature를 죽인 경우의 KillCount 처리
		// by sigi. 2002.9.9
/*		if (pCreature->isDead())
		{
			Creature* pAttacker = pZone->getCreature(m_UserObjectID);

			if (pAttacker!=NULL)
			{ 
				affectKillCount(pAttacker, pCreature);
			}
		}*/
	}
	
	setNextTime(m_Tick);

	//cout << "EffectPoison " << "end" << endl;

	__END_CATCH
}
Beispiel #17
0
bool BloodDrain::executeMonster(Monster* pMonster, Creature* pEnemy)
	throw(Error)
{
	__BEGIN_TRY

	bool isMaster    = pMonster->isMaster()
#ifdef __UNDERWORLD__
	|| pMonster->isUnderworld() || pMonster->getMonsterType() == 599
#endif
	;

	// 죽었으면 흡혈 못하고..
	// 마스터는 아무나 다 빤다 - -;
	// 대상이 죽었으면 못 빤다.
	if (pMonster->isDead()
		|| pMonster->isFlag(Effect::EFFECT_CLASS_COMA)
		|| !pMonster->isEnemyToAttack(pEnemy) && !isMaster
		|| pEnemy->isDead() || pEnemy->isFlag(Effect::EFFECT_CLASS_COMA))
	{
		return false;
	}

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

	GCBloodDrainOK1 _GCBloodDrainOK1;
	GCBloodDrainOK2 _GCBloodDrainOK2;
	GCBloodDrainOK3 _GCBloodDrainOK3;

	// 마스터는 체력 100% 라도 문다.
	int HPMultiplier = (isMaster? 1 : 3);	// 현재 HP가 1/1,  1/3
	bool bHitRoll    = HitRoll::isSuccessBloodDrain(pMonster, pEnemy, HPMultiplier);
	bool bCanHit     = canHit(pMonster, pEnemy, SKILL_BLOOD_DRAIN);
	// 마스터는 거리에 관계없이 문다~
	bool bRangeCheck = isMaster || verifyDistance(pMonster, pEnemy, 1);

	// 흡혈 면역 상태. by sigi. 2002.9.13
	bool bEffected = pEnemy->isFlag(Effect::EFFECT_CLASS_IMMUNE_TO_BLOOD_DRAIN);

	if (bHitRoll && bCanHit && bRangeCheck && !bEffected)
	{
		if (pEnemy->isSlayer())
		{
			// Set EffectBloodDrain
			// 마스터면 안건다.
			if (!isMaster)
			{
				EffectBloodDrain* pEffectBloodDrain = new EffectBloodDrain(pEnemy);
				pEffectBloodDrain->setLevel(pMonster->getLevel());
				pEffectBloodDrain->setDeadline(BLOODDRAIN_DURATION);	// 게임시간으로 3일 정도
				pEnemy->addEffect(pEffectBloodDrain);
				pEffectBloodDrain->create(pEnemy->getName());
				_GCBloodDrainOK2.addShortData(MODIFY_EFFECT_STAT, Effect::EFFECT_CLASS_BLOOD_DRAIN);

				pEnemy->setFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN);

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

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


		_GCBloodDrainOK3.setObjectID(pMonster->getObjectID());
		_GCBloodDrainOK3.setTargetObjectID (pEnemy->getObjectID());

		// 타겟이 뭐든 플래그는 건다.
		// 마스터면 안건다.
		if (!isMaster)
		{
			pEnemy->setFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN);
		}

		if (pEnemy != NULL && pEnemy->isPC()) 
		{
			Player* pTargetPlayer = pEnemy->getPlayer();
			if (pTargetPlayer != NULL) 
			{ 
				_GCBloodDrainOK2.setObjectID(pMonster->getObjectID());
	
				if (!isMaster)
				{
					// _GCBloodDrainOK2.addLongData(MODIFY_DURATION, BLOODDRAIN_DURATION);
				}
				pTargetPlayer->sendPacket(&_GCBloodDrainOK2);
			}
		}

		// target
		int targetLevel = 0;
		int targetMaxHP = 0;

		if (pEnemy->isSlayer()) 
		{
			Slayer* pTargetSlayer  = dynamic_cast<Slayer*>(pEnemy);
			targetLevel = pTargetSlayer->getHighestSkillDomainLevel();
			targetMaxHP = pTargetSlayer->getHP(ATTR_MAX);
		}
		else if (pEnemy->isVampire()) 
		{
			Vampire* pTargetVampire  = dynamic_cast<Vampire*>(pEnemy);
			targetLevel = pTargetVampire->getLevel();
			targetMaxHP = pTargetVampire->getHP(ATTR_MAX);
		}
		else if (pEnemy->isOusters()) 
		{
			Ousters* pTargetOusters  = dynamic_cast<Ousters*>(pEnemy);
			targetLevel = pTargetOusters->getLevel();
			targetMaxHP = pTargetOusters->getHP(ATTR_MAX);
		}
		else if (pEnemy->isMonster())
		{
			Monster* pEnemyMonster = dynamic_cast<Monster*>(pEnemy);

			// 흡혈당하는 몬스터한테 딜레이 걸어준다.
			Timeval DelayTurn;
			DelayTurn.tv_sec = 4;
			DelayTurn.tv_usec = 500000;
			pEnemyMonster->addAccuDelay(DelayTurn);

			if ((pMonster->isMaster()
#ifdef __UNDERWORLD__
				|| pMonster->isUnderworld() || pMonster->getMonsterType() == 599 
#endif
			)
				&& pMonster->getClanType()==pEnemyMonster->getClanType())
			{
				// 같은 clan의 마스터이면 피 상납이라고 볼 수 있을까 -_-;
			}
			else
			{
				pEnemyMonster->addEnemy(pMonster);
			}

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

		// 자신이나 상대방 중.. HP가 많은 쪽의 15~25%
		HP_t maxHP = max((int)pMonster->getHP(ATTR_MAX), targetMaxHP);
		HP_t drainHP = maxHP*(rand()%11+15)/100; // 15~25%

		// 한번에 1000이상 안 찬다.
		if (pMonster->getMonsterType() >= 717 )
			drainHP = min((int)drainHP, 2000);
		else
			drainHP = min((int)drainHP, 1000);

		// 몬스터의 HP를 올려준다.
		HP_t CurrentHP = pMonster->getHP();
		HP_t MaxHP	   = pMonster->getHP(ATTR_MAX);
		HP_t NewHP     = min((int)MaxHP , (int)CurrentHP + (int)drainHP);

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

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

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

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

		// 흡혈 모습 보이게..
		list<Creature *> cList;
		cList.push_back(pEnemy);
		cList.push_back(pMonster);
		pZone->broadcastPacket(pMonster->getX(), pMonster->getY(), &_GCBloodDrainOK3 , cList);

		// 흡혈 성공
		return true;
	}

	__END_CATCH

	return false;
}
void CGTradeMoneyHandler::executeOusters (CGTradeMoney* pPacket , Player* pPlayer)
	 throw(ProtocolException , Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

	// 상위 함수에서 검사를 했기 때문에,
	// 여기서는 포인터가 널인지를 검사하지 않는다.
	ObjectID_t    TargetOID       = pPacket->getTargetObjectID();
	Gold_t        Amount          = pPacket->getAmount();
	BYTE          Code            = pPacket->getCode();
	GamePlayer*   pGamePlayer     = dynamic_cast<GamePlayer*>(pPlayer);
	Creature*     pPC             = pGamePlayer->getCreature();
	Zone*         pZone           = pPC->getZone();
	Creature*     pTargetPC       = pZone->getCreature(TargetOID); 

	// NoSuch제거. by sigi. 2002.5.2
	if (pTargetPC==NULL) return;

	Ousters*      pSender         = dynamic_cast<Ousters*>(pPC);
	Ousters*      pReceiver       = dynamic_cast<Ousters*>(pTargetPC);
	Player*       pTargetPlayer   = pTargetPC->getPlayer();
	Gold_t        finalAmount     = Amount;
	Gold_t        margin          = 0;
	GCTradeMoney  gcTradeMoney;
	GCTradeVerify gcTradeVerify;

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

	// 교환 상태가 맞는지 체크를 해봐야한다.
	TradeInfo* pInfo1 = pTradeManager->getTradeInfo(pSender->getName());
	TradeInfo* pInfo2 = pTradeManager->getTradeInfo(pReceiver->getName());

	// 인벤토리에서 돈을 덜어, 교환창에다 더한다.
	if (Code == CG_TRADE_MONEY_INCREASE)
	{
		// 교환창에다 더할 액수보다 많은 돈을 가지고 있어야 한다.
		if (pSender->getGold() >= Amount)
		{
			// 돈을 받는 쪽이 맥스를 초과하게 된다면, 일부만 넣어줘야 한다.
			// 현재 교환 예정인 돈도 더해서 계산. by sigi. 2003.1.8
			Gold_t receiverGold = pReceiver->getGold() + pInfo1->getGold();
			if (receiverGold + Amount > MAX_MONEY)
			{
				margin		= receiverGold + Amount - MAX_MONEY;
				finalAmount = finalAmount - margin;
			}

			// 인벤토리에서 돈을 빼고, 교환창에다 더한다.
			pSender->setGold(pSender->getGold() - finalAmount);
			pInfo1->setGold(pInfo1->getGold() + finalAmount);

			// 현재 OK를 누른 상태라면, 클라이언트에게 인증 패킷을 보내줘야 한다.
			if (pInfo1->getStatus() == TRADE_FINISH)
			{
				// 인증 패킷을 날려준다.
				gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_MONEY_INCREASE);
				pPlayer->sendPacket(&gcTradeVerify);
			}

			// 아이템을 더하거나 뺄 경우, 상태를 변환해줘야 한다.
			pInfo1->setStatus(TRADE_TRADING);
			pInfo2->setStatus(TRADE_TRADING);

			// 돈을 올린 당사자에게 실제로 인벤토리에서
			// 빠진 금액이 얼마인지 보내준다.
			gcTradeMoney.setTargetObjectID(TargetOID);
			gcTradeMoney.setCode(GC_TRADE_MONEY_INCREASE_RESULT);
			gcTradeMoney.setAmount(finalAmount);
			pPlayer->sendPacket(&gcTradeMoney);

			// 상대방에게 바뀐 정보를 보내준다.
			gcTradeMoney.setTargetObjectID(pSender->getObjectID());
			gcTradeMoney.setCode(GC_TRADE_MONEY_INCREASE);
			gcTradeMoney.setAmount(finalAmount);
			pTargetPlayer->sendPacket(&gcTradeMoney);
		}
		else 
		{
			pTradeManager->cancelTrade(pPC);
			executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_INCREASE_MONEY);
			return;
		}
	}
	// 교환창에서 돈을 덜어, 인벤토리에다가 더한다.
	else if (Code == CG_TRADE_MONEY_DECREASE)
	{
		// 인벤토리에다 더할 액수보다 교환창에 있는 돈이 많아야 한다.
		if (pInfo1->getGold() >= Amount)
		{
			// 돈이 맥스를 초과하게 된다면, 일부만 뺄 수 있다.
			Gold_t senderGold = pSender->getGold() + pInfo2->getGold();
			if (senderGold + Amount > MAX_MONEY)
			{
				margin      = senderGold + Amount - MAX_MONEY;
				finalAmount = finalAmount - margin;
			}

			// 인벤토리에다가 돈을 더하고, 교환창에서 돈을 뺀다.
			pSender->setGold(pSender->getGold() + finalAmount);
			pInfo1->setGold(pInfo1->getGold() - finalAmount);

			// 현재 OK를 누른 상태라면, 클라이언트에게 인증 패킷을 보내줘야 한다.
			if (pInfo1->getStatus() == TRADE_FINISH)
			{
				// 인증 패킷을 날려준다.
				gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_MONEY_DECREASE);
				pPlayer->sendPacket(&gcTradeVerify);
			}

			// 아이템을 더하거나 뺄 경우, 상태를 변환해줘야 한다.
			pInfo1->setStatus(TRADE_TRADING);
			pInfo2->setStatus(TRADE_TRADING);

			// 돈을 올린 당사자에게 실제로 인벤토리에다 
			// 더한 금액이 얼마인지 보내준다.
			gcTradeMoney.setTargetObjectID(TargetOID);
			gcTradeMoney.setCode(GC_TRADE_MONEY_DECREASE_RESULT);
			gcTradeMoney.setAmount(finalAmount);
			pPlayer->sendPacket(&gcTradeMoney);

			// 상대방에게 바뀐 정보를 보내준다.
			gcTradeMoney.setTargetObjectID(pSender->getObjectID());
			gcTradeMoney.setCode(GC_TRADE_MONEY_DECREASE);
			gcTradeMoney.setAmount(finalAmount);
			pTargetPlayer->sendPacket(&gcTradeMoney);
		}
		else
		{
			pTradeManager->cancelTrade(pPC);
			executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_DECREASE_MONEY);
			return;
		}
	}

#endif

	__END_DEBUG_EX __END_CATCH
}
////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionActivatePortal::execute (Creature * pNPC , Creature * pCreature) 
	throw(Error)
{
	__BEGIN_TRY
	__BEGIN_DEBUG

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

	GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pCreature->getPlayer());
	PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature);
	//Zone* pZone = pCreature->getZone();

	bool bTransport = true;

#if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__)
	try {

		ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(m_ZoneID);

		// 유료존인데 유료사용자가 아니면...
		if (pZoneInfo==NULL
			|| pZoneInfo->isPayPlay() && !pGamePlayer->isPayPlaying())
		{
			string connectIP = pGamePlayer->getSocket()->getHost();

			// 유료 서비스 사용이 가능한가?
			if (pGamePlayer->loginPayPlay(connectIP, pGamePlayer->getID()))
			{
				sendPayInfo(pGamePlayer);
			}
			else if (!pGamePlayer->isFamilyFreePass() ) // 패밀리 프리 패스는 유료존으로 갈 수 있다.
			{
				// 유료 서비스 사용 불가인 경우
				GCSystemMessage gcSystemMessage;

				if (g_pConfig->getPropertyInt("IsNetMarble")==0)
				{
					gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER_PAY_ZONE));
				}
				else
				{
					gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER));
				}

				pGamePlayer->sendPacket (&gcSystemMessage);

				bTransport = false;
			}
		}
	} catch (NoSuchElementException&) {
	}
#endif

	if (bTransport)
	{
		if (m_ZoneID == 1410 )
		{
			if (pCreature->isFlag(Effect::EFFECT_CLASS_CAN_ENTER_GDR_LAIR ) )
			{
				Effect* pEffect = pCreature->findEffect(Effect::EFFECT_CLASS_CAN_ENTER_GDR_LAIR);
				if (pEffect != NULL ) pEffect->setDeadline(0);
			}

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

				// 오토바이를 타고 있으면 오토바이에서 내린다.
				if (pSlayer->hasRideMotorcycle() )
				{
					pSlayer->getOffMotorcycle();
				}
			}

			if (pCreature->isOusters() )
			{
				Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);
				Assert(pOusters != NULL);

				// 실프 타고 있으면 내려준다
				if (pOusters->isFlag(Effect::EFFECT_CLASS_SUMMON_SYLPH) )
				{
					Effect* pEffect = pOusters->findEffect(Effect::EFFECT_CLASS_SUMMON_SYLPH);
					if (pEffect != NULL ) pEffect->setDeadline(0);
				}
			}

			if (pCreature->isVampire() )
			{
				Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);
				Assert(pVampire != NULL);

				if (pVampire->isFlag(Effect::EFFECT_CLASS_TRANSFORM_TO_BAT) )
				{
					addUntransformCreature(pVampire->getZone(), pVampire, true);
				}
			}
		}

		if (pNPC != NULL )
		{
			pPC->getGQuestManager()->illegalWarp();
		}

		transportCreature(pCreature, m_ZoneID, m_X, m_Y, true);
	}
	else
	{
	    GCNPCResponse response;
	    response.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
	    pGamePlayer->sendPacket(&response);
	}

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

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

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

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

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

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

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

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

		GCSkillToObjectOK1 _GCSkillToObjectOK1;
		GCSkillToObjectOK2 _GCSkillToObjectOK2;
		GCSkillToObjectOK5 _GCSkillToObjectOK5;

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

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

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

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

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

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

			pEffect->setDeadline(0);

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

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

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

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

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

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

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

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

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

#ifdef __GAME_SERVER__

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

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

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

		bool        Success     = false;

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

			Item*   pItem = pSlayer->getExtraInventorySlotItem();

			if (pItem == NULL)
			{
				GCCannotAdd _GCCannotAdd;
				_GCCannotAdd.setObjectID(pPacket->getObjectID());
				pPlayer->sendPacket(&_GCCannotAdd);
				return;
			}

			ObjectID_t ItemObjectID = pItem->getObjectID();
			SlotID_t   SlotID       = pPacket->getSlotID();
		
			// 아이템의 ObjectID가 일치하는지 체크한다.
			if (ItemObjectID == pPacket->getObjectID()) 
			{
				Item::ItemClass IClass = pItem->getItemClass();
				
				switch (SlotID) // 슬랏을 보고 그 슬랏에 맞는 아이템 유형인지 비교한다.
				{
					case Slayer::WEAR_HEAD:
						if (IClass == Item::ITEM_CLASS_HELM) Success = true;
						break;
					case Slayer::WEAR_NECK:
						if (IClass == Item::ITEM_CLASS_NECKLACE) Success = true;
						break;
					case Slayer::WEAR_FINGER1:
						if (IClass == Item::ITEM_CLASS_RING || IClass == Item::ITEM_CLASS_COUPLE_RING) Success = true;
						break;
					case Slayer::WEAR_FINGER2:
						if (IClass == Item::ITEM_CLASS_RING || IClass == Item::ITEM_CLASS_COUPLE_RING) Success = true;
						break;
					case Slayer::WEAR_FINGER3:
						if (IClass == Item::ITEM_CLASS_RING || IClass == Item::ITEM_CLASS_COUPLE_RING) Success = true;
						break;
					case Slayer::WEAR_FINGER4:
						if (IClass == Item::ITEM_CLASS_RING || IClass == Item::ITEM_CLASS_COUPLE_RING) Success = true;
						break;
					case Slayer::WEAR_WRIST1:
						if (IClass == Item::ITEM_CLASS_BRACELET) Success = true;
						break;
					case Slayer::WEAR_WRIST2:
						if (IClass == Item::ITEM_CLASS_BRACELET) Success = true;
						break;
					case Slayer::WEAR_LEFTHAND:
						if (IClass == Item::ITEM_CLASS_SHIELD) Success = true;
						break;
					case Slayer::WEAR_HAND3:
						if (IClass == Item::ITEM_CLASS_GLOVE) Success = true;
						break;
					case Slayer::WEAR_BODY:
						if (IClass == Item::ITEM_CLASS_COAT) Success = true;
						break;
					case Slayer::WEAR_BELT:
						if (IClass == Item::ITEM_CLASS_BELT) Success = true;
						break;
					case Slayer::WEAR_LEG:
						if (IClass == Item::ITEM_CLASS_TROUSER) Success = true;
						break;
					case Slayer::WEAR_FOOT:
						if (IClass == Item::ITEM_CLASS_SHOES) Success = true;
						break;
					case Slayer::WEAR_RIGHTHAND:
						if (isSlayerWeapon(IClass)) Success = true;
						break;
					case Slayer::WEAR_ZAP1:
					case Slayer::WEAR_ZAP2:
					case Slayer::WEAR_ZAP3:
					case Slayer::WEAR_ZAP4:
						if (IClass == Item::ITEM_CLASS_CORE_ZAP) Success = true;
						break;
					case Slayer::WEAR_PDA:
						if (IClass == Item::ITEM_CLASS_CARRYING_RECEIVER) Success = true;
						break;
					case Slayer::WEAR_SHOULDER:
						if (IClass == Item::ITEM_CLASS_SHOULDER_ARMOR) Success = true;
						break;
					default :
						break;
				}
				
				// 그 슬랏에 맞는 아이템을 장착하려고 하는지 체크한다.
				if (Success) pSlayer->wearItem((Slayer::WearPart)SlotID);
			}
		} 
		else if (pCreature->isVampire())
		{
			Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);
			Assert(pVampire != NULL);

			Item*    pItem    = pVampire->getExtraInventorySlotItem();

			if (pItem == NULL)
			{
				GCCannotAdd _GCCannotAdd;
				_GCCannotAdd.setObjectID(pPacket->getObjectID());
				pPlayer->sendPacket(&_GCCannotAdd);
				return;
			}

			ObjectID_t ItemObjectID = pItem->getObjectID();
			SlotID_t   SlotID       = pPacket->getSlotID();
		
			// 아이템의 ObjectID가 일치하는지 체크한다.
			if (ItemObjectID == pPacket->getObjectID()) 
			{
				Item::ItemClass IClass = pItem->getItemClass();
				
				switch (SlotID) // 슬랏을 보고 그 슬랏에 맞는 아이템 유형인지 비교한다.
				{
					case Vampire::WEAR_NECK:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_NECKLACE) Success = true;
						break;
					case Vampire::WEAR_FINGER1:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_RING || IClass == Item::ITEM_CLASS_VAMPIRE_COUPLE_RING) Success = true;
						break;
					case Vampire::WEAR_FINGER2:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_RING || IClass == Item::ITEM_CLASS_VAMPIRE_COUPLE_RING) Success = true;
						break;
					case Vampire::WEAR_FINGER3:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_RING || IClass == Item::ITEM_CLASS_VAMPIRE_COUPLE_RING) Success = true;
						break;
					case Vampire::WEAR_FINGER4:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_RING || IClass == Item::ITEM_CLASS_VAMPIRE_COUPLE_RING) Success = true;
						break;
					case Vampire::WEAR_WRIST1:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_BRACELET) Success = true;
						break;
					case Vampire::WEAR_WRIST2:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_BRACELET) Success = true;
						break;
					case Vampire::WEAR_EARRING1:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_EARRING) Success = true;
						break;
					case Vampire::WEAR_EARRING2:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_EARRING) Success = true;
						break;
					case Vampire::WEAR_BODY:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_COAT) Success = true;
						break;
					case Vampire::WEAR_LEFTHAND:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_WEAPON) Success = true;
						break;
					case Vampire::WEAR_RIGHTHAND:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_WEAPON) Success = true;
						break;
					case Vampire::WEAR_AMULET1:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_AMULET) Success = true;
						break;
					case Vampire::WEAR_AMULET2:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_AMULET) Success = true;
						break;
					case Vampire::WEAR_AMULET3:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_AMULET) Success = true;
						break;
					case Vampire::WEAR_AMULET4:
						if (IClass == Item::ITEM_CLASS_VAMPIRE_AMULET) Success = true;
						break;
					case Vampire::WEAR_ZAP1:
					case Vampire::WEAR_ZAP2:
					case Vampire::WEAR_ZAP3:
					case Vampire::WEAR_ZAP4:
						if (IClass == Item::ITEM_CLASS_CORE_ZAP) Success = true;
						break;
					case Vampire::WEAR_DERMIS:
						if (IClass == Item::ITEM_CLASS_DERMIS) Success = true;
						break;
					case Vampire::WEAR_PERSONA:
						if (IClass == Item::ITEM_CLASS_PERSONA) Success = true;
						break;

					default :
						break;
				}
				
				// 그 슬랏에 맞는 아이템을 장착하려고 하는지 체크한다.
				if (Success) pVampire->wearItem((Vampire::WearPart)SlotID);
			}
		}
		else if (pCreature->isOusters())
		{
			Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);
			Assert(pOusters != NULL);

			Item*    pItem    = pOusters->getExtraInventorySlotItem();

			if (pItem == NULL)
			{
				GCCannotAdd _GCCannotAdd;
				_GCCannotAdd.setObjectID(pPacket->getObjectID());
				pPlayer->sendPacket(&_GCCannotAdd);
				return;
			}

			ObjectID_t ItemObjectID = pItem->getObjectID();
			SlotID_t   SlotID       = pPacket->getSlotID();
		
			// 아이템의 ObjectID가 일치하는지 체크한다.
			if (ItemObjectID == pPacket->getObjectID()) 
			{
				Item::ItemClass IClass = pItem->getItemClass();
				
				switch (SlotID) // 슬랏을 보고 그 슬랏에 맞는 아이템 유형인지 비교한다.
				{
					case Ousters::WEAR_CIRCLET:
						if (IClass == Item::ITEM_CLASS_OUSTERS_CIRCLET) Success = true;
						break;
					case Ousters::WEAR_COAT:
						if (IClass == Item::ITEM_CLASS_OUSTERS_COAT) Success = true;
						break;
					case Ousters::WEAR_LEFTHAND:
					case Ousters::WEAR_RIGHTHAND:
						if (IClass == Item::ITEM_CLASS_OUSTERS_WRISTLET || IClass == Item::ITEM_CLASS_OUSTERS_CHAKRAM ) Success = true;
						break;
					case Ousters::WEAR_BOOTS:
						if (IClass == Item::ITEM_CLASS_OUSTERS_BOOTS) Success = true;
						break;
					case Ousters::WEAR_ARMSBAND1:
					case Ousters::WEAR_ARMSBAND2:
						if (IClass == Item::ITEM_CLASS_OUSTERS_ARMSBAND) Success = true;
						break;
					case Ousters::WEAR_RING1:
					case Ousters::WEAR_RING2:
						if (IClass == Item::ITEM_CLASS_OUSTERS_RING) Success = true;
						break;
					case Ousters::WEAR_NECKLACE1:
					case Ousters::WEAR_NECKLACE2:
					case Ousters::WEAR_NECKLACE3:
						if (IClass == Item::ITEM_CLASS_OUSTERS_PENDENT) Success = true;
						break;
					case Ousters::WEAR_STONE1:
					case Ousters::WEAR_STONE2:
					case Ousters::WEAR_STONE3:
					case Ousters::WEAR_STONE4:
						if (IClass == Item::ITEM_CLASS_OUSTERS_STONE) Success = true;
						break;

					case Ousters::WEAR_ZAP1:
					case Ousters::WEAR_ZAP2:
					case Ousters::WEAR_ZAP3:
					case Ousters::WEAR_ZAP4:
						if (IClass == Item::ITEM_CLASS_CORE_ZAP) Success = true;
						break;
					case Ousters::WEAR_FASCIA:
						if (IClass == Item::ITEM_CLASS_FASCIA) Success = true;
						break;
					case Ousters::WEAR_MITTEN:
						if (IClass == Item::ITEM_CLASS_MITTEN) Success = true;
						break;

					default :
						break;
				}
				
				// 그 슬랏에 맞는 아이템을 장착하려고 하는지 체크한다.
				if (Success) pOusters->wearItem((Ousters::WearPart)SlotID);
			}
		}

		// Adding에 실패 하였을 경우
		if (!Success) 
		{
			GCCannotAdd _GCCannotAdd;
			_GCCannotAdd.setObjectID(pPacket->getObjectID());
			pPlayer->sendPacket(&_GCCannotAdd);
		}
	} 
	catch (Throwable & t) 
	{
		//cout << t.toString();
	}

#endif	// __GAME_SERVER__

    __END_DEBUG_EX __END_CATCH

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

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

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

		HitBonus = pRankBonus->getPoint();
	}

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

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

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

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

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


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

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

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

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

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

			list<Creature*> cList;

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

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

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

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

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

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

							int EnemyLevel = 0;

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

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

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

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

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

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

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

								increaseAlignment(pVampire, pTargetCreature, _GCSkillToTileOK1);

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

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


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

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

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

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

			pPlayer->sendPacket(&_GCSkillToTileOK1);

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

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

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

					_GCSkillToTileOK2.addShortData(MODIFY_CURRENT_HP, targetHP);

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

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

			cList.push_back(pVampire);

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

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

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

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

#ifdef __GAME_SERVER__

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

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

	Creature* pCreature = pGamePlayer->getCreature();

	Assert(pCreature != NULL);

	Zone* pZone = pCreature->getZone();

	Assert(pZone != NULL);


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

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

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

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

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

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

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

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

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

					g_pResurrectLocationManager->getPosition(pPC, ResurrectCoord);

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

	pGamePlayer->setPlayerStatus(GPS_AFTER_SENDING_GL_INCOMING_CONNECTION);

#endif

	__END_DEBUG_EX __END_CATCH
}
void CGSkillToInventoryHandler::execute (CGSkillToInventory* pPacket , Player* pPlayer)
	 throw(Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX
		
#ifdef __GAME_SERVER__

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

	GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer);
	Assert(pGamePlayer != NULL);	// by sigi

	if (pGamePlayer->getPlayerStatus() == GPS_NORMAL) 
	{
		Creature* pCreature = pGamePlayer->getCreature();
		Assert(pCreature != NULL);	// by sigi

		Zone* pZone = pCreature->getZone();
		Assert(pZone != NULL);
	
		SkillType_t SkillType = pPacket->getSkillType();

		// 완전 안전지대라면 기술 사용 불가. by sigi. 2002.11.14
		ZoneLevel_t ZoneLevel = pZone->getZoneLevel(pCreature->getX(), pCreature->getY());
		if ((ZoneLevel & COMPLETE_SAFE_ZONE) ||
            (pCreature->isFlag(Effect::EFFECT_CLASS_PARALYZE)) ||
            (pCreature->isFlag(Effect::EFFECT_CLASS_CAUSE_CRITICAL_WOUNDS)) ||
            (pCreature->isFlag(Effect::EFFECT_CLASS_EXPLOSION_WATER)) ||
            (pCreature->isFlag(Effect::EFFECT_CLASS_COMA)))
		{
			GCSkillFailed1 _GCSkillFailed1;
			_GCSkillFailed1.setSkillType(SkillType);
			pPlayer->sendPacket(&_GCSkillFailed1);

			return;
		}

        if (pCreature->isFlag(Effect::EFFECT_CLASS_TRANSFORM_TO_WERWOLF)) {
            switch(SkillType) {
                case SKILL_ATTACK_MELEE:
                case SKILL_BITE_OF_DEATH:
                case SKILL_UN_TRANSFORM:
                case SKILL_RAPID_GLIDING:
                    break;
                default:
                    GCSkillFailed1 _GCSkillFailed1;
                    _GCSkillFailed1.setSkillType(SkillType);
                    pPlayer->sendPacket(&_GCSkillFailed1);
                    dynamic_cast<Vampire*>(pCreature)->sendVampireSkillInfo();
                    return;
            }
        }

		BYTE        X         = pPacket->getX();
		BYTE        Y         = pPacket->getY();
		BYTE        TX        = pPacket->getTargetX();
		BYTE        TY        = pPacket->getTargetY();

		disableFlags(pCreature, pZone, SkillType);

		if (pCreature->isSlayer()) 
		{
			Slayer*    pSlayer    = dynamic_cast<Slayer*>(pCreature);
			SkillSlot* pSkillSlot = pSlayer->hasSkill(SkillType);
			bool       bSuccess   = true;

			if (pSkillSlot == NULL) bSuccess = false;
			if (SkillType == SKILL_INSTALL_MINE ) {
				bSuccess = true;
				TY = 0;
			} else {
				if (!isAbleToUseInventorySkill(pSlayer, X, Y, TX, TY)) bSuccess = false;
			}
/*			if (pSlayer->isFlag(Effect::EFFECT_CLASS_SNIPING_MODE))
			{
				g_Sniping.checkRevealRatio(pSlayer, 20, 10);
			} */

			if (bSuccess)
			{
				SkillHandler* pSkillHandler = g_pSkillHandlerManager->getSkillHandler(SkillType);
				Assert(pSkillHandler != NULL);
   			 	pSkillHandler->execute(pSlayer, pPacket->getObjectID(), pPacket->getInventoryItemObjectID(), X, Y, TX, TY, pSkillSlot);
   			 }
             else
             {
                 GCSkillFailed1 _GCSkillFailed1;
				_GCSkillFailed1.setSkillType(SkillType);
                 pPlayer->sendPacket(&_GCSkillFailed1);
             }
		} 
		else if (pCreature->isVampire()) 
		{
			Vampire*          pVampire          = dynamic_cast<Vampire*>(pCreature);
			VampireSkillSlot* pVampireSkillSlot = pVampire->hasSkill(SkillType);
			bool              bSuccess          = true;
			
			if (pVampireSkillSlot == NULL) bSuccess = false;
			if (!isAbleToUseInventorySkill(pVampire, X, Y, TX, TY)) bSuccess = false;

/*			if (pVampire->isFlag(Effect::EFFECT_CLASS_INVISIBILITY))
			{
				addVisibleCreature(pZone, pVampire, true);
			}
		
	        if (pVampire->isFlag(Effect::EFFECT_CLASS_EXTREME))
	        {
		        EffectManager * pEffectManager = pVampire->getEffectManager();
	   		    Assert(pEffectManager != NULL);
	   		    Effect * pEffect = pEffectManager->findEffect(Effect::EFFECT_CLASS_EXTREME);
	   		    if (pEffect != NULL ) {
		   		    pEffect->setDeadline(0);
		        }
			} */

			if (bSuccess) 
			{
				SkillHandler* pSkillHandler = g_pSkillHandlerManager->getSkillHandler(SkillType);
				Assert(pSkillHandler != NULL);
   			 	pSkillHandler->execute(pVampire, pPacket->getObjectID(), pPacket->getInventoryItemObjectID(), X, Y, TX, TY, pVampireSkillSlot);
   			 }
             else
             {
                 GCSkillFailed1 _GCSkillFailed1;
				_GCSkillFailed1.setSkillType(SkillType);
                 pPlayer->sendPacket(&_GCSkillFailed1);
             }
		}
		else if (pCreature->isOusters()) 
		{
			Ousters*          pOusters          = dynamic_cast<Ousters*>(pCreature);
			OustersSkillSlot* pOustersSkillSlot = pOusters->hasSkill(SkillType);
			bool              bSuccess          = true;
			
			if (pOustersSkillSlot == NULL) bSuccess = false;
			if (!isAbleToUseInventorySkill(pOusters, X, Y, TX, TY)) bSuccess = false;

			if (bSuccess) 
			{
				SkillHandler* pSkillHandler = g_pSkillHandlerManager->getSkillHandler(SkillType);
				Assert(pSkillHandler != NULL);
   			 	pSkillHandler->execute(pOusters, pPacket->getObjectID(), pPacket->getInventoryItemObjectID(), X, Y, TX, TY, pOustersSkillSlot);
   			 }
             else
             {
                 GCSkillFailed1 _GCSkillFailed1;
				_GCSkillFailed1.setSkillType(SkillType);
                 pPlayer->sendPacket(&_GCSkillFailed1);
             }
		}
	}

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

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

	Assert(pVampire != NULL);

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

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

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

		GCBloodDrainOK1 _GCBloodDrainOK1;
		GCBloodDrainOK2 _GCBloodDrainOK2;
		GCBloodDrainOK3 _GCBloodDrainOK3;

		Timeval CurrentTime;
		getCurrentTime(CurrentTime);

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

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

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

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

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

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

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

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

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

			shareVampExp(pVampire, Exp, _GCBloodDrainOK1);

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

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

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

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

				_GCBloodDrainOK1.addShortData(MODIFY_CURRENT_HP, NewHP);
			}

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

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

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

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

			_GCBloodDrainOK1.setObjectID(TargetObjectID);

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

			pPlayer->sendPacket(&_GCBloodDrainOK1);

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

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

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

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

	__END_CATCH

}
Beispiel #26
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 CGSelectWayPointHandler::execute(CGSelectWayPoint* pPacket , Player* pPlayer) throw(Error) {
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__
	Assert(pPacket != NULL);
	Assert(pPlayer != NULL);

	static map<Level_t,Price_t> sPriceMap;

	try {
		int targetDynamicZoneType = g_pDynamicZoneInfoManager->getDynamicZoneTypeByZoneID(pPacket->getZoneID());
		if (targetDynamicZoneType != DYNAMIC_ZONE_MAX) {
			executeEnterQuestZone(pPacket, pPlayer, targetDynamicZoneType);
		}

		// 게임 플레이어의 상태가 정상이 아니라면 걍 리턴한다.
		GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer);
		Assert(pGamePlayer != NULL);
		if (pGamePlayer->getPlayerStatus() != GPS_NORMAL) return;

		// 크리쳐가 슬레이어가 아니라면 리턴한다.
		Creature* pCreature = pGamePlayer->getCreature();
		Assert(pCreature != NULL);

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

		if (pPC->getStore()->isOpen()) return;
		if (pCreature->hasRelicItem()) return;

		// 크리쳐가 죽었으면 리턴
		if (pCreature->isDead()) return;

		// 초보존으로 들어가는 경우엔 종족 상관없이 보내준다.
		if (pPacket->getZoneID() == 1122) {
			ZONE_COORD pos(1122);

			if (pCreature->isSlayer()) {
				pos.x = 107;
				pos.y = 27;
			} else if (pCreature->isVampire()) {
				pos.x = 18;
				pos.y = 27;
			} else if (pCreature->isOusters()) {
				pos.x = 12;
				pos.y = 103;
			} else return;

			if (!canEnterBeginnerZone(pCreature)) return;

			// 초보존이 유료존일수도 있을라나...?
#if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__)
			ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(pos.id);
			
			// 유료존인데 유료사용자가 아니면...
      if (pZoneInfo == NULL ||
          ((pZoneInfo->isPayPlay() || pZoneInfo->isPremiumZone())
           && (!pGamePlayer->isPayPlaying() && !pGamePlayer->isFamilyFreePass()))) {
        //Statement* pStmt = NULL;
				string connectIP = pGamePlayer->getSocket()->getHost();

				// 유료 서비스 사용이 가능한가?
				if (pGamePlayer->loginPayPlay(connectIP, pGamePlayer->getID())) {
					sendPayInfo(pGamePlayer);
				} else if (pZoneInfo->isPayPlay()) {
					// 유료 서비스 사용 불가인 경우
					GCSystemMessage gcSystemMessage;

					if (g_pConfig->getPropertyInt("IsNetMarble") == 0) {
						gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER));
					} else {
						gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER));
					}

					pGamePlayer->sendPacket(&gcSystemMessage);

					return;
				}
			}
#endif

			pPC->getGQuestManager()->illegalWarp();
			transportCreature(pCreature, pos.id, pos.x, pos.y, false);
			return;
		}

		if (pPacket->getZoneID() == 1131) {

			if (g_pVariableManager->getVariable(ACTIVE_LEVEL_WAR) == 0) {
				GCSystemMessage gcSystemMessage;
				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER));
				pGamePlayer->sendPacket(&gcSystemMessage);
				return;
			}
/*
			if (g_pConfig->getPropertyInt("ServerID" ) != 0 )
			{
				GCNoticeEvent gcNoticeEvent;

				gcNoticeEvent.setCode(NOTICE_EVENT_NOT_FIRST_SERVER);
				pGamePlayer->sendPacket(&gcNoticeEvent);
//				GCSystemMessage gcSystemMessage;
//				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_LEVEL_WAR_ONLY_FIRST_SERVER ));
//				pGamePlayer->sendPacket (&gcSystemMessage);
				return;
			}
*/

			// 크리쳐 정보 보고 알아서 튕겨주자 =_=;;
			ZONE_COORD pos(g_pLevelWarZoneInfoManager->getCreatureZoneID(pCreature ));

			if (g_pSweeperBonusManager->isAble(g_pLevelWarZoneInfoManager->getCreatureZoneID(pCreature))) {
				GCSystemMessage gcSystemMessage;
				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NO_WAR_IN_ACTIVE ));
				pGamePlayer->sendPacket (&gcSystemMessage);
				return;
			}

			if (pCreature->isSlayer()) {
				pos.x = 12;
				pos.y =  9;
			} else if (pCreature->isVampire()) {
				pos.x = 117;
				pos.y =   8;
			} else if (pCreature->isOusters()) {
				pos.x =   9;
				pos.y = 111;
			}
			
#if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__)
			Zone* pZone = getZoneByZoneID(pos.id);
			Assert(pZone != NULL);
			
			LevelWarManager* pLevelWarManager = pZone->getLevelWarManager();
			Assert(pLevelWarManager != NULL);

			if (!pLevelWarManager->hasWar() && !g_pVariableManager->canEnterLevelWarZoneFree() && !pGamePlayer->isPayPlaying() && pGamePlayer->isFamilyFreePass() && !pLevelWarManager->canEnterFreeUser()) {
				GCSystemMessage gcSystemMessage;
				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER_LEVEL_WAR_ZONE));
				pGamePlayer->sendPacket(&gcSystemMessage);
				return;
			}
#endif
			
			pPC->getGQuestManager()->illegalWarp();
			transportCreature(pCreature, pos.id, pos.x, pos.y, false);
			return;
		}

		if (pPacket->getZoneID() == 72) {
			if (!g_pWarSystem->hasActiveRaceWar()) {
				GCSystemMessage gcSystemMessage;
				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NO_WAR_IN_ACTIVE));
				pGamePlayer->sendPacket (&gcSystemMessage);

				return;
			}
/*
			if (g_pConfig->getPropertyInt("ServerID" ) != 0 )
			{
				GCNoticeEvent gcNoticeEvent;

				gcNoticeEvent.setCode(NOTICE_EVENT_NOT_FIRST_SERVER);
				pGamePlayer->sendPacket(&gcNoticeEvent);
//				GCSystemMessage gcSystemMessage;
//				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_LEVEL_WAR_ONLY_FIRST_SERVER ));
//				pGamePlayer->sendPacket (&gcSystemMessage);
				return;
			}
*/

			// 크리쳐 정보 보고 알아서 튕겨주자 =_=;;
			ZONE_COORD pos;

			if (pCreature->isSlayer()) {
				pos.id = 73;
				pos.x = 30;
				pos.y = 124;
			} else if (pCreature->isVampire()) {
				pos.id = 71;
				pos.x = 104;
				pos.y = 128; 
			} else if (pCreature->isOusters()) {
				pos.id = 72;
				pos.x = 67;
				pos.y = 165;
			}
/*#if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__)
			ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(pos.id);
			
			// 유료존인데 유료사용자가 아니면...
			if (pZoneInfo==NULL
				|| (pZoneInfo->isPayPlay() || pZoneInfo->isPremiumZone())
					&& (!pGamePlayer->isPayPlaying() && !pGamePlayer->isFamilyFreePass() ))
			{
				//Statement* pStmt = NULL;
				string connectIP = pGamePlayer->getSocket()->getHost();

				// 유료 서비스 사용이 가능한가?
				if (pGamePlayer->loginPayPlay(connectIP, pGamePlayer->getID()))
				{
					sendPayInfo(pGamePlayer);
				}
				else if (pZoneInfo->isPayPlay())
				{
					// 유료 서비스 사용 불가인 경우
					GCSystemMessage gcSystemMessage;

					if (g_pConfig->getPropertyInt("IsNetMarble")==0)
					{
						gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER ));
					}
					else
					{
						gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER ));
					}

					pGamePlayer->sendPacket (&gcSystemMessage);

					return;
				}
			}
#endif*/
			if (!g_pVariableManager->isActiveRaceWarLimiter() || pCreature->isFlag(Effect::EFFECT_CLASS_RACE_WAR_JOIN_TICKET)) {
				pPC->getGQuestManager()->illegalWarp();
				transportCreature(pCreature, pos.id, pos.x, pos.y, false);
				return;
			} else {
				GCSystemMessage gcSystemMessage;
				gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER_DURING_RACE_WAR));
				pGamePlayer->sendPacket(&gcSystemMessage);
				return;
			}
		}

		if (!pCreature->isSlayer() && !pCreature->isOusters()) {
			// 뭔가를 해야하지 않을까?
			return;
		}
		
		if (pCreature->isFlag(Effect::EFFECT_CLASS_HAS_FLAG)) {
			// 뭔가를 해야하지 않을까?
			return;
		}

		if (pCreature->isFlag(Effect::EFFECT_CLASS_HAS_SWEEPER)) {
			// 뭔가를 해야하지 않을까?
			return;
		}

		//Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature);
		//Assert(pSlayer != NULL);

		bool bCancel = false;

		// 이펙트가 걸려있어야 정상적인 이동이다.
		if (pCreature->isOusters() || (pCreature->isSlayer() && pCreature->isFlag(Effect::EFFECT_CLASS_SLAYER_PORTAL))) {
			ZoneID_t    id = pPacket->getZoneID();
			ZoneCoord_t x  = pPacket->getX();
			ZoneCoord_t y  = pPacket->getY();

			if (id == 0 && x == 0 && y == 0) {
				bCancel = true;
			} else {
				// 석화 상태일 경우 생깐다.
				if (pCreature->isFlag(Effect::EFFECT_CLASS_PARALYZE)) {
					bCancel = true;
				}

				// 웨이포인트 매니저를 통해서 클라이언트가 보내온
				// 웨이포인트가 정상적인 웨이포인트인지를 검증한다.
				if (!g_pWayPointManager->isValidWayPoint(id, x, y, pCreature->getRace())) {
					// 뭔가를 해야하지 않을까?
					bCancel = true;

					//return;
				}

				try {

					if (!bCancel) {

#if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__)
						ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(id);
						
						// 유료존인데 유료사용자가 아니면...
            if (pZoneInfo==NULL ||
                ((pZoneInfo->isPayPlay() || pZoneInfo->isPremiumZone()) && (!pGamePlayer->isPayPlaying() && !pGamePlayer->isFamilyFreePass()))) {
              //Statement* pStmt = NULL;
							string connectIP = pGamePlayer->getSocket()->getHost();

							// 유료 서비스 사용이 가능한가?
							if (pGamePlayer->loginPayPlay(connectIP, pGamePlayer->getID())) {
								sendPayInfo(pGamePlayer);
							} else if (pZoneInfo->isPayPlay()) {
								// 유료 서비스 사용 불가인 경우
								GCSystemMessage gcSystemMessage;

								if (g_pConfig->getPropertyInt("IsNetMarble") == 0) {
									gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER));
								} else {
									gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER));
								}

								pGamePlayer->sendPacket (&gcSystemMessage);

								bCancel = true;
							}
						}
#endif

						if (!bCancel) {
							// 이동시키기 전에 이펙트를 삭제한다.
							if (pCreature->isSlayer())
								pCreature->removeFlag(Effect::EFFECT_CLASS_SLAYER_PORTAL);

							if (pCreature->isOusters()) {
								Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);
								Assert(pOusters != NULL);

								GCNoticeEvent gcNoticeEvent;

								// 대지정령의 뿔을 사용할라면 시오람과 계약을 맺었어야 한다.
								if (!pOusters->getFlagSet()->isOn(FLAGSET_GNOMES_HORN)) {
									gcNoticeEvent.setCode(NOTICE_EVENT_CONTRACT_GNOMES_HORN);
									pPlayer->sendPacket(&gcNoticeEvent);
									return;
								}

								Level_t level = pOusters->getLevel();
								Price_t price = sPriceMap[level];

								if (price == 0) {
									price = (Price_t)(pow((double)level, 1.3) * 100) / 2;
									sPriceMap[level] = price;
								}

								/*if (g_pFlagManager->hasFlagWar() && 
										pPacket->getZoneID() == 32 &&
										pPacket->getX() == 124 &&
										pPacket->getY() == 144 ) price = 0;*/

								if (pOusters->getGold() < price) {
									gcNoticeEvent.setCode(NOTICE_EVENT_NOT_ENOUGH_MONEY);
									pPlayer->sendPacket(&gcNoticeEvent);
									return;
								} else {
									pOusters->decreaseGoldEx(price);
									GCModifyInformation gcMI;
									gcMI.addLongData(MODIFY_GOLD, pOusters->getGold());
									pPlayer->sendPacket(&gcMI);
								}
							}

							// 올바른 웨이포인트라면 슬레이어를 이동시켜준다.
							pPC->getGQuestManager()->illegalWarp();
							transportCreature(pCreature, id, x, y, false);
						}
					}
				} catch (NoSuchElementException&) {
					bCancel = true;
				}
			}
		}

		if (bCancel && pCreature->isSlayer()) {
			Zone* pZone = pCreature->getZone();
			Assert(pZone != NULL);

			// id, x, y가 모두 0일 경우 이동을 취소한다는 뜻이다.
			pCreature->removeFlag(Effect::EFFECT_CLASS_SLAYER_PORTAL);

			// 헬기를 제거하라고 뿌려준다.
			GCAddHelicopter gcAddHelicopter;
			gcAddHelicopter.setObjectID(pCreature->getObjectID());
			gcAddHelicopter.setCode(1);
			pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcAddHelicopter);
		}
	} 
	catch (Throwable & t) { 
		cerr << t.toString() << endl; 
	}

#endif	// __GAME_SERVER__
		
	__END_DEBUG_EX __END_CATCH
}
Beispiel #28
0
void EffectStormPoison::affect(Creature* pCreature)
	throw(Error)
{
	__BEGIN_TRY

	//cout << "EffectStormPoison " << "begin" << endl;

	Assert(pCreature != NULL);

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

	// 사용자를 가져온다.
	// !! 이미 존을 나갔을 수 있으므로 NULL이 될 수 있다.
	// by bezz. 2003.3.13
	Creature* pCastCreature = pZone->getCreature(m_UserObjectID);
	// 캐스터가 없으면 무시한다.
	if (pCastCreature == NULL )
		return;

	// EffectStormPoison은 AcidStorm, PoisonStorm, BloodyStorm위를 지나갈때 붙는다.
	// 이는 3번의 연속 데미지를 주고 사라진다.

	Damage_t StormDamage = m_Point;
	GCModifyInformation GCAttackerMI;

	if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE)
		// 무적상태 체크. by sigi. 2002.9.5
		&& canAttack(pCastCreature, pCreature )
		)
	{
		if (pCreature->isSlayer())
		{
			Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature);

			GCModifyInformation gcMI;
			setDamage(pSlayer, StormDamage, pCastCreature, SKILL_POISON_STORM, &gcMI, &GCAttackerMI);

			pSlayer->getPlayer()->sendPacket(&gcMI);
		}
		else if (pCreature->isVampire())
		{
			Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);

			GCModifyInformation gcMI;
			setDamage(pVampire, StormDamage, pCastCreature, SKILL_POISON_STORM, &gcMI, &GCAttackerMI);

			pVampire->getPlayer()->sendPacket(&gcMI);
		}
		else if (pCreature->isOusters())
		{
			Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);

			GCModifyInformation gcMI;
			setDamage(pOusters, StormDamage, pCastCreature, SKILL_POISON_STORM, &gcMI, &GCAttackerMI);

			pOusters->getPlayer()->sendPacket(&gcMI);
		}
		else if (pCreature->isMonster())
		{
			Monster* pMonster = dynamic_cast<Monster*>(pCreature);

			setDamage(pMonster, StormDamage, pCastCreature, SKILL_POISON_STORM, NULL, &GCAttackerMI);
		}

		if (pCastCreature->isVampire() && pCreature->isDead() )
		{
			Vampire* pVampire = dynamic_cast<Vampire*>(pCastCreature);
			int exp = computeCreatureExp(pCreature, KILL_EXP);
			shareVampExp(pVampire, exp, GCAttackerMI);
			pVampire->getPlayer()->sendPacket(&GCAttackerMI);
		}

		// m_CasterName이 pCreature를 죽인 경우의 KillCount 처리
		// by sigi. 2002.9.9
		// set damage 를 불러서 처리한다. 주석 처리
		// by bezz. 2002.12.31
/*		if (pCreature->isDead())
		{
			Creature* pAttacker = pZone->getCreature(m_UserObjectID);

			if (pAttacker!=NULL)
			{ 
				affectKillCount(pAttacker, pCreature);
			}
		}*/
	}
	
	setNextTime(m_Tick);

	//cout << "EffectStormPoison " << "end" << endl;

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

#ifdef __GAME_SERVER__

	// 상위 함수에서 에러를 검사했기 때문에,
	// 여기서는 포인터가 널인지를 검사하지 않는다.
	ObjectID_t   TargetOID   = pPacket->getTargetObjectID();
	ObjectID_t   ItemOID     = pPacket->getItemObjectID();
	GamePlayer*  pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer);
	Creature*    pPC         = pGamePlayer->getCreature();
	Zone*        pZone       = pPC->getZone();
	PlayerCreature*    pTargetPC   = dynamic_cast<PlayerCreature*>(pZone->getCreature(TargetOID));

	// NoSuch제거. by sigi. 2002.5.2
	if (pTargetPC==NULL) return;

	Ousters*     pSender     = dynamic_cast<Ousters*>(pPC);

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

	// 교환 대상에 추가할 아이템의 포인터를 얻어낸다.
	CoordInven_t X, Y;
	Inventory*   pInventory = pSender->getInventory();
	Item*        pItem      = pInventory->findItemOID(ItemOID, X, Y);

	// 추가할 아이템이 없다면 당연히 더 이상 처리가 불가능
	// Relic은 교환할 수 없다.
	if (pItem == NULL
	|| !canTrade(pItem )
	|| pSender->getStore()->hasItem(pItem)
	|| (pItem->getItemClass() == Item::ITEM_CLASS_SUB_INVENTORY && hasItemWithItemClass(pTargetPC, Item::ITEM_CLASS_SUB_INVENTORY ) )
    )
	{
		pTradeManager->cancelTrade(pPC);
		executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_ADD_ITEM);
		return;
	}


//
//#ifdef __XMAS_EVENT_CODE__
	// 녹색 선물 상자인 경우에는, 상대방에게 적색 선물 상자가 없는지 검사한 후, 
	// 인증 패킷을 보내줘야 한다.
	if (pItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX)
	{
		PlayerCreature* pReceiver = dynamic_cast<PlayerCreature*>(pTargetPC);
		Item* pExtraSlotItem = pReceiver->getExtraInventorySlotItem();

		if (pItem->getItemType() == 0)
		{
			Inventory* pTargetInventory = pReceiver->getInventory();
			if (pTargetInventory->hasRedGiftBox())
			{
				// 적색 선물 상자를 가지고 있다면 더할 수 없다. 리턴시킨다.
				GCTradeVerify gcTradeVerify;
				gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_FAIL);
				pPlayer->sendPacket(&gcTradeVerify);
				return;
			}
			else if (pExtraSlotItem != NULL)
			{
				if (pExtraSlotItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX && pExtraSlotItem->getItemType() == 1)
				{
					GCTradeVerify gcTradeVerify;
					gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_FAIL);
					pPlayer->sendPacket(&gcTradeVerify);
					return;
				}
			}
			else
			{
				// 적색 선물 상자를 가지고 있지 않다면, 걍 넘어간다.
				GCTradeVerify gcTradeVerify;
				gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_OK);
				pPlayer->sendPacket(&gcTradeVerify);
			}
		}
		else if (pItem->getItemType() == 1)
		{
			// 적색 선물 상자는 교환 품목이 될 수 없다.
			GCTradeVerify gcTradeVerify;
			gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_FAIL);
			pPlayer->sendPacket(&gcTradeVerify);
			return;
		}
	}
//#endif
//

	TradeInfo* pInfo1 = pTradeManager->getTradeInfo(pSender->getName());
	TradeInfo* pInfo2 = pTradeManager->getTradeInfo(pTargetPC->getName());

	list<Item*>      tradeList1  = pInfo1->getItemList();

	if (pItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX && pItem->getItemType() > 1 && pItem->getItemType() < 6)
	{
		for (list<Item*>::iterator itr = tradeList1.begin(); itr != tradeList1.end(); itr++)
		{
			Item* pTradeItem = (*itr);
			if (pTradeItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX && pTradeItem->getItemType() > 1 && pTradeItem->getItemType() < 6)	
			{
				GCTradeVerify gcTradeVerify;
				gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_FAIL);
				pPlayer->sendPacket(&gcTradeVerify);
				return;
			}
		}

		GCTradeVerify gcTradeVerify;
		gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_OK);
		pPlayer->sendPacket(&gcTradeVerify);
	}
	else if (pItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX && pItem->getItemType() >= 6)
	{
		GCTradeVerify gcTradeVerify;
		gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_OK);
		pPlayer->sendPacket(&gcTradeVerify);
	}


	// TradeManager에 교환 대상으로서 아이템을 더한다.
	//Assert(pInfo1->addItem(pItem));
	pInfo1->addItem(pItem);

	// 현재 OK를 누른 상태라면, 클라이언트에게 인증 패킷을 보내줘야 한다.
	if (pInfo1->getStatus() == TRADE_FINISH)
	{
        //cout << "CGTradeRemoveItem [" << pSender->getName() << "]의 상태가 TRADE_FINISH이므로, 인증 패킷을 보내준다." << endl;

		// 인증 패킷을 날려준다.
		GCTradeVerify gcTradeVerify;
		gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_WHEN_ACCEPT);
		pPlayer->sendPacket(&gcTradeVerify);
	}
    else
    {
		//cout << "CGTradeRemoveItem [" << pSender->getName() << "]의 상태가 TRADE_FINISH가 아니므로, 인증 패킷 날리지 않는다." << endl;
    }

	// 아이템을 더하거나 뺄 경우, 상태가 TRADE_FINISH라면 
	// TRADE_TRADING으로 바꿔줘야 한다.
	pInfo1->setStatus(TRADE_TRADING);
	pInfo2->setStatus(TRADE_TRADING);

	// 상대방에게 날려줄 아이템 정보를 구성한다.
	GCTradeAddItem gcTradeAddItem;
	makeGCTradeAddItemPacket(&gcTradeAddItem, pSender->getObjectID(), pItem, X, Y);

	// 상대방에게 교환할 아이템 정보를 날려준다.
	Player* pTargetPlayer = pTargetPC->getPlayer();
	pTargetPlayer->sendPacket(&gcTradeAddItem);

#endif

	__END_DEBUG_EX __END_CATCH
}
Beispiel #30
0
////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionEnterGDRLair::execute (Creature * pNPC , Creature * pCreature) 
	throw(Error)
{
	__BEGIN_TRY
	__BEGIN_DEBUG

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

	GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pCreature->getPlayer());
	PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature);

	Assert(pPC != NULL);

	ZoneID_t zoneID;
	ZoneCoord_t X, Y;

	if (m_PortalID == GDRLairManager::Instance().getCorrectPortal() )
	{
		zoneID = 1412;
		X = 142;
		Y = 169;
	}
	else
	{
		zoneID = 1411;
		X = 125;
		Y = 58;
	}

	bool bTransport = true;
#if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__)
	try {

		ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(zoneID);

		// 유료존인데 유료사용자가 아니면...
		if (pZoneInfo==NULL
			|| pZoneInfo->isPayPlay() && !pGamePlayer->isPayPlaying())
		{
			string connectIP = pGamePlayer->getSocket()->getHost();

			// 유료 서비스 사용이 가능한가?
			if (pGamePlayer->loginPayPlay(connectIP, pGamePlayer->getID()))
			{
				sendPayInfo(pGamePlayer);
			}
			else
			{
				// 유료 서비스 사용 불가인 경우
				GCSystemMessage gcSystemMessage;

				if (g_pConfig->getPropertyInt("IsNetMarble")==0)
				{
					gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER_PAY_ZONE ));
				}
				else
				{
					gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER ));
				}

				pGamePlayer->sendPacket (&gcSystemMessage);

				bTransport = false;

				return;
			}
		}
	} catch (NoSuchElementException&) {
	}
#endif

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

			// 오토바이를 타고 있으면 오토바이에서 내린다.
			if (pSlayer->hasRideMotorcycle() )
			{
				pSlayer->getOffMotorcycle();
			}
		}

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

			// 실프 타고 있으면 내려준다
			if (pOusters->isFlag(Effect::EFFECT_CLASS_SUMMON_SYLPH) )
			{
				Effect* pEffect = pOusters->findEffect(Effect::EFFECT_CLASS_SUMMON_SYLPH);
				if (pEffect != NULL ) pEffect->setDeadline(0);
			}
		}

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

			if (pVampire->isFlag(Effect::EFFECT_CLASS_TRANSFORM_TO_BAT) )
			{
				addUntransformCreature(pVampire->getZone(), pVampire, true);
			}
		}

		Effect* pEffect = pPC->findEffect(Effect::EFFECT_CLASS_CAN_ENTER_GDR_LAIR);
		if (pEffect != NULL ) pEffect->setDeadline(0);

		transportCreature(pCreature, zoneID, X, Y, true);
	}
	else
	{
		GCSystemMessage gcSystemMessage;
		gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER ));
		pGamePlayer->sendPacket (&gcSystemMessage);
	}

	__END_DEBUG
	__END_CATCH
}