#include "stdafx.h" #include "Player_Common.h" #include "ObjectManager.h" #include "SkillManager.h" #include "BaseObject.h" #include "DamageCalc.h" #include "Protocol.h" #include "Player.h" #include "Monster.h" #include "gamesrv.h" #include "Drop.h" #include "GridManager.h" #include "AIManager.h" #include "StageScript.h" cMonsterSkillObject::cMonsterSkillObject() { mMonsterClassIdx = 0; } cMonsterSkillObject::~cMonsterSkillObject() { } void* cMonsterSkillObject::operator new( size_t n ) { if( n != sizeof(cMonsterSkillObject) ) { assert(0); return NULL; } return SKILLMANAGER->AllocMonsterSkillObject(); } void cMonsterSkillObject::operator delete( void* ptr, size_t n ) { /// NULL Æ÷ÀÎÅÍ °Ë»ç if( ptr == 0 ) { assert(0); return; } if( n != sizeof(cMonsterSkillObject) ) { assert(0); return; } SKILLMANAGER->FreeMonsterSkillObject( static_cast(ptr) ); return; } bool cMonsterSkillObject::InitMonsterAttack( unsigned long monsterIdx, unsigned long monsterClassIdx, eMONSTERATTACK_TYPE attackType, sObject target, unsigned long uniqueIdx, bool casting, float speedFactor, unsigned long mapNumber ) { /// °íÀ¯ idx ¼ÂÆÃ mUniqueIdx = uniqueIdx; /// ¸ó½ºÅÍ À妽º mMonsterClassIdx = monsterClassIdx; mDramaKey = monsterClassIdx; /// ½ºÅ³idxÀÇ °ªÀ» ¼ÂÆÃ. mSkillIdx = attackType; mMapNumber = mapNumber; /// °ø°ÝÀÚ ¼ÂÆÃ mAttacker.index = monsterIdx; mAttacker.type = eOBJECTTYPE_MONSTER; mSpeedFactor = speedFactor; /// Ÿ°Ù ¼ÂÆÃ mCenterTarget = target; /// ½ºÅ³ ¿ÀºêÁ§Æ® »ý¼º ½Ã°£ mCreationTime = NETWORK2->GetAccumTime(); cMonster* pMonster = OBJECTMANAGER->GetMonster( monsterIdx ); if( pMonster == NULL ) { /// ½ºÅ³ Á¦°Å assert(NULL); NETWORK2->PostServerEvent("InitMonsterAttack - pMonster == NULL"); return false; } /// ¿¬Ãâ ½ºÅ©¸³Æ® ÆÄÀÏ¿¡¼­ ½Ã°£ °ªÀ» Àоî¿È cDramaturgyInfo* pDramaInfo = DRAMATURGYMAN->GetMonsterDramaturgyInfo( mMonsterClassIdx, (eMONSTERATTACK_TYPE)mSkillIdx ); if( pDramaInfo == NULL ) { /// ½ºÅ³ Á¦°Å assert(NULL); NETWORK2->PostServerEvent("InitMonsterAttack - pDramaInfo == NULL"); return false; } sDramaState* pDramaState = pDramaInfo->GetDramaState(); if( pDramaState == NULL ) { assert(NULL); NETWORK2->PostServerEvent("InitMonsterAttack, GetDramaState error [%d,%d]", mMonsterClassIdx, (eMONSTERATTACK_TYPE)mSkillIdx ); return false; } mDetailCnt = pDramaState->GetDamageCount(); mpDetailBegin = (sDramaAction*)pDramaState->GetDamageBegin(); mpDetailEnd = (sDramaAction*)pDramaState->GetDamageEnd(); /// ½ºÅ©¸³Æ® °Ë»ç if( mDetailCnt >= 10 ) return false; /// ¹ß»çü À¯¹« mIsProjectile = pDramaInfo->IsBullet(); /// ¹ß»çü ¼Óµµ mProjectileSpeed = pDramaInfo->GetBulletSpeed(); /// ¹ßµ¿ Á¾·á½Ã°£ mActivityTime = pDramaInfo->GetActivityEndTime(); /// °ø°Ý ½ÃÀÛÀ§Ä¡ = ¹ß»ç¹° ½ÃÀÛÀ§Ä¡ mProjectilePos = pMonster->GetPos(); /// ¹ß»ç¹° Ÿ°ÙÀ§Ä¡¸¦ ½ÃÀüÀÚ ±âÁØ ¹üÀ§·Î ¹ß»ç¹° ó¸®ÇÒ´ë ¸ñÀûÁöÁ¡À» ¹Ù²Û´Ù. mCenterPos.x = pMonster->GetXPos(); mCenterPos.y = pMonster->GetYPos(); mCenterPos.z = pMonster->Height(); sMonsterSkillScript* pMonsterSkill = SKILLSCRIPT->GetMonsterSkillInfo( mMonsterClassIdx, attackType ); if( pMonsterSkill == NULL ) { NETWORK2->PostServerEvent("cMonsterSkillObject::InitMonsterAttack pMonsterSkill[%d,%d] == NULL", mMonsterClassIdx, attackType); return false; } if( mDetailCnt > 1 ) { if( pMonsterSkill->mApplyValueType1 == eSTATUSPLUS_AROUND_PUSH ) return false; if( pMonsterSkill->mApplyValueType1 == eSTATUSPLUS_AROUND_PULL ) return false; if( pMonsterSkill->mApplyValueType2 == eSTATUSPLUS_AROUND_PUSH ) return false; if( pMonsterSkill->mApplyValueType2 == eSTATUSPLUS_AROUND_PULL ) return false; if( pMonsterSkill->mApplyValueType2 == eSTATUSPLUS_TARGET_PUSH ) return false; } /// Ÿ°Ù ÇØÁ¦ ½ºÅ³ if( pMonsterSkill->mApplyValueType1 == eSTATUSPLUS_DELETE_TARGETING || pMonsterSkill->mApplyValueType2 == eSTATUSPLUS_DELETE_TARGETING ) mCreateType = eSKILLCREATETYPE_DELTARGET; if( pMonsterSkill->mShotType == eMONSTERSHOTTYPE_SPOT ) mCastingTime = 0; else mCastingTime = pMonsterSkill->mCastingTime; if( casting == true ) mSkillState = eSKILLPROCESS_CASTING; else mSkillState = eSKILLPROCESS_ACTIVITY; mAttributeType = pMonsterSkill->mAttributeType; /// °ø°ÝÀÚ ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. cPlayer* pPlayer = GRIDMANAGER->FindFirstPlayer( pMonster, true ); while( pPlayer != NULL ) { mSendAroundSet.Insert( pPlayer->GetObjectID() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } return true; } bool cMonsterSkillObject::InitMonsterSkillPosition( unsigned long monsterIdx, unsigned long monsterClassIdx, eMONSTERATTACK_TYPE attackType, float targetXPos, float targetYPos, unsigned long uniqueIdx, bool casting, unsigned long mapNumber ) { /// °íÀ¯ idx ¼ÂÆÃ mUniqueIdx = uniqueIdx; /// ¸ó½ºÅÍ À妽º mMonsterClassIdx = monsterClassIdx; mDramaKey = monsterClassIdx; /// ½ºÅ³idxÀÇ °ªÀ» ¼ÂÆÃ. mSkillIdx = attackType; mMapNumber = mapNumber; /// °ø°ÝÀÚ ¼ÂÆÃ mAttacker.index = monsterIdx; mAttacker.type = eOBJECTTYPE_MONSTER; /// Ÿ°Ù¿ÀºêÁ§Æ®´Â ¾ø´Ù. mCenterTarget.index = 0; mCenterTarget.type = eOBJECTTYPE_NONE; /// ½ºÅ³ ¿ÀºêÁ§Æ® »ý¼º ½Ã°£ mCreationTime = NETWORK2->GetAccumTime(); cMonster* pMonster = OBJECTMANAGER->GetMonster( monsterIdx ); if( pMonster == NULL ) { NETWORK2->PostServerEvent("cMonsterSkillObject::InitMonsterSkillPosition pMonster == NULL[%d]", mMonsterClassIdx ); return false; } /// ¿¬Ãâ ½ºÅ©¸³Æ® ÆÄÀÏ¿¡¼­ ½Ã°£ °ªÀ» Àоî¿È cDramaturgyInfo* pDramaInfo = DRAMATURGYMAN->GetMonsterDramaturgyInfo( mMonsterClassIdx, attackType ); if( pDramaInfo == NULL ) { /// ½ºÅ³ Á¦°Å NETWORK2->PostServerEvent("cMonsterSkillObject::InitMonsterSkillPosition - pDramaInfo == NULL[%d]", mMonsterClassIdx ); return false; } sDramaState* pDramaState = pDramaInfo->GetDramaState(); if( pDramaState == NULL ) { assert(NULL); NETWORK2->PostServerEvent("cMonsterSkillObject::InitMonsterSkillPosition pDramaState == NULL[%d,%d]", mMonsterClassIdx, mSkillIdx ); return false; } mDetailCnt = pDramaState->GetDamageCount(); mpDetailBegin = (sDramaAction*)pDramaState->GetDamageBegin(); mpDetailEnd = (sDramaAction*)pDramaState->GetDamageEnd(); /// ½ºÅ©¸³Æ® °Ë»ç if( mDetailCnt >= 10 ) return false; /// ¹ß»çü À¯¹« mIsProjectile = pDramaInfo->IsBullet(); /// ¹ß»çü ¼Óµµ mProjectileSpeed = pDramaInfo->GetBulletSpeed(); /// ¹ßµ¿ Á¾·á½Ã°£ mActivityTime = pDramaInfo->GetActivityEndTime(); /// °ø°Ý ½ÃÀÛÀ§Ä¡ = ¹ß»ç¹° ½ÃÀÛÀ§Ä¡ mProjectilePos = pMonster->GetPos(); /// ±âÁØÁÂÇ¥ ¼ÂÆÃ mCenterPos.x = targetXPos; mCenterPos.y = targetYPos; AIMANAGER->CalcHeight( pMonster->GetMapNumber(), &mCenterPos.z, mCenterPos.x, mCenterPos.y ); sMonsterSkillScript* pMonsterSkill = SKILLSCRIPT->GetMonsterSkillInfo( mMonsterClassIdx, attackType ); if( pMonsterSkill == NULL ) { NETWORK2->PostServerEvent("cMonsterSkillObject::InitMonsterAttack pMonsterSkill[%d,%d] == NULL", mMonsterClassIdx, attackType); return false; } if( mDetailCnt > 1 ) { if( pMonsterSkill->mApplyValueType1 == eSTATUSPLUS_AROUND_PUSH ) return false; if( pMonsterSkill->mApplyValueType1 == eSTATUSPLUS_AROUND_PULL ) return false; if( pMonsterSkill->mApplyValueType2 == eSTATUSPLUS_AROUND_PUSH ) return false; if( pMonsterSkill->mApplyValueType2 == eSTATUSPLUS_AROUND_PULL ) return false; if( pMonsterSkill->mApplyValueType2 == eSTATUSPLUS_TARGET_PUSH ) return false; } if( pMonsterSkill->mShotType == eMONSTERSHOTTYPE_SPOT ) mCastingTime = 0; else mCastingTime = pMonsterSkill->mCastingTime; if( casting == true ) mSkillState = eSKILLPROCESS_CASTING; else mSkillState = eSKILLPROCESS_ACTIVITY; mAttributeType = pMonsterSkill->mAttributeType; /// °ø°ÝÀÚ ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. cPlayer* pPlayer = GRIDMANAGER->FindFirstPlayer( pMonster, true ); while( pPlayer != NULL ) { mSendAroundSet.Insert( pPlayer->GetObjectID() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } return true; } bool cMonsterSkillObject::CastingObjectCheck( cBaseObject* pAttacker ) { unsigned char errorCode = FAIL_SKILL_CASTING_DONT_TARGET; /// »ýÁ¸ ¿©ºÎ È®ÀÎ if( pAttacker->GetStateDie() == false ) { sMonsterSkillScript* pSkillInfo = SKILLSCRIPT->GetMonsterSkillInfo( mMonsterClassIdx, (eMONSTERATTACK_TYPE)mSkillIdx ); if( pSkillInfo != NULL ) { if( pAttacker->IsCantSkill( pSkillInfo->mAttributeType ) == false ) { /// ¹üÀ§ ¹æ½Ä¿¡ µû¸¥ Ÿ°Ù °´Ã¼ È®ÀÎ ¿©ºÎ switch( pSkillInfo->mBoundType ) { case eBOUNDTYPE_SELF_NOTARGET: case eBOUNDTYPE_FIELD: return true; case eBOUNDTYPE_NONE: /// ¹üÀ§ ¾øÀ½ case eBOUNDTYPE_TARGET: /// Ÿ°Ù ±âÁعüÀ§ case eBOUNDTYPE_SELF_TARGET: /// ½ÃÀüÀÚ(ÀÚ½Å) ±âÁعüÀ§ - ¹ßµ¿½Ã Ÿ°Ù Á¸Àç { /// ÀÚ½ÅÀÌ Àû¿ë ´ë»óÀÌ¸é ¸®ÅÏ if( pSkillInfo->mApplyType == eAPPLYTYPE_SELF ) return true; } } /// Ÿ°Ù °´Ã¼ üũ cBaseObject* pTarget = OBJECTMANAGER->GetObject( mCenterTarget.type, mCenterTarget.index ); if( pTarget != NULL && pTarget->GetStateDie() == false ) return true; } else errorCode = FAIL_SKILL_CASTING_DONT_OBSTACLE; } else { NETWORK2->PostServerEvent("cMonsterSkillObject[%d]::CastingObjectCheck pSkillInfo[%d,%d] == NULL", pAttacker->GetObjectID(), mMonsterClassIdx, mSkillIdx); errorCode = FAIL_SKILL_CASTING_DONT_SCRIPT; } } else errorCode = FAIL_SKILL_CASTING_DONT_ATTACKER; /// ij½ºÆÃ ¹ßµ¿ ½ÇÆÐ ¸Þ¼¼Áö Àü¼Û MSG_SYN_SKILL_CAST_ACTIVITY_FAIL failMsg; failMsg.Category = NM_SKILL; failMsg.Protocol = NM_SKILL_CAST_ACTIVITY_FAIL_SYN; failMsg.mAttacker = mAttacker; failMsg.mSkillIndex = mUniqueIdx; failMsg.mFailCode = errorCode; NETWORK2->QuickSend( pAttacker, (char*)&failMsg, sizeof(failMsg) ); /// Á¶°ÇÀÌ ¸¸Á·ÇÏ´Â °æ¿ì »ó´Ü¿¡ return true·Î ºüÁ®³ª°¨ ¿©±â±îÁö ¿Â°æ¿ì Á¶°ÇÀ» ¸¸Á· ¸øÇÏ´Â °æ¿ìÀÓ return false; } /// ÁÖÀÇ : ij½ºÆÃ ÇÏ´Â °æ¿ì¸¸ ÀÌÇÔ¼ö·Î µé¾î¿È bool cMonsterSkillObject::RequireValue( cBaseObject* pAttacker ) { sMonsterSkillScript* pSkillInfo = SKILLSCRIPT->GetMonsterSkillInfo( mMonsterClassIdx, (eMONSTERATTACK_TYPE)mSkillIdx ); /// ¼Ò¸ð üũ if( pAttacker->GetMP() < pSkillInfo->mUseMP ) { /// ij½ºÆÃ ¹ßµ¿ ½ÇÆÐ ¸Þ¼¼Áö Àü¼Û MSG_SYN_SKILL_CAST_ACTIVITY_FAIL failMsg; failMsg.Category = NM_SKILL; failMsg.Protocol = NM_SKILL_CAST_ACTIVITY_FAIL_SYN; failMsg.mSkillIndex = mUniqueIdx; failMsg.mFailCode = FAIL_SKILL_CASTING_MP_EMPTY; NETWORK2->QuickSend( pAttacker, (char*)&failMsg, sizeof(failMsg) ); return false; } /// MP¸¦ ¼Ò¸ð ÇÏ´Â ½ºÅ³ if( pSkillInfo->mUseMP != 0 ) pAttacker->MPUse( pSkillInfo->mUseMP, false ); ((cMonster*)pAttacker)->UpdateSkillCoolTime( (eMONSTERATTACK_TYPE)mSkillIdx ); /// ij½ºÆÃ ½ºÅ³ ¹ßµ¿À» ¾Ë¸®´Â ½ÌÅ© Àü¼Û MSG_SYN_SKILL_CAST_ACTIVE msgEtc; msgEtc.Category = NM_SKILL; msgEtc.Protocol = NM_SKILL_CAST_ACTIVE_SYN; msgEtc.mSkillIndex = mUniqueIdx; msgEtc.mAttacker = mAttacker; msgEtc.mAttackerPosX = pAttacker->GetXPos(); msgEtc.mAttackerPosY = pAttacker->GetYPos(); NETWORK2->QuickSendExcept( pAttacker, (char*)&msgEtc, sizeof(msgEtc) ); return true; } bool cMonsterSkillObject::SetCenterPos() { sMonsterSkillScript* pSkillInfo = SKILLSCRIPT->GetMonsterSkillInfo( mMonsterClassIdx, (eMONSTERATTACK_TYPE)mSkillIdx ); /// µ¥¹ÌÁö Àû¿ë½Ã ±âÁØÀÌ µÉ À§Ä¡ÁÂÇ¥ »êÃâ switch( pSkillInfo->mBoundType ) { case eBOUNDTYPE_NONE: /// ¹üÀ§ °ø°ÝÀÌ ¾Æ´Ô case eBOUNDTYPE_TARGET: /// Ÿ°Ù ±âÁعüÀ§ { /// »ç°Å¸® üũ ´ë»óÀÌ ½ÃÀüÀÚÀΰæ¿ì ÇÊ¿ä ¾øÀ½ if( pSkillInfo->mApplyType != eAPPLYTYPE_SELF ) { cBaseObject* pObject = OBJECTMANAGER->GetObject( mCenterTarget.type, mCenterTarget.index ); /// ¹ßµ¿ Àü¿¡ Ÿ°ÙÀÌ »ç¶óÁø°æ¿ì µ¥¹ÌÁö ¹Ì½º if( pObject == NULL || pObject->GetMapNumber() != mMapNumber ) return false; mCenterPos.x = pObject->GetXPos(); mCenterPos.y = pObject->GetYPos(); mCenterPos.z = pObject->Height(); } }break; } return true; } void cMonsterSkillObject::TargetSelect( cBaseObject* pAttacker ) { sMonsterSkillScript* pSkillInfo = SKILLSCRIPT->GetMonsterSkillInfo( mMonsterClassIdx, (eMONSTERATTACK_TYPE)mSkillIdx ); if( pSkillInfo == NULL ) { assert(NULL); NETWORK2->PostServerEvent("cMonsterSkillObject[%d]::TargetSelect pSkillInfo[%d,%d] == NULL", pAttacker->GetObjectID(), mMonsterClassIdx, mSkillIdx ); SKILLMANAGER->InsertDeleteSkillObject( mAttacker, mUniqueIdx ); return; } /// ¹ß»çüÁß Å¸°ÙÀ» ÇâÇØ ³¯¾Æ °¡´Ù Ÿ°ÙÀÌ »ç¶óÁø°æ¿ì µ¥¹ÌÁö ¹Ì½ºÃ³¸® ¿©ºÎ if( mNoTargetNoDamage == true ) return; unsigned char targetMaxCnt = pSkillInfo->mApplyCnt; if( targetMaxCnt == 0 || targetMaxCnt > TARGET_CNT_MAX ) targetMaxCnt = TARGET_CNT_MAX; else { /// Àû¿ë ÀοøÀÌ Á¦ÇÑµÈ °æ¿ì °ø°ÝÀÚ°¡ ¹üÀ§ ½ºÅ³ Àû¿ë Àοø Áõ°¡ È¿°ú¿¡ °É·ÁÀÖ´ÂÁö üũ ÇÏ¿© ³Ö±â if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER || pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER ) { long addApplyCnt = (long)pAttacker->GetStateOddity( eODDITYTYPE_ADD_APPLY_CNT ); if( addApplyCnt > 0 ) { if( (addApplyCnt + targetMaxCnt) > UCHAR_MAX ) { assert(0); targetMaxCnt = TARGET_CNT_MAX; } else { targetMaxCnt = targetMaxCnt + (unsigned char)addApplyCnt; if ( targetMaxCnt > TARGET_CNT_MAX ) { assert(0); targetMaxCnt = TARGET_CNT_MAX; } } } } } bool applyHP = pSkillInfo->mType == eMONSTERSKILLTYPE_MPDAMAGE ? false : true; /// Ÿ°Ù ¼±Á¤ if( pSkillInfo->mBoundType != eBOUNDTYPE_NONE ) { switch( pSkillInfo->mApplyType ) { case eAPPLYTYPE_SELF: { //sMultiTarget multiTarget; //multiTarget.mTarget.type = eOBJECTTYPE_PLAYER; //multiTarget.mTarget.index = pAttacker->GetObjectID(); ////multiTarget.mApplyHP = applyHP; //mTargetAry.PushBack( multiTarget ); sObject object = { eOBJECTTYPE_PLAYER, pAttacker->GetObjectID() }; SKILLTARGETPOOL->AddSkillTarget( &mTargetRoot, object ); } break; case eAPPLYTYPE_BUDDY: { //mTargetAry.Clear(); unsigned char targetCnt = 0; SelectMonsterTarget( pAttacker, mCenterPos, pSkillInfo->mBoundDist1, pSkillInfo->mBoundDist2, &targetCnt, targetMaxCnt, applyHP, pSkillInfo->mBoundType ); //float tempRange = OBJECTMANAGER->ObjectSizeRange( pAttacker, NULL, pSkillInfo->mBoundDist1 ); ///// ¹üÀ§ °ø°ÝÀΰæ¿ì //OBJECTMANAGER->MonsterInCenterPoint( pAttacker->GetMapNumber(), mCenterPos, tempRange, &mTargetAry, applyHP, targetMaxCnt ); }break; case eAPPLYTYPE_ENEMY: case eAPPLYTYPE_FAR: case eAPPLYTYPE_RANDOM: case eAPPLYTYPE_DISTRESS2: case eAPPLYTYPE_DISTRESS3: case eAPPLYTYPE_DISTRESSMIN: case eAPPLYTYPE_HPMAX: case eAPPLYTYPE_HPMIN: { //mTargetAry.Clear(); unsigned char targetCnt = 0; SelectPlayerTarget( pAttacker, mCenterPos, pSkillInfo->mBoundDist1, pSkillInfo->mBoundDist2, &targetCnt, targetMaxCnt, applyHP, true, pSkillInfo->mBoundType ); //float tempRange = OBJECTMANAGER->ObjectSizeRange( pAttacker, NULL, pSkillInfo->mBoundDist1 ); ///// ¹üÀ§ °ø°ÝÀΰæ¿ì //OBJECTMANAGER->PlayerInCenterPoint( pAttacker->GetMapNumber(), mCenterPos, tempRange, &mTargetAry, applyHP, targetMaxCnt ); }break; } } else { //sMultiTarget multiTarget; //multiTarget.mTarget = mCenterTarget; ////multiTarget.mApplyHP = applyHP; //mTargetAry.PushBack( multiTarget ); SKILLTARGETPOOL->AddSkillTarget( &mTargetRoot, mCenterTarget ); } } void cMonsterSkillObject::ApplyDamage( cBaseObject* pAttacker ) { sMonsterSkillScript* pSkillInfo = SKILLSCRIPT->GetMonsterSkillInfo( mMonsterClassIdx, (eMONSTERATTACK_TYPE)mSkillIdx ); if( pSkillInfo == NULL ) { assert(NULL); NETWORK2->PostServerEvent("cMonsterSkillObject[%d]::ApplyDamage pSkillInfo[%d,%d] == NULL", pAttacker->GetObjectID(), mMonsterClassIdx, mSkillIdx ); SKILLMANAGER->InsertDeleteSkillObject( mAttacker, mUniqueIdx ); return; } /// ŸÀÔº° µ¥¹ÌÁö ó¸® switch( pSkillInfo->mType ) { case eMONSTERSKILLTYPE_DAMAGE: { SendDamage( pAttacker, pSkillInfo->mShotType, pSkillInfo->mAttributeType, pSkillInfo->mRangeType, pSkillInfo->mApplyValueType1, pSkillInfo->mApplyValueType2, pSkillInfo->mApplyValue1, pSkillInfo->mApplyValue2, pSkillInfo->mInfulenceIdx, pSkillInfo->mAccuracyValue, pSkillInfo->mCriticalValue, true ); } break; case eMONSTERSKILLTYPE_HEAL: { SendHeal( pAttacker, pSkillInfo->mShotType, pSkillInfo->mApplyValueType1, pSkillInfo->mApplyValueType2, pSkillInfo->mApplyValue1, pSkillInfo->mApplyValue2, pSkillInfo->mInfulenceIdx ); } break; case eMONSTERSKILLTYPE_NONACTIVE: { if( mCreateType == eSKILLCREATETYPE_DELTARGET ) { SendDelTarget( pAttacker, pSkillInfo->mAccuracyValue ); } else { SendApply( pAttacker, pSkillInfo->mShotType, pSkillInfo->mAttributeType, pSkillInfo->mAccuracyValue, pSkillInfo->mApplyValueType1, pSkillInfo->mApplyValueType2, pSkillInfo->mApplyValue1, pSkillInfo->mApplyValue2, pSkillInfo->mInfulenceIdx ); } } break; case eMONSTERSKILLTYPE_MPDAMAGE: { SendDamage( pAttacker, pSkillInfo->mShotType, pSkillInfo->mAttributeType, pSkillInfo->mRangeType, pSkillInfo->mApplyValueType1, pSkillInfo->mApplyValueType2, pSkillInfo->mApplyValue1, pSkillInfo->mApplyValue2, pSkillInfo->mInfulenceIdx, pSkillInfo->mAccuracyValue, pSkillInfo->mCriticalValue, false ); } break; case eMONSTERSKILLTYPE_TOTEM: { unsigned char targetMaxCnt = pSkillInfo->mApplyCnt; if( targetMaxCnt == 0 || targetMaxCnt > TARGET_CNT_MAX ) targetMaxCnt = TARGET_CNT_MAX; else { /// Àû¿ë ÀοøÀÌ Á¦ÇÑµÈ °æ¿ì °ø°ÝÀÚ°¡ ¹üÀ§ ½ºÅ³ Àû¿ë Àοø Áõ°¡ È¿°ú¿¡ °É·ÁÀÖ´ÂÁö üũ ÇÏ¿© ³Ö±â if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER || pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER ) { long addApplyCnt = (long)pAttacker->GetStateOddity( eODDITYTYPE_ADD_APPLY_CNT ); if( addApplyCnt > 0 ) { if( (addApplyCnt + targetMaxCnt) > UCHAR_MAX ) { assert(0); targetMaxCnt = TARGET_CNT_MAX; } else { targetMaxCnt = targetMaxCnt + (unsigned char)addApplyCnt; if ( targetMaxCnt > TARGET_CNT_MAX ) { assert(0); targetMaxCnt = TARGET_CNT_MAX; } } } } } AddTotem( pAttacker, 0, 0, pSkillInfo->mApplyType, pSkillInfo->mAttributeType, pSkillInfo->mInfulenceIdx, targetMaxCnt ); } break; } }