void CGTradeAddItemHandler::executeOusters (CGTradeAddItem* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ // 상위 함수에서 에러를 검사했기 때문에, // 여기서는 포인터가 널인지를 검사하지 않는다. ObjectID_t TargetOID = pPacket->getTargetObjectID(); ObjectID_t ItemOID = pPacket->getItemObjectID(); GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Creature* pPC = pGamePlayer->getCreature(); Zone* pZone = pPC->getZone(); PlayerCreature* pTargetPC = dynamic_cast<PlayerCreature*>(pZone->getCreature(TargetOID)); // NoSuch제거. by sigi. 2002.5.2 if (pTargetPC==NULL) return; Ousters* pSender = dynamic_cast<Ousters*>(pPC); TradeManager* pTradeManager = pZone->getTradeManager(); Assert(pTradeManager != NULL); // 교환 대상에 추가할 아이템의 포인터를 얻어낸다. CoordInven_t X, Y; Inventory* pInventory = pSender->getInventory(); Item* pItem = pInventory->findItemOID(ItemOID, X, Y); // 추가할 아이템이 없다면 당연히 더 이상 처리가 불가능 // Relic은 교환할 수 없다. if (pItem == NULL || !canTrade(pItem ) || pSender->getStore()->hasItem(pItem) || (pItem->getItemClass() == Item::ITEM_CLASS_SUB_INVENTORY && hasItemWithItemClass(pTargetPC, Item::ITEM_CLASS_SUB_INVENTORY ) ) ) { pTradeManager->cancelTrade(pPC); executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_ADD_ITEM); return; } // //#ifdef __XMAS_EVENT_CODE__ // 녹색 선물 상자인 경우에는, 상대방에게 적색 선물 상자가 없는지 검사한 후, // 인증 패킷을 보내줘야 한다. if (pItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX) { PlayerCreature* pReceiver = dynamic_cast<PlayerCreature*>(pTargetPC); Item* pExtraSlotItem = pReceiver->getExtraInventorySlotItem(); if (pItem->getItemType() == 0) { Inventory* pTargetInventory = pReceiver->getInventory(); if (pTargetInventory->hasRedGiftBox()) { // 적색 선물 상자를 가지고 있다면 더할 수 없다. 리턴시킨다. GCTradeVerify gcTradeVerify; gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_FAIL); pPlayer->sendPacket(&gcTradeVerify); return; } else if (pExtraSlotItem != NULL) { if (pExtraSlotItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX && pExtraSlotItem->getItemType() == 1) { GCTradeVerify gcTradeVerify; gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_FAIL); pPlayer->sendPacket(&gcTradeVerify); return; } } else { // 적색 선물 상자를 가지고 있지 않다면, 걍 넘어간다. GCTradeVerify gcTradeVerify; gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_OK); pPlayer->sendPacket(&gcTradeVerify); } } else if (pItem->getItemType() == 1) { // 적색 선물 상자는 교환 품목이 될 수 없다. GCTradeVerify gcTradeVerify; gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_FAIL); pPlayer->sendPacket(&gcTradeVerify); return; } } //#endif // TradeInfo* pInfo1 = pTradeManager->getTradeInfo(pSender->getName()); TradeInfo* pInfo2 = pTradeManager->getTradeInfo(pTargetPC->getName()); list<Item*> tradeList1 = pInfo1->getItemList(); if (pItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX && pItem->getItemType() > 1 && pItem->getItemType() < 6) { for (list<Item*>::iterator itr = tradeList1.begin(); itr != tradeList1.end(); itr++) { Item* pTradeItem = (*itr); if (pTradeItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX && pTradeItem->getItemType() > 1 && pTradeItem->getItemType() < 6) { GCTradeVerify gcTradeVerify; gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_FAIL); pPlayer->sendPacket(&gcTradeVerify); return; } } GCTradeVerify gcTradeVerify; gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_OK); pPlayer->sendPacket(&gcTradeVerify); } else if (pItem->getItemClass() == Item::ITEM_CLASS_EVENT_GIFT_BOX && pItem->getItemType() >= 6) { GCTradeVerify gcTradeVerify; gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_OK); pPlayer->sendPacket(&gcTradeVerify); } // TradeManager에 교환 대상으로서 아이템을 더한다. //Assert(pInfo1->addItem(pItem)); pInfo1->addItem(pItem); // 현재 OK를 누른 상태라면, 클라이언트에게 인증 패킷을 보내줘야 한다. if (pInfo1->getStatus() == TRADE_FINISH) { //cout << "CGTradeRemoveItem [" << pSender->getName() << "]의 상태가 TRADE_FINISH이므로, 인증 패킷을 보내준다." << endl; // 인증 패킷을 날려준다. GCTradeVerify gcTradeVerify; gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_ADD_ITEM_WHEN_ACCEPT); pPlayer->sendPacket(&gcTradeVerify); } else { //cout << "CGTradeRemoveItem [" << pSender->getName() << "]의 상태가 TRADE_FINISH가 아니므로, 인증 패킷 날리지 않는다." << endl; } // 아이템을 더하거나 뺄 경우, 상태가 TRADE_FINISH라면 // TRADE_TRADING으로 바꿔줘야 한다. pInfo1->setStatus(TRADE_TRADING); pInfo2->setStatus(TRADE_TRADING); // 상대방에게 날려줄 아이템 정보를 구성한다. GCTradeAddItem gcTradeAddItem; makeGCTradeAddItemPacket(&gcTradeAddItem, pSender->getObjectID(), pItem, X, Y); // 상대방에게 교환할 아이템 정보를 날려준다. Player* pTargetPlayer = pTargetPC->getPlayer(); pTargetPlayer->sendPacket(&gcTradeAddItem); #endif __END_DEBUG_EX __END_CATCH }
void 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 CGTradeMoneyHandler::executeOusters (CGTradeMoney* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ // 상위 함수에서 검사를 했기 때문에, // 여기서는 포인터가 널인지를 검사하지 않는다. ObjectID_t TargetOID = pPacket->getTargetObjectID(); Gold_t Amount = pPacket->getAmount(); BYTE Code = pPacket->getCode(); GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Creature* pPC = pGamePlayer->getCreature(); Zone* pZone = pPC->getZone(); Creature* pTargetPC = pZone->getCreature(TargetOID); // NoSuch제거. by sigi. 2002.5.2 if (pTargetPC==NULL) return; Ousters* pSender = dynamic_cast<Ousters*>(pPC); Ousters* pReceiver = dynamic_cast<Ousters*>(pTargetPC); Player* pTargetPlayer = pTargetPC->getPlayer(); Gold_t finalAmount = Amount; Gold_t margin = 0; GCTradeMoney gcTradeMoney; GCTradeVerify gcTradeVerify; TradeManager* pTradeManager = pZone->getTradeManager(); Assert(pTradeManager != NULL); // 교환 상태가 맞는지 체크를 해봐야한다. TradeInfo* pInfo1 = pTradeManager->getTradeInfo(pSender->getName()); TradeInfo* pInfo2 = pTradeManager->getTradeInfo(pReceiver->getName()); // 인벤토리에서 돈을 덜어, 교환창에다 더한다. if (Code == CG_TRADE_MONEY_INCREASE) { // 교환창에다 더할 액수보다 많은 돈을 가지고 있어야 한다. if (pSender->getGold() >= Amount) { // 돈을 받는 쪽이 맥스를 초과하게 된다면, 일부만 넣어줘야 한다. // 현재 교환 예정인 돈도 더해서 계산. by sigi. 2003.1.8 Gold_t receiverGold = pReceiver->getGold() + pInfo1->getGold(); if (receiverGold + Amount > MAX_MONEY) { margin = receiverGold + Amount - MAX_MONEY; finalAmount = finalAmount - margin; } // 인벤토리에서 돈을 빼고, 교환창에다 더한다. pSender->setGold(pSender->getGold() - finalAmount); pInfo1->setGold(pInfo1->getGold() + finalAmount); // 현재 OK를 누른 상태라면, 클라이언트에게 인증 패킷을 보내줘야 한다. if (pInfo1->getStatus() == TRADE_FINISH) { // 인증 패킷을 날려준다. gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_MONEY_INCREASE); pPlayer->sendPacket(&gcTradeVerify); } // 아이템을 더하거나 뺄 경우, 상태를 변환해줘야 한다. pInfo1->setStatus(TRADE_TRADING); pInfo2->setStatus(TRADE_TRADING); // 돈을 올린 당사자에게 실제로 인벤토리에서 // 빠진 금액이 얼마인지 보내준다. gcTradeMoney.setTargetObjectID(TargetOID); gcTradeMoney.setCode(GC_TRADE_MONEY_INCREASE_RESULT); gcTradeMoney.setAmount(finalAmount); pPlayer->sendPacket(&gcTradeMoney); // 상대방에게 바뀐 정보를 보내준다. gcTradeMoney.setTargetObjectID(pSender->getObjectID()); gcTradeMoney.setCode(GC_TRADE_MONEY_INCREASE); gcTradeMoney.setAmount(finalAmount); pTargetPlayer->sendPacket(&gcTradeMoney); } else { pTradeManager->cancelTrade(pPC); executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_INCREASE_MONEY); return; } } // 교환창에서 돈을 덜어, 인벤토리에다가 더한다. else if (Code == CG_TRADE_MONEY_DECREASE) { // 인벤토리에다 더할 액수보다 교환창에 있는 돈이 많아야 한다. if (pInfo1->getGold() >= Amount) { // 돈이 맥스를 초과하게 된다면, 일부만 뺄 수 있다. Gold_t senderGold = pSender->getGold() + pInfo2->getGold(); if (senderGold + Amount > MAX_MONEY) { margin = senderGold + Amount - MAX_MONEY; finalAmount = finalAmount - margin; } // 인벤토리에다가 돈을 더하고, 교환창에서 돈을 뺀다. pSender->setGold(pSender->getGold() + finalAmount); pInfo1->setGold(pInfo1->getGold() - finalAmount); // 현재 OK를 누른 상태라면, 클라이언트에게 인증 패킷을 보내줘야 한다. if (pInfo1->getStatus() == TRADE_FINISH) { // 인증 패킷을 날려준다. gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_MONEY_DECREASE); pPlayer->sendPacket(&gcTradeVerify); } // 아이템을 더하거나 뺄 경우, 상태를 변환해줘야 한다. pInfo1->setStatus(TRADE_TRADING); pInfo2->setStatus(TRADE_TRADING); // 돈을 올린 당사자에게 실제로 인벤토리에다 // 더한 금액이 얼마인지 보내준다. gcTradeMoney.setTargetObjectID(TargetOID); gcTradeMoney.setCode(GC_TRADE_MONEY_DECREASE_RESULT); gcTradeMoney.setAmount(finalAmount); pPlayer->sendPacket(&gcTradeMoney); // 상대방에게 바뀐 정보를 보내준다. gcTradeMoney.setTargetObjectID(pSender->getObjectID()); gcTradeMoney.setCode(GC_TRADE_MONEY_DECREASE); gcTradeMoney.setAmount(finalAmount); pTargetPlayer->sendPacket(&gcTradeMoney); } else { pTradeManager->cancelTrade(pPC); executeError(pPacket, pPlayer, GC_TRADE_ERROR_CODE_DECREASE_MONEY); return; } } #endif __END_DEBUG_EX __END_CATCH }
void CGDownSkillHandler::execute (CGDownSkill* 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); Assert(pGamePlayer != NULL); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pGamePlayer->getCreature()); Assert(pPC != NULL); SkillType_t targetSkillType = pPacket->getSkillType(); GCDownSkillFailed failpkt; failpkt.setSkillType(targetSkillType); if (!pPC->isOusters() ) { failpkt.setDesc(NOT_OUSTERS); pPlayer->sendPacket(&failpkt); return; } Ousters* pOusters = dynamic_cast<Ousters*>(pPC); Assert(pOusters != NULL); OustersSkillSlot* pTargetSkillSlot = pOusters->getSkill(targetSkillType); if (pTargetSkillSlot == NULL ) { failpkt.setDesc(HAVE_NOT_SKILL); pPlayer->sendPacket(&failpkt); return; } SkillInfo* pTargetSkillInfo = NULL; try { pTargetSkillInfo = g_pSkillInfoManager->getSkillInfo(targetSkillType); } catch(Exception& e) { failpkt.setDesc(INVALID_SKILL); pPlayer->sendPacket(&failpkt); return; } if (pTargetSkillSlot->getExpLevel() <= 1 ) { if (!pTargetSkillInfo->canDelete() ) { failpkt.setDesc(TOO_LOW); pPlayer->sendPacket(&failpkt); return; } list<SkillType_t>& rRequiredSkills = pTargetSkillInfo->getRequiredSkills(); list<SkillType_t>::iterator itr = rRequiredSkills.begin(); for (; itr != rRequiredSkills.end(); ++itr ) { if (pOusters->hasSkill(*itr) != NULL ) { bool canDrop = false; SkillInfo* pFollowingSkillInfo = g_pSkillInfoManager->getSkillInfo(*itr); list<SkillType_t>& rRequireSkills = pFollowingSkillInfo->getRequireSkills(); list<SkillType_t>::iterator itr2 = rRequireSkills.begin(); for (; itr2 != rRequireSkills.end(); ++itr2 ) { if ((*itr2) != targetSkillType && pOusters->hasSkill(*itr2) != NULL ) { SkillInfo* pAlternativeSkillInfo = g_pSkillInfoManager->getSkillInfo(*itr2); if (getSkillMapID((ElementalDomain)pAlternativeSkillInfo->getElementalDomain()) == getSkillMapID((ElementalDomain)pTargetSkillInfo->getElementalDomain()) ) canDrop = true; } } if (!canDrop ) { failpkt.setDesc(CANNOT_DROP_SKILL); pPlayer->sendPacket(&failpkt); return; } } } } /* if (pTargetSkillSlot->getExpLevel() >= 30 ) { failpkt.setDesc(TOO_HIGH); pPlayer->sendPacket(&failpkt); return; }*/ Assert(pTargetSkillInfo != NULL); int backPoint = pTargetSkillInfo->getLevelUpPoint(); Price_t downPrice = (int)(backPoint * pow(pOusters->getLevel(),1.3) * 200); if (pTargetSkillSlot->getExpLevel() <= 1 ) { downPrice *= 5; if (downPrice == 0 ) downPrice = 1000000; } if (pOusters->getGold() < downPrice ) { failpkt.setDesc(NOT_ENOUGH_MONEY); pPlayer->sendPacket(&failpkt); return; } pOusters->decreaseGoldEx(downPrice); pTargetSkillSlot->setExpLevel(pTargetSkillSlot->getExpLevel() - 1); pTargetSkillSlot->save(); if (pTargetSkillSlot->getExpLevel() <= 0 ) { pTargetSkillSlot->destroy(pOusters->getName()); backPoint = pTargetSkillInfo->getSkillPoint(); pOusters->removeSkill(targetSkillType); } pOusters->setSkillBonus(pOusters->getSkillBonus() + backPoint); char query[50]; sprintf(query, "SkillBonus=%d", pOusters->getSkillBonus()); pOusters->tinysave(query); GCDownSkillOK okpkt; okpkt.setSkillType(targetSkillType); pPlayer->sendPacket(&okpkt); GCModifyInformation gcMI; gcMI.addLongData(MODIFY_GOLD, pOusters->getGold()); gcMI.addShortData(MODIFY_SKILL_BONUS_POINT, pOusters->getSkillBonus()); switch (targetSkillType ) { case SKILL_HIDE_SIGHT: { OUSTERS_RECORD prev; pOusters->getOustersRecord(prev); pOusters->initAllStat(); pOusters->sendRealWearingInfo(); pOusters->addModifyInfo(prev, gcMI); } break; default : break; } pPlayer->sendPacket(&gcMI); #endif // __GAME_SERVER__ __END_DEBUG_EX __END_CATCH }