void EffectReactiveArmor::unaffect(Creature* pCreature) throw(Error) { __BEGIN_TRY //cout << "EffectReactiveArmor" << "unaffect BEGIN" << endl; Assert(pCreature != NULL); Assert(pCreature->isOusters()); // 플래그를 끈다. pCreature->removeFlag(Effect::EFFECT_CLASS_REACTIVE_ARMOR); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); Ousters* pTargetOusters = dynamic_cast<Ousters*>(pCreature); Assert(pTargetOusters != NULL); pTargetOusters->initAllStatAndSend(); // 이펙트를 삭제하라고 알려준다. GCRemoveEffect gcRemoveEffect; gcRemoveEffect.setObjectID(pCreature->getObjectID()); gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_REACTIVE_ARMOR); pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcRemoveEffect); //cout << "EffectReactiveArmor" << "unaffect END" << endl; __END_CATCH }
void GroundBless::execute(Ousters* pOusters, ObjectID_t TargetObjectID, OustersSkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; Assert(pOusters != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pOusters->getPlayer(); Zone* pZone = pOusters->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); Item* pWeapon = pOusters->getWearItem(Ousters::WEAR_RIGHTHAND); if (pWeapon == NULL || pWeapon->getItemClass() != Item::ITEM_CLASS_OUSTERS_WRISTLET || !pOusters->isRealWearingEx(Ousters::WEAR_RIGHTHAND)) { executeSkillFailException(pOusters, pSkillSlot->getSkillType()); return; } Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NPC는 공격할 수 없다. // 저주 면역. by sigi. 2002.9.13 // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || !pTargetCreature->isOusters() ) { executeSkillFailException(pOusters, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; return; } GCSkillToObjectOK1 _GCSkillToObjectOK1; GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK3 _GCSkillToObjectOK3; GCSkillToObjectOK4 _GCSkillToObjectOK4; GCSkillToObjectOK5 _GCSkillToObjectOK5; GCSkillToObjectOK6 _GCSkillToObjectOK6; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillInput input(pOusters, pSkillSlot); SkillOutput output; computeOutput(input, output); int RequiredMP = (int)pSkillInfo->getConsumeMP() + pSkillSlot->getExpLevel()/2; bool bManaCheck = hasEnoughMana(pOusters, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = verifyDistance(pOusters, pTargetCreature, pSkillInfo->getRange()); bool bHitRoll = HitRoll::isSuccessMagic(pOusters, pSkillInfo, pSkillSlot); bool bEffected = pTargetCreature->isFlag(Effect::EFFECT_CLASS_GROUND_BLESS); bool bSatisfyRequire = pOusters->satisfySkillRequire(pSkillInfo); ZoneCoord_t targetX = pTargetCreature->getX(); ZoneCoord_t targetY = pTargetCreature->getY(); ZoneCoord_t myX = pOusters->getX(); ZoneCoord_t myY = pOusters->getY(); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected && bSatisfyRequire) { decreaseMana(pOusters, RequiredMP, _GCSkillToObjectOK1); bool bCanSeeCaster = canSee(pTargetCreature, pOusters); // 이펙트 오브젝트를 생성해 붙인다. EffectGroundBless* pEffect = new EffectGroundBless(pTargetCreature); pEffect->setDeadline(output.Duration); pEffect->setBonus(output.Damage); pTargetCreature->addEffect(pEffect); pTargetCreature->setFlag(Effect::EFFECT_CLASS_GROUND_BLESS); Ousters* pTargetOusters = dynamic_cast<Ousters*>(pTargetCreature); if (pTargetOusters != NULL ) pTargetOusters->initAllStatAndSend(); _GCSkillToObjectOK1.setSkillType(SkillType); _GCSkillToObjectOK1.setCEffectID(CEffectID); _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK1.setDuration(output.Duration); _GCSkillToObjectOK2.setObjectID(pOusters->getObjectID()); _GCSkillToObjectOK2.setSkillType(SkillType); _GCSkillToObjectOK2.setDuration(output.Duration); _GCSkillToObjectOK3.setObjectID(pOusters->getObjectID()); _GCSkillToObjectOK3.setSkillType(SkillType); _GCSkillToObjectOK3.setTargetXY (targetX, targetY); _GCSkillToObjectOK4.setSkillType(SkillType); _GCSkillToObjectOK4.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK4.setDuration(output.Duration); _GCSkillToObjectOK5.setObjectID(pOusters->getObjectID()); _GCSkillToObjectOK5.setSkillType(SkillType); _GCSkillToObjectOK5.setTargetObjectID (TargetObjectID); _GCSkillToObjectOK5.setDuration(output.Duration); _GCSkillToObjectOK6.setXY(myX, myY); _GCSkillToObjectOK6.setSkillType(SkillType); _GCSkillToObjectOK6.setDuration(output.Duration); list<Creature *> cList; cList.push_back(pTargetCreature); cList.push_back(pOusters); cList = pZone->broadcastSkillPacket(myX, myY, targetX, targetY, &_GCSkillToObjectOK5, cList); pZone->broadcastPacket(myX, myY, &_GCSkillToObjectOK3, cList); pZone->broadcastPacket(targetX, targetY, &_GCSkillToObjectOK4, cList); // Send Packet pPlayer->sendPacket(&_GCSkillToObjectOK1); Player* pTargetPlayer = pTargetCreature->getPlayer(); if (pTargetPlayer != NULL ) { if (bCanSeeCaster) pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); else pTargetPlayer->sendPacket(&_GCSkillToObjectOK6); } GCAddEffect gcAddEffect; gcAddEffect.setObjectID(TargetObjectID); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_GROUND_BLESS); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(targetX, targetY, &gcAddEffect); pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pOusters, getSkillType(), pTargetCreature); } } catch (Throwable & t) { executeSkillFailException(pOusters, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; __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 }