////////////////////////////////////////////////////////////////////////////// // 뱀파이어 인벤토리 핸들러 ////////////////////////////////////////////////////////////////////////////// void BloodyTunnel::execute(Vampire* pVampire, ObjectID_t InvenObjectID, ObjectID_t InventoryItemObjectID, CoordInven_t X, CoordInven_t Y, CoordInven_t TargetX, CoordInven_t TargetY, VampireSkillSlot* pSkillSlot) 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(); Inventory* pInventory = pVampire->getInventory(); Assert(pPlayer != NULL); Assert(pZone != NULL); Assert(pInventory!= NULL); // 전쟁 존이라면 BloodyTunnel를 사용할 수 없다. // 일단은 ZoneID로 가는데.. ZoneInfo에 넣도록 해야한다. ///* //if (pZone->getZoneID()==1122 || pZone->getZoneID()==1123) // 이벤트 경기장/OX 막기. by sigi. 2002.8.31 //int zoneID = pZone->getZoneID(); //if (zoneID==1005 || zoneID==1006) if (pZone->isNoPortalZone() || pZone->isMasterLair() || pZone->isCastle() || pZone->isHolyLand()) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } //*/ SubInventory* pInventoryItem = NULL; int invenID = 0; if (InventoryItemObjectID != 0 ) { //cout << "서브 인벤토리에서 사용 : " << InventoryItemObjectID << endl; CoordInven_t X, Y; pInventoryItem = dynamic_cast<SubInventory*>(pInventory->findItemOID(InventoryItemObjectID, X, Y )); TradeManager* pTradeManager = pZone->getTradeManager(); Assert(pTradeManager != NULL); if (pInventoryItem == NULL || pTradeManager->hasTradeInfo(pVampire->getName()) ) { //cout << "근데 서브 인벤토리가 없다." <<endl; executeSkillFailException(pVampire, getSkillType()); return; } pInventory = pInventoryItem->getInventory(); invenID = pInventoryItem->getItemID(); } Item* pItem = pInventory->getItem(X, Y); // 아이템이 없거나, 뱀파이어 포탈 아이템이 아니거나, OID가 틀리다면 기술 사용 불가 if (pItem == NULL || pItem->getItemClass() != Item::ITEM_CLASS_VAMPIRE_PORTAL_ITEM || pItem->getObjectID() != InvenObjectID) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } VampirePortalItem* pVampirePortalItem = dynamic_cast<VampirePortalItem*>(pItem); Assert(pVampirePortalItem != NULL); // 뱀파이어 포탈 아이템에 기록된 위치가 없을 경우에는 실패다. ZoneID_t zoneid = pVampirePortalItem->getZoneID(); ZoneCoord_t tx = pVampirePortalItem->getX(); ZoneCoord_t ty = pVampirePortalItem->getY(); if (zoneid == 0) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } // 얻어온 목표 존과 좌표를 검증한다. Zone* pTargetZone = getZoneByZoneID(zoneid); // 아담의 성지와 다른 존과는 연결되지 않는다. if (pZone->isHolyLand() != pTargetZone->isHolyLand()) { executeSkillFailException(pVampire, getSkillType()); return; } //cout << "타겟 존 포인터 획득 성공" << endl; VSRect* pRect = pTargetZone->getOuterRect(); if (!pRect->ptInRect(tx, ty)) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } //cout << "좌표 검증 성공" << endl; GCSkillToInventoryOK1 _GCSkillToInventoryOK1; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); int RequiredMP = decreaseConsumeMP(pVampire, pSkillInfo); bool bManaCheck = hasEnoughMana(pVampire, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pVampire); //bool bHitRoll = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pSkillSlot); bool bHitRoll = true; if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll) { decreaseMana(pVampire, RequiredMP, _GCSkillToInventoryOK1); SkillInput input(pVampire); SkillOutput output; computeOutput(input, output); // 각각의 존에다가 포탈을 더한다. ZONE_COORD s_coord; ZONE_COORD t_coord; s_coord.id = pZone->getZoneID(); s_coord.x = pVampire->getX(); s_coord.y = pVampire->getY(); t_coord.id = pTargetZone->getZoneID(); t_coord.x = tx; t_coord.y = ty; pZone->addVampirePortal(s_coord.x, s_coord.y, pVampire, t_coord); pTargetZone->addVampirePortal(t_coord.x, t_coord.y, pVampire, s_coord); _GCSkillToInventoryOK1.setSkillType(SkillType); _GCSkillToInventoryOK1.setObjectID(InvenObjectID); _GCSkillToInventoryOK1.setCEffectID(0); _GCSkillToInventoryOK1.setDuration(0); pPlayer->sendPacket(&_GCSkillToInventoryOK1); // 차지 수를 줄인다. pVampirePortalItem->setCharge(pVampirePortalItem->getCharge()-1); if (pVampirePortalItem->getCharge() > 0) { // 아직 차지가 남았다면 살려둔다. pVampirePortalItem->save(pVampire->getName(), STORAGE_INVENTORY, invenID, X, Y); } else { // 포탈 아이템의 차지가 다 소모되었다면 삭제시킨다. pInventory->deleteItem(X, Y); pVampirePortalItem->destroy(); // 아이템 포인터 자체가 지워지고, NULL이 되면, // 이펙트 내부에서의 아이템 포인터도 NULL이 되겠지... SAFE_DELETE(pVampirePortalItem); } pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pVampire, getSkillType(), NULL); } } catch(Throwable & t) { executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " 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 }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 인벤토리 핸들러 ////////////////////////////////////////////////////////////////////////////// void TransformToWolf::execute(Vampire* pVampire, ObjectID_t InvenObjectID, ObjectID_t InventoryItemObjectID, CoordInven_t X, CoordInven_t Y, CoordInven_t TargetX, CoordInven_t TargetY, VampireSkillSlot* pSkillSlot) 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(); Inventory* pInventory = pVampire->getInventory(); Assert(pPlayer != NULL); Assert(pZone != NULL); Assert(pInventory!= NULL); SubInventory* pInventoryItem = NULL; int invenID = 0; if (InventoryItemObjectID != 0 ) { //cout << "서브 인벤토리에서 사용 : " << InventoryItemObjectID << endl; CoordInven_t X, Y; pInventoryItem = dynamic_cast<SubInventory*>(pInventory->findItemOID(InventoryItemObjectID, X, Y )); TradeManager* pTradeManager = pZone->getTradeManager(); Assert(pTradeManager != NULL); if (pInventoryItem == NULL || pTradeManager->hasTradeInfo(pVampire->getName()) ) { //cout << "근데 서브 인벤토리가 없다." <<endl; executeSkillFailException(pVampire, getSkillType()); return; } pInventory = pInventoryItem->getInventory(); invenID = pInventoryItem->getItemID(); } Item* pItem = pInventory->getItem(X, Y); Assert(pItem != NULL); // 적당한 아이템이 아니라면 당연히 변신할 수 없다. // PK존에서는 변신할 수 없다. if (pItem->getItemClass() != Item::ITEM_CLASS_VAMPIRE_ETC || pItem->getItemType() != 0 || pVampire->hasRelicItem() || g_pPKZoneInfoManager->isPKZone(pZone->getZoneID() ) || pVampire->isFlag(Effect::EFFECT_CLASS_REFINIUM_TICKET ) || GDRLairManager::Instance().isGDRLairZone(pZone->getZoneID()) ) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } GCSkillToInventoryOK1 _GCSkillToInventoryOK1; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); ZoneCoord_t x = pVampire->getX(); ZoneCoord_t y = pVampire->getY(); // Knowledge of Innate 가 있다면 hit bonus 10 int HitBonus = 0; if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_INNATE ) ) { RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_INNATE); Assert(pRankBonus != NULL); HitBonus = pRankBonus->getPoint(); } int RequiredMP = decreaseConsumeMP(pVampire, pSkillInfo); bool bManaCheck = hasEnoughMana(pVampire, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pVampire); bool bHitRoll = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pSkillSlot, HitBonus); bool bMoveModeCheck = pVampire->isWalking(); bool bEffected = pVampire->isFlag(Effect::EFFECT_CLASS_TRANSFORM_TO_WOLF) || pVampire->isFlag(Effect::EFFECT_CLASS_HAS_FLAG) || pVampire->isFlag(Effect::EFFECT_CLASS_HAS_SWEEPER); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bMoveModeCheck && !bEffected) { decreaseMana(pVampire, RequiredMP, _GCSkillToInventoryOK1); SkillInput input(pVampire); SkillOutput output; computeOutput(input, output); // 이펙트 클래스를 만들어 붙인다. EffectTransformToWolf* pEffectTTW = new EffectTransformToWolf(pVampire); pEffectTTW->setDeadline(999999999); pVampire->addEffect(pEffectTTW); pVampire->setFlag(Effect::EFFECT_CLASS_TRANSFORM_TO_WOLF); // 이로 인해서 변하는 능력치들을 보내준다. VAMPIRE_RECORD prev; pVampire->getVampireRecord(prev); pVampire->initAllStat(); pVampire->addModifyInfo(prev, _GCSkillToInventoryOK1); _GCSkillToInventoryOK1.setSkillType(SkillType); _GCSkillToInventoryOK1.setCEffectID(0); _GCSkillToInventoryOK1.setDuration(0); pPlayer->sendPacket(&_GCSkillToInventoryOK1); // 뱀파이어 대신 늑대를 더하라고 알려준다. GCAddWolf gcAddWolf; gcAddWolf.setObjectID(pVampire->getObjectID()); gcAddWolf.setName(pVampire->getName()); gcAddWolf.setXYDir(x, y, pVampire->getDir()); gcAddWolf.setItemType(pItem->getItemType()); gcAddWolf.setCurrentHP(pVampire->getHP()); gcAddWolf.setMaxHP(pVampire->getHP(ATTR_MAX)); gcAddWolf.setGuildID(pVampire->getGuildID()); pZone->broadcastPacket(x, y, &gcAddWolf, pVampire); decreaseItemNum(pItem, pInventory, pVampire->getName(), STORAGE_INVENTORY, invenID, X, Y); if (pVampire->getPetInfo() != NULL ) { pVampire->setPetInfo(NULL); sendPetInfo(dynamic_cast<GamePlayer*>(pVampire->getPlayer()), true); } pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pVampire, getSkillType(), NULL); } } catch(Throwable & t) { executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }