//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionWaitForMeetCouple::execute (Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); SYSTEM_RETURN_IF_NOT(SYSTEM_COUPLE); NPC* pNPC = dynamic_cast<NPC*>(pCreature1); Assert(pNPC != NULL); // cout << "ActionWaitForMeeCouple(" << pNPC->getObjectID() << ")" << endl; GCNPCResponse gcNPCResponse; gcNPCResponse.setCode(NPC_RESPONSE_WAIT_FOR_MEET_COUPLE); Player* pPlayer = pCreature2->getPlayer(); pPlayer->sendPacket(&gcNPCResponse); __END_CATCH }
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 }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionShowWarSchedule::execute (Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2); GCWarScheduleList gcWarScheduleList; if (g_pVariableManager->isWarActive() && makeGCWarScheduleList(&gcWarScheduleList, m_ZoneID ) ) { pPC->getPlayer()->sendPacket(&gcWarScheduleList); } else { GCNPCResponse gcNPCResponse; gcNPCResponse.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPC->getPlayer()->sendPacket(&gcNPCResponse); } __END_CATCH }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionCallHelicopter::execute (Creature * pCreature1, Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); // 슬레이어만이 이 액션의 대상이 된다. if (!pCreature2->isSlayer()) return; if (pCreature2->isFlag(Effect::EFFECT_CLASS_HAS_FLAG) || pCreature2->isFlag(Effect::EFFECT_CLASS_HAS_SWEEPER)) return; Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature2); Assert(pSlayer != NULL); // 슬레이어에게 이펙트를 걸어준다. if (!pSlayer->isFlag(Effect::EFFECT_CLASS_SLAYER_PORTAL)) pSlayer->setFlag(Effect::EFFECT_CLASS_SLAYER_PORTAL); Player* pPlayer = pCreature2->getPlayer(); Assert(pPlayer != NULL); GCNPCResponse gcNPCResponse; gcNPCResponse.setCode(NPC_RESPONSE_INTERFACE_HELICOPTER); pPlayer->sendPacket(&gcNPCResponse); __END_CATCH }
void CGRequestRepairHandler::execute (CGRequestRepair* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ Assert(pPacket != NULL); Assert(pPlayer != NULL); ObjectID_t ITEMOID = pPacket->getObjectID(); GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Creature* pPC = pGamePlayer->getCreature(); bool bSlayer = false; bool bVampire = false; bool bOusters = false; Item* pItem = NULL; // 플레이어가 슬레이어인지 뱀파이어인지 구분. if (pPC->isSlayer()) bSlayer = true; else if (pPC->isVampire()) bVampire = true; else if (pPC->isOusters()) bOusters = true; else throw ProtocolException("CGRequestRepairHandler::execute() : Unknown player creature!"); if (ITEMOID == 0) { // ObjectID가 0이라면 모든 아이템을 수리하고자 하는 것이다. executeAll(pPacket, pPlayer); } else { if (bSlayer) pItem = (dynamic_cast<Slayer*>(pPC))->findItemOID(ITEMOID); else if (bVampire) pItem = (dynamic_cast<Vampire*>(pPC))->findItemOID(ITEMOID); else if (bOusters) pItem = (dynamic_cast<Ousters*>(pPC))->findItemOID(ITEMOID); // 플레이어가 아이템을 가지고 있다면 if (pItem != NULL) { // 그 아이템이 모터 사이클 키라면... if (pItem->getItemClass() == Item::ITEM_CLASS_KEY && pItem->getItemType() == 2) { executeMotorcycle(pPacket, pPlayer); return; } else executeNormal(pPacket, pPlayer); } else { // 아이템이 없으니, 당연히 수리할 수 없다. GCNPCResponse response; response.setCode(NPC_RESPONSE_REPAIR_FAIL_ITEM_NOT_EXIST); pPlayer->sendPacket(&response); } } #endif __END_DEBUG_EX __END_CATCH }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionSilverCoating::execute (Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); GCNPCResponse okpkt; okpkt.setCode(NPC_RESPONSE_INTERFACE_SILVER_COATING); Player* pPlayer = pCreature2->getPlayer(); Assert(pPlayer != NULL); pPlayer->sendPacket(&okpkt); __END_CATCH }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionDownSkill::execute (Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); Player* pPlayer = pCreature2->getPlayer(); Assert(pPlayer != NULL); GCNPCResponse okpkt; okpkt.setCode(NPC_RESPONSE_DOWN_SKILL); pPlayer->sendPacket(&okpkt); __END_CATCH }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionDestroyGuild::execute (Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); SYSTEM_RETURN_IF_NOT(SYSTEM_GUILD); Player* pPlayer = pCreature2->getPlayer(); Assert(pPlayer != NULL); GCNPCResponse okpkt; okpkt.setCode(NPC_RESPONSE_INTERFACE_DESTROY_GUILD); pPlayer->sendPacket(&okpkt); __END_CATCH }
void CGStashRequestBuyHandler::execute (CGStashRequestBuy* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX __BEGIN_DEBUG #ifdef __GAME_SERVER__ Assert(pPacket != NULL); Assert(pPlayer != NULL); GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Creature* pPC = pGamePlayer->getCreature(); PlayerCreature* pPlayerCreature = dynamic_cast<PlayerCreature*>(pPC); BYTE curStashNum = pPlayerCreature->getStashNum(); // 가지고 있는 보관함이 맥스라면 리턴 if (curStashNum >= STASH_RACK_MAX) { GCNPCResponse failpkt; failpkt.setCode(NPC_RESPONSE_STASH_SELL_FAIL_MAX); pPlayer->sendPacket(&failpkt); return; } Price_t price = g_pPriceManager->getStashPrice(curStashNum+1); // 돈이 모자라도 실패쥐. if (pPlayerCreature->getGold() < price) { GCNPCResponse failpkt; failpkt.setCode(NPC_RESPONSE_STASH_SELL_FAIL_MONEY); pPlayer->sendPacket(&failpkt); return; } // 보관함 갯수를 한 칸 늘려주고... pPlayerCreature->setStashNumEx(curStashNum+1); // 돈을 줄인다. //pPlayerCreature->setGoldEx(pPlayerCreature->getGold() - price); // by sigi. 2002.9.4 pPlayerCreature->decreaseGoldEx(price); // 마지막으로 OK 패킷을 날려준다. GCNPCResponse okpkt; okpkt.setCode(NPC_RESPONSE_STASH_SELL_OK); pPlayer->sendPacket(&okpkt); #endif __END_DEBUG __END_DEBUG_EX __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 }
void CGSelectQuestHandler::execute (CGSelectQuest* pPacket , Player* pPlayer) throw(Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ GamePlayer* pGP = dynamic_cast<GamePlayer*>(pPlayer); Assert(pGP != NULL); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pGP->getCreature()); GCNPCResponse gcNPCR; gcNPCR.setCode(NPC_RESPONSE_QUEST); Creature* pCreature = pPC->getZone()->getCreature(pPacket->getNPCObjectID()); if (pCreature == NULL || !pCreature->isNPC() ) { gcNPCR.setParameter((uint)START_FAIL_CANNOT_APPLY_QUEST); pPlayer->sendPacket(&gcNPCR); return; } NPC* pNPC = dynamic_cast<NPC*>(pCreature); if (pNPC == NULL ) { gcNPCR.setParameter((uint)START_FAIL_CANNOT_APPLY_QUEST); pPlayer->sendPacket(&gcNPCR); return; } QuestInfoManager* pQIM = pNPC->getQuestInfoManager(); if (pQIM == NULL ) { gcNPCR.setParameter((uint)START_FAIL_CANNOT_APPLY_QUEST); pPlayer->sendPacket(&gcNPCR); return; } pPC->getQuestManager()->adjustQuestStatus(); QuestMessage code = pQIM->startQuest(pPacket->getQuestID(), pPC); list<QuestID_t> qList; pQIM->getEventQuestIDs(pPC->getQuestManager()->getEventQuestAdvanceManager()->getQuestLevel(), pPC, back_inserter(qList)); gcNPCR.setParameter((uint)code); if (!pQIM->isEventQuest(pPacket->getQuestID() ) ) pPlayer->sendPacket(&gcNPCR); if (code == START_SUCCESS ) { pPC->sendCurrentQuestInfo(); //cout << "Quest 시작 " << pPC->getName() << " " << pPacket->getQuestID() << endl; } else { //cout << "Quest 시작 실패 " << pPC->getName() << " " << (int)code << endl; } #endif // __GAME_SERVER__ __END_DEBUG_EX __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 모터 사이클을 처리한다. ////////////////////////////////////////////////////////////////////////////// void CGRequestRepairHandler::executeMotorcycle (CGRequestRepair* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ // 패킷 정보를 뽑아낸다. ObjectID_t ITEMOID = pPacket->getObjectID(); Creature* pPC = dynamic_cast<GamePlayer*>(pPlayer)->getCreature(); Zone* pZone = pPC->getZone(); Gold_t playerMoney = 0; ZoneCoord_t CenterX = pPC->getX(); ZoneCoord_t CenterY = pPC->getY(); Item* pItem = NULL; bool bSlayer = false; bool bVampire = false; bool bOusters = false; GCNPCResponse response; // 플레이어가 슬레이어인지 뱀파이어인지 구분. if (pPC->isSlayer()) bSlayer = true; else if (pPC->isVampire()) bVampire = true; else if (pPC->isOusters()) bOusters = true; else throw ProtocolException("CGRequestRepairHandler::execute() : Unknown player creature!"); // 플레이어가 수리하려고 하는 아이템을 가지고 있는지 // 상위에서 검사를 하기 때문에, pItem이 널일리는 없다. if (bSlayer) { pItem = (dynamic_cast<Slayer*>(pPC))->findItemOID(ITEMOID); playerMoney = (dynamic_cast<Slayer*>(pPC))->getGold(); } else if (bVampire) { pItem = (dynamic_cast<Vampire*>(pPC))->findItemOID(ITEMOID); playerMoney = (dynamic_cast<Vampire*>(pPC))->getGold(); } else if (bOusters) { pItem = (dynamic_cast<Ousters*>(pPC))->findItemOID(ITEMOID); playerMoney = (dynamic_cast<Ousters*>(pPC))->getGold(); } // 주위 일정 범위를 검색해서, 모터 사이클이 있는지 확인한다. for (ZoneCoord_t zx=CenterX-5; zx<=CenterX+5; zx++) { for (ZoneCoord_t zy=CenterY-5; zy<=CenterY+5; zy++) { if (!isValidZoneCoord(pZone, zx, zy)) continue; Tile & tile = pZone->getTile(zx, zy); if (tile.hasItem()) { Item* pItemOnTile = tile.getItem(); Assert(pItemOnTile != NULL); // 만일 아이템이 타일 위에 있을 경우, 모터 사이클인지 확인한다. if (pItemOnTile->getItemClass() == Item::ITEM_CLASS_MOTORCYCLE) { DWORD targetID = dynamic_cast<Key*>(pItem)->getTarget(); ItemID_t motorcycleID = pItemOnTile->getItemID(); if (targetID == motorcycleID) { Price_t repairPrice = g_pPriceManager->getRepairPrice(pItemOnTile); if (repairPrice > playerMoney) { response.setCode(NPC_RESPONSE_REPAIR_FAIL_MONEY); pPlayer->sendPacket(&response); return; } // 수리한다. repairItem(pItemOnTile); // 저장한다. //pItemOnTile->save(pPC->getName(), STORAGE_ZONE, pZone->getZoneID(), zx, zy); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Durability=%d", pItemOnTile->getDurability()); pItemOnTile->tinysave(pField); // 돈을 줄인다. //if (bSlayer) (dynamic_cast<Slayer*>(pPC))->setGoldEx(playerMoney-repairPrice); //else (dynamic_cast<Vampire*>(pPC))->setGoldEx(playerMoney-repairPrice); // by sigi. 2002.9.4 (dynamic_cast<PlayerCreature*>(pPC))->decreaseGoldEx(repairPrice); response.setCode(NPC_RESPONSE_REPAIR_OK); response.setParameter(playerMoney-repairPrice); pPlayer->sendPacket(&response); return; } // if (targetID == } // if (itemclas == MOTORCYCLE } } // end of for (ZoneCoord_t zy=CenterY-5; zy<=CenterY+5; zy++) } // end of for (ZoneCoord_t zx=CenterX-5; zx<=CenterX+5; zx++) // FOR 루프를 다 돌고, 이까지 왔다는 것은 근처에 오토바이가 없다는 말이당... // 그러므로 모터 사이클 팔기가 실패했다는 것을 알린다. response.setCode(NPC_RESPONSE_REPAIR_FAIL_ITEM_NOT_EXIST); pPlayer->sendPacket(&response); #endif __END_DEBUG_EX __END_CATCH }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionRewardEventQuest::execute (Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2); Assert(pPC != NULL); if (pPC->getQuestItem() != NULL ) { TPOINT pt; Item* pItem = pPC->getQuestItem(); if (pItem == NULL || !pPC->getInventory()->getEmptySlot(pItem, pt ) ) { GCNPCResponse gcNPCResponse; gcNPCResponse.setCode(NPC_RESPONSE_QUEST); gcNPCResponse.setParameter(COMPLETE_FAIL_NO_INVENTORY_SPACE); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; } if (pPC->getInventory()->addItem(pItem, pt ) ) { pPC->setQuestItem(NULL); pPC->getZone()->registerObject(pItem); pItem->create(pPC->getName(), STORAGE_INVENTORY, 0, pt.x, pt.y); if (pItem->isUnique() || pItem->isTimeLimitItem() ) { pPC->addTimeLimitItem(pItem, 604800); pPC->sendTimeLimitItemInfo(); } GCCreateItem gcCreateItem; makeGCCreateItem(&gcCreateItem, pItem, pt.x, pt.y); pPC->getPlayer()->sendPacket(&gcCreateItem); GCNPCResponse gcNPCResponse; gcNPCResponse.setCode(NPC_RESPONSE_QUEST); gcNPCResponse.setParameter(COMPLETE_SUCCESS); pPC->getPlayer()->sendPacket(&gcNPCResponse); remainTraceLog(pItem, pCreature1->getName(), pCreature2->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC); return; } else { GCNPCResponse gcNPCResponse; gcNPCResponse.setCode(NPC_RESPONSE_QUEST); gcNPCResponse.setParameter(COMPLETE_FAIL_NO_INVENTORY_SPACE); pPC->getPlayer()->sendPacket(&gcNPCResponse); return; } } int questLevel = pPC->getQuestManager()->getEventQuestAdvanceManager()->getQuestLevel(); ScriptID_t sID = m_ScriptID[ questLevel ]; QuestID_t qID; if (!pPC->getQuestManager()->successEventQuest(questLevel, qID ) ) sID = m_CounterScriptID; if (pPC->getQuestManager()->getEventQuestAdvanceManager()->getStatus(questLevel) == EventQuestAdvance::EVENT_QUEST_INIT && questLevel > 1 ) sID = m_CancelScriptID; GCNPCAsk gcNPCAsk; gcNPCAsk.setObjectID(pCreature1->getObjectID()); gcNPCAsk.setScriptID(sID); gcNPCAsk.setNPCID(dynamic_cast<NPC*>(pCreature1)->getNPCID()); Player* pPlayer = pCreature2->getPlayer(); pPlayer->sendPacket(&gcNPCAsk); __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 }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionGiveLotto::execute (Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2); Assert(pPC != NULL); QuestID_t qID; int questLevel = m_QuestLevel; if (questLevel < 0 ) questLevel = pPC->getQuestManager()->getEventQuestAdvanceManager()->getQuestLevel() - 1; //cout << "Activated : " << toString() << " ... " << pPC->getName() << " ... " << questLevel << endl; EventQuestAdvance::Status status = pPC->getQuestManager()->getEventQuestAdvanceManager()->getStatus(questLevel); int ownerQuestLevel = pPC->getQuestManager()->getEventQuestAdvanceManager()->getQuestLevel(); if ( (ownerQuestLevel > questLevel && status == EventQuestAdvance::EVENT_QUEST_ADVANCED ) || ((questLevel == 4 && ownerQuestLevel == -1 ) || pPC->getQuestManager()->successEventQuest(questLevel, qID ) ) ) { GamePlayer* pGP = dynamic_cast<GamePlayer*>(pPC->getPlayer()); Assert (pGP != NULL); // if (g_pConfig->getPropertyInt("IsNetMarble" ) || !pGP->isPayPlaying() ) if (true ) { pPC->getQuestManager()->getEventQuestAdvanceManager()->rewarded(questLevel); pPC->getQuestManager()->getEventQuestAdvanceManager()->save(); if (questLevel != 4 ) pPC->getQuestManager()->questRewarded(qID); else pPC->getQuestManager()->cancelQuest(); pPC->setLottoQuestLevel(questLevel); list<Item*> iList; pPC->getInventory()->clearQuestItem(iList); list<Item*>::iterator itr = iList.begin(); list<Item*>::iterator endItr = iList.end(); for (; itr != endItr ; ++itr ) { GCDeleteInventoryItem gcDII; gcDII.setObjectID((*itr)->getObjectID()); pPC->getPlayer()->sendPacket(&gcDII); (*itr)->destroy(); SAFE_DELETE(*itr); } iList.clear(); CGLotterySelect cgLS; cgLS.setType(TYPE_FINISH_SCRATCH); cgLS.setQuestLevel(0); cgLS.setGiftID(0); CGLotterySelectHandler::execute(&cgLS, pPC->getPlayer()); // cgLS.execute(pPC->getPlayer()); } else { Player* pPlayer = pCreature2->getPlayer(); // pPlayer->sendPacket(&gcSM); GCNPCResponse gcNPCResponse; gcNPCResponse.setCode(NPC_RESPONSE_LOTTERY); gcNPCResponse.setParameter((uint)questLevel); pPlayer->sendPacket(&gcNPCResponse); filelog("EventQuest.log","ActionGiveLotto : %d to %s", questLevel, pPC->getName().c_str()); } } GCNPCResponse gcNPCResponse; gcNPCResponse.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPC->getPlayer()->sendPacket(&gcNPCResponse); __END_CATCH }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionGiveEventItem::execute(Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2); Assert(pPC != NULL); Player* pPlayer = pPC->getPlayer(); Assert(pPlayer != NULL); Inventory* pInventory = pPC->getInventory(); Assert(pInventory != NULL); Zone* pZone = pPC->getZone(); Assert(pZone != NULL); FlagSet* pFlagSet = pPC->getFlagSet(); Item::ItemClass ItemClass; ItemType_t ItemType; OptionType_t OptionType; OptionType_t OptionType2; Item* pItem; // 이벤트 진행 기간이 아닌 경우 if (!g_pVariableManager->isActiveGiveEventItem()) { GCNPCResponse response; response.setCode(NPC_RESPONSE_GIVE_EVENT_ITEM_FAIL_NOW); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } // 이 값과 관련해서 // 캐릭터 생성시에 FlagSet을 바꿔줘야한다. (default ON 으로) // 이미 선물을 교환해 갔다면 if (pFlagSet->isOn(m_FlagSetType ) ) { GCNPCResponse response; response.setCode(NPC_RESPONSE_GIVE_EVENT_ITEM_FAIL); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } LuaSelectItem* pLuaSelectItem = NULL; string luaFileName; if (pPC->isSlayer() ) { // 루아에 슬레이어 능력치의 합을 set한다. Slayer* pSlayer = dynamic_cast<Slayer*>(pPC); Assert(pSlayer != NULL); Attr_t sum = pSlayer->getSTR(ATTR_BASIC ) + pSlayer->getDEX(ATTR_BASIC ) + pSlayer->getINT(ATTR_BASIC); m_pLuaSlayerItem->setSum(sum); pLuaSelectItem = m_pLuaSlayerItem; luaFileName = m_SlayerFilename; } else if (pPC->isVampire() ) { // 루아에 뱀파이어의 레벨을 set한다. Vampire* pVampire = dynamic_cast<Vampire*>(pPC); Assert(pVampire != NULL); int level = pVampire->getLevel(); m_pLuaVampireItem->setLevel(level); pLuaSelectItem = m_pLuaVampireItem; luaFileName = m_VampireFilename; } //-------------------------------------------------------- // 속도 체크를 위해서 1000번 돌려보는 코드 // 결과는.. 0.07초 정도 나왔다. 감덩~ -_-; /* Timeval beforeTime; getCurrentTime(beforeTime); for (int i=0; i<1000; i++) { // 루아의 계산 결과를 받아 아이템을 생성한다. pLuaSelectItem->prepare(); int result = pLuaSelectItem->executeFile(luaFileName); LuaState::logError(result); pLuaSelectItem->clear(); } Timeval afterTime; getCurrentTime(afterTime); cout << "luaExecute time before : " << beforeTime.tv_sec << "." << beforeTime.tv_usec << endl; cout << "luaExecute time after : " << afterTime.tv_sec << "." << afterTime.tv_usec << endl; */ //-------------------------------------------------------- // 루아의 계산 결과를 받아 아이템을 생성한다. pLuaSelectItem->prepare(); int result = pLuaSelectItem->executeFile(luaFileName); LuaState::logError(result); ItemClass = pLuaSelectItem->getItemClass(); ItemType = pLuaSelectItem->getItemType(); OptionType = pLuaSelectItem->getOptionType(); OptionType2 = pLuaSelectItem->getOptionType2(); pLuaSelectItem->clear(); if(ItemClass >= Item::ITEM_CLASS_MAX ) //|| ItemType >= ITEM_TYPE_MAX || ItemType < 0 // || OptionType == 0) { filelog("GiveEventItemError.txt", "[ ItemInfo Error ] : ItemClass = %d , ItemType = %d , OptionType = %d", ItemClass, ItemType, OptionType); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } // 선물(Item)을 만든다. list<OptionType_t> optionTypeList; if (OptionType != 0 ) optionTypeList.push_back(OptionType); if (OptionType2 != 0 ) optionTypeList.push_back(OptionType2); pItem = g_pItemFactoryManager->createItem(ItemClass, ItemType, optionTypeList); Assert(pItem != NULL); _TPOINT pt; if (!pInventory->getEmptySlot(pItem, pt)) { SAFE_DELETE(pItem); GCNPCResponse response; response.setCode(NPC_RESPONSE_NO_EMPTY_SLOT); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } CoordInven_t X = pt.x; CoordInven_t Y = pt.y; // 선물을 인벤토리에 추가한다. pZone->getObjectRegistry().registerObject(pItem); pInventory->addItem(X, Y, pItem); pItem->create(pPC->getName(), STORAGE_INVENTORY, 0, X, Y); // ItemTraceLog 를 남긴다 if (pItem != NULL && pItem->isTraceItem() ) { remainTraceLog(pItem, pCreature1->getName(), pCreature2->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC); remainTraceLogNew(pItem, pCreature2->getName(), ITL_GET, ITLD_EVENTNPC, pCreature1->getZone()->getZoneID(), pCreature1->getX(), pCreature1->getY()); } // 클라이언트에 선물이 추가되었음을 알린다. GCCreateItem gcCreateItem; makeGCCreateItem(&gcCreateItem, pItem, X, Y); pPlayer->sendPacket(&gcCreateItem); // Flag을 켠다. pFlagSet->turnOn(m_FlagSetType); // Flag을 저장한다. pFlagSet->save(pPC->getName()); // 아이템 교환이 이루어 졌다고 클라이언트에 알린다. GCNPCResponse response; response.setCode(NPC_RESPONSE_GIVE_EVENT_ITEM_OK); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 일반 아이템을 처리한다. ////////////////////////////////////////////////////////////////////////////// void CGRequestRepairHandler::executeNormal (CGRequestRepair* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ ObjectID_t ITEMOID = pPacket->getObjectID(); Creature* pPC = dynamic_cast<GamePlayer*>(pPlayer)->getCreature(); bool bSlayer = false; bool bVampire = false; bool bOusters = false; Gold_t playerMoney = 0; Price_t repairPrice = 0; Item* pItem = NULL; Slayer* pSlayer = NULL; Vampire* pVampire = NULL; Ousters* pOusters = NULL; int storage = 0; int X = 0; int Y = 0; GCNPCResponse response; // 플레이어가 슬레이어인지 뱀파이어인지 구분. if (pPC->isSlayer()) bSlayer = true; else if (pPC->isVampire()) bVampire = true; else if (pPC->isOusters()) bOusters = true; // 플레이어가 수리하려고 하는 아이템을 가지고 있는지 검사 if (bSlayer) { pSlayer = dynamic_cast<Slayer*>(pPC); playerMoney = pSlayer->getGold(); pItem = pSlayer->findItemOID(ITEMOID, storage, X, Y); } else if (bVampire) { pVampire = dynamic_cast<Vampire*>(pPC); playerMoney = pVampire->getGold(); pItem = pVampire->findItemOID(ITEMOID, storage, X, Y); } else if (bOusters) { pOusters = dynamic_cast<Ousters*>(pPC); playerMoney = pOusters->getGold(); pItem = pOusters->findItemOID(ITEMOID, storage, X, Y); } // 플레이어가 수리하려고 하는 아이템을 가지고 있는지 // 상위에서 검사를 하기 때문에, pItem이 널일리는 없다. // 단, 수리할 수 없는 아이템인지를 검사한다. if (isRepairableItem(pItem) == false) { response.setCode(NPC_RESPONSE_REPAIR_FAIL_ITEM_TYPE); pPlayer->sendPacket(&response); return; } // 이전 내구도를 저장한다. Durability_t oldDurability = pItem->getDurability(); repairPrice = g_pPriceManager->getRepairPrice(pItem); if (repairPrice > playerMoney) { response.setCode(NPC_RESPONSE_REPAIR_FAIL_MONEY); pPlayer->sendPacket(&response); return; } // 수리한다. repairItem(pItem); // 수리한 아이템이 기어창의 아이템이고 이전 내구도가 0 이었다면 정보를 새로 보내줘야한다. if (storage == STORAGE_GEAR && oldDurability == 0 ) { if (bSlayer && pSlayer != NULL ) { pSlayer->initAllStatAndSend(); pSlayer->sendRealWearingInfo(); } else if (bVampire && pVampire != NULL ) { pVampire->initAllStatAndSend(); pVampire->sendRealWearingInfo(); } else if (bOusters && pOusters != NULL ) { pOusters->initAllStatAndSend(); pOusters->sendRealWearingInfo(); } } // 돈을 줄인다. if (bSlayer) { //pSlayer->setGoldEx(playerMoney-repairPrice); // by sigi. 2002.9.4 pSlayer->decreaseGoldEx(repairPrice); //log(LOG_REPAIR_ITEM, pSlayer->getName(), "", pItem->toString()); } else if (bVampire) { // by sigi. 2002.9.4 pVampire->decreaseGoldEx(repairPrice); //log(LOG_REPAIR_ITEM, pVampire->getName(), "", pItem->toString()); } else if (bOusters) { // by sigi. 2002.9.4 pOusters->decreaseGoldEx(repairPrice); //log(LOG_REPAIR_ITEM, pOusters->getName(), "", pItem->toString()); } // 아이템을 수리했다는 정보를 DB에다가 저장해준다. // 단 분명히 STORAGE_STASH가 돌아올 수 있지만, // 보관함에 있는 것을 수리한다는 것은 말이 안 되므로, // 저장하지 않는다. // item저장 최적화. by sigi. 2002.5.17 if (repairPrice>0) { char pField[80]; if (pItem->getItemClass()==Item::ITEM_CLASS_SLAYER_PORTAL_ITEM) { SlayerPortalItem* pSPItem = dynamic_cast<SlayerPortalItem*>(pItem); sprintf(pField, "Charge=%d", pSPItem->getCharge()); } else if (pItem->getItemClass()==Item::ITEM_CLASS_OUSTERS_SUMMON_ITEM) { OustersSummonItem* pOSItem = dynamic_cast<OustersSummonItem*>(pItem); sprintf(pField, "Charge=%d", pOSItem->getCharge()); } else { sprintf(pField, "Durability=%d", pItem->getDurability()); } pItem->tinysave(pField); } /* // 뭐가 됐든.. durability만 바꾸면 된다. // 근데.. ItemObject에 Durability field가 없는 것도 있고 // Charge를 저장해야 하는 것도 있다. // 그래서.. 일단은 모두 다 저장하는 save를 이용하도록 한다. switch (storage) { case STORAGE_INVENTORY: { pItem->save(pPC->getName(), STORAGE_INVENTORY, 0, X, Y); } break; case STORAGE_GEAR: { if (bSlayer) { pItem->save(pSlayer->getName(), STORAGE_GEAR, 0, X, 0); } else { pItem->save(pVampire->getName(), STORAGE_GEAR, 0, X, 0); } } break; default: break; } */ // OK 패킷을 날려준다. response.setCode(NPC_RESPONSE_REPAIR_OK); response.setParameter(playerMoney-repairPrice); pPlayer->sendPacket(&response); #endif __END_DEBUG_EX __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 모든 아이템 수리하기 ////////////////////////////////////////////////////////////////////////////// void CGRequestRepairHandler::executeAll(CGRequestRepair* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ Creature* pPC = dynamic_cast<GamePlayer*>(pPlayer)->getCreature(); Price_t repairPrice = 0; GCNPCResponse response; bool bSendRealWearingInfo = false; if (pPC->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pPC); // 모든 아이템을 합한 수리비를 계산한다. for (int i=0; i<Slayer::WEAR_MAX; i++) { Item* pItem = pSlayer->getWearItem((Slayer::WearPart)i); if (pItem != NULL) { if (i == Slayer::WEAR_RIGHTHAND && isTwohandWeapon(pItem)) { // 오른손이고, 현재 들고 있는 무기가 양손 무기라면... // 수리 가격에 포함시킬 필요가 없다. } else { repairPrice += g_pPriceManager->getRepairPrice(pItem); } } } // 돈이 모자라다면 리턴한다. if (pSlayer->getGold() < repairPrice) { response.setCode(NPC_RESPONSE_REPAIR_FAIL_MONEY); pPlayer->sendPacket(&response); return; } // 각각의 아이템을 수리하고, DB에 저장한다. char pField[80]; for (int i=0; i<Slayer::WEAR_MAX; i++) { Item* pItem = pSlayer->getWearItem((Slayer::WearPart)i); if (pItem != NULL) { if (i == Slayer::WEAR_RIGHTHAND && isTwohandWeapon(pItem)) { // 오른손이고, 현재 들고 있는 무기가 양손 무기라면... // 수리할 필요가 없다. } else if (isRepairableItem(pItem ) ) { Durability_t oldDurability = pItem->getDurability(); repairItem(pItem); if (pItem->getDurability() != oldDurability) { // DB 쿼리를 줄이기 위해서 // 내구도의 변화가 생긴 경우에만 세이브한다. //pItem->save(pSlayer->getName(), STORAGE_GEAR, 0, i, 0); // item저장 최적화. by sigi. 2002.5.13 sprintf(pField, "Durability=%d", pItem->getDurability()); pItem->tinysave(pField); } if (oldDurability == 0 ) bSendRealWearingInfo = true; } } } // 돈을 줄이고... //pSlayer->setGoldEx(pSlayer->getGold() - repairPrice); // by sigi.2002.9.4 pSlayer->decreaseGoldEx(repairPrice); // 로그를 남긴다. //log(LOG_REPAIR_ITEM, pSlayer->getName(), "", "ALL"); // OK 패킷을 날려준다. response.setCode(NPC_RESPONSE_REPAIR_OK); response.setParameter(pSlayer->getGold()); pPlayer->sendPacket(&response); } else if (pPC->isVampire()) { Vampire* pVampire = dynamic_cast<Vampire*>(pPC); // 모든 아이템을 합한 수리비를 계산한다. for (int i=0; i<Vampire::VAMPIRE_WEAR_MAX; i++) { Item* pItem = pVampire->getWearItem((Vampire::WearPart)i); if (pItem != NULL) { if (i == Vampire::WEAR_RIGHTHAND && isTwohandWeapon(pItem)) { // 양손무기는 한쪽만 수리한다. } else { repairPrice += g_pPriceManager->getRepairPrice(pItem); } } } // 돈이 모자라다면 리턴한다. if (pVampire->getGold() < repairPrice) { response.setCode(NPC_RESPONSE_REPAIR_FAIL_MONEY); pPlayer->sendPacket(&response); return; } // 각각의 아이템을 수리하고, DB에 저장한다. char pField[80]; for (int i=0; i<Vampire::VAMPIRE_WEAR_MAX; i++) { Item* pItem = pVampire->getWearItem((Vampire::WearPart)i); if (pItem != NULL) { if (i == Vampire::WEAR_RIGHTHAND && isTwohandWeapon(pItem)) { // 양손무기는 한쪽만 수리한다. } else { Durability_t oldDurability = pItem->getDurability(); repairItem(pItem); if (pItem->getDurability() != oldDurability) { // DB 쿼리를 줄이기 위해서 // 내구도의 변화가 생긴 경우에만 세이브한다. //pItem->save(pVampire->getName(), STORAGE_GEAR, 0, i, 0); // item저장 최적화. by sigi. 2002.5.13 sprintf(pField, "Durability=%d", pItem->getDurability()); pItem->tinysave(pField); } if (oldDurability == 0 ) bSendRealWearingInfo = true; } } } // 돈을 줄이고... //pVampire->setGoldEx(pVampire->getGold() - repairPrice); // by sigi.2002.9.4 pVampire->decreaseGoldEx(repairPrice); // 로그를 남긴다. //log(LOG_REPAIR_ITEM, pVampire->getName(), "", "ALL"); // OK 패킷을 날려준다. response.setCode(NPC_RESPONSE_REPAIR_OK); response.setParameter(pVampire->getGold()); pPlayer->sendPacket(&response); } else if (pPC->isOusters()) { Ousters* pOusters = dynamic_cast<Ousters*>(pPC); // 모든 아이템을 합한 수리비를 계산한다. for (int i=0; i<Ousters::OUSTERS_WEAR_MAX; i++) { Item* pItem = pOusters->getWearItem((Ousters::WearPart)i); if (pItem != NULL) { if (i == Ousters::WEAR_RIGHTHAND && isTwohandWeapon(pItem)) { // 양손무기는 한쪽만 수리한다. } else { repairPrice += g_pPriceManager->getRepairPrice(pItem); } } } // 돈이 모자라다면 리턴한다. if (pOusters->getGold() < repairPrice) { response.setCode(NPC_RESPONSE_REPAIR_FAIL_MONEY); pPlayer->sendPacket(&response); return; } // 각각의 아이템을 수리하고, DB에 저장한다. char pField[80]; for (int i=0; i<Ousters::OUSTERS_WEAR_MAX; i++) { Item* pItem = pOusters->getWearItem((Ousters::WearPart)i); if (pItem != NULL) { if (i == Ousters::WEAR_RIGHTHAND && isTwohandWeapon(pItem)) { // 양손무기는 한쪽만 수리한다. } else { Durability_t oldDurability = pItem->getDurability(); repairItem(pItem); if (pItem->getDurability() != oldDurability) { // DB 쿼리를 줄이기 위해서 // 내구도의 변화가 생긴 경우에만 세이브한다. //pItem->save(pOusters->getName(), STORAGE_GEAR, 0, i, 0); // item저장 최적화. by sigi. 2002.5.13 sprintf(pField, "Durability=%d", pItem->getDurability()); pItem->tinysave(pField); } if (oldDurability == 0 ) bSendRealWearingInfo = true; } } } // 돈을 줄이고... //pOusters->setGoldEx(pOusters->getGold() - repairPrice); // by sigi.2002.9.4 pOusters->decreaseGoldEx(repairPrice); // 로그를 남긴다. //log(LOG_REPAIR_ITEM, pOusters->getName(), "", "ALL"); // OK 패킷을 날려준다. response.setCode(NPC_RESPONSE_REPAIR_OK); response.setParameter(pOusters->getGold()); pPlayer->sendPacket(&response); } if (bSendRealWearingInfo ) { if (pPC->isSlayer() ) { Slayer* pSlayer = dynamic_cast<Slayer*>(pPC); Assert(pSlayer != NULL); pSlayer->initAllStatAndSend(); pSlayer->sendRealWearingInfo(); } else if (pPC->isVampire() ) { Vampire* pVampire = dynamic_cast<Vampire*>(pPC); Assert(pVampire != NULL); pVampire->initAllStatAndSend(); pVampire->sendRealWearingInfo(); } else if (pPC->isOusters() ) { Ousters* pOusters = dynamic_cast<Ousters*>(pPC); Assert(pOusters != NULL); pOusters->initAllStatAndSend(); pOusters->sendRealWearingInfo(); } } #endif __END_DEBUG_EX __END_CATCH }
void ActionHeal::execute (Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); Player* pPlayer = pCreature2->getPlayer(); Zone* pZone = pCreature2->getZone(); Assert(pPlayer != NULL); // 일단 클라이언트를 위해서 OK 패킷을 함 날린다. GCNPCResponse okpkt; okpkt.setCode(NPC_RESPONSE_HEAL); pPlayer->sendPacket(&okpkt); // 죽었거나 코마 걸려있으면 안 치료해준다. if (pCreature2->isDead() || pCreature2->isFlag(Effect::EFFECT_CLASS_COMA ) ) { return; } // 슬레이어라면... if (pCreature2->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature2); EffectManager* pEffectManager = pSlayer->getEffectManager(); GCModifyInformation modifyPkt; GCRemoveEffect removePkt; GCStatusCurrentHP hpPkt; // 먼저 HP랑 MP를 풀로 채워준다. if (pSlayer->getHP(ATTR_CURRENT) < pSlayer->getHP(ATTR_MAX)) { pSlayer->setHP(pSlayer->getHP(ATTR_MAX), ATTR_CURRENT); modifyPkt.addShortData(MODIFY_CURRENT_HP, pSlayer->getHP(ATTR_CURRENT)); hpPkt.setObjectID(pSlayer->getObjectID()); hpPkt.setCurrentHP(pSlayer->getHP(ATTR_CURRENT)); } if (pSlayer->getMP(ATTR_CURRENT) < pSlayer->getMP(ATTR_MAX)) { pSlayer->setMP(pSlayer->getMP(ATTR_MAX), ATTR_CURRENT); modifyPkt.addShortData(MODIFY_CURRENT_MP, pSlayer->getMP(ATTR_CURRENT)); } // 흡혈 이펙트를 삭제한다. Effect* pBloodDrainEffect = pEffectManager->findEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN); if (pBloodDrainEffect != NULL) { // DB에서 삭제하고, 이펙트 매니저에서 삭제한다. pBloodDrainEffect->destroy(pSlayer->getName()); pEffectManager->deleteEffect(pSlayer, Effect::EFFECT_CLASS_BLOOD_DRAIN); // 흡혈 아르바이트를 방지하기 위한 후유증 이펙트를 붙여준다. if (pSlayer->isFlag(Effect::EFFECT_CLASS_AFTERMATH)) { Effect* pEffect = pEffectManager->findEffect(Effect::EFFECT_CLASS_AFTERMATH); EffectAftermath* pEffectAftermath = dynamic_cast<EffectAftermath*>(pEffect); pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다. } else { EffectAftermath* pEffectAftermath = new EffectAftermath(pSlayer); pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다. pEffectManager->addEffect(pEffectAftermath); pSlayer->setFlag(Effect::EFFECT_CLASS_AFTERMATH); pEffectAftermath->create(pSlayer->getName()); } // 패킷에다 정보를 더한다. removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_BLOOD_DRAIN); // 흡혈을 치료하면 능력치가 변화하게 된다. SLAYER_RECORD prev; pSlayer->getSlayerRecord(prev); pSlayer->initAllStat(); pSlayer->sendModifyInfo(prev); pSlayer->sendRealWearingInfo(); } // 독 이펙트를 삭제한다. Effect* pEffectPoison = pEffectManager->findEffect(Effect::EFFECT_CLASS_POISON); if (pEffectPoison != NULL) { // 이펙트 매니저에서 삭제한다. pEffectManager->deleteEffect(pSlayer, Effect::EFFECT_CLASS_POISON); // 패킷에다 정보를 더한다. removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_POISON); } // 다크블루 포이즌 이펙트를 삭제한다. Effect* pEffectDarkBluePoison = pEffectManager->findEffect(Effect::EFFECT_CLASS_DARKBLUE_POISON); if (pEffectDarkBluePoison != NULL) { // 이펙트 매니저에서 삭제한다. pEffectManager->deleteEffect(pSlayer, Effect::EFFECT_CLASS_DARKBLUE_POISON); // 패킷에다 정보를 더한다. removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_DARKBLUE_POISON); } // 패킷 날려준다. removePkt.setObjectID(pSlayer->getObjectID()); pPlayer->sendPacket(&modifyPkt); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &removePkt); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &hpPkt, pSlayer); //log(LOG_HEAL, pSlayer->getName(), ""); } else if (pCreature2->isVampire()) { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature2); //EffectManager* pEffectManager = pVampire->getEffectManager(); GCModifyInformation modifyPkt; GCRemoveEffect removePkt; GCStatusCurrentHP hpPkt; // HP 채워주고... if (pVampire->getHP(ATTR_CURRENT) < pVampire->getHP(ATTR_MAX)) { pVampire->setHP(pVampire->getHP(ATTR_MAX), ATTR_CURRENT); modifyPkt.addShortData(MODIFY_CURRENT_HP, pVampire->getHP(ATTR_CURRENT)); hpPkt.setObjectID(pVampire->getObjectID()); hpPkt.setCurrentHP(pVampire->getHP(ATTR_CURRENT)); } // 패킷 날려준다. removePkt.setObjectID(pVampire->getObjectID()); pPlayer->sendPacket(&modifyPkt); pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &removePkt); pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &hpPkt, pVampire); //log(LOG_HEAL, pVampire->getName(), ""); } else if (pCreature2->isOusters()) { Ousters* pOusters = dynamic_cast<Ousters*>(pCreature2); EffectManager* pEffectManager = pOusters->getEffectManager(); GCModifyInformation modifyPkt; GCRemoveEffect removePkt; GCStatusCurrentHP hpPkt; // 먼저 HP랑 MP를 풀로 채워준다. if (pOusters->getHP(ATTR_CURRENT) < pOusters->getHP(ATTR_MAX) || pOusters->getSilverDamage() != 0 ) { Silver_t prev = pOusters->getSilverDamage(); if (prev != 0 ) { pOusters->setSilverDamage(0); modifyPkt.addShortData(MODIFY_SILVER_DAMAGE, pOusters->getSilverDamage()); } pOusters->setHP(pOusters->getHP(ATTR_MAX), ATTR_CURRENT); modifyPkt.addShortData(MODIFY_CURRENT_HP, pOusters->getHP(ATTR_CURRENT)); hpPkt.setObjectID(pOusters->getObjectID()); hpPkt.setCurrentHP(pOusters->getHP(ATTR_CURRENT)); } if (pOusters->getMP(ATTR_CURRENT) < pOusters->getMP(ATTR_MAX)) { pOusters->setMP(pOusters->getMP(ATTR_MAX), ATTR_CURRENT); modifyPkt.addShortData(MODIFY_CURRENT_MP, pOusters->getMP(ATTR_CURRENT)); } // 독 이펙트를 삭제한다. Effect* pEffectPoison = pEffectManager->findEffect(Effect::EFFECT_CLASS_POISON); if (pEffectPoison != NULL) { // 이펙트 매니저에서 삭제한다. pEffectManager->deleteEffect(pOusters, Effect::EFFECT_CLASS_POISON); // 패킷에다 정보를 더한다. removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_POISON); } // 다크블루 포이즌 이펙트를 삭제한다. Effect* pEffectDarkBluePoison = pEffectManager->findEffect(Effect::EFFECT_CLASS_DARKBLUE_POISON); if (pEffectDarkBluePoison != NULL) { // 이펙트 매니저에서 삭제한다. pEffectManager->deleteEffect(pOusters, Effect::EFFECT_CLASS_DARKBLUE_POISON); // 패킷에다 정보를 더한다. removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_DARKBLUE_POISON); } // 흡혈 이펙트를 삭제한다. Effect* pBloodDrainEffect = pEffectManager->findEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN); if (pBloodDrainEffect != NULL) { pBloodDrainEffect->setDeadline(0); // 흡혈 아르바이트를 방지하기 위한 후유증 이펙트를 붙여준다. if (pOusters->isFlag(Effect::EFFECT_CLASS_AFTERMATH)) { Effect* pEffect = pEffectManager->findEffect(Effect::EFFECT_CLASS_AFTERMATH); EffectAftermath* pEffectAftermath = dynamic_cast<EffectAftermath*>(pEffect); pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다. } else { EffectAftermath* pEffectAftermath = new EffectAftermath(pOusters); pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다. pEffectManager->addEffect(pEffectAftermath); pOusters->setFlag(Effect::EFFECT_CLASS_AFTERMATH); pEffectAftermath->create(pOusters->getName()); } // 패킷에다 정보를 더한다. removePkt.addEffectList((EffectID_t)Effect::EFFECT_CLASS_BLOOD_DRAIN); } // 패킷 날려준다. removePkt.setObjectID(pOusters->getObjectID()); pPlayer->sendPacket(&modifyPkt); pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &removePkt); pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &hpPkt, pOusters); //log(LOG_HEAL, pOusters->getName(), ""); } __END_CATCH }
void CGModifyTaxRatioHandler::execute (CGModifyTaxRatio* 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); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pGamePlayer->getCreature()); Assert(pPC != NULL); #ifdef __OLD_GUILD_WAR__ GCSystemMessage gcSM; gcSM.setMessage("아직 지원되지 않는 기능입니다."); pGamePlayer->sendPacket(&gcSM); return; #endif GuildID_t guildID = pPC->getGuildID(); list<CastleInfo*> pCastleInfoList = g_pCastleInfoManager->getGuildCastleInfos(guildID); if (pCastleInfoList.empty() ) { GCNPCResponse fail; fail.setCode(NPC_RESPONSE_MODIFY_TAX_RATIO_FAIL); pGamePlayer->sendPacket(&fail); return; } bool bOwner = false; list<CastleInfo*>::iterator itr = pCastleInfoList.begin(); CastleInfo* pCastleInfo = NULL; for (; itr != pCastleInfoList.end() ; itr++ ) { if ((*itr)->getZoneID() == pPC->getZoneID() ) { pCastleInfo = (*itr); bOwner = true; break; } } if (!g_pGuildManager->isGuildMaster(guildID, pPC ) // 길드 마스터가 아니다. || !bOwner // 이 플레이어의 길드가 점령한 성이 아니다. || pPacket->getRatio() > 10 ) { GCNPCResponse fail; fail.setCode(NPC_RESPONSE_MODIFY_TAX_RATIO_FAIL); pGamePlayer->sendPacket(&fail); return; } g_pCastleInfoManager->setItemTaxRatio(pPC->getZone(), pPacket->getRatio()+100); GCNPCResponse ok; ok.setCode(NPC_RESPONSE_MODIFY_TAX_RATIO_OK); pGamePlayer->sendPacket(&ok); #endif // __GAME_SERVER__ __END_DEBUG_EX __END_CATCH }
void CGSilverCoatingHandler::execute (CGSilverCoating* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ Assert(pPacket != NULL); Assert(pPlayer != NULL); ObjectID_t ITEMOID = pPacket->getObjectID(); Creature* pPC = dynamic_cast<GamePlayer*>(pPlayer)->getCreature(); bool bSlayer = true; Gold_t playerMoney = 0; Price_t coatingPrice = 0; Item* pItem = NULL; Slayer* pSlayer = NULL; Vampire* pVampire = NULL; int storage = 0; int X = 0; int Y = 0; GCNPCResponse response; // 플레이어가 슬레이어인지 뱀파이어인지 구분. if (pPC->isSlayer()) bSlayer = true; else if (pPC->isVampire()) bSlayer = false; // 플레이어가 코팅하려고 하는 아이템을 가지고 있는지 검사 if (bSlayer) { pSlayer = dynamic_cast<Slayer*>(pPC); playerMoney = pSlayer->getGold(); pItem = pSlayer->findItemOID(ITEMOID, storage, X, Y); } else { pVampire = dynamic_cast<Vampire*>(pPC); playerMoney = pVampire->getGold(); pItem = pVampire->findItemOID(ITEMOID, storage, X, Y); } // 아이템이 없다면 당연히 코팅할 수 없다. if (pItem == NULL) { response.setCode(NPC_RESPONSE_SILVER_COATING_FAIL_ITEM_NOT_EXIST); pPlayer->sendPacket(&response); return; } // 코팅하려는 아이템이 코팅될 수 없는 아이템이라면... switch (pItem->getItemClass()) { case Item::ITEM_CLASS_BLADE: case Item::ITEM_CLASS_SWORD: case Item::ITEM_CLASS_CROSS: case Item::ITEM_CLASS_MACE: break; default: response.setCode(NPC_RESPONSE_SILVER_COATING_FAIL_ITEM_TYPE); pPlayer->sendPacket(&response); return; } coatingPrice = g_pPriceManager->getSilverCoatingPrice(pItem); if (coatingPrice > playerMoney) { response.setCode(NPC_RESPONSE_SILVER_COATING_FAIL_MONEY); pPlayer->sendPacket(&response); return; } // 최대 은 도금량을 얻어와서... 도금한다. ItemInfo* pItemInfo = g_pItemInfoManager->getItemInfo(pItem->getItemClass(), pItem->getItemType()); pItem->setSilver(pItemInfo->getMaxSilver()); // 돈을 줄인다. if (bSlayer) { //pSlayer->setGoldEx(playerMoney - coatingPrice); // by sigi. 2002.9.4 pSlayer->decreaseGoldEx(coatingPrice); //log(LOG_REPAIR_ITEM, pSlayer->getName(), "", pItem->toString()); } else { //pVampire->setGoldEx(playerMoney - coatingPrice); // by sigi. 2002.9.4 pVampire->decreaseGoldEx(coatingPrice); //log(LOG_REPAIR_ITEM, pVampire->getName(), "", pItem->toString()); } // silver만 저장하면 된다. // 아이템 저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Silver=%d", pItem->getSilver()); pItem->tinysave(pField); // 아이템을 은으로 코팅했다는 정보를 DB에다가 저장해준다. // 단 분명히 STORAGE_STASH가 돌아올 수 있지만, // 보관함에 있는 것을 수리한다는 것은 말이 안 되므로, // 저장하지 않는다. /* switch (storage) { case STORAGE_INVENTORY: pItem->save(pPC->getName(), STORAGE_INVENTORY, 0, X, Y); break; case STORAGE_GEAR: if (bSlayer) pItem->save(pSlayer->getName(), STORAGE_GEAR, 0, X, 0); else pItem->save(pVampire->getName(), STORAGE_GEAR, 0, X, 0); break; default: break; } */ // OK 패킷을 날려준다. response.setCode(NPC_RESPONSE_SILVER_COATING_OK); response.setParameter(playerMoney-coatingPrice); pPlayer->sendPacket(&response); #endif __END_DEBUG_EX __END_CATCH }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionTradeLairItem::execute(Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); if (m_Type <= 5 ) { SYSTEM_RETURN_IF_NOT(SYSTEM_MASTER_LAIR); } PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2); Assert(pPC != NULL); Player* pPlayer = pPC->getPlayer(); Assert(pPlayer != NULL); GCNPCResponse okpkt; pPlayer->sendPacket(&okpkt); StringStream message; /* GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage("아직 지원되지 않는 기능입니다"); pPlayer->sendPacket(&gcSystemMessage); */ //cout << "ActionTradeLairItem" << ":" << m_Type; Inventory* pInventory = pPC->getInventory(); // 먼저 아이템을 가지고 있는가를 체크한다. Item* pMasterItem = NULL; MonsterType_t MonsterType = 0; Item* pItem1 = NULL; bool bUpgrade = false; // 옵션에 따라서 다른 아이템을 검사해야 한다. // 코난 : 팬던트/ 비쥬만 체크한다. // 브리콜라카스: 테페즈 펜던트/비쥬만 체크해야 한다 // 카임 : 바토리 팬던트/비쥬만 체크해야 한다. if (m_Type == 0) // 코난, 비쥬 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 0); MonsterType = BATORI_TYPE; if (pMasterItem == NULL ) { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 2); MonsterType = TEPEZ_TYPE; if (pMasterItem == NULL ) { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); //질드레 비쥬 MonsterType = GDR_TYPE; bUpgrade = true; } } } else if (m_Type == 1) // 코난, 팬던트 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 1); MonsterType = BATORI_TYPE; if (pMasterItem == NULL) { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 3); MonsterType = TEPEZ_TYPE; if (pMasterItem == NULL ) { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); //질드레 펜던트 MonsterType = GDR_TYPE; bUpgrade = true; } } } else if (m_Type == 2) // 브리콜라카스, 비쥬 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 2); // if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); //질드레 비쥬 MonsterType = TEPEZ_TYPE; } else if (m_Type == 3) // 브리콜라카스, 팬던트 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 3); // if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); //질드레 펜던트 MonsterType = TEPEZ_TYPE; } else if (m_Type == 4) // 카임, 비쥬 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 0); // if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); //질드레 비쥬 MonsterType = BATORI_TYPE; } else if (m_Type == 5) // 카임, 팬던트 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 1); // if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); //질드레 펜던트 MonsterType = BATORI_TYPE; } else if (m_Type == 10) // 질드레, 비쥬 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); bUpgrade = true; MonsterType = GDR_TYPE; } else if (m_Type == 11) // 질드레, 팬던트 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); bUpgrade = true; MonsterType = GDR_TYPE; } else if (m_Type == 6) // 젬스톤이지롱~ { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 4); MonsterType = BATORI_TYPE; } else if (m_Type == 7) // 보름달~ { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 5); ItemMineInfo* pItemMineInfo; if (pPC->isSlayer() ) { Slayer* pSlayer = dynamic_cast<Slayer*>(pPC); Assert(pSlayer != NULL); Attr_t totalAttr = pSlayer->getTotalAttr(ATTR_BASIC); if (totalAttr <= 130 ) // 하드코딩 ㅜ.ㅠ pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(0); else if (totalAttr <= 210 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(1); else if (totalAttr <= 270 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(2); else if (totalAttr <= 300 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(3); else pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(4); } else if (pPC->isVampire() ) { Vampire* pVampire = dynamic_cast<Vampire*>(pPC); Assert(pVampire != NULL); Level_t level = pVampire->getLevel(); if (level <= 20 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(5); else if (level <= 40 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(6); else if (level <= 60 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(7); else if (level <= 90 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(8); else pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(9); } else if (pPC->isOusters() ) { Ousters* pOusters = dynamic_cast<Ousters*>(pPC); Assert(pOusters != NULL); Level_t level = pOusters->getLevel(); if (level <= 20 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(10); else if (level <= 40 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(11); else if (level <= 60 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(12); else if (level <= 90 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(13); else pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(14); } else Assert(false); pItem1 = pItemMineInfo->getItem(); setItemGender(pItem1, (pPC->getSex()==FEMALE)?GENDER_FEMALE:GENDER_MALE); } else if (m_Type == 8) // 그믐달~ { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 6); if (pPC->isSlayer() ) { pItem1 = g_pItemMineInfoManager->getRandomItem(15, 32); } else if (pPC->isVampire() ) { pItem1 = g_pItemMineInfoManager->getRandomItem(33, 45); } else if (pPC->isOusters() ) { pItem1 = g_pItemMineInfoManager->getRandomItem(46, 61); } setItemGender(pItem1, (pPC->getSex()==FEMALE)?GENDER_FEMALE:GENDER_MALE); } else if (m_Type == 9) // 빨간색 복주머니 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 7); if (pPC->isSlayer() ) { pItem1 = g_pItemMineInfoManager->getRandomItem(62, 81); } else if (pPC->isVampire() ) { pItem1 = g_pItemMineInfoManager->getRandomItem(82, 96); } else if (pPC->isOusters() ) { pItem1 = g_pItemMineInfoManager->getRandomItem(97, 112); } } else { // 거래를 위한 NPC의 Property가 잘못되었다. 이런 경우에는 // 운영팀으로 문의를 하면 바로 처리를 할 수 있다. GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NPC_ERROR )); pPlayer->sendPacket(&gcSystemMessage); GCNPCResponse response; response.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&response); return; } if (pMasterItem == NULL) { GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NO_LAIR_ITEM )); pPlayer->sendPacket(&gcSystemMessage); GCNPCResponse response; response.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&response); return; } Zone* pZone = pPC->getZone(); // if (MonsterType != 0 ) // 루팅표를 참조해서 아이템을 만들어오는 경우 if (pItem1 == NULL ) { QuestItemInfo* pItemInfo = dynamic_cast<QuestItemInfo*>(g_pQuestItemInfoManager->getItemInfo(pMasterItem->getItemType() )); Assert(pItemInfo!=NULL); /////////////////////////////////////////////////////////////////////////////// // 가장 난감한 부분 // 아이템을 랜덤하게 선택해야 한다. // 일단은 기본 아이템 하나로 한다. ////////////////////////////////////////////////////////////////////////////// const MonsterInfo* pMonsterInfo = g_pMonsterInfoManager->getMonsterInfo(MonsterType); TreasureList *pTreasureList = NULL; // 종족에 따라서 주는 아이템도 달라야 한다. if (pCreature2->isSlayer()) pTreasureList = pMonsterInfo->getSlayerTreasureList(); else if (pCreature2->isVampire()) pTreasureList = pMonsterInfo->getVampireTreasureList(); else if (pCreature2->isOusters()) pTreasureList = pMonsterInfo->getOustersTreasureList(); const list<Treasure*>& treasures = pTreasureList->getTreasures(); list<Treasure*>::const_iterator itr = treasures.begin(); ITEM_TEMPLATE it; for(; itr != treasures.end(); itr++) { Treasure* pTreasure = (*itr); it.ItemClass = Item::ITEM_CLASS_MAX; it.ItemType = 0; // QuestItem 마다 다른.. 옵션이 2개 붙을 확률 it.NextOptionRatio = pItemInfo->getBonusRatio(); //cout << "TradeLairItem: BonusRatio = " << it.NextOptionRatio << endl; if (pTreasure->getRandomItem(&it) ) { /* if (bUpgrade && isPossibleUpgradeItemType(it.ItemClass ) ) { it.ItemType = getUpgradeItemType(it.ItemClass, it.ItemType, 1); } */ pItem1 = g_pItemFactoryManager->createItem(it.ItemClass, it.ItemType, it.OptionType); Assert(pItem1 != NULL); } } if (pItem1 == NULL) { StringStream msg; msg << "ActionTradeLairItem: " << (int)it.ItemClass << ", " << (int)it.ItemType << ", " << (int)it.bCreateOption << ", " << getOptionTypeToString(it.OptionType); filelog("tradeLairItemBUG.txt", "%s", msg.toString().c_str()); GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_ITEM_CREATE_ERROR )); pPlayer->sendPacket(&gcSystemMessage); GCNPCResponse response; response.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&response); return; } } TPOINT pt; pItem1->setGrade(min(7,ItemGradeManager::Instance().getRandomBeadGrade())); pZone->registerObject(pItem1); // 만약 inventory에 공간이 있다면, 넣는다. if(pInventory->addItem(pItem1, pt)) { pItem1->create(pPC->getName(), STORAGE_INVENTORY, 0, pt.x, pt.y); GCCreateItem gcCreateItem; /* gcCreateItem.setObjectID(pItem1->getObjectID()); gcCreateItem.setItemClass(pItem1->getItemClass()); gcCreateItem.setItemType(pItem1->getItemType()); gcCreateItem.setOptionType(pItem1->getOptionTypeList()); gcCreateItem.setDurability(pItem1->getDurability()); gcCreateItem.setItemNum(pItem1->getNum()); gcCreateItem.setInvenX(pt.x); gcCreateItem.setInvenY(pt.y); gcCreateItem.setGrade(pItem1->getGrade());*/ makeGCCreateItem(&gcCreateItem, pItem1, pt.x, pt.y); pPlayer->sendPacket(&gcCreateItem); // ItemTraceLog 를 남긴다 if (pItem1 != NULL && pItem1->isTraceItem() ) { remainTraceLog(pItem1, pCreature1->getName(), pCreature2->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC); } // 기존의 아이템을 없앤다 GCDeleteInventoryItem gcDeleteInventoryItem; gcDeleteInventoryItem.setObjectID(pMasterItem->getObjectID()); pPlayer->sendPacket(&gcDeleteInventoryItem); // 서버에서 없애준다. pInventory->deleteItem(pMasterItem->getObjectID()); // 좌표로 바꿔주면 좋을건데.. // ItemTraceLog 를 남긴다 if (pMasterItem != NULL && pMasterItem->isTraceItem() ) { remainTraceLog(pMasterItem, pCreature2->getName(), pCreature1->getName(), ITEM_LOG_DELETE, DETAIL_EVENTNPC); } pMasterItem->destroy(); SAFE_DELETE(pMasterItem); // 사용자에게 성공 메시지 출력 // StringStream message; // message << "성공적으로 교환되었습니다"; GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_TRADE_SUCCESS )); pPlayer->sendPacket(&gcSystemMessage); } else { // StringStream buf; // buf << "인벤토리에 공간이 부족합니다"; GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NOT_ENOUGH_INVENTORY_SPACE )); pPlayer->sendPacket(&gcSystemMessage); } GCNPCResponse response; response.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&response); __END_CATCH }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionEnterQuestZone::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); 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() || pGamePlayer->isFamilyFreePass())) { 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; } } } catch (NoSuchElementException&) { } #endif if (bTransport) { // Dynamic 존인지 확인. int targetDynamicZoneType = g_pDynamicZoneInfoManager->getDynamicZoneTypeByZoneID(m_ZoneID); if (targetDynamicZoneType != DYNAMIC_ZONE_MAX ) { // Dynamic 존일 경우 DynamicZoneGroup* pDynamicZoneGroup = g_pDynamicZoneManager->getDynamicZoneGroup(targetDynamicZoneType); Assert(pDynamicZoneGroup != NULL); DynamicZone* pDynamicZone = pDynamicZoneGroup->getAvailableDynamicZone(); Assert(pDynamicZone != NULL); transportCreature(pCreature, pDynamicZone->getZoneID(), m_X, m_Y, true); if (targetDynamicZoneType == DYNAMIC_ZONE_ALTER_OF_BLOOD ) { DynamicZoneAlterOfBlood* pAlterOfBlood = dynamic_cast<DynamicZoneAlterOfBlood*>(pDynamicZone); Assert(pAlterOfBlood != NULL); pAlterOfBlood->setRace(pPC->getRace()); } } else { // Dynamic 존이 아닐 경우 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 }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionGiveAccountEventItem::execute(Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2); Assert(pPC != NULL); Player* pPlayer = pPC->getPlayer(); Assert(pPlayer != NULL); GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Assert(pGamePlayer != NULL); Inventory* pInventory = pPC->getInventory(); Assert(pInventory != NULL); Zone* pZone = pPC->getZone(); Assert(pZone != NULL); Item::ItemClass ItemClass; ItemType_t ItemType; OptionType_t OptionType; OptionType_t OptionType2; Item* pItem; // 이벤트가 진행중이지 않은 경우 if (!g_pVariableManager->isActiveGiveEventItem()) { GCNPCResponse response; response.setCode(NPC_RESPONSE_GIVE_EVENT_ITEM_FAIL_NOW); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } // 이미 받았는지 체크한다. if (pGamePlayer->getSpecialEventCount() & m_SpecialEventFlag) { GCNPCResponse response; response.setCode(NPC_RESPONSE_GIVE_EVENT_ITEM_FAIL); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } // 유료 사용자 여부를 체크한다. if (!PaySystem::isPayPlayingPeriodPersonal(pGamePlayer->getID() ) ) { GCNPCResponse response; response.setCode(NPC_RESPONSE_GIVE_PREMIUM_USER_ONLY); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } LuaSelectItem* pLuaSelectItem = NULL; string luaFileName; if (pPC->isSlayer() ) { // 루아에 슬레이어 능력치의 합을 set한다. Slayer* pSlayer = dynamic_cast<Slayer*>(pPC); Assert(pSlayer != NULL); Attr_t sum = pSlayer->getSTR(ATTR_BASIC ) + pSlayer->getDEX(ATTR_BASIC ) + pSlayer->getINT(ATTR_BASIC); m_pLuaSlayerItem->setSum(sum); pLuaSelectItem = m_pLuaSlayerItem; luaFileName = m_SlayerFilename; } else if (pPC->isVampire() ) { // 루아에 뱀파이어의 레벨을 set한다. Vampire* pVampire = dynamic_cast<Vampire*>(pPC); Assert(pVampire != NULL); int level = pVampire->getLevel(); m_pLuaVampireItem->setLevel(level); pLuaSelectItem = m_pLuaVampireItem; luaFileName = m_VampireFilename; } // 루아의 계산 결과를 받아 아이템을 생성한다. pLuaSelectItem->prepare(); int result = pLuaSelectItem->executeFile(luaFileName); LuaState::logError(result); ItemClass = pLuaSelectItem->getItemClass(); ItemType = pLuaSelectItem->getItemType(); OptionType = pLuaSelectItem->getOptionType(); OptionType2 = pLuaSelectItem->getOptionType2(); pLuaSelectItem->clear(); if(ItemClass >= Item::ITEM_CLASS_MAX ) { filelog("AccountEventItemError.txt", "[ ItemInfo Error ] : ItemClass = %d , ItemType = %d , OptionType = %d", ItemClass, ItemType, OptionType); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } // 선물(Item)을 만든다. list<OptionType_t> optionTypeList; if (OptionType != 0 ) optionTypeList.push_back(OptionType); if (OptionType2 != 0 ) optionTypeList.push_back(OptionType2); pItem = g_pItemFactoryManager->createItem(ItemClass, ItemType, optionTypeList); Assert(pItem != NULL); // 인벤토리에 아이템을 넣을 빈 자리를 받아온다. TPOINT p; if (!pInventory->getEmptySlot(pItem, p)) { SAFE_DELETE(pItem); GCNPCResponse response; response.setCode(NPC_RESPONSE_NO_EMPTY_SLOT); pGamePlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } // 선물을 인벤토리에 추가한다. pZone->getObjectRegistry().registerObject(pItem); pInventory->addItem(p.x, p.y, pItem); pItem->create(pPC->getName(), STORAGE_INVENTORY, 0, p.x, p.y); // ItemTraceLog 를 남긴다 if (pItem != NULL && pItem->isTraceItem() ) { remainTraceLog(pItem, pCreature1->getName(), pCreature2->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC); remainTraceLogNew(pItem, pCreature2->getName(), ITL_GET, ITLD_EVENTNPC, pCreature1->getZone()->getZoneID(), pCreature1->getX(), pCreature1->getY()); } // 클라이언트에 선물이 추가되었음을 알린다. GCCreateItem gcCreateItem; makeGCCreateItem(&gcCreateItem, pItem, p.x, p.y); pPlayer->sendPacket(&gcCreateItem); // 선물을 받았다고 Flag 를 켠다. pGamePlayer->setSpecialEventCount(pGamePlayer->getSpecialEventCount() | m_SpecialEventFlag); // Flag 를 저장한다. pGamePlayer->saveSpecialEventCount(); // 보상을 받았다고 클라이언트에 보낸다. GCNPCResponse response; response.setCode(NPC_RESPONSE_GIVE_EVENT_ITEM_OK); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); __END_CATCH }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionTradeGiftBox::execute(Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2); Assert(pPC != NULL); Player* pPlayer = pPC->getPlayer(); Assert(pPlayer != NULL); Inventory* pInventory = pPC->getInventory(); Assert(pInventory != NULL); Zone* pZone = pPC->getZone(); Assert(pZone != NULL); FlagSet* pFlagSet = pPC->getFlagSet(); Item::ItemClass ItemClass; ItemType_t ItemType; OptionType_t OptionType; Item* pItem; Item* pGiftBoxItem; // 이미 선물을 교환해 갔다면 if (pFlagSet->isOn(FLAGSET_TRADE_GIFT_BOX_2002_12 ) ) { GCNPCResponse response; response.setCode(NPC_RESPONSE_TRADE_GIFT_BOX_ALREADY_TRADE); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } // 빨간 선물 상자가 있는지 확인한다. CoordInven_t X,Y; pGiftBoxItem = pInventory->findItem(Item::ITEM_CLASS_EVENT_GIFT_BOX, 1, X, Y); if (pGiftBoxItem == NULL ) { GCNPCResponse response; response.setCode(NPC_RESPONSE_TRADE_GIFT_BOX_NO_ITEM); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } LuaSelectItem* pLuaSelectItem = NULL; string luaFileName; if (pPC->isSlayer() ) { // 루아에 슬레이어 능력치의 합을 set한다. Slayer* pSlayer = dynamic_cast<Slayer*>(pPC); Assert(pSlayer != NULL); Attr_t sum = pSlayer->getSTR(ATTR_BASIC ) + pSlayer->getDEX(ATTR_BASIC ) + pSlayer->getINT(ATTR_BASIC); m_pLuaSlayerItem->setSum(sum); pLuaSelectItem = m_pLuaSlayerItem; luaFileName = m_SlayerFilename; } else if (pPC->isVampire() ) { // 루아에 뱀파이어의 레벨을 set한다. Vampire* pVampire = dynamic_cast<Vampire*>(pPC); Assert(pVampire != NULL); int level = pVampire->getLevel(); m_pLuaVampireItem->setLevel(level); pLuaSelectItem = m_pLuaVampireItem; luaFileName = m_VampireFilename; } //-------------------------------------------------------- // 속도 체크를 위해서 1000번 돌려보는 코드 // 결과는.. 0.07초 정도 나왔다. 감덩~ -_-; /* Timeval beforeTime; getCurrentTime(beforeTime); for (int i=0; i<1000; i++) { // 루아의 계산 결과를 받아 아이템을 생성한다. pLuaSelectItem->prepare(); int result = pLuaSelectItem->executeFile(luaFileName); LuaState::logError(result); pLuaSelectItem->clear(); } Timeval afterTime; getCurrentTime(afterTime); cout << "luaExecute time before : " << beforeTime.tv_sec << "." << beforeTime.tv_usec << endl; cout << "luaExecute time after : " << afterTime.tv_sec << "." << afterTime.tv_usec << endl; */ //-------------------------------------------------------- // 루아의 계산 결과를 받아 아이템을 생성한다. pLuaSelectItem->prepare(); int result = pLuaSelectItem->executeFile(luaFileName); LuaState::logError(result); ItemClass = pLuaSelectItem->getItemClass(); ItemType = pLuaSelectItem->getItemType(); OptionType = pLuaSelectItem->getOptionType(); pLuaSelectItem->clear(); if(ItemClass >= Item::ITEM_CLASS_MAX ) //|| ItemType >= ITEM_TYPE_MAX || ItemType < 0 // || OptionType == 0) { filelog("XMasEventError.txt", "[ ItemInfo Error ] : ItemClass = %d , ItemType = %d , OptionType = %d", ItemClass, ItemType, OptionType); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } // 클라이언트에 선물상자를 지우도록 한다. GCDeleteInventoryItem gcDeleteInventoryItem; gcDeleteInventoryItem.setObjectID(pGiftBoxItem->getObjectID()); pPlayer->sendPacket(&gcDeleteInventoryItem); // 선물상자를 지운다. pInventory->deleteItem(X, Y); // ItemTraceLog 를 남긴다 if (pGiftBoxItem != NULL && pGiftBoxItem->isTraceItem() ) { remainTraceLog(pGiftBoxItem, pCreature2->getName(), pCreature1->getName(), ITEM_LOG_DELETE, DETAIL_EVENTNPC); } pGiftBoxItem->destroy(); SAFE_DELETE(pGiftBoxItem); // 선물(Item)을 만든다. list<OptionType_t> optionTypeList; if (OptionType != 0 ) optionTypeList.push_back(OptionType); pItem = g_pItemFactoryManager->createItem(ItemClass, ItemType, optionTypeList); Assert(pItem != NULL); // 선물을 인벤토리에 추가한다. pZone->getObjectRegistry().registerObject(pItem); pInventory->addItem(X, Y, pItem); pItem->create(pPC->getName(), STORAGE_INVENTORY, 0, X, Y); // ItemTraceLog 를 남긴다 if (pItem != NULL && pItem->isTraceItem() ) { remainTraceLog(pItem, pCreature1->getName(), pCreature2->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC); } // 클라이언트에 선물이 추가되었음을 알린다. GCCreateItem gcCreateItem; makeGCCreateItem(&gcCreateItem, pItem, X, Y); pPlayer->sendPacket(&gcCreateItem); // Flag을 켠다. pFlagSet->turnOn(FLAGSET_TRADE_GIFT_BOX_2002_12); // Flag을 저장한다. pFlagSet->save(pPC->getName()); // 아이템 교환이 이루어 졌다고 클라이언트에 알린다. GCNPCResponse response; response.setCode(NPC_RESPONSE_TRADE_GIFT_BOX_OK); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); __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 ActionShowTaxBalance::execute (Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); bool bSuccess = true; PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2); Player* pPlayer = pPC->getPlayer(); Assert(pPlayer != NULL); GuildID_t guildID = pPC->getGuildID(); GCNPCResponse deny; Guild* pGuild = g_pGuildManager->getGuild(guildID); if(bSuccess && pGuild == NULL ) { // 길드가 없다. bSuccess = false; deny.setCode(NPC_RESPONSE_NO_GUILD); } if(bSuccess && pGuild->getMaster() != pPC->getName() ) { // 길드 마스터가 아니다. bSuccess = false; deny.setCode(NPC_RESPONSE_NOT_GUILD_MASTER); } // 길드 마스터이다. list<CastleInfo*> pCastleInfoList = g_pCastleInfoManager->getGuildCastleInfos(guildID); if(bSuccess && pCastleInfoList.empty() ) { // 길드가 소유한 성이 없다. bSuccess = false; deny.setCode(NPC_RESPONSE_HAS_NO_CASTLE); } list<CastleInfo*>::iterator itr = pCastleInfoList.begin(); CastleInfo* pCastleInfo = NULL; for (; itr != pCastleInfoList.end() ; itr++ ) { if ((*itr)->getZoneID() == pCreature1->getZoneID() ) { pCastleInfo = (*itr); break; } } if(bSuccess && pCastleInfo == NULL) { bSuccess = false; deny.setCode(NPC_RESPONSE_NOT_YOUR_CASTLE); } if (bSuccess ) { GCNPCResponse response; response.setCode(NPC_RESPONSE_SHOW_TAX_BALANCE); response.setParameter((uint)pCastleInfo->getTaxBalance()); pPlayer->sendPacket(&response); } else { pPlayer->sendPacket(&deny); } GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); __END_CATCH }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionWarpToNoviceZone::execute (Creature * pNPC , Creature * pCreature) throw(Error) { __BEGIN_TRY __BEGIN_DEBUG Assert(pCreature != NULL); Assert(pCreature->isPC()); if (!pCreature->isSlayer() ) return; Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); ZoneID_t ZoneID = pSlayer->getZoneID(); ZoneCoord_t X = pSlayer->getX(); ZoneCoord_t Y = pSlayer->getY(); Attr_t totalAttr = pSlayer->getTotalAttr(ATTR_BASIC); GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pCreature->getPlayer()); bool bTransport = true; if (totalAttr <= 40 ) { ZoneID = m_NoviceZoneID; X = m_NoviceX; Y = m_NoviceY; } else if (totalAttr <= 60 ) { ZoneID = m_BeginnerZoneID; X = m_BeginnerX; Y = m_BeginnerY; } else { GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NOT_BEGINNER )); pGamePlayer->sendPacket (&gcSystemMessage); bTransport = false; } //Zone* pZone = pCreature->getZone(); #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; } } } catch (NoSuchElementException&) { } #endif if (bTransport) { transportCreature(pCreature, ZoneID, X, Y, true); } else { if (pNPC != NULL ) { GCNPCResponse response; response.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pGamePlayer->sendPacket(&response); } } __END_DEBUG __END_CATCH }