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 }