#include "stdafx.h" #include "BaseSkillObject.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 "DuelManager.h" #include "GridManager.h" #include "UserPortal.h" #include "StageScript.h" #include "Player.h" #include "Monster.h" #include "Party.h" #include "PartyManager.h" #include "MonsterScript.h" cBaseSkillObject::cBaseSkillObject() { mUniqueIdx = 0; mAttacker.index = 0; mAttacker.index = eOBJECTTYPE_NONE; mCenterTarget.index = 0; mCenterTarget.index = eOBJECTTYPE_NONE; mIsProjectile = false; mActivityTime = 0; mSpeedFactor = 1.0f; mNoTargetNoDamage = false; mMapNumber = 0; mDetailPos = 0; mDetailEndTime = 0; mIsChgMonsSkill = false; mAttackerDie = 0; mCreateType = eSKILLCREATETYPE_NORMAL; mUseItemIdx = 0; mDistressPoint = 0; mDelTarget = false; mAttributeType = eATTRIBUTETYPE_PHYSICAL; mSendAttackerSet.Clear(); mSendTargetSet.Clear(); mSendAroundSet.Clear(); mPushPull = 0; mPushRange = 0; mCashMapNum = 0; mCashX = 0.0f; mCashY = 0.0f; mIsChanneling = false; mpChannelDramaState = 0; mChannelingTime = 0; } cBaseSkillObject::~cBaseSkillObject() { SKILLMANAGER->DelSkillUniqueIdx( mUniqueIdx ); PerNode* node = mTargetRoot.pool; while ( node != NULL ) { sSkillTargetInfo* pInfo = (sSkillTargetInfo*)node; node = node->next; SKILLTARGETPOOL->ReleaseSkillTarget( &mTargetRoot, pInfo ); } } void cBaseSkillObject::Process( unsigned long elapsedTime, unsigned long accumTime ) { /// °ø°ÝÀÚ°¡ ¾ø´Â °æ¿ì this¿ÀºêÁ§Æ®¸¦ »èÁ¦ ¸®½ºÆ®¿¡ ³ÖÀ½ cBaseObject* pAttacker = OBJECTMANAGER->GetObject( mAttacker.type, mAttacker.index ); if( pAttacker == NULL || mMapNumber != pAttacker->GetMapNumber() ) { AttackerNullDamage(); /// ¼Ò¸ê ÇÁ·Î¼¼½º ¼öÇà mSkillState = eSKILLPROCESS_DESTRUCTION; } if( mIsChanneling ) { /// ä³Î¸µ Áö¼Ó ½Ã°£ üũ. if( mChannelingTime <= accumTime ) { /// ½ºÅ³ »èÁ¦ ¸Þ½ÃÁö º¸³»±â if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER || pAttacker->GetObjectType() == eOBJECTTYPE_HERO ) { cPlayer* pPlayer = (cPlayer*)pAttacker; if( pPlayer->ChangeState( eOBJECT_STATE_IDLE ) == false ) { if( pPlayer->GetStateDie() == false ) { NETWORK2->PostServerEvent("cBaseSkillObject::Process ChannelingSkillCancel pAttacker[%d,%d,%d,%d]->ChangeState( eOBJECT_STATE_IDLE ) == false", mAttacker.index, pPlayer->GetState(), pPlayer->GetStateStop(), pPlayer->GetRequestRejection() ); } } } /// ij½ºÆÃ ¹ßµ¿ ½ÇÆÐ ¸Þ¼¼Áö Àü¼Û MSG_RES_CHANNELING_SKILL_CANCEL synSkillEnd; synSkillEnd.Category = NM_SKILL; synSkillEnd.Protocol = NM_SKILL_CAST_ACTIVITY_FAIL_SYN; synSkillEnd.mUniqueSkillIndex = mUniqueIdx; NETWORK2->QuickSend( pAttacker, (char*)&synSkillEnd, sizeof(synSkillEnd) ); mSkillState = eSKILLPROCESS_DESTRUCTION; } } /// ij½ºÆÃ if( mSkillState == eSKILLPROCESS_CASTING ) { /// ij½ºÆÃ½Ã °ø°ÝÀÚ / Ÿ°Ù °´Ã¼ üũ if( CastingObjectCheck( pAttacker ) == false ) mSkillState = eSKILLPROCESS_DESTRUCTION; /// ij½ºÆÃ ³¡³¯¶§±îÁö ·çÇÁ /// ¡Ø À§¿¡¼­ Á×¾ú´Ù¶ó°í ÆÇÁ¤À̳ªµµ ½ÇÁ¦ ¹ßµ¿ ½Ã°£À» Ã¼Å©ÇØ¼­ ¹ßµ¿ °¡´É½Ã°£ÀÌ¸é ¹ßµ¿ if( mCastingTime <= accumTime - mCreationTime ) { /// ¼Ò¸ð Ç׸ñ Àû¿ë if( RequireValue( pAttacker ) == true ) mSkillState = eSKILLPROCESS_ACTIVITY; /// ¹ßµ¿ else mSkillState = eSKILLPROCESS_DESTRUCTION; /// ¼Ò¸ê } } /// ¹ßµ¿ if( mSkillState == eSKILLPROCESS_ACTIVITY ) { if( pAttacker->GetStateDie() == false ) { /// ¹ßµ¿ ³¡³¯¶§±îÁö ·çÇÁ if( mActivityTime > ( (accumTime - ( mCreationTime + mCastingTime )) * mSpeedFactor ) ) return; /// ¹ß»çü À¯¹« °Ë»ç if( mIsProjectile == true ) mSkillState = eSKILLPROCESS_PROJECTILE; /// ¹ß»çü else { if( mCreateType == eSKILLCREATETYPE_NORMAL ) SetCenterPos(); mSkillState = eSKILLPROCESS_DAMAGE; /// µ¥¹ÌÁö } } else { mSkillState = eSKILLPROCESS_DAMAGE; if( mActivityTime * 0.7 > ( (accumTime - ( mCreationTime + mCastingTime )) * mSpeedFactor ) ) mAttackerDie = 1; else mAttackerDie = 2; } if( mIsChanneling ) { /// ij½ºÆÃ½Ã °ø°ÝÀÚ / Ÿ°Ù °´Ã¼ üũ if( CastingObjectCheck( pAttacker ) == false ) mSkillState = eSKILLPROCESS_DESTRUCTION; } } /// ¹ß»çü À̵¿ if( mSkillState == eSKILLPROCESS_PROJECTILE ) { /// ¹ß»çü ¸ñÀûÁö ¼³Á¤ ///¡Ø ¹ß»çü°¡ µµ´ÞÇϱâ±îÁö ¸ñÀûÁö ÁÂÇ¥°¡ Ʋ·ÁÁú¼ö ÀÖÀ¸¹Ç·Î ¸ñÀûÁö´Â °è¼Ó üũ if( SetCenterPos() == false ) { /// Ÿ°ÙÀÌ ¾øÀ¸¸é 0µ¥¹ÌÁö ¹ß¼Û mNoTargetNoDamage = true; mSkillState = eSKILLPROCESS_DAMAGE; } else { /// ¹ß»çü À̵¿ if( IsProjectileEndProcess( elapsedTime ) == true ) mSkillState = eSKILLPROCESS_DAMAGE; /// µ¥¹ÌÁö } } /// µ¥¹ÌÁö if( mSkillState == eSKILLPROCESS_DAMAGE ) { /// Ÿ°Ù ¼±Á¤ if( mCreateType == eSKILLCREATETYPE_NORMAL ) TargetSelect( pAttacker ); /// µ¥¹ÌÁö Àû¿ë ApplyDamage( pAttacker ); mSkillState = eSKILLPROCESS_HP; /// ¼Ò¸ê } /// HPÀû¿ë if( mSkillState == eSKILLPROCESS_HP ) { /// ½Ã°£ üũ if( mDetailEndTime > accumTime ) return; /// ´õ Àû¿ë ÇÒ°ÍÀÌ ¾øÀ¸¸é ¼Ò¸ê if( ApplyHP( pAttacker ) == false ) { if( mIsChanneling == false ) mSkillState = eSKILLPROCESS_DESTRUCTION; /// ¼Ò¸ê else { mCreationTime = accumTime; if( mpChannelDramaState ) { mpDetailBegin = (sDramaAction*)mpChannelDramaState->GetDamageBegin(); mpDetailEnd = (sDramaAction*)mpChannelDramaState->GetDamageEnd(); } else mDetailCnt = 0; mSendAttackerSet.Clear(); mSendTargetSet.Clear(); mSendAroundSet.Clear(); PerNode* node = mTargetRoot.pool; while ( node != NULL ) { sSkillTargetInfo* pInfo = (sSkillTargetInfo*)node; node = node->next; SKILLTARGETPOOL->ReleaseSkillTarget( &mTargetRoot, pInfo ); } mDetailPos = 0; mSkillState = eSKILLPROCESS_ACTIVITY; } } } /// ¼Ò¸ê if( mSkillState == eSKILLPROCESS_DESTRUCTION ) { SKILLMANAGER->InsertDeleteSkillObject( mAttacker, mUniqueIdx ); return; } } bool cBaseSkillObject::IsProjectileEndProcess( unsigned long elapsedTime ) { float moveElapsedTime = (float)elapsedTime / SECOND_THOUSAND; /// ¹æÇâ ¼³Á¤ NiPoint2 dir1; dir1.x = mCenterPos.x - mProjectilePos.x; dir1.y = mCenterPos.y - mProjectilePos.y; dir1.Unitize(); /// ¼Óµµ * °æ°ú½Ã°£ ¸¸Å­ÀÇ ½ºÅ³ È¿°úÀ§Ä¡ À̵¿ NiPoint2 estimatePos; estimatePos.x = mProjectilePos.x + (mProjectileSpeed*moveElapsedTime*dir1.x); estimatePos.y = mProjectilePos.y + (mProjectileSpeed*moveElapsedTime*dir1.y); /// ¸ñÀûÁö ÁÂÇ¥¿Í ¿¹»ó À̵¿ À§Ä¡¸¦ ºñ±³ NiPoint2 dir2; dir2.x = mCenterPos.x - estimatePos.x; dir2.y = mCenterPos.y - estimatePos.y; dir2.Unitize(); /// ¿¹»ó À̵¿À§Ä¡°¡ ¸ñÀûÁö ÁÂÇ¥¸¦ ³Ñ¾î°¡¸é ¸ñÀûÁö µµ´ÞÇÒ¶§±îÁö À̵¿ if( dir1.Dot(dir2) > 0 ) { mProjectilePos = estimatePos; /// ÇÁ·Î¼¼½º °è¼Ó ¼öÇà return false; } return true; } void cBaseSkillObject::AttackerNullDamage() { cPlayer* pPlayer = NULL; PerIoContext* perIoContext = NETWORK2->GetIoContext( IOCP_REQUEST_WRITE ); MSG_SYN_SKILL_APPLY* applyMsg = NULL; /// Àû¿ë ¸Þ¼¼Áö applyMsg = (MSG_SYN_SKILL_APPLY*)perIoContext->buffer; applyMsg->Category = NM_SKILL; applyMsg->Protocol = NM_SKILL_APPLY_SYN; applyMsg->mSkillIndex = mUniqueIdx; applyMsg->mAttackerType = mAttacker.type; applyMsg->mSkillClassIndex = mSkillIdx; applyMsg->mDramaKey = mDramaKey; applyMsg->mIsChangeMonster = mIsChgMonsSkill; /// Ÿ°ÙÀÇ ¼ö¸¸Å­ µ¥¹ÌÁö °è»ê & ÅëÇÕ ¸Þ¼¼Áö ¹ß¼Û cBaseObject* pTarget = NULL; sObject target; unsigned long targetCnt = 0; PerNode* node = mTargetRoot.pool; while ( node != NULL ) { sSkillTargetInfo* pSkillTarget = (sSkillTargetInfo*)node; if( pSkillTarget == NULL ) { node = node->next; continue; } target = pSkillTarget->mTarget; switch( target.type ) { case eOBJECTTYPE_MONSTER: pTarget = GRIDMANAGER->GetMonster( target.index ); break; case eOBJECTTYPE_PLAYER: pTarget = GRIDMANAGER->GetPlayer( target.index ); break; default: pTarget = NULL; } if( pTarget == NULL ) { node = node->next; continue; } applyMsg->mApplyObject[targetCnt].mTarget = target; ++targetCnt; /// Ÿ°Ù ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. pPlayer = GRIDMANAGER->FindFirstPlayer( pTarget, true ); while( pPlayer != NULL ) { mSendAroundSet.Insert( pPlayer->GetObjectID() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } node = node->next; } applyMsg->mApplyCount = (unsigned char)targetCnt; cHashSet::cIterator begin = mSendAroundSet.Begin(); cHashSet::cIterator end = mSendAroundSet.End(); while( begin != end ) { cPlayer* pSendPlayer = GRIDMANAGER->GetPlayer( *begin++ ); if( pSendPlayer != NULL ) NETWORK2->SendToUser( pSendPlayer->GetConnectionIdx(), (char*)applyMsg, applyMsg->GetMsgLength() ); } perIoContext->offset = applyMsg->GetMsgLength(); NETWORK2->ReleaseIoContext( perIoContext ); } void cBaseSkillObject::SelectPlayerTarget( cBaseObject* pAttacker, NiPoint3 centerPos, float rangeX, float rangeY, unsigned char* pTargetCnt, unsigned long maxCnt, bool /*applyHP*/, bool enemy, eBOUNDTYPE boundType ) { if( pAttacker == NULL ) return; if( pTargetCnt == NULL ) return; mObjectIdxAry.Clear(); if( rangeY == 0 ) { GRIDMANAGER->FindPlayers( centerPos.x, centerPos.y, pAttacker->GetMapNumber(), 1600, &mObjectIdxAry ); for( unsigned long i = 0 ; i < mObjectIdxAry.GetSize() ; ++i ) { cPlayer* pTarget = OBJECTMANAGER->GetPlayer( mObjectIdxAry[i] ); if( pTarget == NULL || pTarget->GetStateDie() == true ) continue; if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER && enemy == true ) { if( pTarget->IsAttack( pAttacker->GetObjectID() ) == false ) continue; } float tempRange = OBJECTMANAGER->ObjectSizeRange( pAttacker, pTarget, rangeX ); mRangeCheck.SetRadius( tempRange ); sObject target; NiPoint3 targetPoint; targetPoint.x = pTarget->GetXPos(); targetPoint.y = pTarget->GetYPos(); targetPoint.z = pTarget->Height(); /// Ç÷¹À̾ ¹üÀ§ ¾È¿¡ µé¾î¿Ô´ÂÁö üũ if ( mRangeCheck.IsRange( mCenterPos, targetPoint ) ) { target.index = pTarget->GetObjectID(); target.type = pTarget->GetObjectType(); //sMultiTarget multiTarget; //multiTarget.mTarget = target; ////multiTarget.mApplyHP = applyHP; //mTargetAry.PushBack( multiTarget ); SKILLTARGETPOOL->AddSkillTarget( &mTargetRoot, target ); ++(*pTargetCnt); if( *pTargetCnt >= maxCnt ) return; } } } else { NiPoint2 centerPos; centerPos.x = mCenterPos.x; centerPos.y = mCenterPos.y; float direction = pAttacker->GetDirection(); float cos = cosf( direction ); float sin = sinf( direction ); /// »ç°¢¹üÀ§ À§Ä¡ °è»ê NiPoint2 rectPos[4]; if( boundType == eBOUNDTYPE_SELF_TARGET || boundType == eBOUNDTYPE_SELF_NOTARGET ) { rectPos[0].x = ( ( -rangeX * 0.5f ) * cos + ( +rangeY * 0.0f ) * sin ); rectPos[0].y = ( ( +rangeY * 0.0f ) * cos - ( -rangeX * 0.5f ) * sin ); rectPos[1].x = ( ( -rangeX * 0.5f ) * cos + ( -rangeY * 1.0f ) * sin ); rectPos[1].y = ( ( -rangeY * 1.0f ) * cos - ( -rangeX * 0.5f ) * sin ); rectPos[2].x = ( ( +rangeX * 0.5f ) * cos + ( -rangeY * 1.0f ) * sin ); rectPos[2].y = ( ( -rangeY * 1.0f ) * cos - ( +rangeX * 0.5f ) * sin ); rectPos[3].x = ( ( +rangeX * 0.5f ) * cos + ( +rangeY * 0.0f ) * sin ); rectPos[3].y = ( ( +rangeY * 0.0f ) * cos - ( +rangeX * 0.5f ) * sin ); } else { rectPos[0].x = ( ( -rangeX * 0.5f ) * cos + ( +rangeY * 0.5f ) * sin ); rectPos[0].y = ( ( +rangeY * 0.5f ) * cos - ( -rangeX * 0.5f ) * sin ); rectPos[1].x = ( ( -rangeX * 0.5f ) * cos + ( -rangeY * 0.5f ) * sin ); rectPos[1].y = ( ( -rangeY * 0.5f ) * cos - ( -rangeX * 0.5f ) * sin ); rectPos[2].x = ( ( +rangeX * 0.5f ) * cos + ( -rangeY * 0.5f ) * sin ); rectPos[2].y = ( ( -rangeY * 0.5f ) * cos - ( +rangeX * 0.5f ) * sin ); rectPos[3].x = ( ( +rangeX * 0.5f ) * cos + ( +rangeY * 0.5f ) * sin ); rectPos[3].y = ( ( +rangeY * 0.5f ) * cos - ( +rangeX * 0.5f ) * sin ); } rectPos[0] = rectPos[0] + centerPos; rectPos[1] = rectPos[1] + centerPos; rectPos[2] = rectPos[2] + centerPos; rectPos[3] = rectPos[3] + centerPos; float maxRange = rangeX > rangeY ? rangeX : rangeY; maxRange = maxRange * 1.5f; GRIDMANAGER->FindPlayers( centerPos.x, centerPos.y, pAttacker->GetMapNumber(), maxRange, &mObjectIdxAry ); for( unsigned long i = 0 ; i < mObjectIdxAry.GetSize() ; ++i ) { cPlayer* pTarget = OBJECTMANAGER->GetPlayer( mObjectIdxAry[i] ); if( pTarget == NULL || pTarget->GetStateDie() == true ) continue; if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER ) { if( pTarget->IsAttack( pAttacker->GetObjectID() ) == false ) continue; } NiPoint2 targetPoint; targetPoint.x = pTarget->GetXPos(); targetPoint.y = pTarget->GetYPos(); if( STAGESCRIPT->InsidePolygon( rectPos, 4, targetPoint ) == 1 ) continue; sObject target; target.index = pTarget->GetObjectID( ); target.type = pTarget->GetObjectType(); //sMultiTarget multiTarget; //multiTarget.mTarget = target; ////multiTarget.mApplyHP = applyHP; //mTargetAry.PushBack( multiTarget ); SKILLTARGETPOOL->AddSkillTarget( &mTargetRoot, target ); ++(*pTargetCnt); if( *pTargetCnt >= maxCnt ) return; } } mObjectIdxAry.Clear(); } void cBaseSkillObject::SelectMonsterTarget( cBaseObject* pAttacker, NiPoint3 centerPos, float rangeX, float rangeY, unsigned char* pTargetCnt, unsigned long maxCnt, bool /*applyHP*/, eBOUNDTYPE boundType ) { if( pAttacker == NULL ) return; if( pTargetCnt == NULL ) return; mObjectIdxAry.Clear(); if( rangeY == 0 ) { GRIDMANAGER->FindMonsters( centerPos.x, centerPos.y, pAttacker->GetMapNumber(), 1600, &mObjectIdxAry ); for( unsigned long i = 0 ; i < mObjectIdxAry.GetSize() ; ++i ) { cMonster* pTarget = OBJECTMANAGER->GetMonster( mObjectIdxAry[i] ); if( pTarget == NULL || pTarget->GetStateDie() == true ) continue; if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER ) { cPlayer* pPlayerAttacker = (cPlayer*)pAttacker; unsigned long attackerTeamType = pPlayerAttacker->GetPvPDMTeam(); if( ePVPDM_TEAMTYPE_MAX != attackerTeamType ) { if( attackerTeamType == pTarget->GetDMTeamType() ) continue; } } float tempRange = OBJECTMANAGER->ObjectSizeRange( pAttacker, pTarget, rangeX ); mRangeCheck.SetRadius( tempRange ); sObject target; NiPoint3 targetPoint; targetPoint.x = pTarget->GetXPos(); targetPoint.y = pTarget->GetYPos(); targetPoint.z = pTarget->Height(); /// Ç÷¹À̾ ¹üÀ§ ¾È¿¡ µé¾î¿Ô´ÂÁö üũ if ( mRangeCheck.IsRange( mCenterPos, targetPoint ) ) { target.index = pTarget->GetObjectID(); target.type = pTarget->GetObjectType(); //sMultiTarget multiTarget; //multiTarget.mTarget = target; ////multiTarget.mApplyHP = applyHP; //mTargetAry.PushBack( multiTarget ); SKILLTARGETPOOL->AddSkillTarget( &mTargetRoot, target ); ++(*pTargetCnt); if( *pTargetCnt >= maxCnt ) return; } } } else { NiPoint2 centerPos; centerPos.x = mCenterPos.x; centerPos.y = mCenterPos.y; float direction = pAttacker->GetDirection(); float cos = cosf( direction ); float sin = sinf( direction ); /// »ç°¢¹üÀ§ À§Ä¡ °è»ê NiPoint2 rectPos[4]; if( boundType == eBOUNDTYPE_SELF_TARGET || boundType == eBOUNDTYPE_SELF_NOTARGET ) { rectPos[0].x = ( ( -rangeX * 0.5f ) * cos + ( +rangeY * 0.0f ) * sin ); rectPos[0].y = ( ( +rangeY * 0.0f ) * cos - ( -rangeX * 0.5f ) * sin ); rectPos[1].x = ( ( -rangeX * 0.5f ) * cos + ( -rangeY * 1.0f ) * sin ); rectPos[1].y = ( ( -rangeY * 1.0f ) * cos - ( -rangeX * 0.5f ) * sin ); rectPos[2].x = ( ( +rangeX * 0.5f ) * cos + ( -rangeY * 1.0f ) * sin ); rectPos[2].y = ( ( -rangeY * 1.0f ) * cos - ( +rangeX * 0.5f ) * sin ); rectPos[3].x = ( ( +rangeX * 0.5f ) * cos + ( +rangeY * 0.0f ) * sin ); rectPos[3].y = ( ( +rangeY * 0.0f ) * cos - ( +rangeX * 0.5f ) * sin ); } else { rectPos[0].x = ( ( -rangeX * 0.5f ) * cos + ( +rangeY * 0.5f ) * sin ); rectPos[0].y = ( ( +rangeY * 0.5f ) * cos - ( -rangeX * 0.5f ) * sin ); rectPos[1].x = ( ( -rangeX * 0.5f ) * cos + ( -rangeY * 0.5f ) * sin ); rectPos[1].y = ( ( -rangeY * 0.5f ) * cos - ( -rangeX * 0.5f ) * sin ); rectPos[2].x = ( ( +rangeX * 0.5f ) * cos + ( -rangeY * 0.5f ) * sin ); rectPos[2].y = ( ( -rangeY * 0.5f ) * cos - ( +rangeX * 0.5f ) * sin ); rectPos[3].x = ( ( +rangeX * 0.5f ) * cos + ( +rangeY * 0.5f ) * sin ); rectPos[3].y = ( ( +rangeY * 0.5f ) * cos - ( +rangeX * 0.5f ) * sin ); } rectPos[0] = rectPos[0] + centerPos; rectPos[1] = rectPos[1] + centerPos; rectPos[2] = rectPos[2] + centerPos; rectPos[3] = rectPos[3] + centerPos; float maxRange = rangeX > rangeY ? rangeX : rangeY; maxRange = maxRange * 1.5f; GRIDMANAGER->FindMonsters( centerPos.x, centerPos.y, pAttacker->GetMapNumber(), maxRange, &mObjectIdxAry ); for( unsigned long i = 0 ; i < mObjectIdxAry.GetSize() ; ++i ) { cMonster* pTarget = OBJECTMANAGER->GetMonster( mObjectIdxAry[i] ); if( pTarget == NULL || pTarget->GetStateDie() == true ) continue; if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER ) { cPlayer* pPlayerAttacker = (cPlayer*)pAttacker; unsigned long attackerTeamType = pPlayerAttacker->GetPvPDMTeam(); if( ePVPDM_TEAMTYPE_MAX != attackerTeamType ) { if( attackerTeamType == pTarget->GetDMTeamType() ) continue; } } NiPoint2 targetPoint; targetPoint.x = pTarget->GetXPos(); targetPoint.y = pTarget->GetYPos(); if( STAGESCRIPT->InsidePolygon( rectPos, 4, targetPoint ) == 1 ) continue; sObject target; target.index = pTarget->GetObjectID( ); target.type = pTarget->GetObjectType(); //sMultiTarget multiTarget; //multiTarget.mTarget = target; ////multiTarget.mApplyHP = applyHP; //mTargetAry.PushBack( multiTarget ); SKILLTARGETPOOL->AddSkillTarget( &mTargetRoot, target ); ++(*pTargetCnt); if( *pTargetCnt >= maxCnt ) return; } } mObjectIdxAry.Clear(); } void cBaseSkillObject::AddSendTarget( unsigned long playerIdx ) { /// °ø°ÝÀÚÀ̰ųª °ø°ÝÀÚ¿Í °°ÀºÆÄƼ¸é °ø°ÝÀÚ¸Þ¼¼Áö¼Â¿¡ ³Ö¾îÁØ´Ù. if( mAttacker.type == eOBJECTTYPE_PLAYER ) { cPlayer* pAttacker = GRIDMANAGER->GetPlayer( mAttacker.index ); if( pAttacker == NULL ) return; if( mAttacker.index == playerIdx ) { mSendAttackerSet.Insert( playerIdx ); return; } cParty* pParty = NULL; if( pAttacker->GetPartyIndex() != 0 ) pParty = PARTYMAN->GetParty( pAttacker->GetPartyIndex() ); if( pParty != NULL ) { unsigned long* pPartyIdx = pParty->GetUserArr(); if( pPartyIdx == NULL ) return; unsigned long partyCnt = pParty->GetCount(); for( unsigned long i = 0 ; i < partyCnt ; ++i ) { if( pPartyIdx[i] == playerIdx ) { mSendAttackerSet.Insert( playerIdx ); return; } } } } /// Ÿ°ÙÀ̰ųª Ÿ°ÙÀÇ ÆÄƼÀ̸é Ÿ°Ù¸Þ¼¼Áö¼Â¿¡ ³Ö´Â´Ù. PerNode* node = mTargetRoot.pool; while ( node != NULL ) { sSkillTargetInfo* pSkillTarget = (sSkillTargetInfo*)node; if( pSkillTarget == NULL ) { node = node->next; continue; } sObject target = pSkillTarget->mTarget; if( target.type != eOBJECTTYPE_PLAYER ) { node = node->next; continue; } cPlayer* pTarget = GRIDMANAGER->GetPlayer( target.index ); if( pTarget == NULL ) return; if( target.index == playerIdx ) { mSendTargetSet.Insert( playerIdx ); return; } cParty* pParty = NULL; if( pTarget->GetPartyIndex() != 0 ) pParty = PARTYMAN->GetParty( pTarget->GetPartyIndex() ); if( pParty != NULL ) { unsigned long* pPartyIdx = pParty->GetUserArr(); if( pPartyIdx == NULL ) return; unsigned long partyCnt = pParty->GetCount(); for( unsigned long i = 0 ; i < partyCnt ; ++i ) { if( pPartyIdx[i] == playerIdx ) { mSendAttackerSet.Insert( playerIdx ); return; } } } node = node->next; } /// ¾î´À°÷¿¡µµ Æ÷ÇÔµÇÁö ¾ÊÀ¸¸é ÁÖº¯¸Þ¼¼Áö¼Â¿¡ ³Ö´Â´Ù. mSendAroundSet.Insert( playerIdx ); } void cBaseSkillObject::SendDamage( cBaseObject* pAttacker, unsigned long shotType, eATTRIBUTETYPE attribType, eRANGETYPE rangeType, unsigned short applyType1, unsigned short applyType2, unsigned long applyValue1, unsigned long applyValue2, unsigned long influenceClassIdx, short accuracyValue, unsigned short criticalValue, bool applyHP ) { /// °ø°ÝÀÚ ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. cPlayer* pPlayer = GRIDMANAGER->FindFirstPlayer( pAttacker, true ); while( pPlayer != NULL ) { mSendAroundSet.Insert( pPlayer->GetObjectID() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } cBaseObject* pTarget = NULL; bool allDamageKindMiss = false; /// Ç®¿¡¼­ ¸Þ¸ð¸® ÇÒ´ç PerIoContext* perIoContext = NETWORK2->GetIoContext( IOCP_REQUEST_WRITE ); if( perIoContext == NULL ) { NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage perIoContext == NULL" ); return; } MSG_SYN_SKILL_DAMAGE_ATTACKER* damageMsg = (MSG_SYN_SKILL_DAMAGE_ATTACKER*)perIoContext->buffer; damageMsg->Category = NM_SKILL; damageMsg->Protocol = NM_SKILL_DAMAGE_ATTACKER_SYN; damageMsg->mSkillIndex = mUniqueIdx; damageMsg->mAttackerType = mAttacker.type; damageMsg->mSkillClassIndex = mSkillIdx; damageMsg->mDramaKey = mDramaKey; damageMsg->mIsChangeMonster = mIsChgMonsSkill; damageMsg->mTargetCount = 0; damageMsg->mAttackerDie = mAttackerDie == 1; damageMsg->SetMsgLength( sizeof(MSG_SYN_SKILL_DAMAGE_ATTACKER) - sizeof(sTargetDamage) ); sTargetDamage* targetDamage = damageMsg->mTargetDamage; /// Ç®¿¡¼­ ¸Þ¸ð¸® ÇÒ´ç PerIoContext* perIoContext2 = NETWORK2->GetIoContext( IOCP_REQUEST_WRITE ); if( perIoContext2 == NULL ) { NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage perIoContext2 == NULL" ); return; } MSG_SYN_INFLUENCEARY_CREATE* pInfMsg = (MSG_SYN_INFLUENCEARY_CREATE*)perIoContext2->buffer; pInfMsg->Category = NM_SKILL; pInfMsg->Protocol = NM_SKILL_INFLUENCE_CREATELIST_SYN; pInfMsg->mTargetCnt = 0; sInfluenceCreate* pInf = pInfMsg->mTable; /// Ÿ°ÙÀÇ ¼ö¸¸Å­ µ¥¹ÌÁö °è»ê & ÅëÇÕ ¸Þ¼¼Áö ¹ß¼Û sObject target; unsigned long targetCnt = 0; unsigned long damage = 0; /// °è»êµÈ µ¥¹ÌÁö long attkAbsorbHPPer = pAttacker->GetStateOddity( eODDITYTYPE_HP_ABSORB ); /// °ø°ÝÀÚ HPÈí¼ö ºñÀ² long attkAbsorbMPPer = pAttacker->GetStateOddity( eODDITYTYPE_MP_ABSORB ); /// °ø°ÝÀÚ MPÈí¼ö ºñÀ² long absorbPer = 0; /// Ÿ°ÙÀÌ µ¥¹ÌÁö Èí¼ö ºñÀ² long reflectionPer = 0; /// Ÿ°ÙÀÌ µ¥¹ÌÁö ¹Ý»ç ºñÀ² long absorbPhyRangePer = 0; /// Ÿ°ÙÀÌ ¹°¸® ¿ø°Å¸® µ¥¹ÌÁö Èí¼ö ºñÀ² bool ignoreDefence = false; /// ¹æ¾î·Â ¹«½Ã. if( mAttackerDie != 1 ) { PerNode* node = mTargetRoot.pool; while ( node != NULL ) { sSkillTargetInfo* pSkillTarget = (sSkillTargetInfo*)node; if( pSkillTarget == NULL ) { node = node->next; continue; } target = pSkillTarget->mTarget; switch( target.type ) { case eOBJECTTYPE_MONSTER: pTarget = GRIDMANAGER->GetMonster( target.index ); break; case eOBJECTTYPE_PLAYER: pTarget = GRIDMANAGER->GetPlayer( target.index ); break; default: pTarget = NULL; } if( pTarget == NULL ) { node = node->next; continue; } if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER ) { if( target.type == eOBJECTTYPE_MONSTER ) { ((cPlayer*)pAttacker)->UpdateDutyActiveSkill( pTarget->GetRaceGender(), mSkillIdx ); } } pTarget->AddTakeDamage( mAttacker, 0, 2, eTAKEDAMAGETYPE_ADDPLAYER ); targetDamage->mTarget = target; unsigned long instantSkillSuccessPer = 0; unsigned long instantSkillSuccess = 0; unsigned long instantSkillCriPer = 0; unsigned long instantSkillCri = 0; unsigned long instantSkillDamagePer = 0; unsigned long instantSkillDamage = 0; /// ¸ó½ºÅÍ ¼Ó¼º/ ºÐ·ù¿¡ µû¸¥ Ãß°¡ ´ë¹ÌÁö »êÃâ [4/9/2010 Jo_Client] float addTotalDamage = 0.0f; float perTotalDamage = 1.0f; /// ½ºÅ³ÀÇ µ¥¹ÌÁö Ç׸ñ Àоî¿È switch( applyType1 ) { case 0: break; case eSTATUSPLUS_INSTANTPERHIT: instantSkillSuccessPer += applyValue1; break; case eSTATUSPLUS_INSTANTPLUSHIT: instantSkillSuccess += applyValue1; break; case eSTATUSPLUS_INSTANTPERCRI: instantSkillCriPer += applyValue1; break; case eSTATUSPLUS_INSTANTPLUSCRI: instantSkillCri += applyValue1; break; case eSTATUSPLUS_AROUND_PUSH: mPushPull = eSTATUSPLUS_AROUND_PUSH; mPushRange = applyValue1; break; case eSTATUSPLUS_AROUND_PULL: mPushPull = eSTATUSPLUS_AROUND_PULL; break; case eSTATUSPLUS_INSTANTPERATTACK: instantSkillDamagePer += applyValue1; break; case eSTATUSPLUS_INSTANTPLUSATTACK: instantSkillDamage += applyValue1; break; case eSTATUSPLUS_HPABSORB_PER: attkAbsorbHPPer += applyValue1; break; case eSTATUSPLUS_MPABSORB_PER: attkAbsorbMPPer += applyValue1; break; case eSTATUSPLUS_TARGET_PUSH: mPushPull = eSTATUSPLUS_TARGET_PUSH; mPushRange = applyValue1; break; case eSTATUSPLUS_INSTANT_IGNORE_DEFENCE: ignoreDefence = true; break; case eSTATUSPLUS_INSTANT_HUMAN_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_ANIMAL_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_PLANT_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_BUG_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_SOUL_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_UNDEAD_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_GIANT_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_DRAGON_TYPE_PER_ATTACK: if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonType = (applyType1 - eSTATUSPLUS_INSTANT_HUMAN_TYPE_PER_ATTACK ) / 2; if( pMonScriptInfo->mType == (instantMonType + 1) ) /// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ perTotalDamage += ((float)applyValue1 * 0.01f); } } } else if( pTarget->GetObjectType() == eOBJECTTYPE_MONSTER ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = ((cMonster*)pTarget)->GetMonsterInfo(); if( pMonScriptInfo ) { int instantMonType = (applyType1 - eSTATUSPLUS_INSTANT_HUMAN_TYPE_PER_ATTACK ) / 2; if( pMonScriptInfo->mType == (instantMonType + 1) ) /// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ perTotalDamage += ((float)applyValue1 * 0.01f); } } } else if( pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { /// À¯Àú°¡ ¸ó½ºÅÍ·Î º¯½ÅÇß´ÂÁö üũÇÏ¿© ¼Ó¼º µ¥¹ÌÁö ¹Ý¿µ unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonType = (applyType1 - eSTATUSPLUS_INSTANT_HUMAN_TYPE_PER_ATTACK ) / 2; if( pMonScriptInfo->mType == (instantMonType + 1) ) /// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ perTotalDamage += ((float)applyValue1 * 0.01f); } } } } break; case eSTATUSPLUS_INSTANT_NORMAL_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_VETERAN_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_ELITE_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_BOSS_TYPE_PER_ATTACK: if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonKindType = (applyType1 - eSTATUSPLUS_INSTANT_NORMAL_TYPE_PER_ATTACK) / 2; if( pMonScriptInfo->mType == instantMonKindType ) perTotalDamage += ((float)applyValue1 * 0.01f); } } } else if( pTarget->GetObjectType() == eOBJECTTYPE_MONSTER ) { /// ¸ó½ºÅÍÀÇ ºÐ·ù(eMONSTER_KIND_TYPE)¸¦ Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = ((cMonster*)pTarget)->GetMonsterInfo(); if( pMonScriptInfo ) { int instantMonKindType = (applyType1 - eSTATUSPLUS_INSTANT_NORMAL_TYPE_PER_ATTACK) / 2; if( pMonScriptInfo->mType == instantMonKindType ) perTotalDamage += ((float)applyValue1 * 0.01f); } } } else if( pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonKindType = (applyType1 - eSTATUSPLUS_INSTANT_NORMAL_TYPE_PER_ATTACK) / 2; if( pMonScriptInfo->mType == instantMonKindType ) perTotalDamage += ((float)applyValue1 * 0.01f); } } } } break; case eSTATUSPLUS_INSTANT_CHARACTER_TYPE_PER_ATTACK: { if( pTarget && (pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER || pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER) ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { /// º¯½Å ¾ÈÇÑ °æ¿ì¿¡¸¸ µ¥¹ÌÁö Ãß°¡ unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex == 0 ) { perTotalDamage += ((float)applyValue1 * 0.01f); } } } } break; case eSTATUSPLUS_INSTANT_HUMAN_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_ANIMAL_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_PLANT_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_BUG_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_SOUL_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_UNDEAD_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_GIANT_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_DRAGON_TYPE_PLUS_ATTACK: if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonType = (applyType1 - eSTATUSPLUS_INSTANT_HUMAN_TYPE_PLUS_ATTACK ) / 2; if( pMonScriptInfo->mType == (instantMonType+ 1) ) /// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ addTotalDamage += (float)applyValue1; } } } else if( pTarget->GetObjectType() == eOBJECTTYPE_MONSTER ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = ((cMonster*)pTarget)->GetMonsterInfo(); if( pMonScriptInfo ) { int instantMonType = (applyType1 - eSTATUSPLUS_INSTANT_HUMAN_TYPE_PLUS_ATTACK ) / 2; if( pMonScriptInfo->mType == (instantMonType+ 1) ) /// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ addTotalDamage += (float)applyValue1; } } } else if( pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonType = (applyType1 - eSTATUSPLUS_INSTANT_HUMAN_TYPE_PLUS_ATTACK ) / 2; if( pMonScriptInfo->mType == (instantMonType+ 1) ) /// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ addTotalDamage += (float)applyValue1; } } } } break; case eSTATUSPLUS_INSTANT_NORMAL_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_VETERAN_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_ELITE_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_BOSS_TYPE_PLUS_ATTACK: if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonKindType = (applyType1 - eSTATUSPLUS_INSTANT_NORMAL_TYPE_PLUS_ATTACK) / 2; if( pMonScriptInfo->mType == instantMonKindType ) addTotalDamage += (float)applyValue1; } } } else if( pTarget->GetObjectType() == eOBJECTTYPE_MONSTER ) { /// ¸ó½ºÅÍÀÇ ºÐ·ù(eMONSTER_KIND_TYPE)¸¦ Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = ((cMonster*)pTarget)->GetMonsterInfo(); if( pMonScriptInfo ) { int instantMonKindType = (applyType1 - eSTATUSPLUS_INSTANT_NORMAL_TYPE_PLUS_ATTACK) / 2; if( pMonScriptInfo->mType == instantMonKindType ) addTotalDamage += (float)applyValue1; } } } else if( pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonKindType = (applyType1 - eSTATUSPLUS_INSTANT_NORMAL_TYPE_PLUS_ATTACK) / 2; if( pMonScriptInfo->mType == instantMonKindType ) addTotalDamage += (float)applyValue1; } } } } break; case eSTATUSPLUS_INSTANT_CHARACTER_TYPE_PLUS_ATTACK: { if( pTarget && (pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER || pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER) ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { /// º¯½Å ¾ÈÇÑ °æ¿ì¿¡¸¸ µ¥¹ÌÁö Ãß°¡ unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex == 0 ) { addTotalDamage += (float)applyValue1; } } } } break; default: NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage applyType1[%d,%d,%d,%d,%d]", mAttacker.type, mAttacker.index, mSkillIdx, applyType1, applyValue1 ); } switch( applyType2 ) { case 0: break; case eSTATUSPLUS_INSTANTPERHIT: instantSkillSuccessPer += applyValue2; break; case eSTATUSPLUS_INSTANTPLUSHIT: instantSkillSuccess += applyValue2; break; case eSTATUSPLUS_INSTANTPERCRI: instantSkillCriPer += applyValue2; break; case eSTATUSPLUS_INSTANTPLUSCRI: instantSkillCri += applyValue2; break; case eSTATUSPLUS_AROUND_PUSH: mPushPull = eSTATUSPLUS_AROUND_PUSH; mPushRange = applyValue2; break; case eSTATUSPLUS_AROUND_PULL: mPushPull = eSTATUSPLUS_AROUND_PULL; break; case eSTATUSPLUS_INSTANTPERATTACK: instantSkillDamagePer += applyValue2; break; case eSTATUSPLUS_INSTANTPLUSATTACK: instantSkillDamage += applyValue2; break; case eSTATUSPLUS_HPABSORB_PER: attkAbsorbHPPer += applyValue2; break; case eSTATUSPLUS_MPABSORB_PER: attkAbsorbMPPer += applyValue2; break; case eSTATUSPLUS_TARGET_PUSH: mPushPull = eSTATUSPLUS_TARGET_PUSH; mPushRange = applyValue2; break; case eSTATUSPLUS_INSTANT_IGNORE_DEFENCE: ignoreDefence = true; break; case eSTATUSPLUS_INSTANT_HUMAN_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_ANIMAL_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_PLANT_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_BUG_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_SOUL_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_UNDEAD_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_GIANT_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_DRAGON_TYPE_PER_ATTACK: if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonType = (applyType1 - eSTATUSPLUS_INSTANT_HUMAN_TYPE_PER_ATTACK ) / 2; if( pMonScriptInfo->mType == (instantMonType + 1) ) /// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ perTotalDamage += ((float)applyValue1 * 0.01f); } } } else if( pTarget->GetObjectType() == eOBJECTTYPE_MONSTER ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = ((cMonster*)pTarget)->GetMonsterInfo(); if( pMonScriptInfo ) { int instantMonType = (applyType1 - eSTATUSPLUS_INSTANT_HUMAN_TYPE_PER_ATTACK ) / 2; if( pMonScriptInfo->mType == (instantMonType + 1) ) /// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ perTotalDamage += ((float)applyValue1 * 0.01f); } } } else if( pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonType = (applyType1 - eSTATUSPLUS_INSTANT_HUMAN_TYPE_PER_ATTACK ) / 2; if( pMonScriptInfo->mType == (instantMonType + 1) ) /// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ perTotalDamage += ((float)applyValue1 * 0.01f); } } } } break; case eSTATUSPLUS_INSTANT_NORMAL_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_VETERAN_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_ELITE_TYPE_PER_ATTACK: case eSTATUSPLUS_INSTANT_BOSS_TYPE_PER_ATTACK: if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonKindType = (applyType1 - eSTATUSPLUS_INSTANT_NORMAL_TYPE_PER_ATTACK) / 2; if( pMonScriptInfo->mType == instantMonKindType ) perTotalDamage += ((float)applyValue1 * 0.01f); } } } else if( pTarget->GetObjectType() == eOBJECTTYPE_MONSTER ) { /// ¸ó½ºÅÍÀÇ ºÐ·ù(eMONSTER_KIND_TYPE)¸¦ Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = ((cMonster*)pTarget)->GetMonsterInfo(); if( pMonScriptInfo ) { int instantMonKindType = (applyType1 - eSTATUSPLUS_INSTANT_NORMAL_TYPE_PER_ATTACK) / 2; if( pMonScriptInfo->mType == instantMonKindType ) perTotalDamage += ((float)applyValue1 * 0.01f); } } } else if( pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonKindType = (applyType1 - eSTATUSPLUS_INSTANT_NORMAL_TYPE_PER_ATTACK) / 2; if( pMonScriptInfo->mType == instantMonKindType ) perTotalDamage += ((float)applyValue1 * 0.01f); } } } } break; case eSTATUSPLUS_INSTANT_HUMAN_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_ANIMAL_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_PLANT_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_BUG_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_SOUL_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_UNDEAD_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_GIANT_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_DRAGON_TYPE_PLUS_ATTACK: if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonType = (applyType1 - eSTATUSPLUS_INSTANT_HUMAN_TYPE_PLUS_ATTACK ) / 2; if( pMonScriptInfo->mType == (instantMonType+ 1) ) /// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ addTotalDamage += (float)applyValue1; } } } else if( pTarget->GetObjectType() == eOBJECTTYPE_MONSTER ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = ((cMonster*)pTarget)->GetMonsterInfo(); if( pMonScriptInfo ) { int instantMonType = (applyType1 - eSTATUSPLUS_INSTANT_HUMAN_TYPE_PLUS_ATTACK ) / 2; if( pMonScriptInfo->mType == (instantMonType+ 1) ) /// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ addTotalDamage += (float)applyValue1; } } } else if( pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonType = (applyType1 - eSTATUSPLUS_INSTANT_HUMAN_TYPE_PLUS_ATTACK ) / 2; if( pMonScriptInfo->mType == (instantMonType+ 1) ) /// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ addTotalDamage += (float)applyValue1; } } } } break; case eSTATUSPLUS_INSTANT_CHARACTER_TYPE_PER_ATTACK: { if( pTarget && (pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER || pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER) ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { /// º¯½Å ¾ÈÇÑ °æ¿ì¿¡¸¸ µ¥¹ÌÁö Ãß°¡ unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex == 0 ) { perTotalDamage += ((float)applyValue1 * 0.01f); } } } } break; case eSTATUSPLUS_INSTANT_NORMAL_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_VETERAN_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_ELITE_TYPE_PLUS_ATTACK: case eSTATUSPLUS_INSTANT_BOSS_TYPE_PLUS_ATTACK: if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonKindType = (applyType1 - eSTATUSPLUS_INSTANT_NORMAL_TYPE_PLUS_ATTACK) / 2; if( pMonScriptInfo->mType == instantMonKindType ) addTotalDamage += (float)applyValue1; } } } else if( pTarget->GetObjectType() == eOBJECTTYPE_MONSTER ) { /// ¸ó½ºÅÍÀÇ ºÐ·ù(eMONSTER_KIND_TYPE)¸¦ Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = ((cMonster*)pTarget)->GetMonsterInfo(); if( pMonScriptInfo ) { int instantMonKindType = (applyType1 - eSTATUSPLUS_INSTANT_NORMAL_TYPE_PLUS_ATTACK) / 2; if( pMonScriptInfo->mType == instantMonKindType ) addTotalDamage += (float)applyValue1; } } } else if( pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER && pTarget ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { int instantMonKindType = (applyType1 - eSTATUSPLUS_INSTANT_NORMAL_TYPE_PLUS_ATTACK) / 2; if( pMonScriptInfo->mType == instantMonKindType ) addTotalDamage += (float)applyValue1; } } } } break; case eSTATUSPLUS_INSTANT_CHARACTER_TYPE_PLUS_ATTACK: { if( pTarget && (pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER || pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER) ) { if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { /// º¯½Å ¾ÈÇÑ °æ¿ì¿¡¸¸ µ¥¹ÌÁö Ãß°¡ unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex == 0 ) { addTotalDamage += (float)applyValue1; } } } } break; default: NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage applyType2[%d,%d,%d,%d,%d]", mAttacker.type, mAttacker.index, mSkillIdx, applyType2, applyValue2 ); } /// µ¥¹ÌÁö ¹«½Ã È¿°ú°¡ Àִ°æ¿ì ¶Ç üũÇÒ Çʿ䰡 ¾øÀ½ if( ignoreDefence == false ) { /// ¹°¸® µ¥¹ÌÁö ¹«½Ã È¿°ú¸¦ °¡Áö°í ÀÖ´ÂÁö üũ if( attribType == eATTRIBUTETYPE_PHYSICAL ) ignoreDefence = (pAttacker->GetStateOddity( eODDITYTYPE_IGNORE_DEFENCE_PHY ) != 0) ? true : false ; /// ¸¶¹ý µ¥¹ÌÁö ¹«½Ã È¿°ú¸¦ °¡Áö°í ÀÖ´ÂÁö üũ else if( attribType == eATTRIBUTETYPE_MAGIC ) ignoreDefence = (pAttacker->GetStateOddity( eODDITYTYPE_IGNORE_DEFENCE_MAG ) != 0) ? true : false ; } /// ¸ó½ºÅÍ ¼Ó¼º¿¡ µû¸¥ Ãß°¡ µ¥¹ÌÁö if( pTarget && pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)°ú ºÐ·ù(eMONSTER_KIND_TYPE) Àоî¿Â´Ù. unsigned char monsterType = (unsigned char)eMONSTERTYPE_MAX; unsigned char monsterKindType = (unsigned char)eMONSTER_KIND_MAX; if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { unsigned long chgMonIndex = ((cPlayer*)pTarget)->GetChgMonsterIdx(); if( chgMonIndex != 0 ) { /// ¸ó½ºÅÍÀÇ ¼Ó¼º(eMONSTER_TYPE)À» Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = MONSTERSCRIPT->GetMonsterListInfo( chgMonIndex ); if( pMonScriptInfo ) { monsterType = pMonScriptInfo->mType; monsterKindType = pMonScriptInfo->mKind; } } else { /// º¯½Å ¾ÈÇѰæ¿ì ij¸¯ÅÍ(À¯Àú)ÇüÀ¸·Î ºÐ·ù monsterType = eMONSTERTYPE_CHARACTER; } } else if( pTarget->GetObjectType() == eOBJECTTYPE_MONSTER ) { if( pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER ) NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage Monster Attacked Monster[%d,%d,%d,%d,%d]", mAttacker.type, mAttacker.index, target.index, target.type, mSkillIdx ); /// ¸ó½ºÅÍÀÇ ºÐ·ù(eMONSTER_KIND_TYPE)¸¦ Àоî¿Â´Ù. const sMonsterScript* pMonScriptInfo = ((cMonster*)pTarget)->GetMonsterInfo(); if( pMonScriptInfo ) { monsterType = pMonScriptInfo->mType; monsterKindType = pMonScriptInfo->mKind; } } if( monsterType != (unsigned char)eMONSTERTYPE_MAX ) { ePLAYER_STATUS_EXT status2Index = ePLAYER_STATUS_EXT(ePLAYER_STATUS_EXT_HUMAN_ATK + monsterType -1); if( monsterType == eMONSTERTYPE_CHARACTER ) /// ij¸¯ÅÍÇüÀÌ Ãß°¡µÇ¼­ À妽º °è»ê ½Ã ¿¹¿Ü ó¸®. [5/10/2010 Jo_Client] status2Index = ePLAYER_STATUS_EXT_CHARACTER_ATK; float status2Add = ((cPlayer*)pAttacker)->GetStatus2Plus( status2Index );/// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ addTotalDamage += status2Add; float status2Per = ((cPlayer*)pAttacker)->GetStatus2Per( status2Index );/// eMONSTER_TYPE °¡ 1ºÎÅÍ ½ÃÀÛÇØ¼­ 1À» º¸Á¤ÇØÁáÀ½ perTotalDamage += (status2Per * 0.01f); } if( monsterKindType != (unsigned char)eMONSTER_KIND_MAX ) { ePLAYER_STATUS_EXT status2Index = ePLAYER_STATUS_EXT(ePLAYER_STATUS_EXT_NORMAL_ATK + monsterKindType); float status2Add = ((cPlayer*)pAttacker)->GetStatus2Plus( status2Index ); addTotalDamage += status2Add; float status2Per = ((cPlayer*)pAttacker)->GetStatus2Per( status2Index ); perTotalDamage += (status2Per * 0.01f ); } } /// µ¥¹ÌÁö »êÃâ damage = pAttacker->DamageCalc( target, mSkillIdx, attribType, rangeType, instantSkillDamage, instantSkillDamagePer, ignoreDefence, addTotalDamage, perTotalDamage ); if( attribType == eATTRIBUTETYPE_MAGIC ) { /// ¸¶¹ý µ¥¹ÌÁö Èí¼ö absorbPer = pTarget->GetStateOddity( eODDITYTYPE_DAMAGE_ABSORB_MAG ); /// ¸¶¹ý µ¥¹ÌÁö ¹Ý»ç reflectionPer = pTarget->GetStateOddity( eODDITYTYPE_DAMAGE_REFLECTION_MAG ); } else { /// ¹°¸® µ¥¹ÌÁö Èí¼ö absorbPer = pTarget->GetStateOddity( eODDITYTYPE_DAMAGE_ABSORB_PHY ); /// ¹°¸® µ¥¹ÌÁö ¹Ý»ç reflectionPer = pTarget->GetStateOddity( eODDITYTYPE_DAMAGE_REFLECTION_PHY ); /// ¹°¸® ¿ø°Å¸® µ¥¹ÌÁö Èí¼ö if( rangeType == eRANGETYPE_LONG ) absorbPhyRangePer = pTarget->GetStateOddity( eODDITYTYPE_DAMAGE_ABSORB_PHY_RANGE ); } // ¿ÀÅä ´õ¹Ì ¼¼ÆÃ bool IsAutoDummy = false; if( pAttacker->GetObjectType() == eOBJECTTYPE_MONSTER ) { // °ø°ÝÀÚ°¡ ¿ÀÅä´õ¹Ì cMonster* mon = (cMonster*)pAttacker; if( mon && mon->IsAutoDummy() == true ) { IsAutoDummy = true; } } else if( pTarget->GetObjectType() == eOBJECTTYPE_MONSTER ) { // Ÿ°ÙÀÌ ¿ÀÅä´õ¹Ì cMonster* mon = (cMonster*)pTarget; if( mon && mon->IsAutoDummy() == true ) { IsAutoDummy = true; } } sDramaAction* damageThis = mpDetailBegin; if( mDetailCnt != 0 ) allDamageKindMiss = true; /// ´ë¹ÌÁö ºÐÇÒ °è»ê unsigned long damageI = 0; for( ; damageI < mDetailCnt ; ++damageI ) { long divideDamage = 0; long divideReflection = 0; long divideAttkAbsorbHP = 0; long divideAttkAbsorbMP = 0; eDAMAGE_KIND damageKind = eDAMAGE_MISS; bool applyMP = applyHP == false; long hideDamage = 0; if( pTarget->GetStateDie() == false ) { /// °ø°Ý¼º°ø½Ã ´ë¹ÌÁö ºÐÇÒ °è»ê bool success = pAttacker->AttackSuccess( target, attribType, accuracyValue, instantSkillSuccess, instantSkillSuccessPer ); if( success == true && mAttackerDie != 2 ) { /// Å©¸®Æ¼Äà üũ bool critical = pAttacker->CriticalSuccess( target, attribType, criticalValue, instantSkillCri, instantSkillCriPer ); if( critical == false ) { allDamageKindMiss = false; damageKind = ( applyHP == true ) ? eDAMAGE_NORMAL : eDAMAGE_NORMAL_MP; divideDamage = FloatToInt( damage * damageThis->percent ); bool damageZero = false; /// ¹«Àû È®ÀÎ (1) if( attribType == eATTRIBUTETYPE_PHYSICAL && pTarget->GetStateOddity( eODDITYTYPE_INVINCIBILITY_PHY ) != 0 ) { divideDamage = 0; damageZero = true; } else if( attribType == eATTRIBUTETYPE_MAGIC && pTarget->GetStateOddity( eODDITYTYPE_INVINCIBILITY_MAG ) != 0 ) { divideDamage = 0; damageZero = true; } /// º¸È£¸· (2) if( damageZero == false && divideDamage != 0 ) { divideDamage = pTarget->CalcGuard( (unsigned char)attribType, divideDamage ); if( divideDamage == 0 ) damageZero = true; } /// µ¥¹ÌÁö Èí¼ö °è»ê (3) if( damageZero == false && ( absorbPer != 0 || absorbPhyRangePer != 0) ) { if( absorbPhyRangePer != 0 ) absorbPer += absorbPhyRangePer; if( absorbPer < -100 ) absorbPer = -100; if( absorbPer > 100 ) absorbPer = 100; divideDamage = FloatToInt( divideDamage * ( 100 - absorbPer ) * 0.01f ); if( divideDamage == 0 ) damageZero = true; } /// µ¥¹ÌÁö ¹Ý»ç (4) if( damageZero == false && reflectionPer != 0 ) { /// °ø°ÝÀÚ°¡ ¹Þ´Â ´ë¹ÌÁö = °ø°ÝÀÚÀÇ ´ë¹ÌÁö*(¹æ¾îÀÚÀÇ ¹Ý»ç·®/100) divideReflection = (long)( divideDamage * ( reflectionPer * 0.01f ) ); // ¹æ¾îÀÚ°¡ ¹Þ´Â ´ë¹ÌÁö = IF((°ø°ÝÀÚÀÇ ´ë¹ÌÁö-ABS(°ø°ÝÀÚ°¡ ¹ÞÀº ¹Ý»ç·®))<0,0,(°ø°ÝÀÚÀÇ ´ë¹ÌÁö-ABS(°ø°ÝÀÚ°¡ ¹ÞÀº ¹Ý»ç·®))) if( divideDamage - abs( divideReflection ) < 0 ) divideDamage = 0; else divideDamage = divideDamage - abs( divideReflection ); if( divideDamage == 0 ) damageZero = true; } /// °ø°ÝÀÚ µ¥¹ÌÁö hpÈí¼ö (6) if( damageZero == false && attkAbsorbHPPer != 0 ) { if( attkAbsorbHPPer < -100 ) attkAbsorbHPPer = -100; if( attkAbsorbHPPer > 100 ) attkAbsorbHPPer = 100; divideAttkAbsorbHP = FloatToInt( ( divideDamage * abs(attkAbsorbHPPer) ) * 0.01f ); if( attkAbsorbHPPer < 0 ) divideAttkAbsorbHP = divideAttkAbsorbHP * -1; } /// °ø°ÝÀÚ µ¥¹ÌÁö mpÈí¼ö (6) if( damageZero == false && attkAbsorbMPPer != 0 ) { if( attkAbsorbMPPer < -100 ) attkAbsorbMPPer = -100; if( attkAbsorbMPPer > 100 ) attkAbsorbMPPer = 100; divideAttkAbsorbMP = FloatToInt( ( divideDamage * abs(attkAbsorbMPPer) ) * 0.01f ); if( attkAbsorbMPPer < 0 ) divideAttkAbsorbMP = divideAttkAbsorbMP * -1; } /// mpº¸È£¸· (6) if( damageZero == false && divideDamage != 0 ) { /// Àû¿ëµÆÁö¸¸ ³²Àº hpµ¥¹ÌÁö¿¡°¡·Á º¸ÀÌÁö ¾Ê´Â mpµ¥¹ÌÁö hideDamage = divideDamage; long leftDamage = pTarget->CalcChangeMPDamage( (unsigned char)attribType, divideDamage, applyHP ); /// Àû¿ëÇÏ°í ³²Àº°ªÀÌ ¾øÀ¸¸é ÀüºÎmpµ¥¹ÌÁö·Î Èí¼ö if( leftDamage == 0 ) { /// mpÇ÷¡±×¸¦ÄÑÁØ´Ù. applyMP = true; /// ÀÜ¿© mpµ¥¹ÌÁö ¾øÀ½ hideDamage = 0; } else { /// Àû¿ëÀº µÆÁö¸¸ ¿ÏÀüÈ÷ Àû¿ëÀÌ ¾ÈµÇ°í ÀϺθ¸ µÈ°æ¿ì if( leftDamage != divideDamage ) { /// Àû¿ëµÈ mpµ¥¹ÌÁö °ª¸¸ ±â·Ï hideDamage = divideDamage - leftDamage; /// hpÀû¿ë°ª ±â·Ï divideDamage = leftDamage; } else hideDamage = 0; } } if( applyHP == true ) { if( applyMP == true ) damageKind = eDAMAGE_NORMAL_MP; } if( damageZero == false && divideDamage < 1 ) divideDamage = 1; if( IsAutoDummy == true ) divideDamage = 1; } else { if( applyHP == true ) damageKind = eDAMAGE_CRITICAL; else damageKind = eDAMAGE_CRITICAL_MP; divideDamage = FloatToInt( damage * damageThis->percent * CRITICAL_RATE ); divideReflection = 0; divideAttkAbsorbHP = 0; divideAttkAbsorbMP = 0; allDamageKindMiss = false; bool damageZero = false; /// ¹«Àû È®ÀÎ (1) if( attribType == eATTRIBUTETYPE_PHYSICAL && pTarget->GetStateOddity( eODDITYTYPE_INVINCIBILITY_PHY ) != 0 ) { divideDamage = 0; damageZero = true; } else if( attribType == eATTRIBUTETYPE_MAGIC && pTarget->GetStateOddity( eODDITYTYPE_INVINCIBILITY_MAG ) != 0 ) { divideDamage = 0; damageZero = true; } /// º¸È£¸· (2) if( damageZero == false && divideDamage != 0 ) { divideDamage = pTarget->CalcGuard( (unsigned char)attribType, divideDamage ); if( divideDamage == 0 ) damageZero = true; } /// µ¥¹ÌÁö Èí¼ö °è»ê (3) if( damageZero == false && ( absorbPer != 0 || absorbPhyRangePer != 0) ) { if( absorbPhyRangePer != 0 ) absorbPer += absorbPhyRangePer; if( absorbPer < -100 ) absorbPer = -100; if( absorbPer > 100 ) absorbPer = 100; divideDamage = FloatToInt( divideDamage * ( 100 - absorbPer ) * 0.01f ); if( divideDamage == 0 ) damageZero = true; } /// µ¥¹ÌÁö ¹Ý»ç (4) if( damageZero == false && reflectionPer != 0 ) { /// °ø°ÝÀÚ°¡ ¹Þ´Â ´ë¹ÌÁö = °ø°ÝÀÚÀÇ ´ë¹ÌÁö*(¹æ¾îÀÚÀÇ ¹Ý»ç·®/100) divideReflection = (long)( divideDamage * ( reflectionPer * 0.01f ) ); // ¹æ¾îÀÚ°¡ ¹Þ´Â ´ë¹ÌÁö = IF((°ø°ÝÀÚÀÇ ´ë¹ÌÁö-ABS(°ø°ÝÀÚ°¡ ¹ÞÀº ¹Ý»ç·®))<0,0,(°ø°ÝÀÚÀÇ ´ë¹ÌÁö-ABS(°ø°ÝÀÚ°¡ ¹ÞÀº ¹Ý»ç·®))) if( divideDamage - abs( divideReflection ) < 0 ) divideDamage = 0; else divideDamage = divideDamage - abs( divideReflection ); if( divideDamage == 0 ) damageZero = true; } /// °ø°ÝÀÚ µ¥¹ÌÁö hpÈí¼ö (6) if( damageZero == false && attkAbsorbHPPer != 0 ) { if( attkAbsorbHPPer < -100 ) attkAbsorbHPPer = -100; if( attkAbsorbHPPer > 100 ) attkAbsorbHPPer = 100; divideAttkAbsorbHP = FloatToInt( ( divideDamage * abs(attkAbsorbHPPer) ) * 0.01f ); if( attkAbsorbHPPer < 0 ) divideAttkAbsorbHP = divideAttkAbsorbHP * -1; } /// °ø°ÝÀÚ µ¥¹ÌÁö mpÈí¼ö (6) if( damageZero == false && attkAbsorbMPPer != 0 ) { if( attkAbsorbMPPer < -100 ) attkAbsorbMPPer = -100; if( attkAbsorbMPPer > 100 ) attkAbsorbMPPer = 100; divideAttkAbsorbMP = FloatToInt( ( divideDamage * abs(attkAbsorbMPPer) ) * 0.01f ); if( attkAbsorbMPPer < 0 ) divideAttkAbsorbMP = divideAttkAbsorbMP * -1; } /// mpº¸È£¸· (6) if( damageZero == false && divideDamage != 0 ) { /// Àû¿ëµÆÁö¸¸ ³²Àº hpµ¥¹ÌÁö¿¡°¡·Á º¸ÀÌÁö ¾Ê´Â mpµ¥¹ÌÁö hideDamage = divideDamage; long leftDamage = pTarget->CalcChangeMPDamage( (unsigned char)attribType, divideDamage, applyHP ); /// Àû¿ëÇÏ°í ³²Àº°ªÀÌ ¾øÀ¸¸é ÀüºÎmpµ¥¹ÌÁö·Î Èí¼ö if( leftDamage == 0 ) { /// mpÇ÷¡±×¸¦ÄÑÁØ´Ù. applyMP = true; /// ÀÜ¿© mpµ¥¹ÌÁö ¾øÀ½ hideDamage = 0; } else { /// Àû¿ëÀº µÆÁö¸¸ ¿ÏÀüÈ÷ Àû¿ëÀÌ ¾ÈµÇ°í ÀϺθ¸ µÈ°æ¿ì if( leftDamage != divideDamage ) { /// Àû¿ëµÈ mpµ¥¹ÌÁö °ª¸¸ ±â·Ï hideDamage = hideDamage - divideDamage; /// hpÀû¿ë°ª ±â·Ï divideDamage = leftDamage; } else hideDamage = 0; } } if( applyHP == true ) { if( applyMP == true ) damageKind = eDAMAGE_CRITICAL_MP; } if( damageZero == false && divideDamage < 1 ) divideDamage = 1; if( IsAutoDummy == true ) divideDamage = 1; } } } damageThis = (sDramaAction*)damageThis->pNext; targetDamage->mDetail[damageI].mDamage = (short)divideDamage; targetDamage->mDetail[damageI].mDamageKind = (unsigned char)damageKind; targetDamage->mDetail[damageI].mDamageReflection = (short)divideReflection; targetDamage->mDetail[damageI].mDamageAbsorbHP = (short)divideAttkAbsorbHP; targetDamage->mDetail[damageI].mDamageAbsorbMP = (short)divideAttkAbsorbMP; //! °Ë»ç¿ë ÄÚµå Å×½ºÆ®ÈÄ »èÁ¦. if ( !(damageI < 10) ) NETWORK2->PostServerEvent( "cBaseSkillObject::SendDamage:mDetailCnt(=%d), damageI(=%d).", mDetailCnt, damageI ); if( applyHP ) { if( applyMP == true ) { pSkillTarget->mDetail[damageI].mDetailDamageHP = 0; pSkillTarget->mDetail[damageI].mDetailDamageMP = divideDamage; } else { pSkillTarget->mDetail[damageI].mDetailDamageHP = divideDamage; if( hideDamage != 0 ) { pSkillTarget->mDetail[damageI].mDetailDamageMP = hideDamage; } } } else { pSkillTarget->mDetail[damageI].mDetailDamageHP = 0; pSkillTarget->mDetail[damageI].mDetailDamageMP = divideDamage; } pSkillTarget->mDetail[damageI].mDetailDamageKind = (unsigned char)damageKind; pSkillTarget->mDetail[damageI].mDetailReflection = divideReflection; pSkillTarget->mDetail[damageI].mDetailAttkAbsorbHP = divideAttkAbsorbHP; pSkillTarget->mDetail[damageI].mDetailAttkAbsorbMP = divideAttkAbsorbMP; } pSkillTarget->mDetailCnt = damageI; targetDamage->mDetailCnt = (unsigned char)damageI; /// ½ºÅ³°ø°ÝÀÌ Àüü ½ÇÆÐ°¡ ¾Æ´Ò°æ¿ì ºÎ°¡ È¿°ú/¹Ð°í´ç±â±â üũ if( allDamageKindMiss == false ) { /// È¿°ú À妽º¿Í °ø°ÝŸÀÔ Ã¼Å© if( influenceClassIdx != 0 && shotType != eSHOTTYPE_AURA ) { /// È¿°ú »ý¼º if( SKILLMANAGER->AddInfluence( mAttacker, target, influenceClassIdx, mSkillIdx, true, &pInf[pInfMsg->mTargetCnt] ) == false ) targetDamage->mInfluenceMiss = true; else ++pInfMsg->mTargetCnt; } /// °ø°Ý ¼º°ø½Ã ¹Ð±â/´ç±â±â ¼³Á¤ÀÌ ÀÖ´ÂÁö üũ if( mPushPull != 0 ) { /// ¹Ð±â/´ç±â±â È¿°ú»ý¼º µÑÁß¿¡ Çϳª¶óµµ ½ÇÆÐ½Ã ¹Ì½º¸¦ Ãâ·ÂÇÑ´Ù. if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { /// ¸é¿ª üũ if( ((cPlayer*)pTarget)->IsImmuneApplyAll( mPushPull ) == true ) { mPushPull = 0; targetDamage->mInfluenceMiss = true; } } else if( pTarget->GetObjectType() == eOBJECTTYPE_MONSTER ) { if( ((cMonster*)pTarget)->IsImmuneApplyAll( mPushPull ) == true ) { mPushPull = 0; targetDamage->mInfluenceMiss = true; } } } } else mPushPull = 0; /// ¹Ð±â/´ç±â±â ±â´É »ç¿ë ¾ÈÇÔ damageMsg->SetMsgLength( damageMsg->GetMsgLength() + (unsigned short)targetDamage->GetLength( ) ); targetDamage = (sTargetDamage*)((char*)targetDamage + (unsigned short)targetDamage->GetLength( )); ++targetCnt; node = node->next; } } damageMsg->mTargetCount = (unsigned char)targetCnt; /// ±×¸®µå¿¡¼­ ¸Þ¼¼Áö ¹ß¼ÛÀÚ ¸í´ÜÀ» ¹Þ¾Æ¿Â´Ù. GRIDMANAGER->FindSkillSendPlayer( this ); ////////////////////////////////////////////////////////////////////////// /// °ø°ÝÀÚ¿¡°Ô ¹ß¼ÛÇÏ´Â ¸Þ¼¼Áö { cHashSet::cIterator b = mSendAttackerSet.Begin(); cHashSet::cIterator e = mSendAttackerSet.End(); for( ; b != e ; ++b ) { cPlayer* pPlayer = GRIDMANAGER->GetPlayer( *b ); if( pPlayer == NULL ) continue; mSendAroundSet.Erase( *b ); /// µ¥¹ÌÁö ¹ß¼Û unsigned long connectionIdx = pPlayer->GetConnectionIdx(); if( NETWORK2->SendToUser( connectionIdx, (char*)damageMsg, damageMsg->GetMsgLength() ) == false ) NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage[%d,%d] damageMsg attacker == false", damageMsg->GetMsgLength(), damageMsg->mTargetCount ); /// È¿°ú ¹ß¼Û if( pInfMsg->mTargetCnt > 0 ) { if( NETWORK2->SendToUser( connectionIdx, (char*)pInfMsg, pInfMsg->GetMsgLength() ) == false ) NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage[%d,%d] pInfMsg attacker == false", pInfMsg->GetMsgLength(), pInfMsg->mTargetCnt ); } } } ////////////////////////////////////////////////////////////////////////// /// Ÿ°Ùµé¿¡°Ô ¹ß¼ÛÇÏ´Â ¸Þ¼¼Áö { cHashSet::cIterator b = mSendTargetSet.Begin(); cHashSet::cIterator e = mSendTargetSet.End(); for( ; b != e ; ++b ) { cPlayer* pSendPlayer = GRIDMANAGER->GetPlayer( *b ); if( pSendPlayer == NULL ) continue; mSendAroundSet.Erase( *b ); /// Ç®¿¡¼­ ¸Þ¸ð¸® ÇÒ´ç PerIoContext* pIoTarget = NETWORK2->GetIoContext( IOCP_REQUEST_WRITE ); if( pIoTarget == NULL ) { NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage pIoTarget == NULL" ); return; } MSG_SYN_SKILL_DAMAGE_ATTACKER* targetMsg = (MSG_SYN_SKILL_DAMAGE_ATTACKER*)pIoTarget->buffer; targetMsg->Category = NM_SKILL; targetMsg->Protocol = NM_SKILL_DAMAGE_TARGET_SYN; targetMsg->mSkillIndex = mUniqueIdx; targetMsg->mAttackerType = mAttacker.type; targetMsg->mSkillClassIndex = mSkillIdx; targetMsg->mDramaKey = mDramaKey; targetMsg->mIsChangeMonster = mIsChgMonsSkill; targetMsg->mAttackerDie = mAttackerDie == 1; targetMsg->SetMsgLength( sizeof(MSG_SYN_SKILL_DAMAGE_ATTACKER) - sizeof(sTargetDamage) ); unsigned short msgSize = sizeof(MSG_SYN_SKILL_DAMAGE_ATTACKER) - sizeof(sTargetDamage); sTargetDamage* pTargetDamage = targetMsg->mTargetDamage; sTargetDamage* pBaseDamage = damageMsg->mTargetDamage; for( int i = 0 ; i < damageMsg->mTargetCount ; ++i ) { /// Ÿ°ÙÀ̰ųª °°ÀºÆÄƼ ¼Ò¼ÓÀÎÁö üũ bool viewInfo = false; if( pBaseDamage->mTarget.type == eOBJECTTYPE_PLAYER ) { if( pBaseDamage->mTarget.index == pSendPlayer->GetObjectID() ) viewInfo = true; else { if( pSendPlayer->GetPartyIndex() != 0 ) { cPlayer* pTargetPlayer = GRIDMANAGER->GetPlayer( pBaseDamage->mTarget.index ); if( pTargetPlayer != NULL && pSendPlayer->GetPartyIndex() == pTargetPlayer->GetPartyIndex() ) viewInfo = true; } } } memcpy( pTargetDamage, pBaseDamage, pBaseDamage->GetLength() ); if( viewInfo == false ) pTargetDamage->mDetailCnt = 0; msgSize = msgSize + (unsigned short)pTargetDamage->GetLength(); pTargetDamage = (sTargetDamage*)(((char*)pTargetDamage) + (unsigned short)pTargetDamage->GetLength()); pBaseDamage = (sTargetDamage*)(((char*)pBaseDamage) + (unsigned short)pBaseDamage->GetLength()); } targetMsg->mTargetCount = damageMsg->mTargetCount; targetMsg->SetMsgLength( msgSize ); if( NETWORK2->SendToUser( pSendPlayer->GetConnectionIdx(), (char*)targetMsg, targetMsg->GetMsgLength() ) == false ) NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage[%d,%d] targetMsg target == false", targetMsg->GetMsgLength(), targetMsg->mTargetCount ); /// È¿°ú ¹ß¼Û if( pInfMsg->mTargetCnt > 0 ) { if( NETWORK2->SendToUser( pSendPlayer->GetConnectionIdx(), (char*)pInfMsg, pInfMsg->GetMsgLength() ) == false ) NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage[%d,%d] pInfMsg target == false", pInfMsg->GetMsgLength(), pInfMsg->mTargetCnt ); } pIoTarget->offset = targetMsg->GetMsgLength(); NETWORK2->ReleaseIoContext( pIoTarget ); } } ////////////////////////////////////////////////////////////////////////// /// ÁÖº¯ À¯Àú¿¡°Ô¹ß¼ÛÇÏ´Â ¸Þ¼¼Áö { PerIoContext* pIoAround = NETWORK2->GetIoContext( IOCP_REQUEST_WRITE ); if( pIoAround == NULL ) { NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage pIoAround == NULL" ); return; } if( mIsChanneling ) { MSG_SYN_SKILL_DAMAGE_AROUND_CHANNELING* aroundChannelingMsg = (MSG_SYN_SKILL_DAMAGE_AROUND_CHANNELING*)pIoAround->buffer; aroundChannelingMsg->Category = NM_SKILL; aroundChannelingMsg->Protocol = NM_SKILL_DAMAGE_AROUND_CHANNELING_SYN; aroundChannelingMsg->mSkillIndex = mUniqueIdx; aroundChannelingMsg->mAttackerType = mAttacker.type; aroundChannelingMsg->mSkillClassIndex = mSkillIdx; aroundChannelingMsg->mDramaKey = mDramaKey; aroundChannelingMsg->mIsChangeMonster = mIsChgMonsSkill; aroundChannelingMsg->mAttackerDie = mAttackerDie == 1; aroundChannelingMsg->mTargetCount = damageMsg->mTargetCount; /// ä³Î¸µ Ãß°¡ ¸Þ½ÃÁö aroundChannelingMsg->mTargetPosX = mCenterPos.x; aroundChannelingMsg->mTargetPosY = mCenterPos.y; aroundChannelingMsg->mPlayerIdx = mAttacker.index; for( int i = 0 ; i < damageMsg->mTargetCount ; ++i ) { aroundChannelingMsg->mTarget[i].type = damageMsg->mTargetDamage[i].mTarget.type; aroundChannelingMsg->mTarget[i].index = damageMsg->mTargetDamage[i].mTarget.index; } /// ¹ß¼Û cHashSet::cIterator b = mSendAroundSet.Begin(); cHashSet::cIterator e = mSendAroundSet.End(); for( ; b != e ; ++b ) { cPlayer* pSendPlayer = GRIDMANAGER->GetPlayer( *b ); if( pSendPlayer == NULL ) continue; /// µ¥¹ÌÁö ¹ß¼Û unsigned long connectionIdx = pSendPlayer->GetConnectionIdx(); if( NETWORK2->SendToUser( connectionIdx, (char*)aroundChannelingMsg, aroundChannelingMsg->GetMsgLength() ) == false ) NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage[%d,%d] aroundChannelingMsg around == false", aroundChannelingMsg->GetMsgLength(), aroundChannelingMsg->mTargetCount ); /// È¿°ú ¹ß¼Û if( pInfMsg->mTargetCnt > 0 ) { if( NETWORK2->SendToUser( connectionIdx, (char*)pInfMsg, pInfMsg->GetMsgLength() ) == false ) NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage[%d,%d] pInfMsg around == false", pInfMsg->GetMsgLength(), pInfMsg->mTargetCnt ); } } pIoAround->offset = aroundChannelingMsg->GetMsgLength(); } else { MSG_SYN_SKILL_DAMAGE_AROUND* aroundMsg = (MSG_SYN_SKILL_DAMAGE_AROUND*)pIoAround->buffer; aroundMsg->Category = NM_SKILL; aroundMsg->Protocol = NM_SKILL_DAMAGE_AROUND_SYN; aroundMsg->mSkillIndex = mUniqueIdx; aroundMsg->mAttackerType = mAttacker.type; aroundMsg->mSkillClassIndex = mSkillIdx; aroundMsg->mDramaKey = mDramaKey; aroundMsg->mIsChangeMonster = mIsChgMonsSkill; aroundMsg->mAttackerDie = mAttackerDie == 1; aroundMsg->mTargetCount = damageMsg->mTargetCount; for( int i = 0 ; i < damageMsg->mTargetCount ; ++i ) { aroundMsg->mTarget[i].type = damageMsg->mTargetDamage[i].mTarget.type; aroundMsg->mTarget[i].index = damageMsg->mTargetDamage[i].mTarget.index; } /// ¹ß¼Û cHashSet::cIterator b = mSendAroundSet.Begin(); cHashSet::cIterator e = mSendAroundSet.End(); for( ; b != e ; ++b ) { cPlayer* pSendPlayer = GRIDMANAGER->GetPlayer( *b ); if( pSendPlayer == NULL ) continue; /// µ¥¹ÌÁö ¹ß¼Û unsigned long connectionIdx = pSendPlayer->GetConnectionIdx(); if( NETWORK2->SendToUser( connectionIdx, (char*)aroundMsg, aroundMsg->GetMsgLength() ) == false ) NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage[%d,%d] aroundMsg around == false", aroundMsg->GetMsgLength(), aroundMsg->mTargetCount ); /// È¿°ú ¹ß¼Û if( pInfMsg->mTargetCnt > 0 ) { if( NETWORK2->SendToUser( connectionIdx, (char*)pInfMsg, pInfMsg->GetMsgLength() ) == false ) NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage[%d,%d] pInfMsg around == false", pInfMsg->GetMsgLength(), pInfMsg->mTargetCnt ); } } pIoAround->offset = aroundMsg->GetMsgLength(); } NETWORK2->ReleaseIoContext( pIoAround ); } ////////////////////////////////////////////////////////////////////////// /// È¿°ú ¸Þ¸ð¸® Á¦°Å perIoContext2->offset = pInfMsg->GetMsgLength(); NETWORK2->ReleaseIoContext( perIoContext2 ); ////////////////////////////////////////////////////////////////////////// /// µ¥¹ÌÁö ¸Þ¸ð¸® Á¦°Å perIoContext->offset = damageMsg->GetMsgLength(); NETWORK2->ReleaseIoContext( perIoContext ); /// ºÐÇÒ ´ë¹ÌÁö Àû¿ë ½ÃÀÛ ½ÃÁ¡ °è»ê mDetailStartTime = NETWORK2->GetAccumTime(); if( mpDetailBegin != NULL ) mDetailEndTime = mDetailStartTime + mpDetailBegin->time; } void cBaseSkillObject::SendHeal( cBaseObject* pAttacker, unsigned long shotType, unsigned short applyType1, unsigned short applyType2, unsigned long applyValue1, unsigned long applyValue2, unsigned long influenceClassIdx ) { /// °ø°ÝÀÚ ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. cPlayer* pPlayer = GRIDMANAGER->FindFirstPlayer( pAttacker, true ); while( pPlayer != NULL ) { mSendAroundSet.Insert( pPlayer->GetConnectionIdx() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } PerIoContext* perIoContext = NETWORK2->GetIoContext( IOCP_REQUEST_WRITE ); MSG_SYN_SKILL_HEAL_ATTACKER* healMsg = NULL; /// Èú ¸Þ¼¼Áö healMsg = (MSG_SYN_SKILL_HEAL_ATTACKER*)perIoContext->buffer; healMsg->Category = NM_SKILL; healMsg->Protocol = NM_SKILL_HEAL_ATTACKER_SYN; healMsg->mSkillIndex = mUniqueIdx; healMsg->mAttackerType = mAttacker.type; healMsg->mSkillClassIndex = mSkillIdx; healMsg->mDramaKey = mDramaKey; healMsg->mAttackerDie = mAttackerDie == 1; healMsg->mIsChangeMonster = mIsChgMonsSkill; healMsg->mTargetCount = 0; /// Àڽŵµ Ÿ°Ù¿¡ Æ÷ÇԵǾú´ÂÁö üũ bool attackerTarget = false; /// Ÿ°ÙÀÇ ¼ö¸¸Å­ µ¥¹ÌÁö °è»ê & ÅëÇÕ ¸Þ¼¼Áö ¹ß¼Û cBaseObject* pTarget = NULL; sObject target; unsigned long heal = 0; unsigned long targetCnt = 0; if( mAttackerDie != 1 ) { PerNode* node = mTargetRoot.pool; while ( node != NULL ) { sSkillTargetInfo* pSkillTarget = (sSkillTargetInfo*)node; if( pSkillTarget == NULL ) { node = node->next; continue; } target = pSkillTarget->mTarget; switch( target.type ) { case eOBJECTTYPE_MONSTER: pTarget = GRIDMANAGER->GetMonster( target.index ); break; case eOBJECTTYPE_PLAYER: pTarget = GRIDMANAGER->GetPlayer( target.index ); break; default: pTarget = NULL; } if( pTarget == NULL ) { node = node->next; continue; } if( mAttacker.type == target.type && mAttacker.index == target.index ) attackerTarget = true; /// ½ºÅ³ ȸº¹ ±âº»·® unsigned long skillHealPlus = 0; unsigned long skillHealPer = 0; if( applyType1 != 0 ) { if( applyType1 == eSTATUSPLUS_INSTANTPLUSFINAL ) skillHealPlus = skillHealPlus + applyValue1; else if( applyType1 == eSTATUSPLUS_INSTANTPERFINAL ) skillHealPer = skillHealPer + pTarget->GetMaxHP() * applyValue1 / 100; else { assert(NULL); NETWORK2->PostServerEvent("eSKILLTYPE_HEAL ApplyValue1[%d,%d,%d,%d,%d] error", mAttacker.type, mAttacker.index, mSkillIdx, applyType1, applyValue1 ); } } if( applyType2 != 0 ) { if( applyType2 == eSTATUSPLUS_INSTANTPLUSFINAL ) skillHealPlus = skillHealPlus + applyValue2; else if( applyType2 == eSTATUSPLUS_INSTANTPERFINAL ) skillHealPer = skillHealPer + pTarget->GetMaxHP() * applyValue2 / 100; else { assert(NULL); NETWORK2->PostServerEvent("eSKILLTYPE_HEAL ApplyValue2[%d,%d,%d,%d,%d] error", mAttacker.type, mAttacker.index, mSkillIdx, applyType2, applyValue2 ); } } if( mAttackerDie != 2 ) { /// È¿°ú »ý¼ºÁ¶°Ç ¸¸Á· È®ÀÎ if( influenceClassIdx != 0 && shotType != eSHOTTYPE_AURA ) { NiPoint2 pos( mCenterPos.x, mCenterPos.y ); /// È¿°ú »ý¼º if( SKILLMANAGER->AddInfluence( mAttacker, target, influenceClassIdx, mSkillIdx, true ) == false ) healMsg->mTargetHeal[targetCnt].mInfluenceMiss = true; } /// Èú °è»ê heal = pAttacker->HealCalc( target, skillHealPlus, skillHealPer, true ); } /// ¹Ð±â/´ç±â±â È¿°ú»ý¼º µÑÁß¿¡ Çϳª¶óµµ ½ÇÆÐ½Ã ¹Ì½º¸¦ Ãâ·ÂÇÑ´Ù. if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { if( mPushPull == 1 ) { if( ((cPlayer*)pTarget)->IsImmuneApplyAll( eSTATUSPLUS_AROUND_PUSH ) == true ) { mPushPull = 0; healMsg->mTargetHeal[targetCnt].mInfluenceMiss = true; } } else if( mPushPull == 2 ) { if( ((cPlayer*)pTarget)->IsImmuneApplyAll( eSTATUSPLUS_AROUND_PULL ) == true ) { mPushPull = 0; healMsg->mTargetHeal[targetCnt].mInfluenceMiss = true; } } } else if( pTarget->GetObjectType() == eOBJECTTYPE_MONSTER ) { if( mPushPull == 1 ) { if( ((cMonster*)pTarget)->IsImmuneApplyAll( eSTATUSPLUS_AROUND_PUSH ) == true ) { mPushPull = 0; healMsg->mTargetHeal[targetCnt].mInfluenceMiss = true; } } else if( mPushPull == 2 ) { if( ((cMonster*)pTarget)->IsImmuneApplyAll( eSTATUSPLUS_AROUND_PULL ) == true ) { mPushPull = 0; healMsg->mTargetHeal[targetCnt].mInfluenceMiss = true; } } } healMsg->mTargetHeal[targetCnt].mTarget = target; healMsg->mTargetHeal[targetCnt].mHeal = (short)heal; pSkillTarget->mDetailCnt = 1; pSkillTarget->mDetail[0].mDetailDamageHP = heal * -1; pSkillTarget->mDetail[0].mDetailDamageKind = eDAMAGE_NORMAL; pSkillTarget->mDetail[0].mDetailDamageMP = 0; pSkillTarget->mDetail[0].mDetailReflection = 0; pSkillTarget->mDetail[0].mDetailAttkAbsorbHP = 0; pSkillTarget->mDetail[0].mDetailAttkAbsorbMP = 0; ++targetCnt; node = node->next; } } healMsg->mTargetCount = (unsigned char)targetCnt; perIoContext->offset = healMsg->GetMsgLength(); /// ±×¸®µå¿¡¼­ ¸Þ¼¼Áö ¹ß¼ÛÀÚ ¸í´ÜÀ» ¹Þ¾Æ¿Â´Ù. GRIDMANAGER->FindSkillSendPlayer( this ); ////////////////////////////////////////////////////////////////////////// /// °ø°ÝÀÚ¿¡°Ô ¹ß¼ÛÇÏ´Â ¸Þ¼¼Áö { cHashSet::cIterator b = mSendAttackerSet.Begin(); cHashSet::cIterator e = mSendAttackerSet.End(); for( ; b != e ; ++b ) { cPlayer* pPlayer = GRIDMANAGER->GetPlayer( *b ); if( pPlayer == NULL ) continue; mSendAroundSet.Erase( *b ); unsigned long connectionIdx = pPlayer->GetConnectionIdx(); NETWORK2->SendToUser( connectionIdx, (char*)healMsg, healMsg->GetMsgLength() ); } } ////////////////////////////////////////////////////////////////////////// /// Ÿ°Ùµé¿¡°Ô ¹ß¼ÛÇÏ´Â ¸Þ¼¼Áö { cHashSet::cIterator b = mSendTargetSet.Begin(); cHashSet::cIterator e = mSendTargetSet.End(); for( ; b != e ; ++b ) { cPlayer* pSendPlayer = GRIDMANAGER->GetPlayer( *b ); if( pSendPlayer == NULL ) continue; mSendAroundSet.Erase( *b ); PerIoContext* pIoTarget = NETWORK2->GetIoContext( IOCP_REQUEST_WRITE ); if( pIoTarget == NULL ) { NETWORK2->PostServerEvent("cBaseSkillObject::SendHeal pIoTarget == NULL" ); return; } MSG_SYN_SKILL_HEAL_ATTACKER* targetMsg = (MSG_SYN_SKILL_HEAL_ATTACKER*)pIoTarget->buffer; targetMsg->Category = NM_SKILL; targetMsg->Protocol = NM_SKILL_HEAL_TARGET_SYN; targetMsg->mSkillIndex = mUniqueIdx; targetMsg->mAttackerType = mAttacker.type; targetMsg->mSkillClassIndex = mSkillIdx; targetMsg->mDramaKey = mDramaKey; targetMsg->mAttackerDie = mAttackerDie == 1; targetMsg->mIsChangeMonster = mIsChgMonsSkill; targetMsg->mTargetCount = healMsg->mTargetCount; sTargetHeal* pTargetDamage = targetMsg->mTargetHeal; sTargetHeal* pBaseDamage = healMsg->mTargetHeal; for( int i = 0 ; i < healMsg->mTargetCount ; ++i ) { /// Ÿ°ÙÀ̰ųª °°ÀºÆÄƼ ¼Ò¼ÓÀÎÁö üũ bool viewInfo = false; if( pBaseDamage->mTarget.type == eOBJECTTYPE_PLAYER ) { if( pBaseDamage->mTarget.index == pSendPlayer->GetObjectID() ) viewInfo = true; else { if( pSendPlayer->GetPartyIndex() != 0 ) { cPlayer* pTargetPlayer = GRIDMANAGER->GetPlayer( pBaseDamage->mTarget.index ); if( pTargetPlayer != NULL && pSendPlayer->GetPartyIndex() == pTargetPlayer->GetPartyIndex() ) viewInfo = true; } } } memcpy( pTargetDamage, pBaseDamage, sizeof(sTargetHeal) ); if( viewInfo == false ) pTargetDamage->mHeal = 0; ++pTargetDamage; ++pBaseDamage; } NETWORK2->SendToUser( pSendPlayer->GetConnectionIdx(), (char*)targetMsg, targetMsg->GetMsgLength() ); pIoTarget->offset = targetMsg->GetMsgLength(); NETWORK2->ReleaseIoContext( pIoTarget ); } } ////////////////////////////////////////////////////////////////////////// /// ÁÖº¯ À¯Àú¿¡°Ô¹ß¼ÛÇÏ´Â ¸Þ¼¼Áö { PerIoContext* pIoAround = NETWORK2->GetIoContext( IOCP_REQUEST_WRITE ); if( pIoAround == NULL ) { NETWORK2->PostServerEvent("cBaseSkillObject::SendHeal pIoAround == NULL" ); return; } MSG_SYN_SKILL_HEAL_AROUND* aroundMsg = (MSG_SYN_SKILL_HEAL_AROUND*)pIoAround->buffer; aroundMsg->Category = NM_SKILL; aroundMsg->Protocol = NM_SKILL_HEAL_AROUND_SYN; aroundMsg->mSkillIndex = mUniqueIdx; aroundMsg->mAttackerType = mAttacker.type; aroundMsg->mSkillClassIndex = mSkillIdx; aroundMsg->mDramaKey = mDramaKey; aroundMsg->mAttackerDie = mAttackerDie == 1; aroundMsg->mIsChangeMonster = mIsChgMonsSkill; aroundMsg->mTargetCount = healMsg->mTargetCount; for( int i = 0 ; i < healMsg->mTargetCount ; ++i ) { aroundMsg->mTarget[i].type = healMsg->mTargetHeal[i].mTarget.type; aroundMsg->mTarget[i].index = healMsg->mTargetHeal[i].mTarget.index; } /// ¹ß¼Û cHashSet::cIterator b = mSendAroundSet.Begin(); cHashSet::cIterator e = mSendAroundSet.End(); for( ; b != e ; ++b ) { cPlayer* pSendPlayer = GRIDMANAGER->GetPlayer( *b ); if( pSendPlayer == NULL ) continue; unsigned long connectionIdx = pSendPlayer->GetConnectionIdx(); NETWORK2->SendToUser( connectionIdx, (char*)aroundMsg, aroundMsg->GetMsgLength() ); } pIoAround->offset = aroundMsg->GetMsgLength(); NETWORK2->ReleaseIoContext( pIoAround ); } NETWORK2->ReleaseIoContext( perIoContext ); mDetailStartTime = NETWORK2->GetAccumTime(); if( mpDetailBegin != NULL ) mDetailEndTime = mDetailStartTime + mpDetailBegin->time; /// °ËÁõ ÄÚµå if( mDetailCnt > 1 ) mDetailCnt = 0; } void cBaseSkillObject::SendApply( cBaseObject* pAttacker, unsigned long shotType, eATTRIBUTETYPE attribType, short accuracyValue, unsigned short applyType1, unsigned short applyType2, unsigned long applyValue1, unsigned long applyValue2, unsigned long influenceClassIdx ) { /// °ø°ÝÀÚ ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. cPlayer* pPlayer = GRIDMANAGER->FindFirstPlayer( pAttacker, true ); while( pPlayer != NULL ) { mSendAroundSet.Insert( pPlayer->GetObjectID() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } PerIoContext* perIoContext = NETWORK2->GetIoContext( IOCP_REQUEST_WRITE ); MSG_SYN_SKILL_APPLY* applyMsg = NULL; /// Àû¿ë ¸Þ¼¼Áö applyMsg = (MSG_SYN_SKILL_APPLY*)perIoContext->buffer; applyMsg->Category = NM_SKILL; applyMsg->Protocol = NM_SKILL_APPLY_SYN; applyMsg->mSkillIndex = mUniqueIdx; applyMsg->mAttackerType = mAttacker.type; applyMsg->mSkillClassIndex = mSkillIdx; applyMsg->mDramaKey = mDramaKey; applyMsg->mAttackerDie = mAttackerDie == 1; applyMsg->mIsChangeMonster = mIsChgMonsSkill; /// Ÿ°ÙÀÇ ¼ö¸¸Å­ µ¥¹ÌÁö °è»ê & ÅëÇÕ ¸Þ¼¼Áö ¹ß¼Û cBaseObject* pTarget = NULL; sObject target; unsigned long targetCnt = 0; if( mAttackerDie != 1 ) { //for( unsigned long i = 0 ; i < mTargetAry.GetSize() ; ++i ) //{ // /// Ÿ°Ù °´Ã¼ È®ÀÎ // target = mTargetAry[i].mTarget; PerNode* node = mTargetRoot.pool; while ( node != NULL ) { sSkillTargetInfo* pSkillTarget = (sSkillTargetInfo*)node; if( pSkillTarget == NULL ) { node = node->next; continue; } target = pSkillTarget->mTarget; switch( target.type ) { case eOBJECTTYPE_MONSTER: pTarget = GRIDMANAGER->GetMonster( target.index ); break; case eOBJECTTYPE_PLAYER: pTarget = GRIDMANAGER->GetPlayer( target.index ); break; default: pTarget = NULL; } if( pTarget == NULL ) { node = node->next; continue; } pTarget->AddTakeDamage( mAttacker, 0, mDistressPoint, eTAKEDAMAGETYPE_DAMAGE ); applyMsg->mApplyObject[targetCnt].mTarget = target; /// Ÿ°Ù ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. pPlayer = GRIDMANAGER->FindFirstPlayer( pTarget, true ); while( pPlayer != NULL ) { mSendAroundSet.Insert( pPlayer->GetObjectID() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } if( mAttackerDie != 2 ) { switch( mCreateType ) { case eSKILLCREATETYPE_NORMAL: { if( influenceClassIdx != 0 ) { /// ¿À¶ó ó¸® if( target.index == mAttacker.index && target.type == mAttacker.type && shotType == eSHOTTYPE_AURA ) { if( SKILLMANAGER->AddInfSwitch( mAttacker, target, influenceClassIdx, mSkillIdx, true ) == 0 ) applyMsg->mApplyObject[targetCnt].mInfluenceMiss = true; } /// ¿À¶ó¿Ü È¿°ú ó¸® if( shotType != eSHOTTYPE_AURA ) { /// È¿°ú »ý¼º if( SKILLMANAGER->AddInfluence( mAttacker, target, influenceClassIdx, mSkillIdx, true ) == false ) applyMsg->mApplyObject[targetCnt].mInfluenceMiss = true; } } unsigned long instantSkillSuccessPer = 0; unsigned long instantSkillSuccess = 0; /// ½ºÅ³ÀÇ µ¥¹ÌÁö Ç׸ñ Àоî¿È switch( applyType1 ) { case 0: break; case eSTATUSPLUS_INSTANTPERHIT: instantSkillSuccessPer += applyValue1; break; case eSTATUSPLUS_INSTANTPLUSHIT: instantSkillSuccess += applyValue1; break; case eSTATUSPLUS_AROUND_PUSH: mPushPull = eSTATUSPLUS_AROUND_PUSH; mPushRange = applyValue1; break; case eSTATUSPLUS_AROUND_PULL: mPushPull = eSTATUSPLUS_AROUND_PULL; break; case eSTATUSPLUS_TARGET_PUSH: mPushPull = eSTATUSPLUS_TARGET_PUSH; mPushRange = applyValue1; break; break; default: NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage applyType1[%d,%d,%d,%d,%d]", mAttacker.type, mAttacker.index, mSkillIdx, applyType1, applyValue1 ); } switch( applyType2 ) { case 0: break; case eSTATUSPLUS_INSTANTPERHIT: instantSkillSuccessPer += applyValue2; break; case eSTATUSPLUS_INSTANTPLUSHIT: instantSkillSuccess += applyValue2; break; case eSTATUSPLUS_AROUND_PUSH: mPushPull = eSTATUSPLUS_AROUND_PUSH; mPushRange = applyValue2; break; case eSTATUSPLUS_AROUND_PULL: mPushPull = eSTATUSPLUS_AROUND_PULL; break; case eSTATUSPLUS_TARGET_PUSH: mPushPull = eSTATUSPLUS_TARGET_PUSH; mPushRange = applyValue2; break; default: NETWORK2->PostServerEvent("cBaseSkillObject::SendDamage applyType2[%d,%d,%d,%d,%d]", mAttacker.type, mAttacker.index, mSkillIdx, applyType2, applyValue2 ); } /// °ø°Ý¼º°ø½Ã ´ë¹ÌÁö ºÐÇÒ °è»ê if( pAttacker->AttackSuccess( target, attribType, accuracyValue, instantSkillSuccess, instantSkillSuccessPer ) == true ) { /// ¹Ð±â/´ç±â±â È¿°ú»ý¼º µÑÁß¿¡ Çϳª¶óµµ ½ÇÆÐ½Ã ¹Ì½º¸¦ Ãâ·ÂÇÑ´Ù. if( pTarget->GetObjectType() == eOBJECTTYPE_PLAYER ) { if( ((cPlayer*)pTarget)->IsImmuneApplyAll( mPushPull ) == true ) { mPushPull = 0; applyMsg->mApplyObject[targetCnt].mInfluenceMiss = true; } } else if( pTarget->GetObjectType() == eOBJECTTYPE_MONSTER ) { if( ((cMonster*)pTarget)->IsImmuneApplyAll( mPushPull ) == true ) { mPushPull = 0; applyMsg->mApplyObject[targetCnt].mInfluenceMiss = true; } } pTarget->SetSkillPushPull( mPushPull, pAttacker, mPushRange ); } } break; case eSKILLCREATETYPE_MAPCHANGE: { if( applyType1 == eSTATUSPLUS_MAPCHANGE && target.type == eOBJECTTYPE_PLAYER ) { ((cPlayer*)pTarget)->ItemMapChange( applyValue1, mUseItemIdx ); } if( applyType2 == eSTATUSPLUS_MAPCHANGE && target.type == eOBJECTTYPE_PLAYER ) { ((cPlayer*)pTarget)->ItemMapChange( applyValue2, mUseItemIdx ); } } break; case eSKILLCREATETYPE_VEHICLE: { if( influenceClassIdx != 0 && target.index == mAttacker.index && target.type == mAttacker.type ) { if( SKILLMANAGER->AddInfSwitch( mAttacker, target, influenceClassIdx, mSkillIdx, true ) == 0 ) applyMsg->mApplyObject[targetCnt].mInfluenceMiss = true; } } break; case eSKILLCREATETYPE_CASHMAPCHANGE: { if( applyType1 == eSTATUSPLUS_CASHMAPCHANGE && target.type == eOBJECTTYPE_PLAYER ) { ((cPlayer*)pTarget)->CashItemMapChange( mCashMapNum, mCashX, mCashY, mUseItemIdx ); } if( applyType2 == eSTATUSPLUS_CASHMAPCHANGE && target.type == eOBJECTTYPE_PLAYER ) { ((cPlayer*)pTarget)->CashItemMapChange( mCashMapNum, mCashX, mCashY, mUseItemIdx ); } } break; } } ++targetCnt; node = node->next; } } applyMsg->mApplyCount = (unsigned char)targetCnt; cHashSet::cIterator begin = mSendAroundSet.Begin(); cHashSet::cIterator end = mSendAroundSet.End(); while( begin != end ) { cPlayer* pSendPlayer = GRIDMANAGER->GetPlayer( *begin++ ); if( pSendPlayer != NULL ) NETWORK2->SendToUser( pSendPlayer->GetConnectionIdx(), (char*)applyMsg, applyMsg->GetMsgLength() ); } perIoContext->offset = applyMsg->GetMsgLength(); char text[255]; sprintf( text, "cBaseSkillObject::SendApply:MSG_SYN_SKILL_APPLY(%d %d %d %d %d %d %d %d %d)", mAttacker.type, mAttacker.index, applyMsg->GetMsgLength(), applyMsg->mSkillIndex, applyMsg->mAttackerType, applyMsg->mSkillClassIndex, applyMsg->mDramaKey, applyMsg->mIsChangeMonster, applyMsg->mApplyCount ); NETWORK2->ReleaseIoContext( perIoContext, text ); mDetailStartTime = NETWORK2->GetAccumTime(); if( mpDetailBegin != NULL ) mDetailEndTime = mDetailStartTime + mpDetailBegin->time; /// °ËÁõ ÄÚµå if( mDetailCnt > 1 ) mDetailCnt = 0; } void cBaseSkillObject::SendDelTarget( cBaseObject* pAttacker, short accuracyValue ) { /// °ø°ÝÀÚ ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. cPlayer* pPlayer = GRIDMANAGER->FindFirstPlayer( pAttacker, true ); while( pPlayer != NULL ) { mSendAroundSet.Insert( pPlayer->GetObjectID() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } PerIoContext* perIoContext = NETWORK2->GetIoContext( IOCP_REQUEST_WRITE ); MSG_SYN_SKILL_DELTARGET* applyMsg = NULL; /// Àû¿ë ¸Þ¼¼Áö applyMsg = (MSG_SYN_SKILL_DELTARGET*)perIoContext->buffer; applyMsg->Category = NM_SKILL; applyMsg->Protocol = NM_SKILL_DELTARGET_SYN; applyMsg->mSkillIndex = mUniqueIdx; applyMsg->mSkillClassIndex = mSkillIdx; applyMsg->mAttackerType = mAttacker.type; applyMsg->mAttackerDie = mAttackerDie == 1; applyMsg->mDramaKey = mDramaKey; applyMsg->mDelTargetType = pAttacker->GetObjectType(); applyMsg->mDelTargetIndex = pAttacker->GetObjectID(); /// Ÿ°ÙÀÇ ¼ö¸¸Å­ µ¥¹ÌÁö °è»ê & ÅëÇÕ ¸Þ¼¼Áö ¹ß¼Û cBaseObject* pTarget = NULL; sObject target; unsigned long targetCnt = 0; if( mAttackerDie != 1 ) { //for( unsigned long i = 0 ; i < mTargetAry.GetSize() ; ++i ) //{ // /// Ÿ°Ù °´Ã¼ È®ÀÎ // target = mTargetAry[i].mTarget; PerNode* node = mTargetRoot.pool; while ( node != NULL ) { sSkillTargetInfo* pSkillTarget = (sSkillTargetInfo*)node; if( pSkillTarget == NULL ) { node = node->next; continue; } target = pSkillTarget->mTarget; switch( target.type ) { case eOBJECTTYPE_MONSTER: pTarget = GRIDMANAGER->GetMonster( target.index ); break; case eOBJECTTYPE_PLAYER: pTarget = GRIDMANAGER->GetPlayer( target.index ); break; default: pTarget = NULL; } if( pTarget == NULL ) { node = node->next; continue; } pTarget->AddTakeDamage( mAttacker, 0, mDistressPoint, eTAKEDAMAGETYPE_NONETARGET ); applyMsg->mApplyObject[targetCnt].mTarget = target; /// È®·ü üũ unsigned long activityRand = rand() % 100; applyMsg->mApplyObject[targetCnt].mInfluenceMiss = (accuracyValue <= (short)activityRand); /// Ÿ°Ù ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. pPlayer = GRIDMANAGER->FindFirstPlayer( pTarget, true ); while( pPlayer != NULL ) { mSendAroundSet.Insert( pPlayer->GetObjectID() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } ++targetCnt; node = node->next; } } applyMsg->mApplyCount = (unsigned char)targetCnt; //for( unsigned long i = 0 ; i < mTargetAry.GetSize() ; ++i ) //{ // /// apply target // target = mTargetAry[i].mTarget; unsigned long i = 0; PerNode* node = mTargetRoot.pool; while ( node != NULL ) { sSkillTargetInfo* pSkillTarget = (sSkillTargetInfo*)node; if( pSkillTarget == NULL ) { node = node->next; continue; } target = pSkillTarget->mTarget; /// if( target.type == eOBJECTTYPE_PLAYER ) { /// msg send; cPlayer* player = GRIDMANAGER->GetPlayer( target.index ); if( player && applyMsg->mApplyObject[i].mInfluenceMiss == false ) { NETWORK2->SendToUser( player->GetConnectionIdx(), (char*)applyMsg, applyMsg->GetMsgLength() ); mSendAroundSet.Erase( target.index ); } } else { cMonster* monster = GRIDMANAGER->GetMonster( target.index ); if( monster ) { if( applyMsg->mApplyObject[i].mInfluenceMiss == false ) monster->ChangeTargetDeleteSkill(); } } ++i; node = node->next; } //applyMsg->mDelTargetType = 0; //applyMsg->mDelTargetIndex = 0; cHashSet::cIterator begin = mSendAroundSet.Begin(); cHashSet::cIterator end = mSendAroundSet.End(); while( begin != end ) { cPlayer* pSendPlayer = GRIDMANAGER->GetPlayer( *begin++ ); if( pSendPlayer != NULL ) NETWORK2->SendToUser( pSendPlayer->GetConnectionIdx(), (char*)applyMsg, applyMsg->GetMsgLength() ); } perIoContext->offset = applyMsg->GetMsgLength(); char text[255]; sprintf( text, "cBaseSkillObject::SendDelTarget:MSG_SYN_SKILL_DELTARGET(%d %d %d %d %d %d %d %d)", mAttacker.type, mAttacker.index, applyMsg->GetMsgLength(), applyMsg->mSkillIndex, applyMsg->mAttackerType, applyMsg->mSkillClassIndex, applyMsg->mDramaKey, applyMsg->mApplyCount ); NETWORK2->ReleaseIoContext( perIoContext, text ); mDetailStartTime = NETWORK2->GetAccumTime(); if( mpDetailBegin != NULL ) mDetailEndTime = mDetailStartTime + mpDetailBegin->time; } void cBaseSkillObject::ApplyBlink( cBaseObject* pAttacker ) { /// °ø°ÝÀÚ°¡ Á×Àº°æ¿ì´Â ºÎȰ¸Þ¼¼ÁöÂÊ¿¡¼­ ÀÚüÀûÀ¸·Î À§Ä¡¸¦ º¸Á¤ÇØÁØ´Ù. if( pAttacker->GetStateDie() == false ) { pAttacker->SetPos( mCenterPos.x, mCenterPos.y ); if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER ) { cPlayer* pPlayer = (cPlayer*)pAttacker; pPlayer->ClearMoveSyncCalc(); pPlayer->SetMoveTargetPos( mCenterPos.x, mCenterPos.y ); } } } bool cBaseSkillObject::ApplyHP( cBaseObject* pAttacker ) { mSendTargetSet.Clear(); if( mpDetailBegin == NULL ) return false; /// °ø°ÝÀÚ ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. cPlayer* pPlayer = GRIDMANAGER->FindFirstPlayer( pAttacker, true ); while( pPlayer != NULL ) { mSendTargetSet.Insert( pPlayer->GetConnectionIdx() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } bool die = false; unsigned char targetCnt = 0; unsigned long applyDamage = 0; PerNode* node = mTargetRoot.pool; while ( node != NULL ) { sSkillTargetInfo* pSkillTarget = (sSkillTargetInfo*)node; if( pSkillTarget == NULL ) { node = node->next; continue; } sObject target = pSkillTarget->mTarget; cBaseObject* pTarget = OBJECTMANAGER->GetObject( target.type, target.index ); if( pTarget == NULL || pTarget->GetStateDie() == true ) { node = node->next; continue; } /// Ÿ°Ù ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. pPlayer = GRIDMANAGER->FindFirstPlayer( pTarget, true ); while( pPlayer != NULL ) { mSendTargetSet.Insert( pPlayer->GetConnectionIdx() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } long mDetailDamageHP = pSkillTarget->mDetail[mDetailPos].mDetailDamageHP; long mDetailDamageMP = pSkillTarget->mDetail[mDetailPos].mDetailDamageMP; unsigned char mDetailDamageKind = pSkillTarget->mDetail[mDetailPos].mDetailDamageKind; if( mDetailDamageHP > 0 ) { /// °áÅõ µ¥¹ÌÁö üũ½Ã °áÅõ Á¾·á¸é hpdamage ³»ºÎÀûÀ¸·Î ó¸® if( DUELMANAGER->DuelLastAttack( mAttacker, target, mDetailDamageHP, mDetailDamageKind == eDAMAGE_CRITICAL, &applyDamage ) == false ) applyDamage = pTarget->HPDamage( mAttacker, mDetailDamageHP, &die, false, mDetailDamageKind == eDAMAGE_CRITICAL ); } else if( mDetailDamageHP < 0 ) { pTarget->HPHeal( -mDetailDamageHP, false, mAttacker, mDistressPoint, eTAKEDAMAGETYPE_HEAL ); } if( mDetailDamageMP > 0 ) { pTarget->MPDamage( mDetailDamageMP , false ); applyDamage = 0; } if( mDetailDamageHP != 0 || mDetailDamageMP != 0 ) SKILLMANAGER->InsertChangeSet( pTarget, mAttacker, mDetailDamageKind ); ++targetCnt; /// ¹ÞÀº µ¥¹ÌÁö ó¸® pTarget->AddTakeDamage( mAttacker, applyDamage, (mDetailDamageKind == eDAMAGE_MISS ? 0 : mDistressPoint), eTAKEDAMAGETYPE_DAMAGE ); /// µ¥¹ÌÁö¸¦ ¹Þ°í Á×Áö ¾ÊÀº °æ¿ì¸¸ ¹Ð°í´ç±ä´Ù. if( mDetailDamageKind != eDAMAGE_MISS && pTarget->GetStateDie() == false ) pTarget->SetSkillPushPull( mPushPull, pAttacker, mPushRange ); node = node->next; } long damage = 0; long totalDamage = 0; long mp = 0; long totalMp = 0; /// µ¥¹ÌÁö ¹Ý»çÀ̰ųª °ø°ÝÀÚ µ¥¹ÌÁö Èí¼ö Àΰæ¿ì if( pAttacker != NULL && pAttacker->GetStateDie() != true ) { PerNode* node = mTargetRoot.pool; while ( node != NULL ) { sSkillTargetInfo* pSkillTarget = (sSkillTargetInfo*)node; if( pSkillTarget == NULL ) { node = node->next; continue; } sObject target = pSkillTarget->mTarget; cBaseObject* pTarget = OBJECTMANAGER->GetObject( target.type, target.index ); if( pTarget == NULL ) { node = node->next; continue; } damage = pSkillTarget->mDetail[mDetailPos].mDetailReflection - pSkillTarget->mDetail[mDetailPos].mDetailAttkAbsorbHP; totalDamage = totalDamage + damage; if( damage > 0 ) { if( pSkillTarget->mDetail[mDetailPos].mDetailDamageKind == eDAMAGE_NORMAL || pSkillTarget->mDetail[mDetailPos].mDetailDamageKind == eDAMAGE_CRITICAL ) { /// °áÅõ µ¥¹ÌÁö üũ½Ã °áÅõ Á¾·á¸é hpdamage ³»ºÎÀûÀ¸·Î ó¸® if( DUELMANAGER->DuelLastAttack( target, mAttacker, damage, eDAMAGE_NORMAL, &applyDamage ) == false ) applyDamage = pAttacker->HPDamage( target, damage, &die, false, eDAMAGE_NORMAL ); } else if( pSkillTarget->mDetail[mDetailPos].mDetailDamageKind == eDAMAGE_NORMAL_MP || pSkillTarget->mDetail[mDetailPos].mDetailDamageKind == eDAMAGE_CRITICAL_MP ) { pAttacker->MPDamage( damage, false ); applyDamage = 0; } /// ¹ÞÀº µ¥¹ÌÁö ó¸® pAttacker->AddTakeDamage( target, applyDamage, mDistressPoint, eTAKEDAMAGETYPE_DAMAGE ); } else if( damage < 0 ) { if( pSkillTarget->mDetail[mDetailPos].mDetailDamageKind == eDAMAGE_NORMAL || pSkillTarget->mDetail[mDetailPos].mDetailDamageKind == eDAMAGE_CRITICAL ) pAttacker->HPHeal( -damage, false, pAttacker->GetObject(), 0, eTAKEDAMAGETYPE_NONE ); /// µ¥¹ÌÁö ¹Ý»ç Àΰæ¿ìÀÓ else if( pSkillTarget->mDetail[mDetailPos].mDetailDamageKind == eDAMAGE_NORMAL_MP || pSkillTarget->mDetail[mDetailPos].mDetailDamageKind == eDAMAGE_CRITICAL_MP ) pAttacker->MPHeal( -damage, false ); } mp = pSkillTarget->mDetail[mDetailPos].mDetailAttkAbsorbMP; totalMp = totalMp + mp; if( mp > 0 ) pAttacker->MPHeal( mp, false ); else if( mp < 0 ) pAttacker->MPDamage( abs(mp), false ); node = node->next; } if( totalDamage != 0 || totalMp != 0 ) { SKILLMANAGER->InsertChangeSet( pAttacker, mAttacker, eDAMAGE_NORMAL ); ++targetCnt; } } if( mpDetailBegin == 0 ) { assert(0); return false; } mpDetailBegin = (sDramaAction*)mpDetailBegin->pNext; ++mDetailPos; if( mDetailPos >= 10 ) { NETWORK2->PostServerEvent("cBaseSkillObject::ApplyHP mDetailPos[%d] >= 10", mDetailPos ); return false; } /// Àû¿ëÇ׸ñ ´õ ¾øÀ½ if( mpDetailBegin == NULL) return false; mDetailEndTime = mDetailStartTime + mpDetailBegin->time; return true; } void cBaseSkillObject::AddTotem( cBaseObject* pAttacker, unsigned long partyIdx, unsigned long partyUnionIdx, eAPPLYTYPE applyType, eATTRIBUTETYPE attributeType, unsigned long influenceClassIdx, unsigned char applyCnt ) { /// °ø°ÝÀÚ ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. cPlayer* pPlayer = GRIDMANAGER->FindFirstPlayer( pAttacker, true ); while( pPlayer != NULL ) { mSendAroundSet.Insert( pPlayer->GetObjectID() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } PerIoContext* perIoContext = NETWORK2->GetIoContext( IOCP_REQUEST_WRITE ); MSG_SYN_SKILL_APPLY* applyMsg = NULL; /// Àû¿ë ¸Þ¼¼Áö applyMsg = (MSG_SYN_SKILL_APPLY*)perIoContext->buffer; applyMsg->Category = NM_SKILL; applyMsg->Protocol = NM_SKILL_APPLY_SYN; applyMsg->mSkillIndex = mUniqueIdx; applyMsg->mAttackerType = mAttacker.type; applyMsg->mSkillClassIndex = mSkillIdx; applyMsg->mDramaKey = mDramaKey; applyMsg->mAttackerDie = mAttackerDie == 1; applyMsg->mIsChangeMonster = mIsChgMonsSkill; applyMsg->mApplyCount = 0; /// ¸Þ¼¼Áö º¸³»Á٠Ÿ°Ùµé ¼±Á¤ cBaseObject* pTarget = NULL; sObject target; if( mAttackerDie != 1 ) { PerNode* node = mTargetRoot.pool; while ( node != NULL ) { sSkillTargetInfo* pSkillTarget = (sSkillTargetInfo*)node; if( pSkillTarget == NULL ) { node = node->next; continue; } target = pSkillTarget->mTarget; switch( target.type ) { case eOBJECTTYPE_MONSTER: pTarget = GRIDMANAGER->GetMonster( target.index ); break; case eOBJECTTYPE_PLAYER: pTarget = GRIDMANAGER->GetPlayer( target.index ); break; default: pTarget = NULL; } if( pTarget == NULL ) { node = node->next; continue; } /// Ÿ°Ù ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. pPlayer = GRIDMANAGER->FindFirstPlayer( pTarget, true ); while( pPlayer != NULL ) { mSendAroundSet.Insert( pPlayer->GetObjectID() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } node = node->next; } } cHashSet::cIterator begin = mSendAroundSet.Begin(); cHashSet::cIterator end = mSendAroundSet.End(); while( begin != end ) { cPlayer* pSendPlayer = GRIDMANAGER->GetPlayer( *begin++ ); if( pSendPlayer != NULL ) NETWORK2->SendToUser( pSendPlayer->GetConnectionIdx(), (char*)applyMsg, applyMsg->GetMsgLength() ); } perIoContext->offset = applyMsg->GetMsgLength(); char text[255]; sprintf( text, "cBaseSkillObject::SendApply:MSG_SYN_SKILL_APPLY(%d %d %d %d %d %d %d %d %d)", mAttacker.type, mAttacker.index, applyMsg->GetMsgLength(), applyMsg->mSkillIndex, applyMsg->mAttackerType, applyMsg->mSkillClassIndex, applyMsg->mDramaKey, applyMsg->mIsChangeMonster, applyMsg->mApplyCount ); NETWORK2->ReleaseIoContext( perIoContext, text ); mDetailStartTime = NETWORK2->GetAccumTime(); if( mpDetailBegin != NULL ) mDetailEndTime = mDetailStartTime + mpDetailBegin->time; unsigned long skillIdx = 0; if( target.type == eOBJECTTYPE_PLAYER ) skillIdx = mSkillIdx; NiPoint2 centerPos( mCenterPos.x, mCenterPos.y ); cTotem* pTotem = OBJECTMANAGER->AddTotem( influenceClassIdx, partyIdx, partyUnionIdx, centerPos, pAttacker->GetObject(), applyType, attributeType, skillIdx, pAttacker->GetDirection(), applyCnt ); if( pTotem != NULL ) GRIDMANAGER->AddTotem( pTotem ); } void cBaseSkillObject::AddPortal( cBaseObject* pAttacker, unsigned long mapChangePosIdx ) { /// °ø°ÝÀÚ ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. cPlayer* pPlayer = GRIDMANAGER->FindFirstPlayer( pAttacker, true ); while( pPlayer != NULL ) { mSendAroundSet.Insert( pPlayer->GetObjectID() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } PerIoContext* perIoContext = NETWORK2->GetIoContext( IOCP_REQUEST_WRITE ); MSG_SYN_SKILL_APPLY* applyMsg = NULL; /// Àû¿ë ¸Þ¼¼Áö applyMsg = (MSG_SYN_SKILL_APPLY*)perIoContext->buffer; applyMsg->Category = NM_SKILL; applyMsg->Protocol = NM_SKILL_APPLY_SYN; applyMsg->mSkillIndex = mUniqueIdx; applyMsg->mAttackerType = mAttacker.type; applyMsg->mSkillClassIndex = mSkillIdx; applyMsg->mDramaKey = mDramaKey; applyMsg->mAttackerDie = mAttackerDie == 1; applyMsg->mIsChangeMonster = mIsChgMonsSkill; applyMsg->mApplyCount = 0; /// ¸Þ¼¼Áö º¸³»Á٠Ÿ°Ùµé ¼±Á¤ cBaseObject* pTarget = NULL; sObject target; if( mAttackerDie != 1 ) { PerNode* node = mTargetRoot.pool; while ( node != NULL ) { sSkillTargetInfo* pSkillTarget = (sSkillTargetInfo*)node; if( pSkillTarget == NULL ) { node = node->next; continue; } target = pSkillTarget->mTarget; switch( target.type ) { case eOBJECTTYPE_MONSTER: pTarget = GRIDMANAGER->GetMonster( target.index ); break; case eOBJECTTYPE_PLAYER: pTarget = GRIDMANAGER->GetPlayer( target.index ); break; default: pTarget = NULL; } if( pTarget == NULL ) { node = node->next; continue; } /// Ÿ°Ù ±×¸®µå¿¡ ÇØ´çÇÏ´Â Ç÷¹À̾ ¸ðµÎ ÀÐ¾î µ¥¹ÌÁö ¹ß¼ÛÀÚ ¸í´Ü¿¡ ³Ö´Â´Ù. pPlayer = GRIDMANAGER->FindFirstPlayer( pTarget, true ); while( pPlayer != NULL ) { mSendAroundSet.Insert( pPlayer->GetObjectID() ); pPlayer = GRIDMANAGER->FindNextPlayer( true ); } node = node->next; } } cHashSet::cIterator begin = mSendAroundSet.Begin(); cHashSet::cIterator end = mSendAroundSet.End(); while( begin != end ) { cPlayer* pSendPlayer = GRIDMANAGER->GetPlayer( *begin++ ); if( pSendPlayer != NULL ) NETWORK2->SendToUser( pSendPlayer->GetConnectionIdx(), (char*)applyMsg, applyMsg->GetMsgLength() ); } perIoContext->offset = applyMsg->GetMsgLength(); char text[255]; sprintf( text, "cBaseSkillObject::SendApply:MSG_SYN_SKILL_APPLY(%d %d %d %d %d %d %d %d %d)", mAttacker.type, mAttacker.index, applyMsg->GetMsgLength(), applyMsg->mSkillIndex, applyMsg->mAttackerType, applyMsg->mSkillClassIndex, applyMsg->mDramaKey, applyMsg->mIsChangeMonster, applyMsg->mApplyCount ); NETWORK2->ReleaseIoContext( perIoContext, text ); mDetailStartTime = NETWORK2->GetAccumTime(); if( mpDetailBegin != NULL ) mDetailEndTime = mDetailStartTime + mpDetailBegin->time; if( pAttacker->GetObjectType() == eOBJECTTYPE_PLAYER ) { NiPoint2 centerPos( mCenterPos.x, mCenterPos.y ); cUserPortal* pUserPortal = OBJECTMANAGER->AddUserPortal( mapChangePosIdx, pAttacker->GetObjectID(), pAttacker->GetMapNumber(), centerPos.x, centerPos.y ); if( pUserPortal != NULL ) { ((cPlayer*)pAttacker)->SetUserPortal( pUserPortal->GetObjectID() ); GRIDMANAGER->AddUserPortal( pUserPortal ); } } else NETWORK2->PostServerEvent("cBaseSkillObject::AddPortal pAttacker->GetObjectType() != eOBJECTTYPE_PLAYER" ); } unsigned long cBaseSkillObject::SkillEndTime() { unsigned long detailEndTime = 0; if( mpDetailEnd != NULL ) detailEndTime = mpDetailEnd->time; return (mCreationTime + mCastingTime + mActivityTime) - NETWORK2->GetAccumTime() + detailEndTime; }