void EffectVampireRelic::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY //Timeval nextTime = getNextTime(); //Timeval deadLine = getDeadline(); //Turn_t RemainTime = deadLine.tv_sec - nextTime.tv_sec; /* StringStream msg; if (pCreature->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); msg << pSlayer->getName(); } else { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); msg << pVampire->getName(); } msg << " 님이 뱀파이어 성물을 가졌습니다."; */ char msg[50]; sprintf(msg, g_pStringPool->c_str(STRID_TAKE_VAMPIRE_RELIC ), pCreature->getName().c_str()); string sMsg(msg); GCSystemMessage gcSystemMessage; gcSystemMessage.setType(SYSTEM_MESSAGE_COMBAT); gcSystemMessage.setMessage(sMsg); g_pZoneGroupManager->broadcast(&gcSystemMessage); // Effect붙인다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pCreature->getObjectID()); gcAddEffect.setEffectID(getSendEffectClass()); gcAddEffect.setDuration(65000); pCreature->getZone()->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcAddEffect); setNextTime(m_Tick); __END_CATCH }
void EffectDonation200501::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY pCreature->setFlag(Effect::EFFECT_CLASS_DONATION_200501); // 주위에 뿌려준다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pCreature->getObjectID()); gcAddEffect.setEffectID(getSendEffectClass()); gcAddEffect.setDuration(999999); pCreature->getZone()->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcAddEffect); __END_CATCH }
void EffectPKZoneResurrection::unaffect(Creature* pCreature) throw(Error) { __BEGIN_TRY GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pCreature->getObjectID()); gcAddEffect.setEffectID(getSendEffectClass()); gcAddEffect.setDuration(28); Zone* pZone = pCreature->getZone(); if (pZone != NULL ) pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcAddEffect); pCreature->removeFlag(getEffectClass()); __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void SummonCasket::execute(Vampire* pVampire, VampireSkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pVampire != NULL); Assert(pSkillSlot != NULL); //cout << "SummonCasket try.." << endl; try { Player* pPlayer = pVampire->getPlayer(); Zone* pZone = pVampire->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); if (!pVampire->isVampire() && !pVampire->isMonster()) { executeSkillFailNormal(pVampire, getSkillType(), NULL); return; } GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK3 _GCSkillToSelfOK3; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); ZoneCoord_t x = pVampire->getX(); ZoneCoord_t y = pVampire->getY(); // Knowledge of Summon 이 있다면 hit bonus 10 int HitBonus = 0; if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_SUMMON ) ) { RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_SUMMON); Assert(pRankBonus != NULL); HitBonus = pRankBonus->getPoint(); } int RequiredMP = decreaseConsumeMP(pVampire, pSkillInfo); bool bManaCheck = hasEnoughMana(pVampire, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pVampire); bool bHitRoll = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pSkillSlot, HitBonus); bool bTileCheck = canBurrow(pZone, x, y); bool bMoveModeCheck = pVampire->isWalking(); bool bEffected = pVampire->isFlag(Effect::EFFECT_CLASS_CASKET); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bTileCheck && bMoveModeCheck && !bEffected) { //cout << "SummonCasket Success" << endl; decreaseMana(pVampire, RequiredMP, _GCSkillToSelfOK1); SkillInput input(pVampire); SkillOutput output; computeOutput(input, output); // 뱀파이어를 땅 위에서 삭제하기 이전에 기술 패킷들을 날린다. _GCSkillToSelfOK1.setSkillType(SkillType); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(output.Duration); _GCSkillToSelfOK3.setXY(x, y); _GCSkillToSelfOK3.setSkillType(SkillType); _GCSkillToSelfOK3.setDuration(output.Duration); pPlayer->sendPacket(&_GCSkillToSelfOK1); pZone->broadcastPacket(x, y, &_GCSkillToSelfOK3, pVampire); //--------------------------------------------------------------- // 기존의 지속 마법 효과를 제거한다. //--------------------------------------------------------------- EffectManager* pEffectManager = pVampire->getEffectManager(); Assert(pEffectManager!=NULL); Effect* pCheckEffect = NULL; // 사용자의 level을 구한다. int userLevel = pVampire->getLevel(); Effect::EffectClass effectClass; // EFFECT_CLASS_FLARE effectClass = Effect::EFFECT_CLASS_FLARE; pCheckEffect = pEffectManager->findEffect(effectClass); if (pCheckEffect!=NULL) { int level = (dynamic_cast<EffectFlare*>(pCheckEffect))->getLevel(); if (level < userLevel) { pEffectManager->deleteEffect(effectClass); pVampire->removeFlag(effectClass); } } // EFFECT_CLASS_DOOM effectClass = Effect::EFFECT_CLASS_DOOM; pCheckEffect = pEffectManager->findEffect(effectClass); if (pCheckEffect!=NULL) { int level = (dynamic_cast<EffectDoom*>(pCheckEffect))->getLevel(); if (level < userLevel) { pEffectManager->deleteEffect(effectClass); pVampire->removeFlag(effectClass); } } // EFFECT_CLASS_SEDUCTION effectClass = Effect::EFFECT_CLASS_SEDUCTION; pCheckEffect = pEffectManager->findEffect(effectClass); if (pCheckEffect!=NULL) { int level = (dynamic_cast<EffectSeduction*>(pCheckEffect))->getLevel(); if (level < userLevel) pEffectManager->deleteEffect(effectClass); pVampire->removeFlag(effectClass); } //--------------------------------------------------------------- // 이펙트 오브젝트를 생성해 붙인다. //--------------------------------------------------------------- EffectSummonCasket* pEffect = new EffectSummonCasket(pVampire); pEffect->setDeadline(99999999); pEffect->setType(0); pVampire->addEffect(pEffect); pVampire->setFlag(Effect::EFFECT_CLASS_CASKET); // SUMMON CASKET 에 의해 변하는 능력치가 변한다.. 2002.12.13 by bezz. VAMPIRE_RECORD prev; pVampire->getVampireRecord(prev); pVampire->initAllStat(); pVampire->sendRealWearingInfo(); pVampire->sendModifyInfo(prev); GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pVampire->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_CASKET); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &gcAddEffect, pVampire); pSkillSlot->setRunTime(); } else { //cout << "SummonCasket Failed" << endl; executeSkillFailNormal(pVampire, getSkillType(), NULL); } } catch(Throwable & t) { //cout << "SummonCasket Failed2" << endl; executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void Paralyze::execute(Vampire* pVampire, ObjectID_t TargetObjectID, VampireSkillSlot* pVampireSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; Assert(pVampire != NULL); Assert(pVampireSkillSlot != NULL); try { Player* pPlayer = pVampire->getPlayer(); Zone* pZone = pVampire->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); SkillType_t SkillType = pVampireSkillSlot->getSkillType(); // NPC는 공격할 수가 없다. // 면역이거나. by sigi. 2002.9.13 // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || pTargetCreature->isFlag(Effect::EFFECT_CLASS_IMMUNE_TO_PARALYZE) || !canAttack(pVampire, pTargetCreature ) || pTargetCreature->isNPC()) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; return; } GCSkillToObjectOK1 _GCSkillToObjectOK1; GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK3 _GCSkillToObjectOK3; GCSkillToObjectOK4 _GCSkillToObjectOK4; GCSkillToObjectOK5 _GCSkillToObjectOK5; GCSkillToObjectOK6 _GCSkillToObjectOK6; SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); // Knowledge of Curse 가 있다면 hit bonus 10 int HitBonus = 0; if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_CURSE ) ) { RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_CURSE); Assert(pRankBonus != NULL); HitBonus = pRankBonus->getPoint(); } Tile& rTile = pZone->getTile(pTargetCreature->getX(), pTargetCreature->getY()); int RequiredMP = decreaseConsumeMP(pVampire, pSkillInfo); bool bManaCheck = hasEnoughMana(pVampire, RequiredMP); bool bTimeCheck = verifyRunTime(pVampireSkillSlot); bool bRangeCheck = verifyDistance(pVampire, pTargetCreature, pSkillInfo->getRange()); bool bHitRoll = HitRoll::isSuccessVampireCurse(pSkillInfo->getLevel(), pTargetCreature->getResist(MAGIC_DOMAIN_CURSE)); bool bHitRoll2 = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pVampireSkillSlot, HitBonus); bool bCanHit = canHit(pVampire, pTargetCreature, SkillType); bool bEffected = pTargetCreature->isFlag(Effect::EFFECT_CLASS_PARALYZE) || rTile.getEffect(Effect::EFFECT_CLASS_TRYING_POSITION)!=NULL; bool bPK = verifyPK(pVampire, pTargetCreature); ZoneCoord_t vampX = pVampire->getX(); ZoneCoord_t vampY = pVampire->getY(); ZoneCoord_t targetX = pTargetCreature->getX(); ZoneCoord_t targetY = pTargetCreature->getY(); //if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bHitRoll2 && bCanHit && !bEffected && bPK) if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bHitRoll2 && bCanHit && !bEffected && bPK && pTargetCreature->getCompetence() == 3) { decreaseMana(pVampire, RequiredMP, _GCSkillToObjectOK1); bool bCanSeeCaster = canSee(pTargetCreature, pVampire); SkillInput input(pVampire); SkillOutput output; computeOutput(input, output); // Wisdom of Silence 이 있다면 지속시간 20% 증가 if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_WISDOM_OF_SILENCE ) ) { RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_WISDOM_OF_SILENCE); Assert(pRankBonus != NULL); output.Duration += getPercentValue(output.Duration, pRankBonus->getPoint()); } // pTargetCreature가 저주마법을 반사하는 경우 if (CheckReflection(pVampire, pTargetCreature, getSkillType())) { pTargetCreature = (Creature*)pVampire; TargetObjectID = pVampire->getObjectID(); } Resist_t resist = pTargetCreature->getResist(MAGIC_DOMAIN_CURSE); if (resist > output.Duration ) resist = output.Duration; output.Duration -= resist; if (output.Duration < 20 ) output.Duration = 20; // 이펙트 오브젝트를 생성해서 붙인다. EffectParalyze* pEffectParalyze = new EffectParalyze(pTargetCreature); pEffectParalyze->setLevel(pSkillInfo->getLevel()/2); // pEffectParalyze->setDefensePenalty(output.Damage); pEffectParalyze->setDeadline(output.Duration); pTargetCreature->addEffect(pEffectParalyze); pTargetCreature->setFlag(Effect::EFFECT_CLASS_PARALYZE); if (pTargetCreature->isFlag(Effect::EFFECT_CLASS_BURNING_SOL_CHARGE_1 ) ) { Effect* pEffect = pTargetCreature->findEffect(Effect::EFFECT_CLASS_BURNING_SOL_CHARGE_1); if (pEffect != NULL ) pEffect->setDeadline(0); } // 저주에 걸리면 디펜스가 떨어진다. // 디펜스 페널티가 없어짐. 2002.05.09 - by bezz /* if (pTargetCreature->isSlayer()) { Slayer* pTargetSlayer = dynamic_cast<Slayer*>(pTargetCreature); SLAYER_RECORD prev; pTargetSlayer->getSlayerRecord(prev); pTargetSlayer->initAllStat(); pTargetSlayer->addModifyInfo(prev, _GCSkillToObjectOK2); } else if (pTargetCreature->isVampire()) { Vampire* pTargetVampire = dynamic_cast<Vampire*>(pTargetCreature); VAMPIRE_RECORD prev; pTargetVampire->getVampireRecord(prev); pTargetVampire->initAllStat(); pTargetVampire->addModifyInfo(prev, _GCSkillToObjectOK2); } else if (pTargetCreature->isMonster()) { Monster* pTargetMonster = dynamic_cast<Monster*>(pTargetCreature); pTargetMonster->initAllStat(); } else Assert(false); */ // 이펙트가 붙었다는 것을 브로드캐스팅해준다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pTargetCreature->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_PARALYZE); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(targetX, targetY, &gcAddEffect); _GCSkillToObjectOK1.setSkillType(SkillType); _GCSkillToObjectOK1.setCEffectID(CEffectID); _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK1.setDuration(output.Duration); _GCSkillToObjectOK2.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK2.setSkillType(SkillType); _GCSkillToObjectOK2.setDuration(output.Duration); _GCSkillToObjectOK3.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK3.setSkillType(SkillType); _GCSkillToObjectOK3.setTargetXY(targetX, targetY); _GCSkillToObjectOK4.setSkillType(SkillType); _GCSkillToObjectOK4.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK5.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK5.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK5.setSkillType(SkillType); _GCSkillToObjectOK5.setDuration(output.Duration); _GCSkillToObjectOK6.setXY(vampX, vampY); _GCSkillToObjectOK6.setSkillType(SkillType); _GCSkillToObjectOK6.setDuration(output.Duration); if (bCanSeeCaster) // 10은 땜빵 수치다. { computeAlignmentChange(pTargetCreature, 10, pVampire, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1); } else // 10은 땜빵 수치다. { computeAlignmentChange(pTargetCreature, 10, pVampire, &_GCSkillToObjectOK6, &_GCSkillToObjectOK1); } pPlayer->sendPacket(&_GCSkillToObjectOK1); if (pTargetCreature->isPC()) { Player* pTargetPlayer = pTargetCreature->getPlayer(); Assert(pTargetPlayer != NULL); if (bCanSeeCaster) pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); else pTargetPlayer->sendPacket(&_GCSkillToObjectOK6); } else { Monster* pTargetMonster = dynamic_cast<Monster*>(pTargetCreature); pTargetMonster->addEnemy(pVampire); } list<Creature*> cList; cList.push_back(pVampire); cList.push_back(pTargetCreature); cList = pZone->broadcastSkillPacket(vampX, vampY, targetX, targetY, &_GCSkillToObjectOK5, cList); pZone->broadcastPacket(vampX, vampY, &_GCSkillToObjectOK3 , cList); pZone->broadcastPacket(targetX, targetY, &_GCSkillToObjectOK4 , cList); pVampireSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pVampire, getSkillType(), pTargetCreature); } } catch(Throwable & t) { executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void AirShield::execute(Slayer* pSlayer, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin(slayer)" << endl; Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pSlayer->getPlayer(); Zone* pZone = pSlayer->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); // 무장하고 있는 무기가 널이거나, 도가 아니라면 사용할 수 없다. Item* pItem = pSlayer->getWearItem(Slayer::WEAR_RIGHTHAND); if (pItem == NULL || pItem->getItemClass() != Item::ITEM_CLASS_BLADE) { executeSkillFailException(pSlayer, getSkillType()); return; } bool bIncreaseDomainExp = pSlayer->isRealWearingEx(Slayer::WEAR_RIGHTHAND); GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); SkillLevel_t SkillLevel = pSkillSlot->getExpLevel(); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pSlayer); bool bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot); bool bEffected = pSlayer->isFlag(Effect::EFFECT_CLASS_AIR_SHIELD_1); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { decreaseMana(pSlayer, RequiredMP, _GCSkillToSelfOK1); // 지속 시간을 계산한다. SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); // 이팩트 클래스를 만들어 붙인다. EffectAirShield* pEffect = new EffectAirShield(pSlayer); pEffect->setDeadline(output.Duration); pEffect->setLevel(SkillLevel); pEffect->setDamage(output.Damage); pSlayer->addEffect(pEffect); pSlayer->setFlag(Effect::EFFECT_CLASS_AIR_SHIELD_1); // 경험치를 올린다. SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType)); Exp_t ExpUp = 10* (Grade + 1); if (bIncreaseDomainExp ) { shareAttrExp(pSlayer, ExpUp, 8, 1, 1, _GCSkillToSelfOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToSelfOK1); // increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToSelfOK1); } _GCSkillToSelfOK1.setSkillType(SkillType); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(0); _GCSkillToSelfOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToSelfOK2.setSkillType(SkillType); _GCSkillToSelfOK2.setDuration(0); pPlayer->sendPacket(&_GCSkillToSelfOK1); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &_GCSkillToSelfOK2, pSlayer); GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pSlayer->getObjectID()); gcAddEffect.setEffectID(pEffect->getClientEffectClass()); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcAddEffect); pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pSlayer, getSkillType(), NULL); } } catch (Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End(slayer)" << endl; __END_CATCH }
void Mephisto::execute(Vampire* pVampire) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin(slayerself)" << endl; Assert(pVampire != NULL); if(!pVampire->hasSkill(SKILL_MEPHISTO) ) return; try { Player* pPlayer = pVampire->getPlayer(); Zone* pZone = pVampire->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); GCSkillToObjectOK1 _GCSkillToObjectOK1; GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK3 _GCSkillToObjectOK3; ZoneCoord_t myX = pVampire->getX(); ZoneCoord_t myY = pVampire->getY(); int oX, oY; VSRect rect(0, 0, pZone->getWidth()-1, pZone->getHeight()-1); for(oX = -4; oX <= 4; oX++) for(oY = -4; oY <= 4; oY++) { int tileX = myX+oX; int tileY = myY+oY; if (!rect.ptInRect(tileX, tileY)) continue; // 타일 위에! 뱀파이어가 있는지 본다! Tile& tile = pZone->getTile(tileX, tileY); Creature * pTargetCreature = NULL; if(tile.hasCreature(Creature::MOVE_MODE_WALKING)) pTargetCreature = tile.getCreature(Creature::MOVE_MODE_WALKING); if(pTargetCreature != NULL && pTargetCreature != pVampire && pTargetCreature->isVampire() ) { bool bEffected = pTargetCreature->isFlag(Effect::EFFECT_CLASS_MEPHISTO); if(bEffected ) continue; Vampire* pTargetVampire= dynamic_cast<Vampire*>(pTargetCreature); // 스킬 레벨에 따라 데미지 보너스가 달라진다. SkillInput input(pVampire); SkillOutput output; input.SkillLevel = pVampire->getSTR()+pVampire->getDEX()+pVampire->getINT(); input.DomainLevel = pVampire->getLevel(); computeOutput(input, output); // 이펙트 클래스를 만들어 붙인다. EffectMephisto* pEffect = new EffectMephisto(pTargetVampire); pEffect->setDeadline(output.Duration); pEffect->setBonus(output.Damage); pTargetVampire->addEffect(pEffect); pTargetVampire->setFlag(Effect::EFFECT_CLASS_MEPHISTO); // 이로 인하여 바뀌는 능력치를 보낸다. VAMPIRE_RECORD prev; pTargetVampire->getVampireRecord(prev); pTargetVampire->initAllStat(); pTargetVampire->sendRealWearingInfo(); pTargetVampire->sendModifyInfo(prev); if (pTargetCreature->isPC()) { Player* pTargetPlayer = pTargetCreature->getPlayer(); Assert(pTargetPlayer != NULL); pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); } else { Assert(false); } // 이펙트가 붙었다고 알려준다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pTargetVampire->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_MEPHISTO); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pTargetVampire->getX(), pTargetVampire->getY(), &gcAddEffect); } } } catch (Throwable & t) { executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End(slayerself)" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 셀프 ////////////////////////////////////////////////////////////////////////////// void HolyArmor::execute(Slayer * pSlayer, SkillSlot * pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pSlayer->getPlayer(); Zone* pZone = pSlayer->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); // 무장하고 있는 무기가 널이거나, 검이 아니라면 기술을 쓸 수 없다. /* Item* pWeapon = pSlayer->getWearItem(Slayer::WEAR_RIGHTHAND); if (pWeapon == NULL || pWeapon->getItemClass() != Item::ITEM_CLASS_SWORD) { executeSkillFailException(pSlayer, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; }*/ GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); ZoneCoord_t X = pSlayer->getX(); ZoneCoord_t Y = pSlayer->getY(); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP) && pSlayer->getHP() > 100; bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pSlayer); bool bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot); bool bEffected = pSlayer->isFlag(Effect::EFFECT_CLASS_HOLY_ARMOR); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { decreaseMana(pSlayer, RequiredMP, _GCSkillToSelfOK1); pSlayer->setHP(pSlayer->getHP()-100); _GCSkillToSelfOK1.addShortData(MODIFY_CURRENT_HP, pSlayer->getHP()); SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); // 이펙트 클래스를 만들어 붙인다. EffectHolyArmor* pEffect = new EffectHolyArmor(pSlayer); pEffect->setDeadline(output.Duration); pEffect->setDefBonus(output.Damage); pSlayer->addEffect(pEffect); pSlayer->setFlag(Effect::EFFECT_CLASS_HOLY_ARMOR); // 이로 인하여 바뀌는 능력치를 보낸다. SLAYER_RECORD prev; pSlayer->getSlayerRecord(prev); pSlayer->initAllStat(); pSlayer->sendRealWearingInfo(); pSlayer->sendModifyInfo(prev); // 경험치를 올린다. SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType)); Exp_t ExpUp = 10*(Grade+1); shareAttrExp(pSlayer, ExpUp, 1, 1, 8, _GCSkillToSelfOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToSelfOK1); increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToSelfOK1); // 패킷을 만들어 보낸다. _GCSkillToSelfOK1.setSkillType(SkillType); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(output.Duration); _GCSkillToSelfOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToSelfOK2.setSkillType(SkillType); _GCSkillToSelfOK2.setDuration(output.Duration); GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pSlayer->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_HOLY_ARMOR); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(X, Y, &gcAddEffect); // Send Packet pPlayer->sendPacket(&_GCSkillToSelfOK1); pZone->broadcastPacket(X, Y, &_GCSkillToSelfOK2, pSlayer); pSkillSlot->setRunTime(output.Delay); uint PartyID = pSlayer->getPartyID(); if (PartyID != 0) { LocalPartyManager* pLPM = pZone->getLocalPartyManager(); pLPM->shareHolyArmor(PartyID, pSlayer, output.Damage, input.SkillLevel); } } else { executeSkillFailNormal(pSlayer, getSkillType(), NULL); } } catch (Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); //cout << t.toString() << endl; } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void DivineSpirits::execute(Ousters* pOusters, OustersSkillSlot* pOustersSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin(slayer)" << endl; Assert(pOusters != NULL); Assert(pOustersSkillSlot != NULL); try { Player* pPlayer = pOusters->getPlayer(); Zone* pZone = pOusters->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; SkillType_t SkillType = pOustersSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); //SkillDomainType_t DomainType = pSkillInfo->getDomainType(); //SkillLevel_t SkillLevel = pOustersSkillSlot->getExpLevel(); int RequiredMP = pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pOusters, RequiredMP); bool bTimeCheck = verifyRunTime(pOustersSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pOusters); bool bHitRoll = HitRoll::isSuccessMagic(pOusters, pSkillInfo, pOustersSkillSlot); bool bEffected = pOusters->isFlag(Effect::EFFECT_CLASS_DIVINE_SPIRITS); bool bSatisfyRequire = pOusters->satisfySkillRequire(pSkillInfo); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected && bSatisfyRequire) { decreaseMana(pOusters, RequiredMP, _GCSkillToSelfOK1); // 지속 시간을 계산한다. SkillInput input(pOusters, pOustersSkillSlot); SkillOutput output; computeOutput(input, output); // 이팩트 클래스를 만들어 붙인다. EffectDivineSpirits* pEffect = new EffectDivineSpirits(pOusters); pEffect->setDeadline(output.Duration); pEffect->setBonus(output.Damage); pOusters->addEffect(pEffect); pOusters->setFlag(Effect::EFFECT_CLASS_DIVINE_SPIRITS); // OUSTERS_RECORD prev; // pOusters->getOustersRecord(prev); // pOusters->initAllStat(); // pOusters->addModifyInfo(prev, _GCSkillToSelfOK1); _GCSkillToSelfOK1.setSkillType(SkillType); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(output.Duration); _GCSkillToSelfOK2.setObjectID(pOusters->getObjectID()); _GCSkillToSelfOK2.setSkillType(SkillType); _GCSkillToSelfOK2.setDuration(output.Duration); pPlayer->sendPacket(&_GCSkillToSelfOK1); pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &_GCSkillToSelfOK2, pOusters); GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pOusters->getObjectID()); gcAddEffect.setEffectID(pEffect->getEffectClass()); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &gcAddEffect, pOusters); pOustersSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pOusters, getSkillType(), NULL); } } catch (Throwable & t) { executeSkillFailException(pOusters, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End(slayer)" << 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 DarkBluePoison::execute(Vampire* pVampire, ObjectID_t TargetObjectID, VampireSkillSlot* pVampireSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; Assert(pVampire != NULL); Assert(pVampireSkillSlot != NULL); try { Player* pPlayer = pVampire->getPlayer(); Zone* pZone = pVampire->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NPC는 공격할 수가 없다. // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || !canAttack(pVampire, pTargetCreature ) || pTargetCreature->isNPC()) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; return; } GCSkillToObjectOK1 _GCSkillToObjectOK1; GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK3 _GCSkillToObjectOK3; GCSkillToObjectOK4 _GCSkillToObjectOK4; GCSkillToObjectOK5 _GCSkillToObjectOK5; GCSkillToObjectOK6 _GCSkillToObjectOK6; SkillType_t SkillType = pVampireSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); // Knowledge of Poison 이 있다면 hit bonus 10 int HitBonus = 0; if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_POISON ) ) { RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_POISON); Assert(pRankBonus != NULL); HitBonus = pRankBonus->getPoint(); } int RequiredMP = decreaseConsumeMP(pVampire, pSkillInfo); bool bManaCheck = hasEnoughMana(pVampire, RequiredMP); bool bTimeCheck = verifyRunTime(pVampireSkillSlot); bool bRangeCheck = verifyDistance(pVampire, pTargetCreature, pSkillInfo->getRange()); bool bHitRoll = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pVampireSkillSlot, HitBonus); bool bEffected = pTargetCreature->isFlag(Effect::EFFECT_CLASS_DARKBLUE_POISON); ZoneCoord_t vampX = pVampire->getX(); ZoneCoord_t vampY = pVampire->getY(); ZoneCoord_t targetX = pTargetCreature->getX(); ZoneCoord_t targetY = pTargetCreature->getY(); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { decreaseMana(pVampire, RequiredMP, _GCSkillToObjectOK1); bool bCanSeeCaster = canSee(pTargetCreature, pVampire); SkillInput input(pVampire); SkillOutput output; computeOutput(input, output); Damage_t Damage = computeMagicDamage(pTargetCreature, output.Damage, SkillType, true, pVampire); // 아우스터즈는 절반의 시간만 받는다. if (pTargetCreature->isOusters() ) output.Duration/=2; // 이펙트 오브젝트를 생성해서 붙인다. EffectDarkBluePoison* pEffectDarkBluePoison = new EffectDarkBluePoison(pTargetCreature); pEffectDarkBluePoison->setDamage(Damage); pEffectDarkBluePoison->setLevel(pSkillInfo->getLevel()/2); pEffectDarkBluePoison->setDeadline(output.Duration); pEffectDarkBluePoison->setTick(output.Tick); pEffectDarkBluePoison->setNextTime(0); pTargetCreature->addEffect(pEffectDarkBluePoison); pTargetCreature->setFlag(Effect::EFFECT_CLASS_DARKBLUE_POISON); // 이펙트가 붙었으니, 붙었다고 브로드캐스팅해준다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pTargetCreature->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_DARKBLUE_POISON); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(targetX, targetY, &gcAddEffect); if (bCanSeeCaster) { decreaseDurability(pVampire, pTargetCreature, pSkillInfo, &_GCSkillToObjectOK1, &_GCSkillToObjectOK2); } else { decreaseDurability(pVampire, pTargetCreature, pSkillInfo, &_GCSkillToObjectOK1, &_GCSkillToObjectOK6); } _GCSkillToObjectOK1.setSkillType(SkillType); _GCSkillToObjectOK1.setCEffectID(CEffectID); _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK1.setDuration(output.Duration); _GCSkillToObjectOK2.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK2.setSkillType(SkillType); _GCSkillToObjectOK2.setDuration(output.Duration); _GCSkillToObjectOK3.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK3.setSkillType(SkillType); _GCSkillToObjectOK3.setTargetXY(targetX, targetY); _GCSkillToObjectOK4.setSkillType(SkillType); _GCSkillToObjectOK4.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK5.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK5.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK5.setSkillType(SkillType); _GCSkillToObjectOK5.setDuration(output.Duration); _GCSkillToObjectOK6.setXY(vampX, vampY); _GCSkillToObjectOK6.setSkillType(SkillType); _GCSkillToObjectOK6.setDuration(output.Duration); pPlayer->sendPacket(&_GCSkillToObjectOK1); if (pTargetCreature->isPC()) { Player* pTargetPlayer = pTargetCreature->getPlayer(); Assert(pTargetPlayer != NULL); if (bCanSeeCaster) pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); else pTargetPlayer->sendPacket(&_GCSkillToObjectOK6); } else { Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature); pMonster->addEnemy(pVampire); } list<Creature*> cList; cList.push_back(pVampire); cList.push_back(pTargetCreature); cList = pZone->broadcastSkillPacket(vampX, vampY, targetX, targetY, &_GCSkillToObjectOK5, cList); pZone->broadcastPacket(vampX, vampY, &_GCSkillToObjectOK3 , cList); pZone->broadcastPacket(targetX, targetY, &_GCSkillToObjectOK4 , cList); pVampireSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pVampire, getSkillType(), pTargetCreature); } } catch(Throwable & t) { executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 오브젝트 ////////////////////////////////////////////////////////////////////////////// void JabbingVein::execute (Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY __BEGIN_DEBUG //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; 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 || !canAttack(pSlayer, pTargetCreature ) || pTargetCreature->isNPC()) { executeSkillFailException(pSlayer, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } GCAttackArmsOK1 _GCAttackArmsOK1; GCAttackArmsOK2 _GCAttackArmsOK2; GCAttackArmsOK3 _GCAttackArmsOK3; GCAttackArmsOK4 _GCAttackArmsOK4; GCAttackArmsOK5 _GCAttackArmsOK5; // 들고 있는 무기가 없거나, 총 계열 무기가 아니라면 기술을 쓸 수 없다. // 총 계열 무기 중에서도 SG나 SR은 JabbingVein를 쓸 수가 없다. // SG, SR 도 이제 쓸 수 있다. // 2003. 1. 14 by bezz Item* pWeapon = pSlayer->getWearItem(Slayer::WEAR_RIGHTHAND); if (pWeapon == NULL || isArmsWeapon(pWeapon) == false ) // pWeapon->getItemClass() == Item::ITEM_CLASS_SG || // pWeapon->getItemClass() == Item::ITEM_CLASS_SR) { executeSkillFailException(pSlayer, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } bool bIncreaseExp = pSlayer->isRealWearingEx(Slayer::WEAR_RIGHTHAND); SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); SkillLevel_t SkillLevel = pSkillSlot->getExpLevel(); SkillInput input(pSlayer, pSkillSlot); SkillOutput output; if (pTargetCreature->isPC() ) { input.TargetType = SkillInput::TARGET_PC; } else { input.TargetType = SkillInput::TARGET_MONSTER; } computeOutput(input, output); // 페널티 값을 계산한다. int ToHitPenalty = getPercentValue(pSlayer->getToHit(), output.ToHit); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = verifyDistance(pSlayer, pTargetCreature, pWeapon->getRange()); bool bBulletCheck = (getRemainBullet(pWeapon) > 0) ? true : false; bool bHitRoll = HitRoll::isSuccess(pSlayer, pTargetCreature, ToHitPenalty); bool bPK = verifyPK(pSlayer, pTargetCreature); // 총알 숫자는 무조건 떨어뜨린다. Bullet_t RemainBullet = 0; if (bBulletCheck) { // 총알 숫자를 떨어뜨리고, 저장하고, 남은 총알 숫자를 받아온다. decreaseBullet(pWeapon); // 한발쓸때마다 저장할 필요 없다. by sigi. 2002.5.9 //pWeapon->save(pSlayer->getName(), STORAGE_GEAR, 0, Slayer::WEAR_RIGHTHAND, 0); RemainBullet = getRemainBullet(pWeapon); } if (bManaCheck && bTimeCheck && bRangeCheck && bBulletCheck && bHitRoll && bPK) { //cout << pSlayer->getName().c_str() << " Attack OK" << endl; decreaseMana(pSlayer, RequiredMP, _GCAttackArmsOK1); _GCAttackArmsOK5.setSkillSuccess(true); _GCAttackArmsOK1.setSkillSuccess(true); bool bCriticalHit = false; // 데미지를 계산하고, quickfire 페널티를 가한다. // output.Damage가 음수이기 때문에, %값을 구해 더하면 결국 빼는 것이 된다. int Damage = computeDamage(pSlayer, pTargetCreature, SkillLevel/5, bCriticalHit); Damage += getPercentValue(Damage, output.Damage); Damage = max(0, Damage); //cout << "JabbingVeinDamage:" << Damage << endl; // 데미지를 세팅한다. setDamage(pTargetCreature, Damage, pSlayer, SkillType, &_GCAttackArmsOK2, &_GCAttackArmsOK1); computeAlignmentChange(pTargetCreature, Damage, pSlayer, &_GCAttackArmsOK2, &_GCAttackArmsOK1); bool bAffect = true; if (pTargetCreature->isMonster()) { Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature); if (pMonster->isMaster() ) bAffect = false; } if (bAffect && !pTargetCreature->isFlag(Effect::EFFECT_CLASS_JABBING_VEIN) && rand()%100 < output.Range ) { EffectJabbingVein* pEffect = new EffectJabbingVein(pTargetCreature); pEffect->setDeadline(output.Duration); pTargetCreature->addEffect(pEffect); pTargetCreature->setFlag(pEffect->getEffectClass()); GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pTargetCreature->getObjectID()); gcAddEffect.setEffectID(pEffect->getSendEffectClass()); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &gcAddEffect); } // 크리티컬 히트라면 상대방을 뒤로 물러나게 한다. if (bCriticalHit) { knockbackCreature(pZone, pTargetCreature, pSlayer->getX(), pSlayer->getY()); } if(!pTargetCreature->isSlayer() ) { if (bIncreaseExp) { shareAttrExp(pSlayer, Damage , 1, 8, 1, _GCAttackArmsOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCAttackArmsOK1, pTargetCreature->getLevel()); increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCAttackArmsOK1); } increaseAlignment(pSlayer, pTargetCreature, _GCAttackArmsOK1); } //} if (pTargetCreature->isPC()) { Player* pTargetPlayer = pTargetCreature->getPlayer(); if (pTargetPlayer != NULL) { _GCAttackArmsOK2.setObjectID(getSkillType()); _GCAttackArmsOK2.setObjectID(pSlayer->getObjectID()); pTargetPlayer->sendPacket(&_GCAttackArmsOK2); } } else if (pTargetCreature->isMonster()) { Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature); pMonster->addEnemy(pSlayer); } // 공격자와 상대의 아이템 내구성 떨어트림. decreaseDurability(pSlayer, pTargetCreature, NULL, &_GCAttackArmsOK1, &_GCAttackArmsOK2); ZoneCoord_t targetX = pTargetCreature->getX(); ZoneCoord_t targetY = pTargetCreature->getY(); ZoneCoord_t myX = pSlayer->getX(); ZoneCoord_t myY = pSlayer->getY(); _GCAttackArmsOK1.setSkillType(getSkillType()); _GCAttackArmsOK1.setObjectID(TargetObjectID); _GCAttackArmsOK1.setBulletNum(RemainBullet); _GCAttackArmsOK3.setSkillType(getSkillType()); _GCAttackArmsOK3.setObjectID(pSlayer->getObjectID()); _GCAttackArmsOK3.setTargetXY (targetX, targetY); _GCAttackArmsOK4.setSkillType(getSkillType()); _GCAttackArmsOK4.setTargetObjectID (TargetObjectID); _GCAttackArmsOK5.setSkillType(getSkillType()); _GCAttackArmsOK5.setObjectID(pSlayer->getObjectID()); _GCAttackArmsOK5.setTargetObjectID (TargetObjectID); pPlayer->sendPacket(&_GCAttackArmsOK1); list<Creature *> cList; cList.push_back(pTargetCreature); cList.push_back(pSlayer); cList = pZone->broadcastSkillPacket(myX, myY, targetX, targetY, &_GCAttackArmsOK5, cList); pZone->broadcastPacket(myX, myY, &_GCAttackArmsOK3, cList); pZone->broadcastPacket(targetX, targetY, &_GCAttackArmsOK4, cList); pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormalWithGun(pSlayer, getSkillType(), pTargetCreature, RemainBullet); //cout << pSlayer->getName().c_str() << " Fail : " // << (int)bManaCheck << (int)bTimeCheck << (int)bRangeCheck // << (int)bBulletCheck << (int)bHitRoll << (int)bPK << endl; } } catch (Throwable &t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_DEBUG __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void BackStab::execute(Ousters* pOusters, ObjectID_t TargetObjectID, OustersSkillSlot* pOustersSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY SkillInput input(pOusters, pOustersSkillSlot); SkillOutput output; computeOutput(input, output); Item* pWeapon = pOusters->getWearItem(Ousters::WEAR_RIGHTHAND); if (pWeapon == NULL ) { executeSkillFailException(pOusters, getSkillType()); return; } SIMPLE_SKILL_INPUT param; param.SkillType = getSkillType(); // param.SkillDamage = output.Damage; bool bCritical = false; if (HitRoll::isSuccessBackStab(pOusters ) ) { double ratio = (1.0 + (2 * input.SkillLevel / 30.0 )); param.SkillDamage = (short unsigned int)(max(1, Random(pWeapon->getMinDamage(), pWeapon->getMaxDamage() ) ) * ratio); if (input.SkillLevel == 30 ) param.SkillDamage = (short unsigned int)(param.SkillDamage * 1.1); bCritical = true; } else { param.SkillDamage = 0; } param.Delay = 0; param.ItemClass = Item::ITEM_CLASS_OUSTERS_CHAKRAM; param.STRMultiplier = 0; param.DEXMultiplier = 0; param.INTMultiplier = 0; param.bMagicHitRoll = false; param.bMagicDamage = false; param.bAdd = true; if (input.SkillLevel < 15 ) param.Grade = 0; else if (input.SkillLevel < 30 ) param.Grade = 1; else param.Grade = 2; SIMPLE_SKILL_OUTPUT result; g_SimpleMeleeSkill.execute(pOusters, TargetObjectID, pOustersSkillSlot, param, result, CEffectID); if (bCritical && result.bSuccess ) { GCAddEffect gcAddEffect; gcAddEffect.setObjectID(TargetObjectID); if (param.Grade == 0 ) gcAddEffect.setEffectID(Effect::EFFECT_CLASS_BACK_STAB); else if (param.Grade == 1 ) gcAddEffect.setEffectID(Effect::EFFECT_CLASS_BACK_STAB_2); else gcAddEffect.setEffectID(Effect::EFFECT_CLASS_BACK_STAB_3); gcAddEffect.setDuration(0); Zone* pZone = pOusters->getZone(); if (pZone != NULL ) { Creature* pCreature = pZone->getCreature(TargetObjectID); if (pCreature != NULL ) { pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcAddEffect); } } } __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 아우스터즈 타일 핸들러 ////////////////////////////////////////////////////////////////////////////// void SummonGroundElemental::execute(Ousters* pOusters, ZoneCoord_t X, ZoneCoord_t Y, OustersSkillSlot* pOustersSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; Assert(pOusters != NULL); Assert(pOustersSkillSlot != NULL); BYTE Grade = 0; if (pOustersSkillSlot->getExpLevel() < 15 ) Grade = 0; else if (pOustersSkillSlot->getExpLevel() < 30 ) Grade = 1; else Grade = 2; 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, pOustersSkillSlot->getSkillType(), Grade); return; } GCSkillToTileOK1 _GCSkillToTileOK1; GCSkillToTileOK2 _GCSkillToTileOK2; GCSkillToTileOK3 _GCSkillToTileOK3; GCSkillToTileOK4 _GCSkillToTileOK4; GCSkillToTileOK5 _GCSkillToTileOK5; GCSkillToTileOK6 _GCSkillToTileOK6; SkillType_t SkillType = pOustersSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); // 데미지와 지속 시간을 계산한다. SkillInput input(pOusters, pOustersSkillSlot); SkillOutput output; computeOutput(input, output); int RequiredMP = (int)pSkillInfo->getConsumeMP() + pOustersSkillSlot->getExpLevel()/3; bool bManaCheck = hasEnoughMana(pOusters, RequiredMP); bool bTimeCheck = verifyRunTime(pOustersSkillSlot); bool bRangeCheck = verifyDistance(pOusters, X, Y, pSkillInfo->getRange()); bool bHitRoll = HitRoll::isSuccessMagic(pOusters, pSkillInfo, pOustersSkillSlot); bool bSatisfyRequire = pOusters->satisfySkillRequire(pSkillInfo); bool bTileCheck = false; VSRect rect(0, 0, pZone->getWidth()-1, pZone->getHeight()-1); // if (rect.ptInRect(X, Y)) // { // Tile& tile = pZone->getTile(X, Y); // if (tile.canAddEffect()) bTileCheck = true; // } TPOINT pt = findSuitablePosition(pZone, X, Y, Creature::MOVE_MODE_WALKING); if (pt.x == -1 ) { bTileCheck = false; } else { bTileCheck = true; for (int oX = pt.x - 2 ; oX <= pt.x + 2 ; ++oX ) for (int oY = pt.y - 2 ; oY <= pt.y + 2 ; ++oY ) { if (!rect.ptInRect(oX, oY ) ) continue; if (pZone->getTile(oX, oY).getEffect(Effect::EFFECT_CLASS_GROUND_ELEMENTAL_AURA ) != NULL ) { bTileCheck = false; break; } } } if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bTileCheck && bSatisfyRequire) { decreaseMana(pOusters, RequiredMP, _GCSkillToTileOK1); int oX, oY; /* HP = 200 + (S_level * 10) Defense = 50 + (S_level * 2) Protection = 20 + (S_level * 2) Poison Resistance = 70% Acid Resistance = 60% Curse Resistance = 100% Blood Resistance = 50% Regen = 1 HP per 1 sec */ Monster* pGroundElemental = new Monster(GROUND_ELEMENTAL_TYPE); pGroundElemental->setName("대지 정령"); pGroundElemental->setHP(1000 + input.SkillLevel * 100); pGroundElemental->setHP(1000 + input.SkillLevel * 100, ATTR_MAX); pGroundElemental->setDefense(0); pGroundElemental->setProtection(0); pGroundElemental->setResist(MAGIC_DOMAIN_POISON, 0); pGroundElemental->setResist(MAGIC_DOMAIN_ACID, 0); pGroundElemental->setResist(MAGIC_DOMAIN_CURSE, 0); pGroundElemental->setResist(MAGIC_DOMAIN_BLOOD, 0); pGroundElemental->setFlag(Effect::EFFECT_CLASS_IMMUNE_TO_CURSE); pGroundElemental->removeFlag(Effect::EFFECT_CLASS_HIDE); pGroundElemental->setMoveMode(Creature::MOVE_MODE_WALKING); // 무뇌정령 pGroundElemental->setBrain(NULL); pZone->addCreature(pGroundElemental, X, Y, 2); X = pGroundElemental->getX(); Y = pGroundElemental->getY(); //cout << pGroundElemental->toString() << " 을 " << X << ", " << Y << " 에 불러냈습니다." << endl; EffectGroundElemental* pCreatureEffect = new EffectGroundElemental(pGroundElemental); pCreatureEffect->setDeadline(output.Duration); pGroundElemental->setFlag(pCreatureEffect->getEffectClass()); pGroundElemental->addEffect(pCreatureEffect); GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pGroundElemental->getObjectID()); gcAddEffect.setEffectID(pCreatureEffect->getSendEffectClass()); pZone->broadcastPacket(X, Y, &gcAddEffect); // addSimpleCreatureEffect(pGroundElemental, Effect::EFFECT_CLASS_GROUND_ELEMENTAL_CENTER); // for (int i = 0; i < m_MaskIndex[Grade]; ++i ) for (oX = X - 2 ; oX <= X + 2 ; ++oX ) for (oY = Y - 2 ; oY <= Y + 2 ; ++oY ) { // oX = m_ElementalMask[Grade][i].x; // oY = m_ElementalMask[Grade][i].y; if (!rect.ptInRect(oX, oY)) continue; if (oX == X && oY == Y ) continue; Tile& tile = pZone->getTile(oX, oY); if (!tile.canAddEffect()) continue; if (tile.getEffect(Effect::EFFECT_CLASS_TRYING_POSITION) ) continue; // 같은 이펙트가 이미 존재한다면 삭제한다. Effect* pOldEffect = tile.getEffect(Effect::EFFECT_CLASS_GROUND_ELEMENTAL_AURA); if (pOldEffect != NULL) { ObjectID_t effectID = pOldEffect->getObjectID(); pZone->deleteEffect(effectID); } // 이펙트 오브젝트를 생성한다. EffectSummonGroundElemental* pEffect = new EffectSummonGroundElemental(pZone, oX, oY); pEffect->setDeadline(output.Duration); // 타일에 붙은 이펙트는 OID를 받아야 한다. ObjectRegistry & objectregister = pZone->getObjectRegistry(); objectregister.registerObject(pEffect); // 존 및 타일에다가 이펙트를 추가한다. pZone->addEffect(pEffect); tile.addEffect(pEffect); GCAddEffectToTile gcAddEffect; gcAddEffect.setXY(oX, oY); gcAddEffect.setEffectID(pEffect->getSendEffectClass()); gcAddEffect.setObjectID(pEffect->getObjectID()); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(oX, oY, &gcAddEffect); } ZoneCoord_t myX = pOusters->getX(); ZoneCoord_t myY = pOusters->getY(); _GCSkillToTileOK1.setSkillType(SkillType); _GCSkillToTileOK1.setCEffectID(CEffectID); _GCSkillToTileOK1.setX(X); _GCSkillToTileOK1.setY(Y); _GCSkillToTileOK1.setDuration(output.Duration); _GCSkillToTileOK1.setGrade(Grade); _GCSkillToTileOK3.setObjectID(pOusters->getObjectID()); _GCSkillToTileOK3.setSkillType(SkillType); _GCSkillToTileOK3.setX(X); _GCSkillToTileOK3.setY(Y); _GCSkillToTileOK3.setGrade(Grade); _GCSkillToTileOK4.setSkillType(SkillType); _GCSkillToTileOK4.setX(X); _GCSkillToTileOK4.setY(Y); _GCSkillToTileOK4.setDuration(output.Duration); _GCSkillToTileOK4.setGrade(Grade); _GCSkillToTileOK5.setObjectID(pOusters->getObjectID()); _GCSkillToTileOK5.setSkillType(SkillType); _GCSkillToTileOK5.setX(X); _GCSkillToTileOK5.setY(Y); _GCSkillToTileOK5.setDuration(output.Duration); _GCSkillToTileOK5.setGrade(Grade); pPlayer->sendPacket(&_GCSkillToTileOK1); list<Creature*> cList; cList.push_back(pOusters); cList = pZone->broadcastSkillPacket(myX, myY, X, Y, &_GCSkillToTileOK5, cList); pZone->broadcastPacket(myX, myY, &_GCSkillToTileOK3 , cList); pZone->broadcastPacket(X, Y, &_GCSkillToTileOK4 , cList); pOustersSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pOusters, getSkillType(), NULL, Grade); } } catch (Throwable & t) { executeSkillFailException(pOusters, getSkillType(), Grade); //cout << t.toString() << endl; } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; __END_CATCH }
void DestructionSpear::execute(Ousters* pOusters, ZoneCoord_t X, ZoneCoord_t Y, OustersSkillSlot* pOustersSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY Zone* pZone = pOusters->getZone(); Assert(pZone != NULL); /* Creature* pTargetCreature = pZone->getCreature(TargetObjectID); if (pTargetCreature==NULL || !canAttack(pOusters, pTargetCreature ) || pTargetCreature->isNPC()) { executeSkillFailException(pOusters, getSkillType()); return; }*/ /* if (pTargetCreature->isSlayer() ) { Slayer* pSlayer = dynamic_cast<Slayer*>(pTargetCreature); targetLevel = pSlayer->getHighestSkillDomainLevel(); } else { targetLevel = pTargetCreature->getLevel(); }*/ SkillInput input(pOusters, pOustersSkillSlot); SkillOutput output; computeOutput(input, output); Item* pWeapon = pOusters->getWearItem(Ousters::WEAR_RIGHTHAND); if (pWeapon == NULL ) { executeSkillFailException(pOusters, getSkillType()); return; } SIMPLE_SKILL_INPUT param; param.SkillType = getSkillType(); param.SkillDamage = output.Damage; param.Delay = output.Delay; param.ItemClass = Item::ITEM_CLASS_OUSTERS_CHAKRAM; param.STRMultiplier = 0; param.DEXMultiplier = 0; param.INTMultiplier = 0; param.bMagicHitRoll = false; param.bMagicDamage = false; param.bAdd = true; SIMPLE_SKILL_OUTPUT result; int offset = 0; OustersSkillSlot* pMastery = pOusters->hasSkill(SKILL_DESTRUCTION_SPEAR_MASTERY); if (pMastery != NULL ) { offset = 1; if (pMastery->getExpLevel() <= 15 ) param.SkillDamage = min(70,param.SkillDamage + 10 + pMastery->getExpLevel()/3); else param.SkillDamage = min(90,param.SkillDamage + 10 + pMastery->getExpLevel()/2); param.Grade=4; } for (int i=-offset; i<=offset; ++i ) for (int j=-offset; j<=offset; ++j ) param.addMask(i, j, 100); g_SimpleTileMissileSkill.execute(pOusters, X, Y, pOustersSkillSlot, param, result, CEffectID); list<Creature*>::iterator itr = result.targetCreatures.begin(); for (; itr != result.targetCreatures.end() ; ++itr ) { Creature* pTargetCreature = *itr; if (pTargetCreature->getX() == X && pTargetCreature->getY() == Y ) { GCModifyInformation gcMI, gcAttackerMI; Damage_t damage = computeElementalCombatSkill(pOusters, pTargetCreature, gcAttackerMI); if (damage != 0 ) { ::setDamage(pTargetCreature, damage, pOusters, SKILL_DESTRUCTION_SPEAR, &gcMI, &gcAttackerMI); if (pTargetCreature->isPC() ) pTargetCreature->getPlayer()->sendPacket(&gcMI); if (pTargetCreature->isDead()) { int exp = computeCreatureExp(pTargetCreature, 70, pOusters); shareOustersExp(pOusters, exp, gcAttackerMI); } pOusters->getPlayer()->sendPacket(&gcAttackerMI); } } if (!pTargetCreature->isFlag(Effect::EFFECT_CLASS_DESTRUCTION_SPEAR ) && result.bSuccess ) { int targetLevel = pTargetCreature->getLevel(); int ratio = 0; if (input.SkillLevel <= 15 ) { ratio = max(20, min(80, (int)(pOusters->getLevel() + (input.SkillLevel * 8.0 / 3.0) - targetLevel ) )); } else { ratio = max(20, min(80, (int)(pOusters->getLevel() + 20.0 + (input.SkillLevel * 4.0 / 3.0) - targetLevel ) )); } if (rand() % 100 < ratio ) { EffectDestructionSpear* pEffect = new EffectDestructionSpear(pTargetCreature); Assert(pEffect != NULL); pEffect->setDamage(2 + (input.SkillLevel/3 )); pEffect->setNextTime(20); pEffect->setCasterID(pOusters->getObjectID()); pEffect->setDeadline(output.Duration); if (pTargetCreature->getX() == X && pTargetCreature->getY() == Y ) pEffect->setSteal(true); pTargetCreature->setFlag(Effect::EFFECT_CLASS_DESTRUCTION_SPEAR); pTargetCreature->addEffect(pEffect); GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pTargetCreature->getObjectID()); gcAddEffect.setEffectID(pEffect->getSendEffectClass()); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &gcAddEffect); } } } __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void Light::execute(Slayer* pSlayer, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pSlayer->getPlayer(); Zone* pZone = pSlayer->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillLevel_t SkillLevel = pSkillSlot->getExpLevel(); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pSlayer); bool bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot); bool bEffected = pSlayer->isFlag(Effect::EFFECT_CLASS_LIGHT); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { decreaseMana(pSlayer, RequiredMP, _GCSkillToSelfOK1); // 기술이 유지되는 시간은 숙련도에 따라서 달라진다. SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); Sight_t CurrentSight = pSlayer->getSight(); Sight_t oldSight = CurrentSight; // 혹시라도 옛날 이펙트가 남아있다면 삭제한다. if (pSlayer->isEffect(Effect::EFFECT_CLASS_LIGHT)) { EffectLight* pOldEffectLight = (EffectLight*)pSlayer->findEffect(Effect::EFFECT_CLASS_LIGHT); CurrentSight = pOldEffectLight->getOldSight(); pSlayer->deleteEffect(Effect::EFFECT_CLASS_LIGHT); } // 이펙트를 만들어 붙인다. EffectLight* pEffectLight = new EffectLight (pSlayer); pEffectLight->setDeadline(output.Duration); pEffectLight->setOldSight(CurrentSight); pSlayer->setFlag(Effect::EFFECT_CLASS_LIGHT); pSlayer->addEffect(pEffectLight); //pEffectLight->create(pSlayer->getName()); // 시야처리.. Sight_t MinSight = pSkillInfo->getMinDamage(); Sight_t MaxSight = pSkillInfo->getMaxDamage(); Sight_t NewSight = MinSight + (MaxSight - MinSight)* SkillLevel / 100; // 시야 변경에 따른 오브젝트 가감 패킷을 보낸다. pZone->updateScan(pSlayer, oldSight, NewSight); pSlayer->setSight(NewSight); if (NewSight != oldSight) _GCSkillToSelfOK1.addShortData(MODIFY_VISION, NewSight); _GCSkillToSelfOK1.setSkillType(SkillType); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(output.Duration); _GCSkillToSelfOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToSelfOK2.setSkillType(SkillType); _GCSkillToSelfOK2.setDuration(output.Duration); // EXP UP! SkillDomainType_t DomainType = pSkillInfo->getDomainType(); SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType)); Exp_t ExpUp = 10* (Grade + 1)* 2; shareAttrExp(pSlayer, ExpUp, 1, 1, 8, _GCSkillToSelfOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToSelfOK1); increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToSelfOK1); // Send Packet pPlayer->sendPacket(&_GCSkillToSelfOK1); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &_GCSkillToSelfOK2 , pSlayer); // 이펙트가 붙었다고 알려준다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pSlayer->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_LIGHT); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcAddEffect); pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pSlayer, getSkillType(), NULL); } } catch(Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void ChargingPower::execute(Slayer* pSlayer, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin(slayerself)" << endl; Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pSlayer->getPlayer(); Zone* pZone = pSlayer->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); // 무장하고 있는 무기가 널이거나, 도가 아니라면 사용할 수 없다. Item* pItem = pSlayer->getWearItem(Slayer::WEAR_RIGHTHAND); if (pItem == NULL || pItem->getItemClass() != Item::ITEM_CLASS_BLADE) { executeSkillFailException(pSlayer, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End(slayerself)" << endl; return; } bool bIncreaseExp = pSlayer->isRealWearingEx(Slayer::WEAR_RIGHTHAND); GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pSlayer); bool bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot); // 버서커랑 동시에 사용할 수 없다. bool bEffected = pSlayer->isFlag(Effect::EFFECT_CLASS_CHARGING_POWER) || pSlayer->isFlag(Effect::EFFECT_CLASS_BERSERKER); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { decreaseMana(pSlayer, RequiredMP, _GCSkillToSelfOK1); // 스킬 레벨에 따라 데미지 보너스가 달라진다. SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); // 이펙트 클래스를 만들어 붙인다. EffectChargingPower* pEffect = new EffectChargingPower(pSlayer); pEffect->setDeadline(output.Duration); pEffect->setDamageBonus(output.Damage); pSlayer->addEffect(pEffect); pSlayer->setFlag(Effect::EFFECT_CLASS_CHARGING_POWER); // 이로 인하여 바뀌는 능력치를 보낸다. SLAYER_RECORD prev; pSlayer->getSlayerRecord(prev); pSlayer->initAllStat(); pSlayer->sendRealWearingInfo(); pSlayer->sendModifyInfo(prev); // 경험치를 올린다. SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType)); Exp_t ExpUp = 10*(Grade+1); if (bIncreaseExp ) { shareAttrExp(pSlayer, ExpUp, 8, 1, 1, _GCSkillToSelfOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToSelfOK1); // increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToSelfOK1); } // 패킷을 만들어 보낸다. _GCSkillToSelfOK1.setSkillType(SkillType); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(output.Duration); _GCSkillToSelfOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToSelfOK2.setSkillType(SkillType); _GCSkillToSelfOK2.setDuration(output.Duration); pPlayer->sendPacket(&_GCSkillToSelfOK1); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &_GCSkillToSelfOK2, pSlayer); // 이펙트가 붙었다고 알려준다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pSlayer->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_CHARGING_POWER); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcAddEffect); // set Next Run Time pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pSlayer, getSkillType(), NULL); } } catch (Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End(slayerself)" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void Death::execute(Vampire* pVampire, ObjectID_t TargetObjectID, VampireSkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; Assert(pVampire != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pVampire->getPlayer(); Zone* pZone = pVampire->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NPC는 공격할 수 없다. // 저주 면역. by sigi. 2002.9.13 // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || pTargetCreature->isFlag(Effect::EFFECT_CLASS_IMMUNE_TO_CURSE) || !canAttack(pVampire, pTargetCreature ) || pTargetCreature->isNPC()) { executeSkillFailException(pVampire, 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); // Knowledge of Curse 가 있다면 hit bonus 10 int HitBonus = 0; if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_CURSE ) ) { RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_CURSE); Assert(pRankBonus != NULL); HitBonus = pRankBonus->getPoint(); } int RequiredMP = decreaseConsumeMP(pVampire, pSkillInfo); bool bManaCheck = hasEnoughMana(pVampire, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = verifyDistance(pVampire, pTargetCreature, pSkillInfo->getRange()); bool bHitRoll = HitRoll::isSuccessVampireCurse(pSkillInfo->getLevel(), pTargetCreature->getResist(MAGIC_DOMAIN_CURSE)); bool bHitRoll2 = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pSkillSlot, HitBonus); bool bCanHit = canHit(pVampire, pTargetCreature, SkillType); bool bEffected = pTargetCreature->isFlag(Effect::EFFECT_CLASS_DEATH); bool bPK = verifyPK(pVampire, pTargetCreature); ZoneCoord_t targetX = pTargetCreature->getX(); ZoneCoord_t targetY = pTargetCreature->getY(); ZoneCoord_t myX = pVampire->getX(); ZoneCoord_t myY = pVampire->getY(); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bHitRoll2 && bCanHit && !bEffected && bPK) { decreaseMana(pVampire, RequiredMP, _GCSkillToObjectOK1); bool bCanSeeCaster = canSee(pTargetCreature, pVampire); SkillInput input(pVampire); SkillOutput output; computeOutput(input, output); // pTargetCreature가 저주마법을 반사하는 경우 if (CheckReflection(pVampire, pTargetCreature, getSkillType())) { pTargetCreature = (Creature*)pVampire; TargetObjectID = pVampire->getObjectID(); } Resist_t resist = pTargetCreature->getResist(MAGIC_DOMAIN_CURSE); if ((resist*10/3) > output.Duration ) output.Duration=0; else output.Duration -= resist*10/3; if (output.Duration < 20 ) output.Duration = 20; // 이펙트 오브젝트를 생성해 붙인다. EffectDeath* pEffect = new EffectDeath(pTargetCreature); pEffect->setDeadline(output.Duration); pEffect->setLevel(pSkillInfo->getLevel()/2); pEffect->setResistPenalty(output.Damage); pTargetCreature->addEffect(pEffect); pTargetCreature->setFlag(Effect::EFFECT_CLASS_DEATH); // 능력치를 계산해서 보내준다. if (pTargetCreature->isSlayer()) { Slayer* pTargetSlayer = dynamic_cast<Slayer*>(pTargetCreature); if (bCanSeeCaster) { SLAYER_RECORD prev; pTargetSlayer->getSlayerRecord(prev); pTargetSlayer->initAllStat(); pTargetSlayer->addModifyInfo(prev, _GCSkillToObjectOK2); } else { SLAYER_RECORD prev; pTargetSlayer->getSlayerRecord(prev); pTargetSlayer->initAllStat(); pTargetSlayer->addModifyInfo(prev, _GCSkillToObjectOK6); } } else if (pTargetCreature->isVampire()) { Vampire* pTargetVampire = dynamic_cast<Vampire*>(pTargetCreature); VAMPIRE_RECORD prev; pTargetVampire->getVampireRecord(prev); pTargetVampire->initAllStat(); if (bCanSeeCaster) { pTargetVampire->addModifyInfo(prev, _GCSkillToObjectOK2); } else { pTargetVampire->addModifyInfo(prev, _GCSkillToObjectOK6); } } else if (pTargetCreature->isOusters()) { Ousters* pTargetOusters = dynamic_cast<Ousters*>(pTargetCreature); OUSTERS_RECORD prev; pTargetOusters->getOustersRecord(prev); pTargetOusters->initAllStat(); if (bCanSeeCaster) { pTargetOusters->addModifyInfo(prev, _GCSkillToObjectOK2); } else { pTargetOusters->addModifyInfo(prev, _GCSkillToObjectOK6); } } else if (pTargetCreature->isMonster()) { Monster* pTargetMonster = dynamic_cast<Monster*>(pTargetCreature); pTargetMonster->initAllStat(); } else Assert(false); _GCSkillToObjectOK1.setSkillType(SkillType); _GCSkillToObjectOK1.setCEffectID(CEffectID); _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK1.setDuration(output.Duration); _GCSkillToObjectOK2.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK2.setSkillType(SkillType); _GCSkillToObjectOK2.setDuration(output.Duration); _GCSkillToObjectOK3.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK3.setSkillType(SkillType); _GCSkillToObjectOK3.setTargetXY (targetX, targetY); _GCSkillToObjectOK4.setSkillType(SkillType); _GCSkillToObjectOK4.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK4.setDuration(output.Duration); _GCSkillToObjectOK5.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK5.setSkillType(SkillType); _GCSkillToObjectOK5.setTargetObjectID (TargetObjectID); _GCSkillToObjectOK5.setDuration(output.Duration); _GCSkillToObjectOK6.setXY(myX, myY); _GCSkillToObjectOK6.setSkillType(SkillType); _GCSkillToObjectOK6.setDuration(output.Duration); if (bCanSeeCaster) // 10은 땜빵 수치다. { computeAlignmentChange(pTargetCreature, 10, pVampire, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1); } else // 10은 땜빵 수치다. { computeAlignmentChange(pTargetCreature, 10, pVampire, &_GCSkillToObjectOK6, &_GCSkillToObjectOK1); } list<Creature *> cList; cList.push_back(pTargetCreature); cList.push_back(pVampire); 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); if (pTargetCreature->isPC()) { Player* pTargetPlayer = pTargetCreature->getPlayer(); if (pTargetPlayer == NULL) { //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; return; } if (bCanSeeCaster) pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); else pTargetPlayer->sendPacket(&_GCSkillToObjectOK6); } else if (pTargetCreature->isMonster()) { Monster* pTargetMonster = dynamic_cast<Monster*>(pTargetCreature); pTargetMonster->addEnemy(pVampire); } GCAddEffect gcAddEffect; gcAddEffect.setObjectID(TargetObjectID); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_DEATH); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(targetX, targetY, &gcAddEffect); //cout << pTargetCreature->getName() << "에게 Death를 " << output.Duration << " duration 동안 건다." << endl; pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pVampire, getSkillType(), pTargetCreature); } } catch (Throwable & t) { executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void Revealer::execute(Slayer* pSlayer, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pSlayer->getPlayer(); Zone* pZone = pSlayer->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pSlayer); bool bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot); bool bEffected = pSlayer->isFlag(Effect::EFFECT_CLASS_REVEALER); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { decreaseMana(pSlayer, RequiredMP, _GCSkillToSelfOK1); // 기술이 유지되는 시간은 숙련도에 따라서 달라진다. SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); // 이펙트 오브젝트를 생성해서 붙인다. EffectRevealer* pEffectRevealer = new EffectRevealer (pSlayer); pEffectRevealer->setSkillLevel(pSkillSlot->getExpLevel()); pEffectRevealer->setDeadline(output.Duration); pSlayer->addEffect(pEffectRevealer); pSlayer->setFlag(Effect::EFFECT_CLASS_REVEALER); // 이 이펙트가 붙음으로써, 안 보이던 것이 보인다. pZone->updateMineScan(pSlayer); //pZone->updateInvisibleScan(pSlayer); pZone->updateHiddenScan(pSlayer); // 경험치를 올린다. SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType)); Exp_t ExpUp = 10* (Grade + 1)* 2; shareAttrExp(pSlayer, ExpUp, 1, 8, 1, _GCSkillToSelfOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToSelfOK1); // increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToSelfOK1); _GCSkillToSelfOK1.setSkillType(SkillType); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(output.Duration); _GCSkillToSelfOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToSelfOK2.setSkillType(SkillType); _GCSkillToSelfOK2.setDuration(output.Duration); pPlayer->sendPacket(&_GCSkillToSelfOK1); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &_GCSkillToSelfOK2, pSlayer); // 이펙트가 붙었다고 알려준다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pSlayer->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_REVEALER); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcAddEffect); pSkillSlot->setRunTime(output.Delay); uint PartyID = pSlayer->getPartyID(); if (PartyID != 0) { LocalPartyManager* pLPM = pZone->getLocalPartyManager(); pLPM->shareRevealer(PartyID, pSlayer, output.Duration); } } else { executeSkillFailNormal(pSlayer, getSkillType(), NULL); } } catch(Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void DarkBluePoison::execute(Monster* pMonster, Creature* pEnemy) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; Assert(pMonster != NULL); Assert(pEnemy != NULL); try { Zone* pZone = pMonster->getZone(); Assert(pZone != NULL); GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK3 _GCSkillToObjectOK3; GCSkillToObjectOK4 _GCSkillToObjectOK4; GCSkillToObjectOK5 _GCSkillToObjectOK5; GCSkillToObjectOK6 _GCSkillToObjectOK6; SkillType_t SkillType = SKILL_DARKBLUE_POISON; SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); bool bRangeCheck = verifyDistance(pMonster, pEnemy, pSkillInfo->getRange()); bool bHitRoll = HitRoll::isSuccessMagic(pMonster, pSkillInfo); bool bEffected = pEnemy->isFlag(Effect::EFFECT_CLASS_DARKBLUE_POISON); ZoneCoord_t vampX = pMonster->getX(); ZoneCoord_t vampY = pMonster->getY(); ZoneCoord_t targetX = pEnemy->getX(); ZoneCoord_t targetY = pEnemy->getY(); if (bRangeCheck && bHitRoll && !bEffected) { bool bCanSeeCaster = canSee(pEnemy, pMonster); SkillInput input(pMonster); SkillOutput output; computeOutput(input, output); Damage_t Damage = computeMagicDamage(pEnemy, output.Damage, SkillType); // 이펙트 오브젝트를 생성해서 붙인다. EffectDarkBluePoison* pEffectDarkBluePoison = new EffectDarkBluePoison(pEnemy); pEffectDarkBluePoison->setDamage(Damage); pEffectDarkBluePoison->setLevel(pSkillInfo->getLevel()/2); pEffectDarkBluePoison->setDeadline(output.Duration); pEffectDarkBluePoison->setTick(output.Tick); pEffectDarkBluePoison->setNextTime(0); pEnemy->addEffect(pEffectDarkBluePoison); pEnemy->setFlag(Effect::EFFECT_CLASS_DARKBLUE_POISON); // 이펙트가 붙었으니, 붙었다고 브로드캐스팅해준다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pEnemy->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_DARKBLUE_POISON); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(targetX, targetY, &gcAddEffect); if (bCanSeeCaster) { decreaseDurability(pMonster, pEnemy, pSkillInfo, NULL, &_GCSkillToObjectOK2); } else { decreaseDurability(pMonster, pEnemy, pSkillInfo, NULL, &_GCSkillToObjectOK6); } _GCSkillToObjectOK2.setObjectID(pMonster->getObjectID()); _GCSkillToObjectOK2.setSkillType(SkillType); _GCSkillToObjectOK2.setDuration(output.Duration); _GCSkillToObjectOK3.setObjectID(pMonster->getObjectID()); _GCSkillToObjectOK3.setSkillType(SkillType); _GCSkillToObjectOK3.setTargetXY(targetX, targetY); _GCSkillToObjectOK4.setSkillType(SkillType); _GCSkillToObjectOK4.setTargetObjectID(pEnemy->getObjectID()); _GCSkillToObjectOK5.setObjectID(pMonster->getObjectID()); _GCSkillToObjectOK5.setTargetObjectID(pEnemy->getObjectID()); _GCSkillToObjectOK5.setSkillType(SkillType); _GCSkillToObjectOK5.setDuration(output.Duration); _GCSkillToObjectOK6.setXY(vampX, vampY); _GCSkillToObjectOK6.setSkillType(SkillType); _GCSkillToObjectOK6.setDuration(output.Duration); if (pEnemy->isPC()) { Player* pTargetPlayer = pEnemy->getPlayer(); if (pTargetPlayer == NULL) { //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; return; } if (bCanSeeCaster) pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); else pTargetPlayer->sendPacket(&_GCSkillToObjectOK6); } else { Monster* pTargetMonster = dynamic_cast<Monster*>(pEnemy); pTargetMonster->addEnemy(pMonster); } list<Creature*> cList; cList.push_back(pMonster); cList.push_back(pEnemy); cList = pZone->broadcastSkillPacket(vampX, vampY, targetX, targetY, &_GCSkillToObjectOK5, cList); pZone->broadcastPacket(vampX, vampY, &_GCSkillToObjectOK3 , cList); pZone->broadcastPacket(targetX, targetY, &_GCSkillToObjectOK4 , cList); } else { executeSkillFailNormal(pMonster, getSkillType(), pEnemy); } } catch(Throwable & t) { executeSkillFailException(pMonster, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void GroundBless::execute(Ousters* pOusters, OustersSkillSlot* pOustersSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin(slayer)" << endl; Assert(pOusters != NULL); Assert(pOustersSkillSlot != 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, pOustersSkillSlot->getSkillType()); return; } GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; SkillType_t SkillType = pOustersSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); //SkillDomainType_t DomainType = pSkillInfo->getDomainType(); //SkillLevel_t SkillLevel = pOustersSkillSlot->getExpLevel(); int RequiredMP = (int)pSkillInfo->getConsumeMP() + pOustersSkillSlot->getExpLevel()/2; bool bManaCheck = hasEnoughMana(pOusters, RequiredMP); bool bTimeCheck = verifyRunTime(pOustersSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pOusters); bool bHitRoll = HitRoll::isSuccessMagic(pOusters, pSkillInfo, pOustersSkillSlot); bool bEffected = pOusters->isFlag(Effect::EFFECT_CLASS_GROUND_BLESS); bool bSatisfyRequire = pOusters->satisfySkillRequire(pSkillInfo); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected && bSatisfyRequire) { decreaseMana(pOusters, RequiredMP, _GCSkillToSelfOK1); // 지속 시간을 계산한다. SkillInput input(pOusters, pOustersSkillSlot); SkillOutput output; input.STR = pOusters->getSTR(ATTR_BASIC); input.DEX = pOusters->getDEX(ATTR_BASIC); input.INTE = pOusters->getINT(ATTR_BASIC); computeOutput(input, output); // 이팩트 클래스를 만들어 붙인다. EffectGroundBless* pEffect = new EffectGroundBless(pOusters); pEffect->setDeadline(output.Duration); pEffect->setBonus(output.Damage); pOusters->addEffect(pEffect); pOusters->setFlag(Effect::EFFECT_CLASS_GROUND_BLESS); pOusters->initAllStatAndSend(); _GCSkillToSelfOK1.setSkillType(SkillType); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(output.Duration); _GCSkillToSelfOK2.setObjectID(pOusters->getObjectID()); _GCSkillToSelfOK2.setSkillType(SkillType); _GCSkillToSelfOK2.setDuration(output.Duration); pPlayer->sendPacket(&_GCSkillToSelfOK1); pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &_GCSkillToSelfOK2, pOusters); GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pOusters->getObjectID()); gcAddEffect.setEffectID(pEffect->getEffectClass()); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pOusters->getX(), pOusters->getY(), &gcAddEffect); pOustersSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pOusters, getSkillType(), NULL); } } catch (Throwable & t) { executeSkillFailException(pOusters, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End(slayer)" << endl; __END_CATCH }
void Flare::execute(Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; 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); // NPC이거나, 슬레이어에게는 Flare를 쓸 수가 없다. // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || pTargetCreature->isNPC() || pTargetCreature->isSlayer()) { executeSkillFailException(pSlayer, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } GCSkillToObjectOK1 _GCSkillToObjectOK1; GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK3 _GCSkillToObjectOK3; GCSkillToObjectOK4 _GCSkillToObjectOK4; GCSkillToObjectOK5 _GCSkillToObjectOK5; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); SkillLevel_t SkillLevel = pSkillSlot->getExpLevel(); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = verifyDistance(pSlayer, pTargetCreature, pSkillInfo->getRange()); bool bHitRoll = HitRoll::isSuccessFlare(pTargetCreature, SkillLevel) && canAttack(pSlayer, pTargetCreature); bool bEffected = pTargetCreature->isFlag(Effect::EFFECT_CLASS_FLARE); //if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected && pTargetCreature->getCompetence() == 3) { decreaseMana(pSlayer, RequiredMP, _GCSkillToObjectOK1); // 지속 시간을 계산한다. SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); // 이펙트 클래스를 만들어 붙인다. EffectFlare* pEffect = new EffectFlare(pTargetCreature); //pEffect->setOldSight(13); pEffect->setOldSight(pTargetCreature->getSight()); // 제거할때 level체크하기 위햇서.by sigi. 2002.6.21 pEffect->setLevel(pSkillInfo->getLevel()); pEffect->setDeadline(output.Duration); pTargetCreature->setFlag(Effect::EFFECT_CLASS_FLARE); pTargetCreature->addEffect(pEffect); // 이펙트를 적용시킨다. pEffect->affect(pTargetCreature); // 경험치를 올린다. SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType)); Exp_t ExpUp = 10* (Grade + 1); shareAttrExp(pSlayer, ExpUp, 1, 1, 8, _GCSkillToObjectOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToObjectOK1); increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToObjectOK1); // 패킷을 준비한다. ZoneCoord_t targetX = pTargetCreature->getX(); ZoneCoord_t targetY = pTargetCreature->getY(); ZoneCoord_t myX = pSlayer->getX(); ZoneCoord_t myY = pSlayer->getY(); _GCSkillToObjectOK1.setSkillType(SkillType); _GCSkillToObjectOK1.setCEffectID(CEffectID); _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK1.setDuration(0); _GCSkillToObjectOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK2.setSkillType(SkillType); _GCSkillToObjectOK2.addShortData(MODIFY_VISION, FLARE_SIGHT); _GCSkillToObjectOK2.setDuration(0); _GCSkillToObjectOK3.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK3.setSkillType(SkillType); _GCSkillToObjectOK3.setTargetXY (targetX, targetY); _GCSkillToObjectOK4.setSkillType(SkillType); _GCSkillToObjectOK4.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK4.setDuration(0); _GCSkillToObjectOK5.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK5.setSkillType(SkillType); _GCSkillToObjectOK5.setTargetObjectID (TargetObjectID); _GCSkillToObjectOK5.setDuration(0); list<Creature *> cList; cList.push_back(pTargetCreature); cList.push_back(pSlayer); cList = pZone->broadcastSkillPacket(myX, myY, targetX, targetY, &_GCSkillToObjectOK5, cList); pZone->broadcastPacket(myX, myY, &_GCSkillToObjectOK3, cList); pZone->broadcastPacket(targetX, targetY, &_GCSkillToObjectOK4, cList); pPlayer->sendPacket(&_GCSkillToObjectOK1); if (pTargetCreature->isPC()) { Player* pTargetPlayer = pTargetCreature->getPlayer(); Assert(pTargetPlayer != NULL); pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); } else { Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature); pMonster->addEnemy(pSlayer); } GCAddEffect gcAddEffect; gcAddEffect.setObjectID(TargetObjectID); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_FLARE); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(targetX, targetY, &gcAddEffect); pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pSlayer, getSkillType(), pTargetCreature); } } catch (Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 셀프 ////////////////////////////////////////////////////////////////////////////// void InstallTurret::execute(Slayer * pSlayer, SkillSlot * pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pSlayer->getPlayer(); Zone* pZone = pSlayer->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); Item* pWeapon = pSlayer->getWearItem(Slayer::WEAR_RIGHTHAND); if (pWeapon == NULL || !isArmsWeapon(pWeapon) || pSlayer->hasRelicItem()) { executeSkillFailException(pSlayer, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } bool bIncreaseDomainExp = pSlayer->isRealWearingEx(Slayer::WEAR_RIGHTHAND); GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); ZoneCoord_t X = pSlayer->getX(); ZoneCoord_t Y = pSlayer->getY(); Tile& rTile = pZone->getTile(X,Y); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pSlayer); bool bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot); bool bEffected = pSlayer->isFlag(Effect::EFFECT_CLASS_INSTALL_TURRET); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { decreaseMana(pSlayer, RequiredMP, _GCSkillToSelfOK1); SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); EffectInstallTurret* pEffect = new EffectInstallTurret(pSlayer); pEffect->setDeadline(output.Duration); pEffect->setDamage(output.Damage); pEffect->setDefense(output.ToHit); //cout << "Turret Duration : " << output.Duration << endl; //cout << "Turret Delay : " << output.Delay << endl; pSlayer->setFlag(pEffect->getEffectClass()); pSlayer->addEffect(pEffect); GCAddEffect gcAE; gcAE.setObjectID(pSlayer->getObjectID()); gcAE.setDuration(output.Duration); gcAE.setEffectID(pEffect->getSendEffectClass()); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcAE); SLAYER_RECORD prev; pSlayer->getSlayerRecord(prev); pSlayer->initAllStat(); pSlayer->sendRealWearingInfo(); pSlayer->addModifyInfo(prev, _GCSkillToSelfOK1); // 패킷을 만들어 보낸다. _GCSkillToSelfOK1.setSkillType(SkillType); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(output.Duration); _GCSkillToSelfOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToSelfOK2.setSkillType(SkillType); _GCSkillToSelfOK2.setDuration(output.Duration); // Send Packet pPlayer->sendPacket(&_GCSkillToSelfOK1); pZone->broadcastPacket(X, Y, &_GCSkillToSelfOK2, pSlayer); pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pSlayer, getSkillType(), NULL); } } catch (Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); //cout << t.toString() << endl; } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void WillOfLife::execute(Vampire* pVampire, VampireSkillSlot* pVampireSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin(slayerself)" << endl; Assert(pVampire != NULL); Assert(pVampireSkillSlot != NULL); try { Player* pPlayer = pVampire->getPlayer(); Zone* pZone = pVampire->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; SkillType_t SkillType = pVampireSkillSlot->getSkillType(); //SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); // 스킬 레벨에 따라 데미지 보너스가 달라진다. SkillInput input(pVampire); SkillOutput output; computeOutput(input, output); int RequiredMP = output.Damage; bool bManaCheck = hasEnoughMana(pVampire, RequiredMP); bool bTimeCheck = verifyRunTime(pVampireSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pVampire); bool bHitRoll = HitRoll::isSuccessWillOfLife(pVampire); bool bEffected = pVampire->isFlag(Effect::EFFECT_CLASS_WILL_OF_LIFE); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { decreaseMana(pVampire, RequiredMP, _GCSkillToSelfOK1); // 이펙트 클래스를 만들어 붙인다. EffectWillOfLife* pEffect = new EffectWillOfLife(pVampire); pEffect->setDeadline(output.Duration); pEffect->setBonus(output.Damage); pEffect->setNextTime(0); pVampire->addEffect(pEffect); pVampire->setFlag(Effect::EFFECT_CLASS_WILL_OF_LIFE); // 패킷을 만들어 보낸다. _GCSkillToSelfOK1.setSkillType(SkillType); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(output.Duration); _GCSkillToSelfOK2.setObjectID(pVampire->getObjectID()); _GCSkillToSelfOK2.setSkillType(SkillType); _GCSkillToSelfOK2.setDuration(output.Duration); pPlayer->sendPacket(&_GCSkillToSelfOK1); GCStatusCurrentHP gcStatusCurrentHP; gcStatusCurrentHP.setObjectID(pVampire->getObjectID()); gcStatusCurrentHP.setCurrentHP(pVampire->getHP()); pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &_GCSkillToSelfOK2, pVampire); pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &gcStatusCurrentHP); // 이펙트가 붙었다고 알려준다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pVampire->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_WILL_OF_LIFE); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &gcAddEffect); } else { executeSkillFailNormal(pVampire, getSkillType(), NULL); } // set Next Run Time if (bTimeCheck ) pVampireSkillSlot->setRunTime(output.Delay); } catch (Throwable & t) { executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End(slayerself)" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void ProtectionFromAcid::execute(Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; 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() ) { executeSkillFailException(pSlayer, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; return; } GCSkillToObjectOK1 _GCSkillToObjectOK1; GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK5 _GCSkillToObjectOK5; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); 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); bool bEffected = pTargetCreature->isFlag(Effect::EFFECT_CLASS_PROTECTION_FROM_ACID); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { // 마나를 줄인다. decreaseMana(pSlayer, RequiredMP, _GCSkillToObjectOK1); // 경험치를 올려준다. SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType)); Exp_t ExpUp = 10* (Grade + 1); shareAttrExp(pSlayer, ExpUp, 1, 1, 8, _GCSkillToObjectOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToObjectOK1); increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToObjectOK1); // 이펙트의 효과와 지속시간을 계산한다. SkillInput input(pSlayer, pSkillSlot); SkillOutput output; input.TargetType = SkillInput::TARGET_OTHER; computeOutput(input, output); // 이펙트를 생성해서 붙인다. EffectProtectionFromAcid* pEPFP = new EffectProtectionFromAcid (pTargetCreature); Assert(pEPFP != NULL); pEPFP->setDeadline(output.Duration); pEPFP->setResist(output.Damage); pTargetCreature->addEffect(pEPFP); pTargetCreature->setFlag(Effect::EFFECT_CLASS_PROTECTION_FROM_ACID); if (pTargetCreature->isSlayer()) { Slayer* pTargetSlayer = dynamic_cast<Slayer*>(pTargetCreature); SLAYER_RECORD prev; pTargetSlayer->getSlayerRecord(prev); pTargetSlayer->initAllStat(); pTargetSlayer->addModifyInfo(prev, _GCSkillToObjectOK1); } else { Assert(false); } // 패킷을 준비해서 보낸다. _GCSkillToObjectOK1.setSkillType(SkillType); _GCSkillToObjectOK1.setCEffectID(CEffectID); _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK1.setDuration(output.Duration); _GCSkillToObjectOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK2.setSkillType(SkillType); _GCSkillToObjectOK2.setDuration (output.Duration); _GCSkillToObjectOK5.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK5.setSkillType(SkillType); _GCSkillToObjectOK5.setTargetObjectID (TargetObjectID); _GCSkillToObjectOK5.setDuration (output.Duration); // Send Packet pPlayer->sendPacket(&_GCSkillToObjectOK1); if (pSlayer != pTargetCreature && pTargetCreature->isPC()) { Player* pTargetPlayer = pTargetCreature->getPlayer(); Assert(pTargetPlayer != NULL); pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); } list<Creature*> cList; cList.push_back(pSlayer); cList.push_back(pTargetCreature); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &_GCSkillToObjectOK5 , cList); // 이펙트가 붙었다고 알려준다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pTargetCreature->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_PROTECTION_FROM_ACID); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &gcAddEffect); pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pSlayer, getSkillType(), pTargetCreature); } } catch (Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; __END_CATCH }
bool EffectEnergyDrop::affectCreature(Creature* pTargetCreature, bool bAffectByMove) throw(Error) { __BEGIN_TRY //cout << "EffectEnergyDrop " << "affectCreature Begin " << endl; Assert(pTargetCreature != NULL); // 상대에게 이미 poison 이펙트가 걸려져 있는 경우에는 걸리지 않는다. if (pTargetCreature->isFlag(Effect::EFFECT_CLASS_ENERGY_DROP_TO_CREATURE)) { //cout << "EffectEnergyDrop " << "affectCreature End(Already Effected) " << endl; return false; } // 안전지대 체크 // 2003.1.10 by bezz, Sequoia if (!checkZoneLevelToHitTarget(pTargetCreature) ) { return false; } Zone* pZone = pTargetCreature->getZone(); // 상대방에게 미칠 독 데미지를 계산한다. int DropDamage = computeMagicDamage(pTargetCreature, m_Damage, SKILL_ENERGY_DROP); //cout << "EffectEnergyDrop(Damage:" << DropDamage << ") Affected" << endl; if (DropDamage > 0) { // 포이즌 이펙트를 생성해서, 타겟 크리쳐에 붙이고, 플래그를 켜준다. // 현제는 EnergyDrop Effect를 지속적으로 운영하지 않는다. 다른 Effeect기술의 // 경우 시전자의 레벨이 올라갈수록 Duration이 증가하게 되고 이에 대한 Effect를 붙이게 // 되지만, --Drop, --Storm류의 기술은 일단 성공이 되면 해당 구역의 모든 사람이 // 기술을 당하게 되고, 각각 시간으로 데미지를 주는 것이 아니라 일정량의 데미지를 // 3등분해서 주게 된다. 몇번의 데미지를 주는 함수는 아직 개발되지 않은 단계라서 // Deadline과 tick을 사용해서 임의로 구현을 하였다. // 1.6초 동안에 0.5초 간격으로 데미지를 주게 되면, 3번의 데미지를 줄 수 있게 된다. // 여기서는 하드코딩이 되어 있는데, 이는 다른 방법으로 교체되어야 할 거 같다. // EffectEnergyDrop Class에 member variable로 // m_Tick // m_Count // 를 두어서 이를 바탕으로 deadline을 계산해서 적용한다면 더욱 더 편할 것이다. EffectEnergyDropToCreature* pEffectEnergyDropToCreature = new EffectEnergyDropToCreature(pTargetCreature); // 우선권 시스템을 위하여 이름과 파티 아이디를 넣는다. // pEffectEnergyDropToCreature->setCasterName(m_CasterName); // pEffectEnergyDropToCreature->setPartyID(m_PartyID); pEffectEnergyDropToCreature->setUserObjectID(m_UserObjectID); pEffectEnergyDropToCreature->setLevel(m_Level); pEffectEnergyDropToCreature->setPoint(DropDamage/3); pEffectEnergyDropToCreature->setDeadline(16); // 이부분 바꿔야 한다. pEffectEnergyDropToCreature->setTick(5); // 이부분도 바꿔야 한다. pEffectEnergyDropToCreature->affect(pTargetCreature); pTargetCreature->addEffect(pEffectEnergyDropToCreature); pTargetCreature->setFlag(Effect::EFFECT_CLASS_ENERGY_DROP_TO_CREATURE); // 이펙트가 붙었다고 주변에 알려준다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pTargetCreature->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_ENERGY_DROP_TO_CREATURE); gcAddEffect.setDuration(m_Duration); pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &gcAddEffect); } //cout << "EffectEnergyDrop " << "affectCreature End " << endl; return true; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void Sacrifice::execute(Slayer* pSlayer, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pSlayer->getPlayer(); Zone* pZone = pSlayer->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); ZoneCoord_t X = pSlayer->getX(); ZoneCoord_t Y = pSlayer->getY(); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pSlayer); bool bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot); bool bEffected = pSlayer->isFlag(Effect::EFFECT_CLASS_SACRIFICE); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { decreaseMana(pSlayer, RequiredMP, _GCSkillToSelfOK1); SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); // 이펙트 클래스를 만들어 붙인다. EffectSacrifice* pEffect = new EffectSacrifice(pSlayer); pEffect->setDeadline(output.Duration); pSlayer->addEffect(pEffect); pSlayer->setFlag(Effect::EFFECT_CLASS_SACRIFICE); // 경험치를 올린다. SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType)); Exp_t ExpUp = 10*(Grade+1); shareAttrExp(pSlayer, ExpUp , 1, 1, 8, _GCSkillToSelfOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToSelfOK1); increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToSelfOK1); _GCSkillToSelfOK1.setSkillType(SkillType); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(0); _GCSkillToSelfOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToSelfOK2.setSkillType(SkillType); _GCSkillToSelfOK2.setDuration(0); pPlayer->sendPacket(&_GCSkillToSelfOK1); pZone->broadcastPacket(X, Y, &_GCSkillToSelfOK2, pSlayer); GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pSlayer->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_SACRIFICE); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcAddEffect); pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pSlayer, getSkillType(), NULL); } } catch (Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void MindControl::execute(Slayer* pSlayer, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin(slayerself)" << endl; Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pSlayer->getPlayer(); Zone* pZone = pSlayer->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); ZoneCoord_t myX = pSlayer->getX(); ZoneCoord_t myY = pSlayer->getY(); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pSlayer); bool bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot); bool bEffected = pSlayer->isFlag(Effect::EFFECT_CLASS_MIND_CONTROL); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { decreaseMana(pSlayer, RequiredMP, _GCSkillToSelfOK1); SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); // 이펙트를 만들어 붙인다. EffectMindControl* pEffect = new EffectMindControl(pSlayer); pEffect->setDeadline(output.Duration); pEffect->setDefenseBonus(output.Damage); pEffect->setToHitBonus(output.Damage); pSlayer->setFlag(Effect::EFFECT_CLASS_MIND_CONTROL); pSlayer->addEffect(pEffect); // 이펙트를 붙였으니, 능력치를 재계산한다. SLAYER_RECORD prev; pSlayer->getSlayerRecord(prev); pSlayer->initAllStat(); pSlayer->sendRealWearingInfo(); pSlayer->addModifyInfo(prev, _GCSkillToSelfOK1); // 경험치를 올려준다. SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType)); Exp_t ExpUp = 10* (Grade + 1); shareAttrExp(pSlayer, ExpUp, 1, 8, 1, _GCSkillToSelfOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToSelfOK1); increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToSelfOK1); _GCSkillToSelfOK1.setSkillType(SkillType); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(output.Duration); _GCSkillToSelfOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToSelfOK2.setSkillType(SkillType); _GCSkillToSelfOK2.setDuration(output.Duration); pPlayer->sendPacket(&_GCSkillToSelfOK1); pZone->broadcastPacket(myX, myY, &_GCSkillToSelfOK2, pSlayer); GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pSlayer->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_MIND_CONTROL); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(myX, myY, &gcAddEffect); pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pSlayer, getSkillType(), NULL); } } catch (Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End(slayerself)" << endl; __END_CATCH }
void Howl::execute(Vampire* pVampire, VampireSkillSlot* pVampireSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pVampire != NULL); // 패킷 핸들러에서 직접 수행하는 기술 핸들러이기 때문에 // 스킬 핸들러가 널이다. //Assert(pSkillSlot != NULL); try { Player* pPlayer = pVampire->getPlayer(); Zone* pZone = pVampire->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; SkillInput input(pVampire); SkillOutput output; computeOutput(input, output); int RequiredMP = 10; bool bManaCheck = hasEnoughMana(pVampire, RequiredMP); bool bTimeCheck = verifyRunTime(pVampireSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pVampire); bool bHitRoll = (rand()%100)<output.Range; bool bEffected = pVampire->isFlag(Effect::EFFECT_CLASS_HOWL); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { decreaseMana(pVampire, RequiredMP, _GCSkillToSelfOK1); ZoneCoord_t x = pVampire->getX(); ZoneCoord_t y = pVampire->getY(); ObjectID_t objectID = pVampire->getObjectID(); EffectHowl* pEffect = new EffectHowl(pVampire); pEffect->setDeadline(output.Duration); pVampire->setFlag(Effect::EFFECT_CLASS_HOWL); pVampire->addEffect(pEffect); VAMPIRE_RECORD prev; pVampire->getVampireRecord(prev); pVampire->initAllStat(); pVampire->sendModifyInfo(prev); _GCSkillToSelfOK1.setSkillType(SKILL_HOWL); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(0); _GCSkillToSelfOK2.setObjectID(objectID); _GCSkillToSelfOK2.setSkillType(SKILL_HOWL); _GCSkillToSelfOK2.setDuration(0); pPlayer->sendPacket(&_GCSkillToSelfOK1); pZone->broadcastPacket(x, y, &_GCSkillToSelfOK2, pVampire); GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pVampire->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_HOWL); gcAddEffect.setDuration(output.Duration); pPlayer->sendPacket(&gcAddEffect); } else { executeSkillFailNormal(pVampire, getSkillType(), NULL); } } catch(Throwable & t) { executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void Mephisto::execute(Vampire* pVampire, VampireSkillSlot* pVampireSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin(slayerself)" << endl; Assert(pVampire != NULL); Assert(pVampireSkillSlot != NULL); try { Player* pPlayer = pVampire->getPlayer(); Zone* pZone = pVampire->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; SkillType_t SkillType = pVampireSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); // Knowledge of Curse 가 있다면 hit bonus 10 int HitBonus = 0; if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_CURSE ) ) { RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_CURSE); Assert(pRankBonus != NULL); HitBonus = pRankBonus->getPoint(); } int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pVampire, RequiredMP); bool bTimeCheck = verifyRunTime(pVampireSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pVampire); bool bHitRoll = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pVampireSkillSlot, HitBonus); bool bEffected = pVampire->isFlag(Effect::EFFECT_CLASS_MEPHISTO); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { decreaseMana(pVampire, RequiredMP, _GCSkillToSelfOK1); // 스킬 레벨에 따라 데미지 보너스가 달라진다. SkillInput input(pVampire); SkillOutput output; input.SkillLevel = pVampire->getSTR()+pVampire->getDEX()+pVampire->getINT(); input.DomainLevel = pVampire->getLevel(); computeOutput(input, output); // 이펙트 클래스를 만들어 붙인다. EffectMephisto* pEffect = new EffectMephisto(pVampire); pEffect->setDeadline(output.Duration); pEffect->setBonus(output.Damage); pVampire->addEffect(pEffect); pVampire->setFlag(Effect::EFFECT_CLASS_MEPHISTO); // 이로 인하여 바뀌는 능력치를 보낸다. VAMPIRE_RECORD prev; pVampire->getVampireRecord(prev); pVampire->initAllStat(); pVampire->sendRealWearingInfo(); pVampire->sendModifyInfo(prev); // 패킷을 만들어 보낸다. _GCSkillToSelfOK1.setSkillType(SkillType); _GCSkillToSelfOK1.setCEffectID(CEffectID); _GCSkillToSelfOK1.setDuration(output.Duration); _GCSkillToSelfOK2.setObjectID(pVampire->getObjectID()); _GCSkillToSelfOK2.setSkillType(SkillType); _GCSkillToSelfOK2.setDuration(output.Duration); pPlayer->sendPacket(&_GCSkillToSelfOK1); pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &_GCSkillToSelfOK2, pVampire); // 이펙트가 붙었다고 알려준다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pVampire->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_MEPHISTO); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &gcAddEffect); // set Next Run Time pVampireSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pVampire, getSkillType(), NULL); } } catch (Throwable & t) { executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End(slayerself)" << endl; __END_CATCH }