////////////////////////////////////////////////////////////////////////////// // 뱀파이어 인벤토리 핸들러 ////////////////////////////////////////////////////////////////////////////// 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 }
//////////////////////////////////////////////////////////////////////////////// // is satisfied? //////////////////////////////////////////////////////////////////////////////// bool ConditionEnterCastle::isSatisfied (Creature * pCreature1 , Creature * pCreature2, void* pParam) const throw() { /*if (!g_pVariableManager->isActiveCastle()) { return false; }*/ // 나중에 전쟁중인지 체크해야 된다 Assert(pCreature2 != NULL); Assert(pCreature2->isPC()); //cout << "Condition: EnterCastle" << endl; bool bPayPlay = false; GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pCreature2->getPlayer()); Assert(pGamePlayer!=NULL); #if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__) // 이미 유료존에 있는 경우라면... 관계없겠지. // 패밀리 요금 적용중일 경우 if (pGamePlayer->isPayPlaying() || pGamePlayer->isFamilyFreePass()) { bPayPlay = true; } else { // 일단 zone 요금 체크 string connectIP = pGamePlayer->getSocket()->getHost(); if (pGamePlayer->loginPayPlay(connectIP, pGamePlayer->getID())) { sendPayInfo(pGamePlayer); bPayPlay = true; } } #else bPayPlay = true; #endif // 돈 낸 사람만 castle 에 들어갈 수 있다. if (bPayPlay) { // 존을 찾는다. Zone* pZone = getZoneByZoneID(m_TargetZoneID); Assert(pZone!=NULL); // castle 이 아니면 체크할 필요가 없는거다. if (!pZone->isCastle()) { return true; } // 종족간 전쟁중에는 종족에 상관없이 누구나 통과시켜야 한다. // 동족간 전쟁중에는 타종족을 통과시켜서는 안 된다. // 평시에는 NPC를 통해야 하므로 누구도 통과시킬 수 없다. // 전쟁시스템 만들때 이거 다 추가시켜야 된다. 2003. 1.20. PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2); return g_pCastleInfoManager->canPortalActivate(m_TargetZoneID, pPC); } return false; }
void CGUseMessageItemFromInventoryHandler::executeEventTree(CGUseMessageItemFromInventory* 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(); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature); Inventory* pInventory = pPC->getInventory(); Zone* pZone = pPC->getZone(); CoordInven_t InvenX = pPacket->getX(); CoordInven_t InvenY = pPacket->getY(); Item* pItem = pInventory->getItem(InvenX, InvenY); ObjectID_t ItemObjectID = pItem->getObjectID(); MonsterType_t MType = 0; int time = 0; switch (pItem->getItemType() ) { case 12: MType = 482; time = g_pVariableManager->getVariable(CHRISTMAS_TREE_DECAY_TIME ) / 10; break; case 26: MType = 650; time = 21600; break; case 27: MType = 650; time = 43200; break; case 28: MType = 650; time = 86400; break; default: { filelog("EventTree.log", "이상한 아템을 썼다. : %s 가 %d", pPC->getName().c_str(), pItem->getItemType()); GCCannotUse _GCCannotUse; _GCCannotUse.setObjectID(pPacket->getObjectID()); pGamePlayer->sendPacket(&_GCCannotUse); } return; } // 타일에 스킬을 쓰는 것이라고 보고 쓸 수 있는지를 체크한다. // 안전지대에서는 사용할 수 없다. // 쓸 수 있는 아이템 타입인지 왁인한다. ItemType 이 12인 것만 사용할 수 있다. // 근처에(플레이어 주위의 5x5타일 이내) 다른 트리가 있다면 사용할 수 없다. if (!isAbleToUseTileSkill(pCreature ) || pZone->isMasterLair() || ItemObjectID != pPacket->getObjectID() || checkCorpse(pZone, MType, pPC->getX() - 2, pPC->getY() - 2, pPC->getX() + 2, pPC->getY() + 2 ) ) { GCCannotUse _GCCannotUse; _GCCannotUse.setObjectID(pPacket->getObjectID()); pGamePlayer->sendPacket(&_GCCannotUse); return; } // 성이면 성주 길드원만 쓸 수 있다. if (!pPC->isGOD() ) { if (pZone->isCastle() ) { if (!g_pCastleInfoManager->isCastleMember(pZone->getZoneID(), pPC ) ) { GCCannotUse _GCCannotUse; _GCCannotUse.setObjectID(pPacket->getObjectID()); pGamePlayer->sendPacket(&_GCCannotUse); return; } } // 성이 아닌 곳의 안전지대에선 절대 못 쓴다. else if (pZone->getZoneLevel(pCreature->getX(), pCreature->getY()) & SAFE_ZONE) { GCCannotUse _GCCannotUse; _GCCannotUse.setObjectID(pPacket->getObjectID()); pGamePlayer->sendPacket(&_GCCannotUse); return; } } /* // 트리를 존에 추가한다. (트리는 몬스터 시체를 이용한다) MonsterCorpse* pMonsterCorpse = new MonsterCorpse(482, pPacket->getMessage(), 2); Assert(pMonsterCorpse!=NULL); pZone->getObjectRegistry().registerObject(pMonsterCorpse); // 생성된 시체를 존에 추가한다. int delayTime = g_pVariableManager->getVariable(CHRISTMAS_TREE_DECAY_TIME); // by sigi. 2002.12.17 TPOINT pt = pZone->addItem(pMonsterCorpse, pPC->getX(), pPC->getY(), true, delayTime); // 6시간 뒤에 트리(시체)가 사라진다. if (pt.x == -1)*/ if (!createBulletinBoard(pZone, pPC->getX(), pPC->getY(), MType, pPacket->getMessage(), VSDateTime::currentDateTime().addSecs(time ) ) ) { GCCannotUse _GCCannotUse; _GCCannotUse.setObjectID(pPacket->getObjectID()); pGamePlayer->sendPacket(&_GCCannotUse); return; } // 사용한 아이템이므로 지워준다. pInventory->deleteItem(InvenX, InvenY); pItem->destroy(); SAFE_DELETE(pItem); // 아이템을 사용했다고 클라이언트에 알린다. GCUseOK gcUseOK; pGamePlayer->sendPacket(&gcUseOK); //pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcAddEffectToTile); #endif __END_DEBUG_EX __END_CATCH }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionRegisterSiege::execute (Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY #ifndef __OLD_GUILD_WAR__ Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); SYSTEM_RETURN_IF_NOT(SYSTEM_GUILD_WAR); GCNPCResponse gcNPCResponse; PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2); GuildID_t guildID = pPC->getGuildID(); if (!g_pVariableManager->isWarActive() || !g_pVariableManager->isActiveGuildWar() ) { gcNPCResponse.setCode(NPC_RESPONSE_WAR_UNAVAILABLE); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; } if (!g_pGuildManager->isGuildMaster(guildID, pPC ) ) { gcNPCResponse.setCode(NPC_RESPONSE_NOT_GUILD_MASTER); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; } Gold_t warRegistrationFee = g_pVariableManager->getVariable(WAR_REGISTRATION_FEE); if (pPC->getGold() < warRegistrationFee ) { gcNPCResponse.setCode(NPC_RESPONSE_NOT_ENOUGH_MONEY); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; } Zone* pZone = getZoneByZoneID(m_ZoneID); Assert(pZone != NULL); Assert(pZone->isCastle()); WarScheduler* pWarScheduler = pZone->getWarScheduler(); Assert(pWarScheduler != NULL); /* 성을 소유했어도 전쟁 신청이 되도록 수정함 (자기 성에는 신청 못하겠지 -_-;;) // 이미 성을 소유한 길드인가? if (g_pGuildManager->hasCastle(guildID ) ) { gcNPCResponse.setCode(NPC_RESPONSE_ALREADY_HAS_CASTLE); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; } */ // ServerID_t serverID; // ZoneID_t zoneID; // bool bHasCastle = g_pGuildManager->hasCastle(guildID , serverID , zoneID); // if (bHasCastle && serverID == g_pConfig->getPropertyInt("ServerID" ) && zoneID == m_ZoneID ) CastleInfo* pCastleInfo = g_pCastleInfoManager->getCastleInfo(m_ZoneID); GuildID_t ownerGuildID = pCastleInfo->getGuildID(); if (guildID == ownerGuildID ) { gcNPCResponse.setCode(NPC_RESPONSE_ALREADY_HAS_CASTLE); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; } // 이미 전쟁 신청을 했는가? if (g_pGuildManager->hasWarSchedule(guildID ) ) { gcNPCResponse.setCode(NPC_RESPONSE_WAR_ALREADY_REGISTERED); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; } // 전쟁 스케쥴이 다 찼는가? /* if (!pWarScheduler->canAddWar(WAR_GUILD ) ) { gcNPCResponse.setCode(NPC_RESPONSE_WAR_SCHEDULE_FULL); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; } GuildWar* pWar = new GuildWar(m_ZoneID, guildID, War::WAR_STATE_WAIT); pWar->setRegistrationFee(warRegistrationFee); if (!pWarScheduler->addWar(pWar ) ) { gcNPCResponse.setCode(NPC_RESPONSE_WAR_SCHEDULE_FULL); pPC->getPlayer()->sendPacket(&gcNPCResponse); SAFE_DELETE(pWar); return; }*/ Schedule* pNextSchedule = pWarScheduler->getRecentSchedule(); Work* pNextWork = NULL; if (pNextSchedule != NULL ) pNextWork = pNextSchedule->getWork(); SiegeWar* pNextWar = dynamic_cast<SiegeWar*>(pNextWork); if (pNextWar == NULL ) { pNextWar = new SiegeWar(m_ZoneID, War::WAR_STATE_WAIT); pNextWar->addRegistrationFee(warRegistrationFee); pNextWar->addChallengerGuild(guildID); if (!pWarScheduler->addWar(pNextWar ) ) { gcNPCResponse.setCode(NPC_RESPONSE_WAR_SCHEDULE_FULL); pPC->getPlayer()->sendPacket(&gcNPCResponse); SAFE_DELETE(pNextWar); return; } } else if (pNextWar->getChallengerGuildCount() < 5 ) { WarSchedule* pNextWarSchedule = dynamic_cast<WarSchedule*>(pNextSchedule); Assert(pNextWarSchedule != NULL); pNextWar->addRegistrationFee(warRegistrationFee); pNextWar->addChallengerGuild(guildID); pNextWarSchedule->save(); } else { gcNPCResponse.setCode(NPC_RESPONSE_WAR_SCHEDULE_FULL); pPC->getPlayer()->sendPacket(&gcNPCResponse); // SAFE_DELETE(pNextWar); return; } pPC->decreaseGoldEx(warRegistrationFee); GCModifyInformation gcMI; gcMI.addLongData(MODIFY_GOLD, pPC->getGold()); pPC->getPlayer()->sendPacket(&gcMI); gcNPCResponse.setCode(NPC_RESPONSE_WAR_REGISTRATION_OK); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; #endif __END_CATCH }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionDenyReinforce::execute (Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY #ifndef __OLD_GUILD_WAR__ Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); SYSTEM_RETURN_IF_NOT(SYSTEM_GUILD_WAR); GCNPCResponse gcNPCResponse; PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2); GuildID_t guildID = pPC->getGuildID(); if (!g_pVariableManager->isWarActive() || !g_pVariableManager->isActiveGuildWar() ) { gcNPCResponse.setCode(NPC_RESPONSE_WAR_UNAVAILABLE); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; } if (!g_pGuildManager->isGuildMaster(guildID, pPC ) ) { gcNPCResponse.setCode(NPC_RESPONSE_NOT_GUILD_MASTER); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; } Zone* pZone = getZoneByZoneID(m_ZoneID); Assert(pZone != NULL); Assert(pZone->isCastle()); WarScheduler* pWarScheduler = pZone->getWarScheduler(); Assert(pWarScheduler != NULL); CastleInfo* pCastleInfo = g_pCastleInfoManager->getCastleInfo(m_ZoneID); GuildID_t ownerGuildID = pCastleInfo->getGuildID(); if (guildID != ownerGuildID ) { gcNPCResponse.setCode(NPC_RESPONSE_NOT_YOUR_CASTLE); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; } Schedule* pNextSchedule = pWarScheduler->getRecentSchedule(); Work* pNextWork = NULL; if (pNextSchedule != NULL ) pNextWork = pNextSchedule->getWork(); SiegeWar* pNextWar = dynamic_cast<SiegeWar*>(pNextWork); if (pNextWar == NULL || pNextWar->recentReinforceCandidate() == 0 ) { gcNPCResponse.setCode(NPC_RESPONSE_NO_WAR_REGISTERED); pPC->getPlayer()->sendPacket(&gcNPCResponse); //SAFE_DELETE(pNextWar); return; } else if (pNextWar->getReinforceGuildID() == 0 ) { WarSchedule* pNextWarSchedule = dynamic_cast<WarSchedule*>(pNextSchedule); Assert(pNextWarSchedule != NULL); if (!pNextWar->denyReinforce() ) { gcNPCResponse.setCode(NPC_RESPONSE_CANNOT_ACCEPT); pPC->getPlayer()->sendPacket(&gcNPCResponse); //SAFE_DELETE(pNextWar); return; } } else { gcNPCResponse.setCode(NPC_RESPONSE_ALREADY_REINFORCE_ACCEPTED); pPC->getPlayer()->sendPacket(&gcNPCResponse); //SAFE_DELETE(pNextWar); return; } gcNPCResponse.setCode(NPC_RESPONSE_ACCEPT_OK); pPC->getPlayer()->sendPacket(&gcNPCResponse); gcNPCResponse.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; #endif __END_CATCH }