////////////////////////////////////////////////////////////////////// // // SwordWave::execute() // ////////////////////////////////////////////////////////////////////// void SwordWave::execute(Slayer * pSlayer, ZoneCoord_t X, ZoneCoord_t Y, SkillSlot * pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " begin" << endl; SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); SIMPLE_SKILL_INPUT param; param.SkillType = getSkillType(); param.SkillDamage = output.Damage; param.Delay = output.Delay; param.ItemClass = Item::ITEM_CLASS_SWORD; param.STRMultiplier = 8; param.DEXMultiplier = 1; param.INTMultiplier = 1; param.bMagicHitRoll = false; param.bMagicDamage = false; param.bAdd = true; SIMPLE_SKILL_OUTPUT result; ZoneCoord_t myX = pSlayer->getX(); ZoneCoord_t myY = pSlayer->getY(); Dir_t dir = calcDirection(myX, myY, X, Y); for (int i=0; i<3; i++) { param.addMask(m_pSwordWaveMask[dir][i].x, m_pSwordWaveMask[dir][i].y, 60); } g_SimpleTileMeleeSkill.execute(pSlayer, myX, myY, pSkillSlot, param, result); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 몬스터 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void IceWave::execute(Monster* pMonster, ZoneCoord_t X, ZoneCoord_t Y) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pMonster != NULL); try { Zone* pZone = pMonster->getZone(); Assert(pZone != NULL); if (pMonster->isFlag(Effect::EFFECT_CLASS_HIDE)) { //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } if (pMonster->isFlag(Effect::EFFECT_CLASS_INVISIBILITY)) { addVisibleCreature(pZone, pMonster, true); } int dx = (rand()%7)-3; int dy = (rand()%7)-3; X -= min((int)X, dx); Y -= min((int)Y, dy); if (X > pZone->getWidth() ) X = pZone->getWidth()-1; if (Y > pZone->getHeight() ) Y = pZone->getHeight()-1; pZone->moveFastMonster(pMonster, pMonster->getX(), pMonster->getY(), X, Y, getSkillType()); ZoneCoord_t x = pMonster->getX(); ZoneCoord_t y = pMonster->getY(); bool bRangeCheck = checkZoneLevelToUseSkill(pMonster); bool bMoveModeCheck = pMonster->isWalking(); if (bRangeCheck && bMoveModeCheck) { //-------------------------------------------------------- // 주위에 knockback되는맞는 애들을 체크해준다. //-------------------------------------------------------- SkillInput input(pMonster); SkillOutput output; computeOutput(input, output); SIMPLE_SKILL_INPUT param; param.SkillType = getSkillType(); param.SkillDamage = output.Damage; param.Delay = output.Delay; param.ItemClass = Item::ITEM_CLASS_MAX; param.STRMultiplier = 0; param.DEXMultiplier = 0; param.INTMultiplier = 0; param.bMagicHitRoll = true; param.bMagicDamage = true; param.bAdd = false; SIMPLE_SKILL_OUTPUT result; for (int i=0; i<8; ++i ) { for (int j=0; j<3; ++j ) { int ox = pMonster->getX() + dirMoveMask[i].x * j * 3 + dirMoveMask[i].x * 2; int oy = pMonster->getY() + dirMoveMask[i].y * j * 3 + dirMoveMask[i].y * 2; GCAddEffectToTile gcAE; gcAE.setXY(ox, oy); gcAE.setEffectID(Effect::EFFECT_CLASS_ICICLE_AUGER_LARGE); gcAE.setDuration(15); pMonster->getZone()->broadcastPacket(ox, oy, &gcAE); } } for (int i=0; i<193; i++) { if ((abs((int)x - (int)m_pIceWaveMask[i].x) <= 2) && (abs((int)y - (int)m_pIceWaveMask[i].y) <= 2)) param.addMask(m_pIceWaveMask[i].x, m_pIceWaveMask[i].y, 80); else param.addMask(m_pIceWaveMask[i].x, m_pIceWaveMask[i].y, 100); } // 강제로 맞는 애들을 knockback 시킨다. bool bForceKnockback = false; g_SimpleTileMeleeSkill.execute(pMonster, x, y, param, result, 0, bForceKnockback); } else { executeSkillFailNormal(pMonster, getSkillType(), NULL); } } catch(Throwable & t) { executeSkillFailException(pMonster, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
void ThunderStorm::execute(Slayer * pSlayer, ZoneCoord_t X, ZoneCoord_t Y, SkillSlot * pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; /* SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); SIMPLE_SKILL_INPUT param; param.SkillType = getSkillType(); param.SkillDamage = output.Damage; param.Delay = output.Delay; param.ItemClass = Item::ITEM_CLASS_SWORD; param.STRMultiplier = 8; param.DEXMultiplier = 1; param.INTMultiplier = 1; param.bMagicHitRoll = false; param.bMagicDamage = false; param.bAdd = true; SIMPLE_SKILL_OUTPUT result; g_SimpleMeleeSkill.execute(pSlayer, TargetObjectID, pSkillSlot, param, result); */ //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); SIMPLE_SKILL_INPUT param; param.SkillType = getSkillType(); param.SkillDamage = output.Damage; param.Delay = output.Delay; param.ItemClass = Item::ITEM_CLASS_SWORD; param.STRMultiplier = 8; param.DEXMultiplier = 1; param.INTMultiplier = 1; param.bMagicHitRoll = false; param.bMagicDamage = false; param.bAdd = true; param.bExpForTotalDamage = true; SIMPLE_SKILL_OUTPUT result; // 목표위치+4방향 param.addMask(0, 0, 100); param.addMask(-1, -1, 100); param.addMask(0, -1, 100); param.addMask(1, -1, 100); param.addMask(-1, 0, 100); param.addMask(1, 0, 100); param.addMask(-1, 1, 100); param.addMask(0, 1, 100); param.addMask(1, 1, 100); // 자신의 주변에 떨어뜨린다. // 아니다.. --; //X = pSlayer->getX(); //Y = pSlayer->getY(); g_SimpleTileMissileSkill.execute(pSlayer, X, Y, pSkillSlot, param, result); //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 SwordOfThor::execute(Slayer * pSlayer, ZoneCoord_t X, ZoneCoord_t Y, SkillSlot * pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY // cout << "(x,y)=" << X << "," << Y << endl; Zone* pZone = pSlayer->getZone(); Assert(pZone!=NULL); SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); SIMPLE_SKILL_INPUT param; param.SkillType = getSkillType(); param.SkillDamage = output.Damage; param.Delay = output.Delay; param.ItemClass = Item::ITEM_CLASS_SWORD; param.STRMultiplier = 8; param.DEXMultiplier = 1; param.INTMultiplier = 1; param.bMagicHitRoll = false; param.bMagicDamage = false; param.bAdd = false; param.bExpForTotalDamage = false; for (int i=-2; i<=2; ++i ) for (int j=-2; j<=2; ++j ) { param.addMask(i, j, 100); } SIMPLE_SKILL_OUTPUT result; // 목표위치+4방향 /* param.addMask(0 + dir_advance[dir][0], 0 + dir_advance[dir][1], 100); param.addMask(-1 + dir_advance[dir][0], -1 + dir_advance[dir][1], 100); param.addMask(0 + dir_advance[dir][0], -1 + dir_advance[dir][1], 100); param.addMask(1 + dir_advance[dir][0], -1 + dir_advance[dir][1], 100); param.addMask(-1 + dir_advance[dir][0], 0 + dir_advance[dir][1], 100); param.addMask(1 + dir_advance[dir][0], 0 + dir_advance[dir][1], 100); param.addMask(-1 + dir_advance[dir][0], 1 + dir_advance[dir][1], 100); param.addMask(0 + dir_advance[dir][0], 1 + dir_advance[dir][1], 100); param.addMask(1 + dir_advance[dir][0], 1 + dir_advance[dir][1], 100);*/ g_SimpleTileMissileSkill.execute(pSlayer, X, Y, pSkillSlot, param, result); if (result.bSuccess ) { for (int i=-2; i<=2; ++i ) for (int j=-2; j<=2; ++j ) { ZoneCoord_t tx = X+i; ZoneCoord_t ty = Y+j; if (!isValidZoneCoord(pZone, tx, ty) ) continue; Tile& rTile = pZone->getTile(tx, ty); if (!rTile.canAddEffect() ) continue; EffectSwordOfThor* pEffect = new EffectSwordOfThor(pZone, tx, ty); pEffect->setLevel(input.SkillLevel); pEffect->setDeadline(output.Duration); pZone->registerObject(pEffect); if (i != 0 || j != 0 ) pEffect->setBroadcastingEffect(false); else { GCAddEffectToTile gcAE; gcAE.setEffectID(pEffect->getSendEffectClass()); gcAE.setXY(tx, ty); gcAE.setObjectID(pEffect->getObjectID()); gcAE.setDuration(output.Duration); pZone->broadcastPacket(tx, ty, &gcAE); // cout << tx << ", " << ty << " Effect broadcast" << endl; } pZone->addEffect(pEffect); rTile.addEffect(pEffect); // cout << tx << ", " << ty << " add Effect" << endl; } } __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 몬스터 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void LandMineExplosion::execute(Monster* pMonster) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pMonster != NULL); try { Zone* pZone = pMonster->getZone(); Assert(pZone != NULL); //GCSkillToSelfOK2 _GCSkillToSelfOK2; ZoneCoord_t x = pMonster->getX(); ZoneCoord_t y = pMonster->getY(); bool bRangeCheck = checkZoneLevelToUseSkill(pMonster); if (bRangeCheck) { //-------------------------------------------------------- // 주위에 knockback되는맞는 애들을 체크해준다. //-------------------------------------------------------- SkillInput input(pMonster); SkillOutput output; computeOutput(input, output); SIMPLE_SKILL_INPUT param; param.SkillType = getSkillType(); param.SkillDamage = output.Damage; param.Delay = output.Delay; param.ItemClass = Item::ITEM_CLASS_MAX; param.STRMultiplier = 0; param.DEXMultiplier = 0; param.INTMultiplier = 0; param.bMagicHitRoll = true; param.bMagicDamage = true; param.bAdd = false; SIMPLE_SKILL_OUTPUT result; for (int i=0; i<48; i++) { param.addMask(m_pLandMineExplosionMask[i].x, m_pLandMineExplosionMask[i].y, 100); } // 강제로 맞는 애들을 knockback 시킨다. // bool bForceKnockback = true; g_SimpleTileMeleeSkill.execute(pMonster, x, y, param, result, 0, false); GCAddEffectToTile gcAE; gcAE.setXY(x, y); gcAE.setEffectID(Effect::EFFECT_CLASS_LAND_MINE_EXPLOSION); gcAE.setObjectID(0); gcAE.setDuration(0); pZone->broadcastPacket(x, y, &gcAE); } else { executeSkillFailNormal(pMonster, getSkillType(), NULL); } } catch(Throwable & t) { executeSkillFailException(pMonster, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 몬스터 셀프 핸들러 ////////////////////////////////////////////////////////////////////////////// void SummonMigaAttack::execute(Monster* pMonster) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pMonster != NULL); try { Zone* pZone = pMonster->getZone(); Assert(pZone != NULL); //GCSkillToSelfOK2 _GCSkillToSelfOK2; ZoneCoord_t x = pMonster->getX(); ZoneCoord_t y = pMonster->getY(); bool bRangeCheck = checkZoneLevelToUseSkill(pMonster); if (bRangeCheck) { //-------------------------------------------------------- // 주위에 knockback되는맞는 애들을 체크해준다. //-------------------------------------------------------- SkillInput input(pMonster); SkillOutput output; computeOutput(input, output); SIMPLE_SKILL_INPUT param; param.SkillType = getSkillType(); param.SkillDamage = output.Damage; param.Delay = output.Delay; param.ItemClass = Item::ITEM_CLASS_MAX; param.STRMultiplier = 0; param.DEXMultiplier = 0; param.INTMultiplier = 0; param.bMagicHitRoll = true; param.bMagicDamage = true; param.bAdd = false; SIMPLE_SKILL_OUTPUT result; for (int i=-1; i<=1; ++i ) for (int j=-1; j<=1; ++j ) param.addMask(i, j, 100); g_SimpleTileMissileSkill.execute(pMonster, x, y, param, result, 0, false); if (result.bSuccess ) { // pMonster->setHP(0); EffectKillTimer* pEffect = new EffectKillTimer(pMonster); pEffect->setDeadline(8); pMonster->addEffect(pEffect); } else cout << "미가 자폭 실패" << endl; } else { executeSkillFailNormal(pMonster, getSkillType(), NULL); } } catch(Throwable & t) { executeSkillFailException(pMonster, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }