void EffectChargingPower::unaffect(Creature* pCreature) throw(Error) { __BEGIN_TRY __BEGIN_DEBUG //cout << "EffectChargingPower" << "unaffect BEGIN" << endl; Assert(pCreature != NULL); Assert(pCreature->isSlayer()); pCreature->removeFlag(Effect::EFFECT_CLASS_CHARGING_POWER); Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); SLAYER_RECORD prev; pSlayer->getSlayerRecord(prev); pSlayer->initAllStat(); pSlayer->sendRealWearingInfo(); pSlayer->sendModifyInfo(prev); Zone* pZone = pSlayer->getZone(); Assert(pZone != NULL); // 이펙트가 사라졌다고 알려준다. GCRemoveEffect gcRemoveEffect; gcRemoveEffect.setObjectID(pSlayer->getObjectID()); gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_CHARGING_POWER); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcRemoveEffect); //cout << "EffectChargingPower" << "unaffect END" << endl; __END_DEBUG __END_CATCH }
void EffectExpansion::unaffect(Creature* pCreature) throw(Error) { __BEGIN_TRY __BEGIN_DEBUG //cout << "EffectExpansion " << "unaffect BEGIN" << endl; Assert(pCreature != NULL); Assert(pCreature->isSlayer() == true); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); pCreature->removeFlag(Effect::EFFECT_CLASS_EXPANSION); Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); SLAYER_RECORD prev; pSlayer->getSlayerRecord(prev); pSlayer->initAllStat(); pSlayer->sendRealWearingInfo(); pSlayer->sendModifyInfo(prev); // 이펙트가 사라졌다고 알려준다. GCRemoveEffect gcRemoveEffect; gcRemoveEffect.setObjectID(pSlayer->getObjectID()); gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_EXPANSION); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcRemoveEffect); // 현재 남아있는 체력이 최대 체력보다 크다면, 줄여야 한다. if (pSlayer->getHP(ATTR_CURRENT) > pSlayer->getHP(ATTR_MAX)) { pSlayer->setHP(pSlayer->getHP(ATTR_MAX), ATTR_CURRENT); } GCOtherModifyInfo gcOtherModifyInfo; makeGCOtherModifyInfo(&gcOtherModifyInfo, pSlayer, &prev); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcOtherModifyInfo, pSlayer); //cout << "EffectExpansion " << "unaffect END" << endl; __END_DEBUG __END_CATCH }
void EffectPotentialExplosion::unaffect(Creature* pCreature) throw(Error) { __BEGIN_TRY __BEGIN_DEBUG //cout << "EffectPotentialExplosion " << "unaffect BEGIN" << endl; Assert(pCreature != NULL); Assert(pCreature->isSlayer()); pCreature->removeFlag(Effect::EFFECT_CLASS_POTENTIAL_EXPLOSION); Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); SLAYER_RECORD prev; pSlayer->getSlayerRecord(prev); pSlayer->initAllStat(); pSlayer->sendRealWearingInfo(); pSlayer->sendModifyInfo(prev); Zone* pZone = pSlayer->getZone(); Assert(pZone != NULL); GCRemoveEffect gcRemoveEffect; gcRemoveEffect.setObjectID(pSlayer->getObjectID()); gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_POTENTIAL_EXPLOSION); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcRemoveEffect); GCOtherModifyInfo gcOtherModifyInfo; makeGCOtherModifyInfo(&gcOtherModifyInfo, pSlayer, &prev); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcOtherModifyInfo, pSlayer); //cout << "EffectPotentialExplosion " << "unaffect END" << endl; __END_DEBUG __END_CATCH }
void EffectObservingEye::unaffect(Creature* pCreature) throw(Error) { __BEGIN_TRY //cout << "EffectObservingEye" << "unaffect BEGIN" << endl; Assert(pCreature != NULL); Assert(pCreature->isSlayer()); // 슬레이어말고는 걸리지 않는다. pCreature->removeFlag(Effect::EFFECT_CLASS_OBSERVING_EYE); Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); SLAYER_RECORD prev; pSlayer->getSlayerRecord(prev); pSlayer->initAllStat(); pSlayer->sendRealWearingInfo(); pSlayer->sendModifyInfo(prev); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); GCRemoveEffect gcRemoveEffect; gcRemoveEffect.setObjectID(pCreature->getObjectID()); gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_OBSERVING_EYE); pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcRemoveEffect); // 이 이펙트로 보고 있었던 크리쳐들을 삭제한다. pZone->updateInvisibleScan(pCreature); GCOtherModifyInfo gcOtherModifyInfo; makeGCOtherModifyInfo(&gcOtherModifyInfo, pSlayer, &prev); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcOtherModifyInfo, pSlayer); //cout << "EffectObservingEye" << "unaffect END" << endl; __END_CATCH }
void ActionRedeemMotorcycle::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); // 일단 클라이언트를 위해 ok패킷을 하나 날려주고... GCNPCResponse answerOKpkt; pPlayer->sendPacket(&answerOKpkt); // 플레이어가 슬레이어인지 검사한다. if (pCreature2->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature2); Zone* pZone = pSlayer->getZone(); Inventory* pInventory = pSlayer->getInventory(); uint InvenWidth = pInventory->getWidth(); uint InvenHeight = pInventory->getHeight(); Item* pItem = NULL; Inventory* pBeltInventory = NULL; uint BeltInvenWidth = 0; uint BeltInvenHeight = 0; Item* pBelt = NULL; pBelt = pSlayer->getWearItem(Slayer::WEAR_BELT); if(pBelt != NULL) { pBeltInventory = ((Belt*)pBelt)->getInventory(); BeltInvenWidth = pBeltInventory->getWidth(); BeltInvenHeight = pBeltInventory->getHeight(); } // 인벤토리를 검색한다. for (uint y=0; y<InvenHeight; y++) { for (uint x=0; x<InvenWidth; x++) { // x, y에 아이템이 있다면... if (pInventory->hasItem(x, y)) { pItem = pInventory->getItem(x, y); if (load(pItem, pSlayer, pZone, pSlayer->getX(), pSlayer->getY())) { return; } } } } if(pBelt != NULL) { // 벨트를 검색한다 for (uint y = 0; y < BeltInvenHeight; y++) { for(uint x = 0; x < BeltInvenWidth; x++) { if(pBeltInventory->hasItem(x, y)) { pItem= pBeltInventory->getItem(x, y); if (load(pItem, pSlayer, pZone, pSlayer->getX(), pSlayer->getY())) { return; } } } } } } else // 뱀파이어라면...오토바이를 찾아줄 이유가 있을까? { } __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 EffectCureCriticalWounds::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; int X = pCreature->getX(); int Y = pCreature->getY(); Exp_t ExpUp = 0; bool bCured = false; for(int oY = -2; oY <= 2; oY++) for(int oX = -2; oX <= 2; oX++) { int tileX = X+oX; int tileY = Y+oY; if (isValidZoneCoord(pZone, tileX, tileY)) { Tile& tile = pZone->getTile(tileX, tileY); if (tile.hasCreature(Creature::MOVE_MODE_WALKING ) ) { const list<Object*>& oList = tile.getObjectList(); for(list<Object*>::const_iterator itr = oList.begin(); itr != oList.end(); itr++) { Object* pTarget = *itr; Creature* pTargetCreature = NULL; if (pTarget->getObjectClass() == Object::OBJECT_CLASS_CREATURE && (pTargetCreature = dynamic_cast<Creature*>(pTarget))->isSlayer()) { Assert(pTargetCreature != NULL); HP_t RemainHP = 0; if (pTargetCreature->isSlayer() && !pTargetCreature->isFlag(Effect::EFFECT_CLASS_COMA) ) { Slayer* pSlayer = dynamic_cast<Slayer*>(pTargetCreature); HP_t CurrentHP = pSlayer->getHP(ATTR_CURRENT); HP_t MaxHP = pSlayer->getHP(ATTR_MAX); if (pTargetCreature->isFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN)) { ExpUp++; Effect* pEffect = pSlayer->findEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN); EffectBloodDrain * pEffectBloodDrain = dynamic_cast<EffectBloodDrain*>(pEffect); Assert(pEffectBloodDrain != NULL); if (pEffectBloodDrain->getLevel() < CriticalBloodDrainLevel ) { // 흡혈 아르바이트를 방지하기 위한 후유증 이펙트를 붙여준다. if (pSlayer->isFlag(Effect::EFFECT_CLASS_AFTERMATH)) { Effect* pEffect = pSlayer->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분 동안 지속된다. pSlayer->addEffect(pEffectAftermath); pSlayer->setFlag(Effect::EFFECT_CLASS_AFTERMATH); pEffectAftermath->create(pSlayer->getName()); } pEffectBloodDrain->destroy(pSlayer->getName()); pSlayer->deleteEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN); bCured = true; SLAYER_RECORD prev; pSlayer->getSlayerRecord(prev); pSlayer->initAllStat(); pSlayer->sendRealWearingInfo(); pSlayer->sendModifyInfo(prev); GCRemoveEffect gcRemoveEffect; gcRemoveEffect.setObjectID(pSlayer->getObjectID()); gcRemoveEffect.addEffectList((EffectID_t)Effect::EFFECT_CLASS_BLOOD_DRAIN); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcRemoveEffect); } } if(CurrentHP < MaxHP ) { ExpUp++; bCured = true; RemainHP = min(CurrentHP + m_Point,(int)MaxHP); pSlayer->setHP(RemainHP, ATTR_CURRENT); GCModifyInformation gcMI; gcMI.addShortData(MODIFY_CURRENT_HP, RemainHP); pSlayer->getPlayer()->sendPacket(&gcMI); _GCSkillToSelfOK1.setSkillType(SKILL_CURE_EFFECT); _GCSkillToSelfOK1.setDuration(0); pSlayer->getPlayer()->sendPacket(&_GCSkillToSelfOK1); _GCSkillToSelfOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToSelfOK2.setSkillType(SKILL_CURE_EFFECT); _GCSkillToSelfOK2.setDuration(0); pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &_GCSkillToSelfOK2, pTargetCreature); Zone* pZone = pTargetCreature->getZone(); GCStatusCurrentHP gcStatusCurrentHP; gcStatusCurrentHP.setObjectID(pTargetCreature->getObjectID()); gcStatusCurrentHP.setCurrentHP(RemainHP); pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &gcStatusCurrentHP); } } } } } } } SkillInfo * pSkillInfo = g_pSkillInfoManager->getSkillInfo(SKILL_CURE_CRITICAL_WOUNDS); if(pSkillInfo != NULL && bCured ) { SkillSlot * pSkillSlot = ((Slayer*)pCreature)->hasSkill(SKILL_CURE_CRITICAL_WOUNDS); if(pSkillSlot != NULL ) { Slayer * pCastSlayer = dynamic_cast<Slayer*>(pCreature); GCModifyInformation gcMI; SkillDomainType_t DomainType = pSkillInfo->getDomainType(); // 경험치를 올려준다. shareAttrExp(pCastSlayer, ExpUp, 1 , 1 , 8, gcMI); increaseDomainExp(pCastSlayer, DomainType, ExpUp, gcMI); increaseSkillExp(pCastSlayer, DomainType, pSkillSlot, pSkillInfo, gcMI); pCastSlayer->getPlayer()->sendPacket(&gcMI); } } //cout << "EffectCureCriticalWounds " << "affect BEGIN" << endl; setNextTime(m_Delay); //cout << "EffectCureCriticalWounds " << "affect END" << endl; __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 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 SimpleCureSkill::execute(Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, const SIMPLE_SKILL_INPUT& param, SIMPLE_SKILL_OUTPUT& result, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pSlayer->getPlayer(); Zone* pZone = pSlayer->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // 슬레이어 외에는 치료할 수가 없다. // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || pTargetCreature->isSlayer() == false) { executeSkillFailException(pSlayer, param.SkillType); return; } GCSkillToObjectOK1 _GCSkillToObjectOK1; GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK3 _GCSkillToObjectOK3; GCSkillToObjectOK4 _GCSkillToObjectOK4; GCSkillToObjectOK5 _GCSkillToObjectOK5; SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(param.SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); bool bHPCheck = false; // 체력이 닳거나, 흡혈을 당한 상태여야 한다. Slayer* pTargetSlayer = dynamic_cast<Slayer*>(pTargetCreature); Assert(pTargetSlayer != NULL); EffectBloodDrain* pEffectBloodDrain = NULL; if (pTargetSlayer->getHP(ATTR_CURRENT) < pTargetSlayer->getHP(ATTR_MAX)) { bHPCheck = true; } if (pTargetSlayer->isFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN)) { Effect* pEffect = pTargetSlayer->findEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN); pEffectBloodDrain = dynamic_cast<EffectBloodDrain*>(pEffect); Assert(pEffectBloodDrain != NULL); if (pEffectBloodDrain->getLevel() < param.Level) bHPCheck = true; } int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = verifyDistance(pSlayer, pTargetCreature, pSkillInfo->getRange()); bool bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot); if (bHPCheck && bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && pTargetCreature->isAlive()) { decreaseMana(pSlayer, RequiredMP, _GCSkillToObjectOK1); uint HealPoint = param.SkillDamage; // 흡혈당한 상태라면 흡혈 상태를 날려준다. if (pEffectBloodDrain != NULL && pEffectBloodDrain->getLevel() < param.Level) { // 흡혈 아르바이트를 방지하기 위한 후유증 이펙트를 붙여준다. if (pTargetSlayer->isFlag(Effect::EFFECT_CLASS_AFTERMATH)) { Effect* pEffect = pTargetSlayer->findEffect(Effect::EFFECT_CLASS_AFTERMATH); EffectAftermath* pEffectAftermath = dynamic_cast<EffectAftermath*>(pEffect); pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다. } else { EffectAftermath* pEffectAftermath = new EffectAftermath(pTargetSlayer); pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다. pTargetSlayer->addEffect(pEffectAftermath); pTargetSlayer->setFlag(Effect::EFFECT_CLASS_AFTERMATH); pEffectAftermath->create(pTargetSlayer->getName()); } pEffectBloodDrain->destroy(pTargetSlayer->getName()); pTargetSlayer->deleteEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN); SLAYER_RECORD prev; pTargetSlayer->getSlayerRecord(prev); pTargetSlayer->initAllStat(); pTargetSlayer->sendRealWearingInfo(); pTargetSlayer->addModifyInfo(prev, _GCSkillToObjectOK2); GCRemoveEffect gcRemoveEffect; gcRemoveEffect.setObjectID(pTargetSlayer->getObjectID()); gcRemoveEffect.addEffectList((EffectID_t)Effect::EFFECT_CLASS_BLOOD_DRAIN); pZone->broadcastPacket(pTargetSlayer->getX(), pTargetSlayer->getY(), &gcRemoveEffect); } // 다른 사람을 치료한다. HP_t CurrentHP = pTargetSlayer->getHP(ATTR_CURRENT); HP_t MaxHP = pTargetSlayer->getHP(ATTR_MAX); // 실제 회복 수치를 계산한다. int RealHealPoint = 0; if(CurrentHP + HealPoint <= MaxHP ) { RealHealPoint = max((unsigned int)0, HealPoint); } else { RealHealPoint = max(0, MaxHP - CurrentHP); } // 경험치를 올려준다. shareAttrExp(pSlayer, HealPoint , param.STRMultiplier, param.DEXMultiplier, param.INTMultiplier, _GCSkillToObjectOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToObjectOK1); increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToObjectOK1); CurrentHP = min((int)(MaxHP), (int)(CurrentHP + HealPoint)); pTargetSlayer->setHP(CurrentHP, ATTR_CURRENT); // 치료가 되었으니 HP를 브로드캐스팅한다. GCStatusCurrentHP gcStatusCurrentHP; gcStatusCurrentHP.setObjectID(TargetObjectID); gcStatusCurrentHP.setCurrentHP (CurrentHP); pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &gcStatusCurrentHP); _GCSkillToObjectOK2.addShortData(MODIFY_CURRENT_HP, CurrentHP); ZoneCoord_t myX = pSlayer->getX(); ZoneCoord_t myY = pSlayer->getY(); ZoneCoord_t targetX = pTargetCreature->getX(); ZoneCoord_t targetY = pTargetCreature->getY(); _GCSkillToObjectOK1.setSkillType(param.SkillType); _GCSkillToObjectOK1.setCEffectID(CEffectID); _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK1.setDuration(0); _GCSkillToObjectOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK2.setSkillType(param.SkillType); _GCSkillToObjectOK2.setDuration (0); _GCSkillToObjectOK3.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK3.setSkillType(param.SkillType); _GCSkillToObjectOK3.setTargetXY(targetX, targetY); _GCSkillToObjectOK4.setSkillType(param.SkillType); _GCSkillToObjectOK4.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK5.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK5.setSkillType(param.SkillType); _GCSkillToObjectOK5.setTargetObjectID (TargetObjectID); _GCSkillToObjectOK5.setDuration (0); pPlayer->sendPacket(&_GCSkillToObjectOK1); if (pTargetCreature->isPC()) { Player* pTargetPlayer = pTargetCreature->getPlayer(); Assert(pTargetPlayer != NULL); pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); } list<Creature*> cList; cList.push_back(pSlayer); cList.push_back(pTargetCreature); cList = pZone->broadcastSkillPacket(myX, myY, targetX, targetY, &_GCSkillToObjectOK5, cList); pZone->broadcastPacket(myX, myY, &_GCSkillToObjectOK3 , cList); pZone->broadcastPacket(targetX, targetY, &_GCSkillToObjectOK4 , cList); pSkillSlot->setRunTime(param.Delay); result.bSuccess = true; } else { executeSkillFailNormal(pSlayer, param.SkillType, pTargetCreature); } } catch(Throwable & t) { executeSkillFailException(pSlayer, param.SkillType); } __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 }