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 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 EffectBloodyWallBlocked::affect() throw(Error) { __BEGIN_TRY //cout << "EffectBloodyWallBlocked" << "affect BEGIN" << endl; Assert(m_pZone != NULL); // 현재 이펙트가 붙어있는 타일을 받아온다. Tile& tile = m_pZone->getTile(m_X, m_Y); HP_t CurrentHP = 0; HP_t RemainHP = 0; // 타일 안에 존재하는 오브젝트들을 검색한다. const list<Object*>& oList = tile.getObjectList(); list<Object*>::const_iterator itr = oList.begin(); for (; itr != oList.end(); itr++) { Assert(*itr != NULL); Object* pObject = *itr; Assert(pObject != NULL); if (pObject->getObjectClass() == Object::OBJECT_CLASS_CREATURE) { Creature* pCreature = dynamic_cast<Creature*>(pObject); Assert(pCreature != NULL); // 무적상태 체크. by sigi. 2002.9.5 // 산 면역. by sigi. 2002.9.13 if (!canAttack(NULL, pCreature ) || pCreature->isFlag(Effect::EFFECT_CLASS_IMMUNE_TO_BLOOD_DRAIN) || pCreature->isFlag(Effect::EFFECT_CLASS_COMA) || pCreature->isDead()) { continue; } int AcidDamage = computeMagicDamage(pCreature, m_Damage, SKILL_BLOODY_WALL); if (pCreature->getMoveMode() != Creature::MOVE_MODE_FLYING) { if (pCreature->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); CurrentHP = pSlayer->getHP(ATTR_CURRENT); RemainHP = max(0, CurrentHP -(int)AcidDamage); pSlayer->setHP(RemainHP, ATTR_CURRENT); GCModifyInformation gcMI; gcMI.addShortData(MODIFY_CURRENT_HP, pSlayer->getHP(ATTR_CURRENT)); Player* pPlayer = pSlayer->getPlayer(); Assert(pPlayer != NULL); pPlayer->sendPacket(&gcMI); // 변한 HP를 브로드캐스팅해준다. GCStatusCurrentHP pkt; pkt.setObjectID(pSlayer->getObjectID()); pkt.setCurrentHP(RemainHP); m_pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &pkt); } /* else if (pCreature->isVampire()) { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); CurrentHP = pVampire->getHP(ATTR_CURRENT); RemainHP = max(0, CurrentHP -(int)AcidDamage); pVampire->setHP(RemainHP, ATTR_CURRENT); GCModifyInformation gcMI; gcMI.addShortData(MODIFY_CURRENT_HP, pVampire->getHP(ATTR_CURRENT)); Player* pPlayer = pVampire->getPlayer(); Assert(pPlayer != NULL); pPlayer->sendPacket(&gcMI); // 변한 HP를 브로드캐스팅해준다. GCStatusCurrentHP pkt; pkt.setObjectID(pVampire->getObjectID()); pkt.setCurrentHP(RemainHP); m_pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &pkt); } */ else if (pCreature->isOusters()) { Ousters* pOusters = dynamic_cast<Ousters*>(pCreature); CurrentHP = pOusters->getHP(ATTR_CURRENT); RemainHP = max(0, CurrentHP -(int)AcidDamage); pOusters->setHP(RemainHP, ATTR_CURRENT); GCModifyInformation gcMI; gcMI.addShortData(MODIFY_CURRENT_HP, pOusters->getHP(ATTR_CURRENT)); Player* pPlayer = pOusters->getPlayer(); Assert(pPlayer != NULL); pPlayer->sendPacket(&gcMI); // 변한 HP를 브로드캐스팅해준다. GCStatusCurrentHP pkt; pkt.setObjectID(pOusters->getObjectID()); pkt.setCurrentHP(RemainHP); m_pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &pkt); } else if (pCreature->isMonster()) { Monster* pMonster = dynamic_cast<Monster*>(pCreature); CurrentHP = pMonster->getHP(ATTR_CURRENT); RemainHP = max(0, CurrentHP -(int)AcidDamage); pMonster->setHP(RemainHP, ATTR_CURRENT); if(m_CasterName != "" ) { // 시전자의 데미지를 추가해 준다. // 맞는 놈이 몬스터이고, 공격자가 사람이라면, // 데미지에 따라서 변하는 우선권 테이블을 갱신해 주어야 한다. pMonster->addPrecedence(m_CasterName, m_PartyID, AcidDamage); pMonster->setLastHitCreatureClass(Creature::CREATURE_CLASS_VAMPIRE); } // 변한 HP를 브로드캐스팅해준다. GCStatusCurrentHP pkt; pkt.setObjectID(pMonster->getObjectID()); pkt.setCurrentHP(RemainHP); m_pZone->broadcastPacket(pMonster->getX(), pMonster->getY(), &pkt); } // m_CasterName이 pCreature를 죽인 경우의 KillCount 처리 // by sigi. 2002.8.31 if (pCreature->isDead()) { Creature* pAttacker = m_pZone->getCreature(m_CasterName); if (pAttacker!=NULL) { affectKillCount(pAttacker, pCreature); } } } } } // 한번만.. //setNextTime(m_Tick); //cout << "EffectBloodyWallBlocked" << "affect END" << endl; __END_CATCH }
void EffectDecreaseHP::unaffect(Creature* pCreature) throw(Error) { __BEGIN_TRY __BEGIN_DEBUG Assert(pCreature != NULL); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); pCreature->removeFlag(Effect::EFFECT_CLASS_DECREASE_HP); Damage_t decreaseHP = m_Point; if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE) && !pCreature->isDead() && !pCreature->isFlag(Effect::EFFECT_CLASS_COMA) // 무적상태 체크. by sigi. 2002.9.5 && canAttack(NULL, pCreature ) ) { if (pCreature->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); HP_t CurrentHP = pSlayer->getHP(ATTR_CURRENT); if (CurrentHP > 0) { HP_t RemainHP = max(0, CurrentHP -(int)decreaseHP); pSlayer->setHP(RemainHP, ATTR_CURRENT); GCModifyInformation gcMI; gcMI.addShortData(MODIFY_CURRENT_HP, RemainHP); pSlayer->getPlayer()->sendPacket(&gcMI); // 변한 HP를 브로드캐스팅해준다. GCStatusCurrentHP pkt; pkt.setObjectID(pSlayer->getObjectID()); pkt.setCurrentHP(RemainHP); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &pkt); } } else if (pCreature->isVampire()) { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); HP_t CurrentHP = pVampire->getHP(ATTR_CURRENT); if (CurrentHP > 0) { HP_t RemainHP = max(0, CurrentHP -(int)decreaseHP); pVampire->setHP(RemainHP, ATTR_CURRENT); GCModifyInformation gcMI; gcMI.addShortData(MODIFY_CURRENT_HP, RemainHP); pVampire->getPlayer()->sendPacket(&gcMI); // 공격(흡혈) 당하는 경우에는 공격자의 성향이 바뀜 by sigi. 2002.12.27 Creature* pAttacker = pZone->getCreature(m_UserObjectID); if (pAttacker!=NULL && pAttacker->isVampire()) { Vampire* pAttackVampire = dynamic_cast<Vampire*>(pAttacker); GCModifyInformation gcAttackerMI; computeAlignmentChange(pVampire, decreaseHP, pAttackVampire, NULL, &gcAttackerMI); // 뭔가 변한 정보가 있다면 보내준다. if (gcAttackerMI.getShortCount()+gcAttackerMI.getLongCount() > 0) { pAttackVampire->getPlayer()->sendPacket(&gcAttackerMI); } } // 변한 HP를 브로드캐스팅해준다. GCStatusCurrentHP pkt; pkt.setObjectID(pVampire->getObjectID()); pkt.setCurrentHP(RemainHP); pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &pkt); } } else if (pCreature->isOusters()) { Ousters* pOusters = dynamic_cast<Ousters*>(pCreature); HP_t CurrentHP = pOusters->getHP(ATTR_CURRENT); if (CurrentHP > 0) { HP_t RemainHP = max(0, CurrentHP -(int)decreaseHP); pOusters->setHP(RemainHP, ATTR_CURRENT); GCModifyInformation gcMI; gcMI.addShortData(MODIFY_CURRENT_HP, RemainHP); pOusters->getPlayer()->sendPacket(&gcMI); // 공격(흡혈) 당하는 경우에는 공격자의 성향이 바뀜 by sigi. 2002.12.27 Creature* pAttacker = pZone->getCreature(m_UserObjectID); if (pAttacker!=NULL && pAttacker->isOusters()) { Ousters* pAttackOusters = dynamic_cast<Ousters*>(pAttacker); GCModifyInformation gcAttackerMI; computeAlignmentChange(pOusters, decreaseHP, pAttackOusters, NULL, &gcAttackerMI); // 뭔가 변한 정보가 있다면 보내준다. if (gcAttackerMI.getShortCount()+gcAttackerMI.getLongCount() > 0) { pAttackOusters->getPlayer()->sendPacket(&gcAttackerMI); } } // 변한 HP를 브로드캐스팅해준다. GCStatusCurrentHP pkt; pkt.setObjectID(pOusters->getObjectID()); pkt.setCurrentHP(RemainHP); pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &pkt); } } else if (pCreature->isMonster()) { Monster* pMonster = dynamic_cast<Monster*>(pCreature); HP_t CurrentHP = pMonster->getHP(ATTR_CURRENT); if (CurrentHP > 0) { HP_t RemainHP = max(0, CurrentHP -(int)decreaseHP); pMonster->setHP(RemainHP, ATTR_CURRENT); // 변한 HP를 브로드캐스팅해준다. GCStatusCurrentHP pkt; pkt.setObjectID(pMonster->getObjectID()); pkt.setCurrentHP(RemainHP); pZone->broadcastPacket(pMonster->getX(), pMonster->getY(), &pkt); if (RemainHP == 0 ) { Creature* pAttacker = pZone->getCreature(m_UserObjectID); if (pAttacker != NULL && pAttacker->isVampire() ) { Vampire* pAttackVampire = dynamic_cast<Vampire*>(pAttacker); GCModifyInformation gcMI; increaseAlignment(pAttackVampire, pCreature, gcMI); if (gcMI.getShortCount() > 0 || gcMI.getLongCount() > 0 ) pAttackVampire->getPlayer()->sendPacket(&gcMI); } } } } // m_CasterName이 pCreature를 죽인 경우의 KillCount 처리 // by sigi. 2002.9.9 if (pCreature->isDead()) { Creature* pAttacker = pZone->getCreature(m_UserObjectID); if (pAttacker!=NULL) { if (pAttacker->isVampire()) { Vampire* pVampire = dynamic_cast<Vampire*>(pAttacker); // 죽일때 경험치를 준다. GCModifyInformation mi; int exp = computeCreatureExp(pCreature, KILL_EXP); shareVampExp(pVampire, exp, mi); if (pCreature->isMonster() ) { increaseFame(pVampire, decreaseHP); mi.addLongData(MODIFY_FAME, pVampire->getFame()); } pAttacker->getPlayer()->sendPacket(&mi); } else if (pAttacker->isOusters() ) { Ousters* pOusters = dynamic_cast<Ousters*>(pAttacker); GCModifyInformation mi; int exp = computeCreatureExp(pCreature, 100); shareOustersExp(pOusters, exp, mi); if (pCreature->isMonster() ) { increaseFame(pOusters, decreaseHP); mi.addLongData(MODIFY_FAME, pOusters->getFame()); } } affectKillCount(pAttacker, pCreature); } } } __END_DEBUG __END_CATCH }
void 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 }