#include "stdafx.h" #include "SGame.h" #include "SAction.h" #include "SSkillDB.h" #include "SMotionDB.h" #include "SGameMessage.h" #include "KSeqModel.h" #include "SGameAvatarEx.h" #include "GameDefine.h" #include "SGameUtil.h" #include "KRenderObjectEtc.h" #include "SSkillStageType.h" #include "GameRule.h" #include "SStringDB.h" #include "SMonsterDB.h" #include "SCreatureDB.h" #include "SNpcDB.h" #include "kviewport.h" #include "LuaVM.h" #include #include "EffectIDMng.h" #include "KSeqPathEffect.h" #include "SGameSkillFx.h" #include "SSoundResourceDB.h" #include "SDebug_Util.h" #include "KRenderObjectMesh.h" /// 2011.03.24 - prodongi extern const char * pEP_Name[]; extern const char * pEffectAniKey[]; // 2010.06.15 GameDefine.h로 옮김 - prodongi //#define FORCE_CHIP_SKILL_ID 6008 float g_fEffectSpeed = 0.f; const float g_fParabolaAngle = 90.0f; const float g_fParaboleDirRatio = 20.0f; ////////////////////////////////////////////////////////////////////////// //SGameAction SGameAction::SGameAction() { m_dwOldTime = 0; //전 시간 m_dwTime = 0; //현재 시간 m_dwStartTime = 0; //시작 시간 m_dwEndTime = 0; //끝날 시간 m_dwDelayTime = 0; //지연 시간 m_dwAddHitDelayTime = 0; //부가 히트FX 출력 딜레이 m_dwAddFireDelayTime = 0; //부가 발똥FX 출력 딜레이 //Process m_bIsEnd = false; //끝? m_nStep = STEP_00; //단계 m_nFxPos = EFFECT_POS_BOTTOM; //발바닥 m_fVisibility = 1.f; //투명도 m_velocity = K3DVector(0,0,0); //단위(타겟포스-현재위치) m_acc = 1.f; //가속도 m_SrcPos = K3DVector(0,0,0); //위치 01 m_DstPos = K3DVector(0,0,0); //위치 02 //GameObject m_pAttack = NULL; //시전자 m_pTarget = NULL; //대상 m_caster = 0; m_target = 0; m_pDamage = NULL; //Render m_pCast = NULL; //캐스트 m_pThrow = NULL; //발사체 m_pExplosion = NULL; //폭발 m_pReThrow = NULL; //역발사체 //부가 FX m_pSubStageHit = NULL; //부가 히트 FX m_pSubStageFire = NULL; //부가 발동 FX m_pCastFxSet = NULL; m_pThrowFxSet = NULL; m_pExplosionFxSet = NULL; m_pReThrowFxSet = NULL; m_pSubStageHitFxSet = NULL; m_pSubStageFireFxSet = NULL; m_pCastMat = NULL; m_pTargetMat = NULL; m_pCastBoneMat = NULL; m_pTargetBoneMat = NULL; m_pCasterAttachMat = NULL; m_pTargetAttachMat = NULL; K3DMatrixIdentity( m_Matrix ); Function_Step[STEP_01] = &SGameAction::Step01; Function_Step[STEP_02] = &SGameAction::Step02; Function_Step[STEP_03] = &SGameAction::Step03; Function_Step[STEP_04] = &SGameAction::Step04; Function_Step[STEP_05] = &SGameAction::Step05; Function_Step[STEP_06] = &SGameAction::Step06; Function_Step[STEP_07] = &SGameAction::Step07; Function_Step[STEP_08] = &SGameAction::Step08; Function_Step[STEP_09] = &SGameAction::Step09; Function_Step[STEP_10] = &SGameAction::Step10; m_iPlayStep = 0; m_iSoundIndex = 0; m_fLength = 0.0f; m_fGravity = 0.0f; m_fOldDot = 0.0f; m_btFlyingState = 0; m_iFlyingStyle = 0; m_vFrontNBackDir = K3DVector( 0.0f, 0.0f, 0.0f ); m_vLeftNRightDir = K3DVector( 0.0f, 0.0f, 0.0f ); m_dwFxTimeOver = 0; m_iResultIndex = 0; m_pSkill_FX = NULL; m_fFlyingTime = 0.f; m_fDistance = 0.f; m_fSpeed = 0.f; m_bMultiAttack = false; m_fParabolaDir = 0.0f; } SGameAction::~SGameAction() { SAFE_DELETE( m_pCast ); SAFE_DELETE( m_pThrow ); SAFE_DELETE( m_pExplosion ); SAFE_DELETE( m_pReThrow ); SAFE_DELETE( m_pSubStageHit ); SAFE_DELETE( m_pSubStageFire ); SAFE_DELETE( m_pDamage ); std::vector< SMSG_DAMAGE * >::iterator iter = m_DamageList.begin(); for( ; iter != m_DamageList.end() ; ) { SAFE_DELETE( (*iter) ); iter = m_DamageList.erase( iter ); } m_DamageList.clear(); m_pCastFxSet = NULL; m_pThrowFxSet = NULL; m_pExplosionFxSet = NULL; m_pReThrowFxSet = NULL; m_pSubStageHitFxSet = NULL; m_pSubStageFireFxSet = NULL; m_pCastMat = NULL; m_pTargetMat = NULL; m_pCastBoneMat = NULL; m_pTargetBoneMat = NULL; m_pSkill_FX = NULL; std::vector< SkillResult* >::iterator skillresult = m_vHPMPSPSkillResult.begin(); //HPMPSP SkillResult값 for( ; skillresult != m_vHPMPSPSkillResult.end(); ) { SAFE_DELETE( (*skillresult) ); skillresult = m_vHPMPSPSkillResult.erase( skillresult ); } if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); } } void SGameAction::GetFxPos( K3DMatrix &Out, class SGameAvatarEx * pAvatar ) { K3DMatrix matBonePos, mat, matPos; //뼈는 위치만 참조 K3DMatrixIdentity( matBonePos ); K3DMatrixIdentity( matPos ); assert( m_nFxPos <= EFFECT_POS_MAX && "The effect position is outdated" ); _CID( REQ_EVPOINT ); KMsgREQ_EVPOINT effect_pos_msg; pAvatar->Perform( ANIPART_BIPED, id_REQ_EVPOINT, effect_pos_msg ); KEventPointSeq * pEv = NULL; for( int i(0); effect_pos_msg.GetPointCount()>i; i++ ) { pEv = effect_pos_msg.GetPoint(i); const char * pName = pEv->GetName(); if( strlen(pName) && _stricmp( pName, pEP_Name[m_nFxPos] ) == 0 ) { break; } } if( pEv ) { matBonePos.SetPosVector( pEv->GetPoint().GetPosVector() ); K3DMatrixMultiply( Out, matBonePos, matPos ); } else { Out = *pAvatar->GetTransform(); } } void SGameAction::GetMatrixSet( class SGameAvatarEx * pCaster, class SGameAvatarEx * pTarget, int nFxPos ) { if( pCaster ) { m_pCastMat = pCaster->GetTransform(); m_pCastBoneMat = pCaster->GetEventPointMatrix( nFxPos ); m_pCasterAttachMat = pCaster->GetEventPointAttachMatrix( nFxPos ); } if( pTarget) { m_pTargetMat = pTarget->GetTransform(); m_pTargetBoneMat = pTarget->GetEventPointMatrix( nFxPos ); m_pTargetAttachMat = pTarget->GetEventPointAttachMatrix( nFxPos ); } } const K3DMatrix* SGameAction::GetBoneFxMat( class SGameAvatarEx * pAvatar, int iFxPos ) { assert( iFxPos <= EFFECT_POS_MAX && "The effect position is outdated" ); _CID( REQ_EVPOINT ); KMsgREQ_EVPOINT effect_pos_msg; pAvatar->Perform( ANIPART_BIPED, id_REQ_EVPOINT, effect_pos_msg ); KEventPointSeq * pEv = NULL; for( int i(0); effect_pos_msg.GetPointCount()>i; i++ ) { pEv = effect_pos_msg.GetPoint(i); const char * pName = pEv->GetName(); if( strlen(pName) && _stricmp( pName, pEP_Name[iFxPos] ) == 0 ) return &pEv->GetPoint(); } return NULL; } void SGameAction::GetParentFXMat( class SGameAvatarEx * pAvatar, int iFxPos ) { assert( iFxPos <= EFFECT_POS_MAX && "The effect position is outdated" ); _CID( REQ_EVPOINT ); KMsgREQ_EVPOINT effect_pos_msg; pAvatar->Perform( ANIPART_BIPED, id_REQ_EVPOINT, effect_pos_msg ); KEventPointSeq * pEv = NULL; for( int i(0); effect_pos_msg.GetPointCount()>i; i++ ) { pEv = effect_pos_msg.GetPoint(i); const char * pName = pEv->GetName(); if( strlen(pName) && _stricmp( pName, pEP_Name[iFxPos] ) == 0 ) { // m_pAttachMat = &pEv->GetPoint(); break; } } // m_pParentMat = pAvatar->GetTransform(); } void SGameAction::GetResultMat( K3DMatrix &Out, const K3DMatrix* ParentMat, const K3DMatrix* EvPointMat, const K3DMatrix* EvPointAttachMat ) { if( ParentMat && EvPointMat && EvPointAttachMat ) { K3DMatrixMultiply( Out, *EvPointAttachMat, *ParentMat ); K3DMatrixMultiply( Out, *EvPointMat, Out ); } else if( ParentMat && EvPointAttachMat ) { K3DMatrixMultiply( Out, *EvPointAttachMat, *ParentMat ); } else if( ParentMat && EvPointMat ) { K3DMatrixMultiply( Out, *EvPointMat, *ParentMat ); } else if( ParentMat ) Out = *ParentMat; else K3DMatrixIdentity( Out ); } //부채꼴 범위로 흡수체 시작 위치 가져오기 void SGameAction::GetFanShape() { m_velocity = m_SrcPos - m_DstPos; K3DVectorNormalize( m_velocity, m_velocity ); m_startvelocity = m_DstPos; if( m_iFlyingStyle == 1 || m_iFlyingStyle == 2 ) m_vFrontNBackDir = K3DVector(0.0f, 0.0f, 0.0f); else { m_vFrontNBackDir = m_DstPos; m_vFrontNBackDir.z = m_DstPos.z + 5.f; } int LeftNRight = (int)rand() % 2; float Height = (float)( rand() % 5 ) * 0.1f; // 0도 ~ 45도 사이 각을 구한다 m_vLeftNRightDir = K3DVector( Height, 0.0f, 1.0f ); K3DVectorCross( m_vLeftNRightDir, -m_velocity, m_vLeftNRightDir ); // 랜덤값에 따라 부호를 바꿔줘서 왼쪽이나 오른쪽에서 텨나오게 한다 if( LeftNRight > 0 ) { m_vLeftNRightDir.x = -m_vLeftNRightDir.x; m_vLeftNRightDir.y = -m_vLeftNRightDir.y; } m_dwStartTime = m_dwTime; m_dwEndTime = m_dwTime; } //중간 애니메이션 플레이 여부 void SGameAction::PlayMiddleAnimation( SGameAvatarEx* pCaster, KSeqForm* pSeq, _MOTION_FX_SET* pMoFxSet ) { if( m_iPlayStep == 0 ) { if( !pSeq->IsPlaying() ) { m_iPlayStep = 1; pSeq->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep], KSeqForm::SEQTYPE_LOOP ); if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( pMoFxSet->IsEffect[m_iPlayStep] ) { if( pMoFxSet->IsSound[m_iPlayStep] ) PlaySoundFx( pCaster, GetResourceDB().GetSoundResourceName( pMoFxSet->sound_middle_file_ID ), pMoFxSet, &m_DstPos, true ); } } } } } void SGameAction::PlaySoundFx( SGameAvatarEx* pCaster, const char* pFileName, _MOTION_FX_SET* pFxSetInfo, K3DVector* vPosition, bool bLoop ) { if( m_pMsgHandler && pFxSetInfo ) { m_iSoundIndex = m_pMsgHandler->StartSound( pCaster, pFileName, *vPosition, true, pFxSetInfo->nSound_volumn, bLoop, pFxSetInfo->sound_option ); m_strSound = pFileName; } } //흡수체 비행 스타일 1 bool SGameAction::AbsorberFlyingStyle01( KSeqForm* pSeq ) { if( m_dwTime - m_dwStartTime < 3000 ) { K3DVectorLerp( m_DstPos, m_startvelocity, m_vFrontNBackDir, (float)( m_dwTime - m_dwEndTime ) / 800.f ); if((float)( m_dwTime - m_dwEndTime ) < 800.f) pSeq->SetPosition( m_DstPos ); else { pSeq->SetPosition( m_vFrontNBackDir ); K3DVector vTemp = m_startvelocity; m_startvelocity = m_vFrontNBackDir; m_vFrontNBackDir = vTemp; m_dwEndTime = m_dwTime; } } else { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); m_velocity = m_SrcPos - m_DstPos; m_acc = K3DVectorLength( m_velocity ); calsAcc(); m_dwStartTime = m_dwTime; return false; } return true; } //흡수체 비행 스타일 2 bool SGameAction::AbsorberFlyingStyle02( KSeqForm* pSeq ) { //시전자의 반대방향으로 쑥 빠져나갔다가 부메랑처럼 턴하며 시전자에게로 가속도가 붙으며 날아와 명중함. /* float fSpeedF = ( m_dwTime - m_dwEndTime ) / 8.f; float fSpeedL = ( m_dwTime - m_dwEndTime ) / 25.f; m_dwEndTime = m_dwTime;*/ m_vFrontNBackDir += m_velocity * m_fGravity; m_DstPos += -( m_velocity * 6.f) + ( m_vLeftNRightDir * 2.f ); m_DstPos += m_vFrontNBackDir; float z = 0.f; WORD wTile=0; GetHeight( m_DstPos.x, m_DstPos.y, z, wTile ); z += 10.f; if( m_DstPos.z < z + 5.0f ) m_DstPos.z = z; pSeq->SetPosition( m_DstPos ); //대상의 처음위치와 이동한 만큼의 내적값이 0을 넘으면 시전자에게로 빨려간다 float Dot = K3DVectorDot( m_DstPos - m_startvelocity, m_SrcPos - m_startvelocity ); if( Dot > 0.0f ) { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); m_velocity = m_SrcPos - m_DstPos; m_acc = K3DVectorLength( m_velocity ); calsAcc(); m_dwStartTime = m_dwTime; return false; } return true; } //흡수체 비행 스타일 3 bool SGameAction::AbsorberFlyingStyle03( KSeqForm* pSeq ) { //근거리용. 1처럼 턴하여 시전자에게 날아오는데 시전자를 지나쳐서 날아갔다가 다시 부메랑처럼 턴하며 시전자에 명중함. /* float fSpeedF = ( m_dwTime - m_dwEndTime ) / 8.f; float fSpeedL = ( m_dwTime - m_dwEndTime ) / 25.f; m_dwEndTime = m_dwTime;*/ m_vFrontNBackDir += m_velocity * m_fGravity; m_DstPos += -( m_velocity * 6.f ) + ( m_vLeftNRightDir * 2.f ); m_DstPos += m_vFrontNBackDir ; /* float z = GetHeight( m_DstPos.x, m_DstPos.y ) + 10.0f; if( m_DstPos.z < z + 5.0f ) m_DstPos.z = z;*/ m_Matrix.SetPosVector( m_DstPos ); pSeq->SetTransform( m_Matrix ); K3DVector vTemp = m_startvelocity - m_SrcPos; K3DVector vTemp2 = m_DstPos - m_SrcPos; vTemp.Normalize(); vTemp2.Normalize(); float Dot = K3DVectorDot( vTemp, vTemp2 ); if( m_btFlyingState == 0 ) { if( Dot < 0.0f ) { m_velocity = -m_velocity; m_vLeftNRightDir = -m_vLeftNRightDir * 2.f; m_fGravity = m_fGravity * 4.f; m_fOldDot = Dot; m_btFlyingState = 1; } } else if( m_btFlyingState == 1 ) { if( m_fOldDot < Dot ) { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); m_velocity = m_SrcPos - m_DstPos; m_acc = K3DVectorLength( m_velocity ); calsAcc(); m_dwStartTime = m_dwTime; return false; } m_fOldDot = Dot; } return true; } //슈팅형 발사체 비행 스따일 void SGameAction::ShootingFlyingStyle() { switch( m_iFlyingStyle ) { case 0 : { GetSpeed(); m_btFlyingState = 0; SetStep( STEP_02 ); break; } case 1 : { m_velocity = m_DstPos - m_SrcPos; m_acc = K3DVectorLength( m_velocity ); calsAcc(); m_btFlyingState = 1; SetStep( STEP_02 ); break; } case 2 : { m_velocity = m_DstPos - m_SrcPos; m_acc = K3DVectorLength( m_velocity ); calsAcc(); //m_fLength == Angle; //m_fGravity == Velocity; //m_fOldDot == m_fTime; float fd, fh; m_fLength = -(float)( rand() % 5 - 20 ); fd = sqrtf( (( m_DstPos.x - m_SrcPos.x ) * ( m_DstPos.x - m_SrcPos.x )) + (( m_DstPos.y - m_SrcPos.y ) * ( m_DstPos.y - m_SrcPos.y )) ); fh = m_DstPos.z - m_SrcPos.z; // 각이 안나올경우에 Angle 보정 if( fd * tanf( m_fLength * 3.141592f / g_fParabolaAngle ) - fh <= 0 ) { float fRadian = atanf( fh / fd ); m_fLength = fRadian * g_fParabolaAngle / 3.141592f; m_fLength += 1; } // 초속도랑 걸리는 시간을 구한다. m_fGravity = ( fd / cosf( m_fLength * 3.141592f / g_fParabolaAngle ) ) * sqrtf( 9.8f / ( 2 * ( fd * tanf( m_fLength * 3.141592f / g_fParabolaAngle ) - fh ) ) ); m_fOldDot = fd / ( m_fGravity * cosf( m_fLength * 3.141592f / g_fParabolaAngle ) ); m_fParabolaDir = rand() % (int)g_fParaboleDirRatio; m_btFlyingState = 1; SetStep( STEP_03 ); break; } case 3 : { GetSpeed(); K3DVector vDir = m_DstPos - m_SrcPos; vDir.Normalize(); m_SrcPos = m_DstPos; // m_SrcPos.z = m_DstPos.z; m_SrcPos.z += 150.0f; m_SrcPos.x += vDir.x * 2.0f; m_SrcPos.y += vDir.y * 2.0f; m_btFlyingState = 0; SetStep( STEP_02 ); break; } case 4 : { /* float x = RandomNumber( -30.f, 30.f ); float y = RandomNumber( -30.f, 30.f ); m_SrcPos.x += x; m_SrcPos.y += y; m_DstPos.x += x; m_DstPos.y += y; m_SrcPos.z += RandomNumber( 50.f, 150.f );*/ GetSpeed(); m_SrcPos.z += 150.f; m_velocity = m_DstPos - m_SrcPos; m_velocity.Normalize(); m_SrcPos.x -= m_velocity.x * 50.0f; m_SrcPos.y -= m_velocity.y * 50.0f; m_btFlyingState = 0; SetStep( STEP_02 ); break; } } } float SGameAction::RandomNumber(float fMin, float fMax) { if (fMin == fMax) return(fMin); float fRandom = (float)rand() / (float)RAND_MAX; return((fRandom * (float)fabs(fMax-fMin))+fMin); }; K3DVector SGameAction::RandomNumber(K3DVector vMin, K3DVector vMax) { float x = RandomNumber(vMin.x, vMax.x); float y = RandomNumber(vMin.y, vMax.y); float z = RandomNumber(vMin.z, vMax.z); return(K3DVector(x,y,z)); }; K3DMatrix SGameAction::GetParabolaPos( float fIncrease ) { K3DVector DirVec = K3DVector( m_DstPos.x, m_DstPos.y, m_DstPos.z ) - m_SrcPos; K3DVector ResultVec; float fCount = m_fOldDot * fIncrease; /* K3DVector vDir = DirVec; K3DVector vUp( 0.0f, 0.0f, 1.f ); vDir.Normalize(); vDir = CrossProduct( vDir, vUp );*/ K3DVector vParabolaDir( 0.0f, 0.0f, 1.0f ); if( m_pAttack ) { K3DMatrix matRotY, matRotZ, matTrans; K3DMatrixRotationZ( matRotZ, m_pAttack->GetTargetRoll() + 3.1415926f/2 ); K3DMatrixRotationY( matRotY, m_fParabolaDir * ( ( K3D_PI ) / g_fParaboleDirRatio ) ); matRotY = matRotY * matRotZ; K3DMatrixTranslation( matTrans, -1.0f, 0.0f, 0.0f ); K3DMatrixMultiply( matTrans, matTrans, matRotY ); vParabolaDir = K3DVector( matTrans._41, matTrans._42, matTrans._43 ); vParabolaDir.Normalize(); } ResultVec = fIncrease * DirVec; vParabolaDir *= ( m_fGravity * sinf( m_fLength * 3.141592f / g_fParabolaAngle ) * fCount ) - ( 9.8f * ( fCount * fCount ) / 2 ); ResultVec += vParabolaDir; ResultVec += m_SrcPos; K3DMatrix matTrans; K3DMatrixTranslation( matTrans, ResultVec.x, ResultVec.y, ResultVec.z ); return matTrans; } bool SGameAction::CheckNowState( SGameAvatarEx* pAvatar ) { //임시로 현재 죽은 모션인지 체크한다 // if( pAvatar->GetCurrAnimationID() == 22 ) return false; if( pAvatar->GetCurrAnimationID() == 22 ) return true; return true; } void SGameAction::GetSpeed() { m_fSpeed = 70.0f; if( m_pSkill_FX == NULL ) return; if( g_fEffectSpeed > 0.f ) { m_fSpeed = g_fEffectSpeed; } else { switch( m_pSkill_FX->nStage_Type_Id ) { case SS_TYPE_151 : m_fSpeed = 50.0f; break; case SS_TYPE_201 : case SS_TYPE_212 : case SS_TYPE_251 : { m_fSpeed = m_pSkill_FX->fStage_Data[3]; break; } case SS_TYPE_402 : m_fSpeed = 50.0f; break; case SS_TYPE_411 : case SS_TYPE_412 : m_fSpeed = 70.0f; break; case SS_TYPE_501 : case SS_TYPE_502 : case SS_TYPE_503 : case SS_TYPE_504: /// 2011.03.23 - prodongi { m_fSpeed = m_pSkill_FX->fStage_Data[2]; break; } } } } void SGameAction::GetFlyingTime( const K3DVector* pSrc, const K3DVector* pDst ) { m_fDistance = K3DVectorLength( *pSrc - *pDst ); m_fFlyingTime = (m_fDistance / m_fSpeed) * 1000.f; } //발사체와 대상의 거리를 구한다 void SGameAction::calsAcc() { float velocity = 70.0f; if( m_pSkill_FX ) { if( g_fEffectSpeed > 0.f ) { velocity = g_fEffectSpeed; } else { switch( m_pSkill_FX->nStage_Type_Id ) { case SS_TYPE_151 : velocity = 50.0f; break; case SS_TYPE_201 : case SS_TYPE_212 : case SS_TYPE_251 : { velocity = m_pSkill_FX->fStage_Data[3]; break; } case SS_TYPE_402 : velocity = 50.0f; break; case SS_TYPE_411 : case SS_TYPE_412 : velocity = 70.0f; break; case SS_TYPE_501 : case SS_TYPE_502 : case SS_TYPE_503 : case SS_TYPE_504: /// 2011.03.23 - prodongi { velocity = m_pSkill_FX->fStage_Data[2]; break; } } } } m_acc = ( m_acc / GameRule::DEFAULT_UNIT_SIZE ) * velocity; } bool SGameAction::GetSkillFx( SMSG_SKILL_EVENT* pMsg ) { m_pSkill_FX = GetSkillStageDB().GetSkillStageData( pMsg->skill_id ); //스킬 데이터 if( m_pSkill_FX == NULL ) { _oprint( "Data Error: %d - Skill data not found\n", pMsg->skill_id ); SetEnd( true ); assert( 0 && "Data Error: %d - Skill data not found"); return false; } return true; } // Create normal attack and skill damage void SGameAction::MakeDamage( SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { // Fraun performance tweak if( m_iResultIndex < (int)pMsg->vSkillResult.size() ) { int nType = pMsg->vSkillResult[m_iResultIndex].GetType(); switch (nType) { case SkillResult::DAMAGE_WITH_KNOCK_BACK: { m_pDamage = new SMSG_DAMAGE; m_pDamage->attacker_handle = pMsg->caster; m_pDamage->target_handle = pMsg->vSkillResult[m_iResultIndex].damage_kb.hTarget; m_pDamage->nDamage = pMsg->vSkillResult[m_iResultIndex].damage_kb.damage; m_pDamage->flag = pMsg->vSkillResult[m_iResultIndex].damage_kb.flag; m_pDamage->skillresult = pMsg->vSkillResult[m_iResultIndex]; m_pDamage->nSkillID = pMsg->skill_id; m_pDamage->nSkillLevel = pMsg->skill_level; //m_pDamage->strTargetName = pMsg->target_name; m_pDamage->nHittingAdd_FxID = pSkillFx->nSub_Stage_On_Hit_Id; SGameAvatarEx* pCaster = (SGameAvatarEx*)GetGameObject(m_pDamage->attacker_handle); SGameAvatarEx* pTarget = (SGameAvatarEx*)GetGameObject(m_pDamage->target_handle); SetDamageDisplayName(m_pDamage, pCaster, pTarget); break; } case SkillResult::DAMAGE: case SkillResult::MAGIC_DAMAGE: case SkillResult::RESULT: { m_pDamage = new SMSG_DAMAGE; m_pDamage->attacker_handle = pMsg->caster; m_pDamage->target_handle = pMsg->vSkillResult[m_iResultIndex].GetTargetHandle(); m_pDamage->skillresult = pMsg->vSkillResult[m_iResultIndex]; m_pDamage->nSkillID = pMsg->skill_id; m_pDamage->nSkillLevel = pMsg->skill_level; //m_pDamage->strTargetName = pMsg->target_name; m_pDamage->nHittingAdd_FxID = pSkillFx->nSub_Stage_On_Hit_Id; SGameAvatarEx* pCaster = (SGameAvatarEx*)GetGameObject(m_pDamage->attacker_handle); SGameAvatarEx* pTarget = (SGameAvatarEx*)GetGameObject(m_pDamage->target_handle); SetDamageDisplayName(m_pDamage, pCaster, pTarget); break; } case SkillResult::REBIRTH: { m_pDamage = new SMSG_DAMAGE; m_pDamage->attacker_handle = pMsg->caster; m_pDamage->target_handle = pMsg->vSkillResult[m_iResultIndex].GetTargetHandle(); m_pDamage->skillresult = pMsg->vSkillResult[m_iResultIndex]; m_pDamage->nSkillID = pMsg->skill_id; m_pDamage->nSkillLevel = pMsg->skill_level; //m_pDamage->strTargetName = pMsg->target_name; m_pDamage->nHittingAdd_FxID = pSkillFx->nSub_Stage_On_Hit_Id; SGameAvatarEx* pCaster = (SGameAvatarEx*)GetGameObject(m_pDamage->attacker_handle); SGameAvatarEx* pTarget = (SGameAvatarEx*)GetGameObject(m_pDamage->target_handle); SetDamageDisplayName(m_pDamage, pCaster, pTarget); break; } } } else { if( m_pSkill_FX ) { //스킬 데미지가 없고 피해를 주는 스킬이면 끝낸다 //스킬 데미지가 없다면 버프형 스킬임 //피해를 주는 스킬인데도 불구 하고 데미지가 없다면 버그 if( m_pSkill_FX->szDeal_Damage != 0) SetEnd( true ); } } } //흡수 뎀쥐 만들기 void SGameAction::MakeDamageAbsorbe( SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pDamage = new SMSG_DAMAGE; m_pDamage->attacker_handle = pMsg->caster; m_pDamage->target_handle = pMsg->target; m_pDamage->nSkillID = pMsg->skill_id; m_pDamage->nSkillLevel = pMsg->skill_level; //m_pDamage->strTargetName = pMsg->target_name; m_pDamage->nHittingAdd_FxID = pSkillFx->nSub_Stage_On_Hit_Id; SGameAvatarEx* pCaster = (SGameAvatarEx *)GetGameObject( pMsg->caster ); SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( pMsg->target ); SetDamageDisplayName( m_pDamage, pCaster, pTarget ); int nSkillResultSize = (int)pMsg->vSkillResult.size(); for( int nCount = 0; nCount < nSkillResultSize; ++nCount ) { int nType = pMsg->vSkillResult[nCount].GetType(); // Fraun performance tweak switch (nType) { case SkillResult::DAMAGE: case SkillResult::MAGIC_DAMAGE: case SkillResult::DAMAGE_WITH_KNOCK_BACK: { m_pDamage->nDamage = pMsg->vSkillResult[nCount].damage.damage; m_pDamage->flag = pMsg->vSkillResult[nCount].damage.flag; m_pDamage->skillresult = pMsg->vSkillResult[nCount]; break; } case SkillResult::RESULT: { if (nCount == 0) { m_pDamage->skillresult = pMsg->vSkillResult[nCount]; } break; } default: { if (nType != SkillResult::RUSH && nType != SkillResult::NOT_USE && nCount != 0) { SkillResult* pSkillResult = new SkillResult; *pSkillResult = pMsg->vSkillResult[nCount]; if (IS_AUTO_ATTACK_CHIP_SKILL_ID(pMsg->skill_id) && pMsg->vSkillResult[nCount].GetType() == SkillResult::RESULT && pSkillResult->result.bResult == false) { m_pDamage->skillresult = *pSkillResult; } m_vHPMPSPSkillResult.push_back(pSkillResult); } break; } } /* if( nType == SkillResult::DAMAGE || nType == SkillResult::MAGIC_DAMAGE || nType == SkillResult::DAMAGE_WITH_KNOCK_BACK ) { m_pDamage->nDamage = pMsg->vSkillResult[nCount].damage.damage; m_pDamage->flag = pMsg->vSkillResult[nCount].damage.flag; m_pDamage->skillresult = pMsg->vSkillResult[nCount]; } else if( nType != SkillResult::RUSH && nType != SkillResult::NOT_USE ) { if( nType == SkillResult::RESULT && nCount == 0 ) { m_pDamage->skillresult = pMsg->vSkillResult[nCount]; } else { SkillResult* pSkillResult = new SkillResult; *pSkillResult = pMsg->vSkillResult[nCount]; //포스칩 실패 예외 처리 // 2010.06.15 - prodongi //if( pMsg->skill_id == FORCE_CHIP_SKILL_ID && pMsg->vSkillResult[nCount].GetType() == SkillResult::RESULT && pSkillResult->result.bResult == false ) if( IS_AUTO_ATTACK_CHIP_SKILL_ID(pMsg->skill_id) && pMsg->vSkillResult[nCount].GetType() == SkillResult::RESULT && pSkillResult->result.bResult == false ) { m_pDamage->skillresult = *pSkillResult; } m_vHPMPSPSkillResult.push_back( pSkillResult ); } } */ } } /// 2011.03.23 연쇄 이동형 공격 스킬 데미지 - prodongi void SGameAction::MakeChainDamage(struct _SKILL_FX* pSkillFx, SkillResult const& result, int skillId, char skillLevel, AR_HANDLE hCaster, AR_HANDLE hTarget, AR_HANDLE chainCaster) { int type = result.GetType(); // Fraun performance tweak switch (type) { case SkillResult::CHAIN_DAMAGE: case SkillResult::CHAIN_MAGIC_DAMAGE: { SGameAvatarEx* pCaster = (SGameAvatarEx*)GetGameObject(hCaster); SGameAvatarEx* pTarget = (SGameAvatarEx*)GetGameObject(hTarget); m_pDamage = new SMSG_DAMAGE; m_pDamage->attacker_handle = hCaster; m_pDamage->target_handle = hTarget; m_pDamage->skillresult = result; m_pDamage->nSkillID = skillId; m_pDamage->nSkillLevel = skillLevel; m_pDamage->strTargetName = pTarget->GetName(); m_pDamage->nHittingAdd_FxID = pSkillFx->nSub_Stage_On_Hit_Id; m_pDamage->nDamage = result.GetDamage(); m_pDamage->flag = result.chain_damage.flag; m_pDamage->chainCaster = chainCaster; SetDamageDisplayName(m_pDamage, pCaster, pTarget); break; } case SkillResult::CHAIN_HEAL: { SGameAvatarEx* pCaster = (SGameAvatarEx*)GetGameObject(hCaster); SGameAvatarEx* pTarget = (SGameAvatarEx*)GetGameObject(hTarget); m_pDamage = new SMSG_DAMAGE; m_pDamage->attacker_handle = hCaster; m_pDamage->target_handle = hTarget; m_pDamage->skillresult = result; m_pDamage->nSkillID = skillId; m_pDamage->nSkillLevel = skillLevel; m_pDamage->strTargetName = pTarget->GetName(); m_pDamage->nHittingAdd_FxID = pSkillFx->nSub_Stage_On_Hit_Id; m_pDamage->chainCaster = chainCaster; SetDamageDisplayName(m_pDamage, pCaster, pTarget); break; } } /*if (SkillResult::CHAIN_DAMAGE == type || SkillResult::CHAIN_MAGIC_DAMAGE == type) { SGameAvatarEx* pCaster = (SGameAvatarEx *)GetGameObject( hCaster ); SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( hTarget ); m_pDamage = new SMSG_DAMAGE; m_pDamage->attacker_handle = hCaster; m_pDamage->target_handle = hTarget; m_pDamage->skillresult = result; m_pDamage->nSkillID = skillId; m_pDamage->nSkillLevel = skillLevel; m_pDamage->strTargetName = pTarget->GetName(); m_pDamage->nHittingAdd_FxID = pSkillFx->nSub_Stage_On_Hit_Id; m_pDamage->nDamage = result.GetDamage(); m_pDamage->flag = result.chain_damage.flag; m_pDamage->chainCaster = chainCaster; SetDamageDisplayName( m_pDamage, pCaster, pTarget ); } else if (SkillResult::CHAIN_HEAL == type) { SGameAvatarEx* pCaster = (SGameAvatarEx *)GetGameObject( hCaster ); SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( hTarget ); m_pDamage = new SMSG_DAMAGE; m_pDamage->attacker_handle = hCaster; m_pDamage->target_handle = hTarget; m_pDamage->skillresult = result; m_pDamage->nSkillID = skillId; m_pDamage->nSkillLevel = skillLevel; m_pDamage->strTargetName = pTarget->GetName(); m_pDamage->nHittingAdd_FxID = pSkillFx->nSub_Stage_On_Hit_Id; m_pDamage->chainCaster = chainCaster; SetDamageDisplayName( m_pDamage, pCaster, pTarget ); }*/ } //지면 흡수체 생성 void SGameAction::MakeAbsorbe( SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { if( m_iResultIndex < (int)pMsg->vSkillResult.size() ) { m_pDamage = new SMSG_DAMAGE; m_pDamage->attacker_handle = pMsg->caster; m_pDamage->nSkillID = pMsg->skill_id; m_pDamage->nSkillLevel = pMsg->skill_level; //m_pDamage->strTargetName = pMsg->target_name; SGameAvatarEx* pCaster = (SGameAvatarEx *)GetGameObject( m_pDamage->attacker_handle ); SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( m_pDamage->target_handle ); SetDamageDisplayName( m_pDamage, pCaster, pTarget ); int nType = pMsg->vSkillResult[m_iResultIndex].GetType(); if( nType == SkillResult::ADD_HP || nType == SkillResult::ADD_MP || nType == SkillResult::ADD_HP_MP_SP || nType == SkillResult::REBIRTH || nType == SkillResult::RESULT ) { SkillResult* pSkillResult = new SkillResult; *pSkillResult = pMsg->vSkillResult[m_iResultIndex]; m_pDamage->target_handle = pMsg->vSkillResult[m_iResultIndex].GetTargetHandle(); m_vHPMPSPSkillResult.push_back( pSkillResult ); } } else SetEnd( true ); } void SGameAction::SetDamageDisplayName( SMSG_DAMAGE* pDamage, SGameAvatarEx* pCaster, SGameAvatarEx* pTarget ) { if( pCaster ) { // Fraun performance tweak switch (pCaster->GetObjType()) { case TS_ENTER::GAME_PLAYER: { pDamage->strCasterName = pCaster->GetName(); break; } case TS_ENTER::GAME_MOB: { pDamage->strCasterName = GetStringDB().GetString(GetMonsterDB().GetTextID(pCaster->GetContentID())); break; } case TS_ENTER::GAME_SUMMON: { pDamage->strCasterName = GetStringDB().GetString(GetCreatureDB().GetTextID(pCaster->GetContentID())); break; } case TS_ENTER::GAME_NPC: { pDamage->strCasterName = GetStringDB().GetString(GetNpcDB().GetTextID(pCaster->GetContentID())); break; } default: { pDamage->strCasterName = GetStringDB().GetString(88); break; } } //if( pCaster->GetObjType() == TS_ENTER::GAME_PLAYER ) // pDamage->strCasterName = pCaster->GetName(); //else if( pCaster->GetObjType() == TS_ENTER::GAME_MOB ) // pDamage->strCasterName = GetStringDB().GetString( GetMonsterDB().GetTextID( pCaster->GetContentID() ) ); //else if( pCaster->GetObjType() == TS_ENTER::GAME_SUMMON ) // pDamage->strCasterName = GetStringDB().GetString( GetCreatureDB().GetTextID( pCaster->GetContentID() ) ) ; //else if( pCaster->GetObjType() == TS_ENTER::GAME_NPC ) // pDamage->strCasterName = GetStringDB().GetString( GetNpcDB().GetTextID( pCaster->GetContentID() ) ); //else // pDamage->strCasterName = GetStringDB().GetString( 88 ); } if( pTarget ) { // Fraun performance tweak switch(pTarget->GetObjType()) { case TS_ENTER::GAME_PLAYER: { pDamage->strTargetName = pTarget->GetName(); break; } case TS_ENTER::GAME_MOB: { pDamage->strTargetName = GetStringDB().GetString(GetMonsterDB().GetTextID(pTarget->GetContentID())); break; } case TS_ENTER::GAME_SUMMON: { pDamage->strTargetName = GetStringDB().GetString(GetCreatureDB().GetTextID(pTarget->GetContentID())); break; } case TS_ENTER::GAME_NPC: { pDamage->strTargetName = GetStringDB().GetString(GetNpcDB().GetTextID(pTarget->GetContentID())); break; } default: { pDamage->strTargetName = GetStringDB().GetString(88); break; } } /*if( pTarget->GetObjType() == TS_ENTER::GAME_PLAYER ) pDamage->strTargetName = pTarget->GetName(); else if( pTarget->GetObjType() == TS_ENTER::GAME_MOB ) pDamage->strTargetName = GetStringDB().GetString( GetMonsterDB().GetTextID( pTarget->GetContentID() ) ); else if( pTarget->GetObjType() == TS_ENTER::GAME_SUMMON ) pDamage->strTargetName = GetStringDB().GetString( GetCreatureDB().GetTextID( pTarget->GetContentID() ) ) ; else if( pTarget->GetObjType() == TS_ENTER::GAME_NPC ) pDamage->strTargetName = GetStringDB().GetString( GetNpcDB().GetTextID( pTarget->GetContentID() ) ); else pDamage->strTargetName = GetStringDB().GetString( 88 );*/ } } bool SGameAction::CheckDamage( const struct SMSG_DAMAGE* pDamage ) { if( pDamage == NULL ) //뎀쥐가 없다면 끝낸다 { SetEnd(true); return false; } int nSkilltype = pDamage->skillresult.GetType(); // Fraun performance tweak switch (nSkilltype) { case SkillResult::DAMAGE: case SkillResult::MAGIC_DAMAGE: case SkillResult::CHAIN_DAMAGE: case SkillResult::CHAIN_MAGIC_DAMAGE: { if ((pDamage->skillresult.damage.flag & SkillResult::MISS) || (pDamage->skillresult.damage.flag & SkillResult::PERFECT_BLOCK)) { return false; } else { return true; } break; } case SkillResult::DAMAGE_WITH_KNOCK_BACK: { if ((pDamage->skillresult.damage_kb.flag & SkillResult::MISS) || (pDamage->skillresult.damage_kb.flag & SkillResult::PERFECT_BLOCK)) { return false; } else { return true; } break; } case SkillResult::RESULT: { return pDamage->skillresult.result.bResult; break; } case SkillResult::NOT_USE: { return true; break; } } /*if( nSkilltype == SkillResult::DAMAGE || nSkilltype == SkillResult::MAGIC_DAMAGE || nSkilltype == SkillResult::CHAIN_DAMAGE || nSkilltype == SkillResult::CHAIN_MAGIC_DAMAGE) { if( (pDamage->skillresult.damage.flag & SkillResult::MISS) || (pDamage->skillresult.damage.flag & SkillResult::PERFECT_BLOCK ) ) { return false; } else return true; } else if( nSkilltype == SkillResult::DAMAGE_WITH_KNOCK_BACK ) { if( (pDamage->skillresult.damage_kb.flag & SkillResult::MISS) || (pDamage->skillresult.damage_kb.flag & SkillResult::PERFECT_BLOCK ) ) { return false; } else return true; } else if( nSkilltype == SkillResult::RESULT ) { return pDamage->skillresult.result.bResult; } else if( nSkilltype != SkillResult::NOT_USE ) return true;*/ return false; } void SGameAction::RunScript( const struct SMSG_DAMAGE* pDamage ) { // Fraun performance tweak TODO: Change later /* std::string strSound, strEffect; XStringUtil::Format( strSound, "%s( %u, %u, %d, %d )", "avatar_basic_hit", m_caster, m_target, ( pDamage->flag & SkillResult:: CRITICAL ), ( pDamage->flag & SkillResult::PERFECT_BLOCK ) ); if( strSound.length() ) LUA()->RunString( strSound.c_str() ); XStringUtil::Format( strEffect, "%s( %u, %u )", "call_fx_ch_weapone_attack", m_caster, m_target ); if( strEffect.length() ) LUA()->RunString( strEffect.c_str() ); */ } void SGameAction::AddFxData( const AR_HANDLE & owner, const AR_HANDLE & attack, const AR_HANDLE & target, const int & nFX_ID, const int & nFX_pos ) { if( m_pMsgHandler ) { FX_DATA fx_data; fx_data.owner = owner; fx_data.attack = attack; fx_data.target = target; fx_data.nFX_ID = nFX_ID; //시전(타격)연출 보조FX ID fx_data.nEffPos = nFX_pos; //시전(타격)연출 보조FX 위치 m_pMsgHandler->AddEffect( &fx_data ); } } void SGameAction::SetFxData() { NX3LoadPack loadpack; loadpack.Init(); switch( m_pSkill_FX->nStage_Type_Id ) { //SGameWork에서 처리됨 /* case SS_TYPE_101 : case SS_TYPE_111 : case SS_TYPE_121 : case SS_TYPE_122 : case SS_TYPE_123 : { m_pSubStageHitFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nSub_Fire_Fx_Set_Id ); m_dwAddHitDelayTime = m_pSkill_FX->nSub_Hit_Fx_OutPut_Delay * 1000; m_dwAddFireDelayTime = m_pSkill_FX->nFire_Fx_OutPut_Delay * 1000; m_nFxSubHitPos = m_pSkill_FX->nHit_Fx_Set_Position_Id; m_nFxSubFirePos = m_pSkill_FX->nSub_Fire_Fx_Position; SetStep( STEP_01 ); break; }*/ //연출이 없다 /* case SS_TYPE_171 : { m_nEndFireMotionID = m_pSkill_FX->fStage_Data[6]; m_pExplosionFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->fStage_Data[7] ); if( m_pExplosionFxSet ) { KSeqModel * pExplosion = new KSeqModel; pExplosion->AddAnimation( pEffectAniKey[0], m_pExplosionFxSet->pszGraphic_effect_start_file ); pExplosion->AddAnimation( pEffectAniKey[1], m_pExplosionFxSet->pszGraphic_effect_middle_file ); pExplosion->AddAnimation( pEffectAniKey[2], m_pExplosionFxSet->pszGraphic_effect_end_file ); m_pExplosion = pExplosion; } m_nFxPos = m_pSkill_FX->fStage_Data[8]; m_pSubStageHitFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nSub_Fire_Fx_Set_Id ); m_dwAddHitDelayTime = m_pSkill_FX->nSub_Hit_Fx_OutPut_Delay * 1000; m_dwAddFireDelayTime = m_pSkill_FX->nFire_Fx_OutPut_Delay * 1000; m_nFxSubHitPos = m_pSkill_FX->nHit_Fx_Set_Position_Id; m_nFxSubFirePos = m_pSkill_FX->nSub_Fire_Fx_Position; SetStep( STEP_01 ); break; }*/ //활 계열 case SS_TYPE_201 : case SS_TYPE_212 : { m_pThrowFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->fStage_Data[2] ); //화살 FX if( m_pThrowFxSet ) { KSeqModel * pFire = new KSeqModel; pFire->AddAnimation( pEffectAniKey[0], GetResourceDB().GetEffectResourceName( m_pThrowFxSet->graphic_effect_start_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pFire->AddAnimation( pEffectAniKey[1], GetResourceDB().GetEffectResourceName( m_pThrowFxSet->graphic_effect_middle_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pFire->AddAnimation( pEffectAniKey[2], GetResourceDB().GetEffectResourceName( m_pThrowFxSet->graphic_effect_end_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); m_pThrow = pFire; } m_pSubStageHitFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nSub_Fire_Fx_Set_Id ); m_dwAddHitDelayTime = m_pSkill_FX->nSub_Hit_Fx_OutPut_Delay * 1000; m_dwAddFireDelayTime = m_pSkill_FX->nFire_Fx_OutPut_Delay * 1000; m_nFxSubHitPos = m_pSkill_FX->nHit_Fx_Set_Position_Id; m_nFxSubFirePos = m_pSkill_FX->nSub_Fire_Fx_Position; if( m_pThrowFxSet == NULL ) SetEnd( true ); SetStep( STEP_01 ); break; } case SS_TYPE_251 : { m_pThrowFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->fStage_Data[2] ); //화살 FX m_pReThrowFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->fStage_Data[6] ); //흡수체 FX m_pExplosionFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->fStage_Data[8] ); //회복 FX if( m_pThrowFxSet ) { KSeqModel * pFire = new KSeqModel; pFire->AddAnimation( pEffectAniKey[0], GetResourceDB().GetEffectResourceName( m_pThrowFxSet->graphic_effect_start_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pFire->AddAnimation( pEffectAniKey[1], GetResourceDB().GetEffectResourceName( m_pThrowFxSet->graphic_effect_middle_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pFire->AddAnimation( pEffectAniKey[2], GetResourceDB().GetEffectResourceName( m_pThrowFxSet->graphic_effect_end_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); m_pThrow = pFire; } if( m_pReThrowFxSet ) { KSeqModel * pDeflateFx = new KSeqModel; pDeflateFx->AddAnimation( pEffectAniKey[0], GetResourceDB().GetEffectResourceName( m_pReThrowFxSet->graphic_effect_start_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pDeflateFx->AddAnimation( pEffectAniKey[1], GetResourceDB().GetEffectResourceName( m_pReThrowFxSet->graphic_effect_middle_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pDeflateFx->AddAnimation( pEffectAniKey[2], GetResourceDB().GetEffectResourceName( m_pReThrowFxSet->graphic_effect_end_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); m_pReThrow = pDeflateFx; } m_pSubStageHitFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nSub_Fire_Fx_Set_Id ); m_dwAddHitDelayTime = m_pSkill_FX->nSub_Hit_Fx_OutPut_Delay * 1000; m_dwAddFireDelayTime = m_pSkill_FX->nFire_Fx_OutPut_Delay * 1000; m_nFxSubHitPos = m_pSkill_FX->nHit_Fx_Set_Position_Id; m_nFxSubFirePos = m_pSkill_FX->nSub_Fire_Fx_Position; if( m_pThrowFxSet == NULL || m_pReThrowFxSet == NULL || m_pExplosionFxSet == NULL ) SetEnd( true ); SetStep( STEP_01 ); break; } case SS_TYPE_301 : case SS_TYPE_401 : case SS_TYPE_404 : { m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nSub_Fire_Fx_Set_Id ); m_pSubStageHitFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); if( m_pSubStageFireFxSet ) { KSeqModel* pSubCast = new KSeqModel; pSubCast->AddAnimation( pEffectAniKey[0], GetResourceDB().GetEffectResourceName( m_pSubStageFireFxSet->graphic_effect_start_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pSubCast->AddAnimation( pEffectAniKey[1], GetResourceDB().GetEffectResourceName( m_pSubStageFireFxSet->graphic_effect_middle_file_ID), KNX3Manager::SEQTYPE_ALL, &loadpack ); pSubCast->AddAnimation( pEffectAniKey[2], GetResourceDB().GetEffectResourceName( m_pSubStageFireFxSet->graphic_effect_end_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); m_pSubStageFire = pSubCast; } if( m_pSubStageHitFxSet ) { KSeqModel* pSubHit = new KSeqModel; pSubHit->AddAnimation( pEffectAniKey[0], GetResourceDB().GetEffectResourceName( m_pSubStageHitFxSet->graphic_effect_start_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pSubHit->AddAnimation( pEffectAniKey[1], GetResourceDB().GetEffectResourceName( m_pSubStageHitFxSet->graphic_effect_middle_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pSubHit->AddAnimation( pEffectAniKey[2], GetResourceDB().GetEffectResourceName( m_pSubStageHitFxSet->graphic_effect_end_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); m_pSubStageHit = pSubHit; } m_dwAddHitDelayTime = m_pSkill_FX->nSub_Hit_Fx_OutPut_Delay * 1000; m_dwAddFireDelayTime = m_pSkill_FX->nFire_Fx_OutPut_Delay * 1000; m_nFxSubHitPos = m_pSkill_FX->nHit_Fx_Set_Position_Id; m_nFxSubFirePos = m_pSkill_FX->nSub_Fire_Fx_Position; SetStep( STEP_01 ); break; } case SS_TYPE_151 : case SS_TYPE_402 : case SS_TYPE_403 : { m_pCastFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->fStage_Data[1] ); m_pReThrowFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->fStage_Data[3] ); if( m_pCastFxSet ) { KSeqModel * pManaStill = new KSeqModel; pManaStill->AddAnimation( pEffectAniKey[0], GetResourceDB().GetEffectResourceName( m_pCastFxSet->graphic_effect_start_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pManaStill->AddAnimation( pEffectAniKey[1], GetResourceDB().GetEffectResourceName( m_pCastFxSet->graphic_effect_middle_file_ID), KNX3Manager::SEQTYPE_ALL, &loadpack ); pManaStill->AddAnimation( pEffectAniKey[2], GetResourceDB().GetEffectResourceName( m_pCastFxSet->graphic_effect_end_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); m_pCast = pManaStill; } m_dwDelayTime = m_pSkill_FX->fStage_Data[0] * 1000; m_pSubStageHitFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nSub_Fire_Fx_Set_Id ); m_dwAddHitDelayTime = m_pSkill_FX->nSub_Hit_Fx_OutPut_Delay * 1000; m_dwAddFireDelayTime = m_pSkill_FX->nFire_Fx_OutPut_Delay * 1000; m_nFxSubHitPos = m_pSkill_FX->nHit_Fx_Set_Position_Id; m_nFxSubFirePos = m_pSkill_FX->nSub_Fire_Fx_Position; if( m_pCastFxSet == NULL || m_pReThrowFxSet == NULL ) SetEnd( true ); SetStep( STEP_01 ); break; } case SS_TYPE_411 : { //부가 FX m_pSubStageHitFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nSub_Fire_Fx_Set_Id ); m_dwAddHitDelayTime = m_pSkill_FX->nSub_Hit_Fx_OutPut_Delay * 1000; m_dwAddFireDelayTime = m_pSkill_FX->nFire_Fx_OutPut_Delay * 1000; m_nFxPos = m_pSkill_FX->fStage_Data[1]; m_iFlyingStyle = m_pSkill_FX->fStage_Data[2]; m_nFxSubHitPos = m_pSkill_FX->nHit_Fx_Set_Position_Id; m_nFxSubFirePos = m_pSkill_FX->nSub_Fire_Fx_Position; SetStep( STEP_01 ); break; } case SS_TYPE_412 : { m_pCastFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->fStage_Data[0] ); if( m_pCastFxSet ) { KSeqModel * pCast = new KSeqModel; pCast->AddAnimation( pEffectAniKey[0], GetResourceDB().GetEffectResourceName( m_pCastFxSet->graphic_effect_start_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pCast->AddAnimation( pEffectAniKey[1], GetResourceDB().GetEffectResourceName( m_pCastFxSet->graphic_effect_middle_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pCast->AddAnimation( pEffectAniKey[2], GetResourceDB().GetEffectResourceName( m_pCastFxSet->graphic_effect_end_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); m_pCast = pCast; } m_pSubStageHitFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nSub_Fire_Fx_Set_Id ); m_dwAddHitDelayTime = m_pSkill_FX->nSub_Hit_Fx_OutPut_Delay * 1000; m_dwAddFireDelayTime = m_pSkill_FX->nFire_Fx_OutPut_Delay * 1000; m_nFxPos = m_pSkill_FX->fStage_Data[1]; m_nFxSubHitPos = m_pSkill_FX->nHit_Fx_Set_Position_Id; m_nFxSubFirePos = m_pSkill_FX->nSub_Fire_Fx_Position; SetStep( STEP_01 ); break; } case SS_TYPE_501 : case SS_TYPE_502 : case SS_TYPE_503 : case SS_TYPE_504: /// 2011.03.23 - prodongi { m_pCastFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->fStage_Data[0] ); if( m_pCastFxSet ) { KSeqModel * pCast = new KSeqModel; pCast->AddAnimation( pEffectAniKey[0], GetResourceDB().GetEffectResourceName( m_pCastFxSet->graphic_effect_start_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pCast->AddAnimation( pEffectAniKey[1], GetResourceDB().GetEffectResourceName( m_pCastFxSet->graphic_effect_middle_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pCast->AddAnimation( pEffectAniKey[2], GetResourceDB().GetEffectResourceName( m_pCastFxSet->graphic_effect_end_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); m_pCast = pCast; } m_pSubStageHitFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nSub_Fire_Fx_Set_Id ); m_dwAddHitDelayTime = m_pSkill_FX->nSub_Hit_Fx_OutPut_Delay * 1000; m_dwAddFireDelayTime = m_pSkill_FX->nFire_Fx_OutPut_Delay * 1000; m_nFxSubHitPos = m_pSkill_FX->nHit_Fx_Set_Position_Id; m_nFxSubFirePos = m_pSkill_FX->nSub_Fire_Fx_Position; m_iFlyingStyle = m_pSkill_FX->fStage_Data[1]; if( m_pCastFxSet == NULL ) SetEnd( true ); /// 2011.03.23 - prodongi if (SS_TYPE_504 == m_pSkill_FX->nStage_Type_Id) { setCurChainResultIndex(0); } else { SetStep( STEP_01 ); } break; } case SS_TYPE_601: { if( m_pSkill_FX->fStage_Data[1] != 0 ) //0이면 기존 연출 1이면 동료 및 적 판 { if( IsPartyRaidMemeber( m_target ) ) { m_pExplosionFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->fStage_Data[2] ); m_nFxPos = (int)m_pSkill_FX->fStage_Data[3]; } else { m_pExplosionFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->fStage_Data[4] ); m_nFxPos = (int)m_pSkill_FX->fStage_Data[5]; } } m_pSubStageHitFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nSub_Fire_Fx_Set_Id ); m_dwAddHitDelayTime = m_pSkill_FX->nSub_Hit_Fx_OutPut_Delay * 1000; m_dwAddFireDelayTime = m_pSkill_FX->nFire_Fx_OutPut_Delay * 1000; m_nFxSubHitPos = m_pSkill_FX->nHit_Fx_Set_Position_Id; m_nFxSubFirePos = m_pSkill_FX->nSub_Fire_Fx_Position; } break; case SS_TYPE_604: { m_pSubStageHitFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nSub_Fire_Fx_Set_Id ); m_dwAddHitDelayTime = m_pSkill_FX->nSub_Hit_Fx_OutPut_Delay * 1000; m_dwAddFireDelayTime = m_pSkill_FX->nFire_Fx_OutPut_Delay * 1000; m_nFxSubHitPos = m_pSkill_FX->nHit_Fx_Set_Position_Id; m_nFxSubFirePos = m_pSkill_FX->nSub_Fire_Fx_Position; } break; case SS_TYPE_901: { m_pCastFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->fStage_Data[0] ); if( m_pCastFxSet ) { KSeqModel * pCast = new KSeqModel; pCast->AddAnimation( pEffectAniKey[0], GetResourceDB().GetEffectResourceName( m_pCastFxSet->graphic_effect_start_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pCast->AddAnimation( pEffectAniKey[1], GetResourceDB().GetEffectResourceName( m_pCastFxSet->graphic_effect_middle_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pCast->AddAnimation( pEffectAniKey[2], GetResourceDB().GetEffectResourceName( m_pCastFxSet->graphic_effect_end_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); m_pCast = pCast; } m_pSubStageHitFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nSub_Fire_Fx_Set_Id ); m_dwAddHitDelayTime = m_pSkill_FX->nSub_Hit_Fx_OutPut_Delay * 1000; m_dwAddFireDelayTime = m_pSkill_FX->nFire_Fx_OutPut_Delay * 1000; m_nFxSubHitPos = m_pSkill_FX->nHit_Fx_Set_Position_Id; m_nFxSubFirePos = m_pSkill_FX->nSub_Fire_Fx_Position; m_iFlyingStyle = m_pSkill_FX->fStage_Data[1]; if( m_pCastFxSet == NULL ) SetEnd( true ); SetStep( STEP_01 ); break; } } } bool SGameAction::CheckAttacker() { m_pAttack = (SGameAvatarEx *)GetGameObject( m_caster ); if( m_pAttack == NULL) { SetEnd( TRUE ); return false; } return true; } bool SGameAction::CheckTarget() { m_pTarget = (SGameAvatarEx *)GetGameObject( m_target ); if( m_pTarget == NULL) { SetEnd( TRUE ); return false; } return true; } bool SGameAction::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { return true; } bool SGameAction::Process( DWORD dwTime, unsigned long uProcessBitVector ) { /* m_pAttack = (SGameAvatarEx *)GetGameObject( m_caster ); m_pTarget = (SGameAvatarEx *)GetGameObject( m_target ); if( m_pAttack == NULL ) { SetEnd(TRUE); return true; } if( m_pTarget == NULL ) { SetEnd(TRUE); return true; }*/ return true; } bool SGameAction::Step01(){ return true; } bool SGameAction::Step02(){ return true; } bool SGameAction::Step03(){ return true; } bool SGameAction::Step04(){ return true; } bool SGameAction::Step05(){ return true; } bool SGameAction::Step06(){ return true; } bool SGameAction::Step07(){ return true; } bool SGameAction::Step08(){ return true; } bool SGameAction::Step09(){ return true; } bool SGameAction::Step10(){ return true; } void SGameAction::SendSkillDamage( SGameAvatarEx* pAvatar, AR_HANDLE caster, AR_HANDLE target, SMSG_DAMAGE* pDamage ) { std::vector< SkillResult* >::iterator iter = m_vHPMPSPSkillResult.begin(); for( ; iter != m_vHPMPSPSkillResult.end(); ++iter ) { pDamage->skillresult = *(*iter); pAvatar->OnSkillDamage( caster, pDamage->skillresult.GetTargetHandle(), pDamage ); } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Fire Mng - 데미지 수 만큼의 덩어리 제어 SFireActMng::SFireActMng( SMSG_ATTACK * pMsg, SGameObject * pMsgHandler ) { m_nInterval = 10; //간격 m_nCount = 1; m_nTotalCount = 1; m_nTotalCount = m_nCount = pMsg->count; SetMessageHandler( pMsgHandler ); for( int i(0); m_nCount>i; i++ ) { SGameAction* pAct = g_Effect_ID.GetActionBowSKill( pMsg ); if( pAct ) { pAct->SetMessageHandler( pMsgHandler ); pAct->SetResultIndex( i ); pAct->InitFx( pMsg ); m_pReadyList.push( pAct ); } } if( m_pReadyList.empty() ) m_nTotalCount = 0; if( m_nCount && !m_pReadyList.empty() ) { SGameAction* pAct = m_pReadyList.front(); m_pReadyList.pop(); m_pFireList.push_back( pAct ); } else { SetEnd(true); } } SFireActMng::SFireActMng( SMSG_SKILL_EVENT * pMsg, SGameObject * pMsgHandler ) { assert( ( pMsg->status_type == TS_SC_SKILL::FIRE || pMsg->status_type == TS_SC_SKILL::REGION_FIRE ) && "스킬 메세지가 Fire가 아님" ); if( !GetSkillFx( pMsg ) ) { SetEnd( true ); return; } m_nInterval = 0; //간격 SetMessageHandler( pMsgHandler ); //연타 처리 if( pMsg->fire.bMultiple ) { m_nTotalCount = m_nCount = pMsg->fire.target_count; } else { switch( m_pSkill_FX->nStage_Type_Id ) { case 201: //화살 계열 스킬일경우 한방짤이 case 212: case 251: { m_nTotalCount = m_nCount = pMsg->fire.target_count; } break; case 401: { m_nTotalCount = m_nCount = pMsg->fire.target_count; } break; case 501: case 502: //광역 스킬 { m_nTotalCount = m_nCount = pMsg->fire.count; } break; case 504: /// 2011.03.23 - prodongi if (!pMsg->vSkillResult.empty()) { m_nTotalCount = m_nCount = 1; } break; case 601: case 604: { m_nTotalCount = m_nCount = pMsg->fire.target_count; } break; default: { //타겟에 한번에 여러발 쏘기 if( pMsg->fire.target_count > 0 ) { m_nTotalCount = m_nCount = pMsg->fire.fire_count; //한번에 여러발이 나가는 스킬일 경우 간격을 준다 ( 뎀쥐 수치가 겹치기 때문에 간격을 줘야한다 ) if( m_nCount > 1 ) m_nInterval = 10; } else m_nTotalCount = m_nCount = 0; } } } for( int i = 0; m_nCount > i; i++ ) { SGameAction* pAct = g_Effect_ID.GetActionSkill( m_pSkill_FX ); if( pAct ) { pAct->SetMessageHandler( pMsgHandler ); pAct->SetResultIndex( i ); if( m_nCount > 1 ) pAct->SetMultiAttackInfo( true ); pAct->InitFx( pMsg, m_pSkill_FX ); m_pReadyList.push( pAct ); } } if( m_pReadyList.empty() ) m_nTotalCount = 0; if( m_nCount && !m_pReadyList.empty() ) { SGameAction* pAct = m_pReadyList.front(); m_pReadyList.pop(); m_pFireList.push_back( pAct ); } else { SetEnd(true); } } SFireActMng::SFireActMng( SGameAction* pGameAction, struct SMSG_SKILL_EVENT * pMsg, SGameObject * pMsgHandler ) { m_nInterval = 0; //간격 SetMessageHandler( pMsgHandler ); m_nTotalCount = m_nCount = pMsg->fire.count; if( !GetSkillFx( pMsg ) ) { SetEnd( true ); return; } pGameAction->SetMessageHandler( pMsgHandler ); pGameAction->InitFx( pMsg, m_pSkill_FX ); m_pReadyList.push( pGameAction ); if( m_pReadyList.empty() ) m_nTotalCount = 0; if( m_nCount && !m_pReadyList.empty() ) { SGameAction* pAct = m_pReadyList.front(); m_pReadyList.pop(); m_pFireList.push_back( pAct ); } else { SetEnd(true); } } SFireActMng::~SFireActMng() { for( unsigned int i(0); m_pFireList.size()>i; i++ ) { delete m_pFireList[i]; } m_pFireList.clear(); } bool SFireActMng::IsEnd() { //발사 준비 할 것들이 남아 있나? if( !m_pReadyList.empty() ) return false; //전체 갯수와 총 발사된 갯수가 같나? if( m_nTotalCount != m_pFireList.size() ) return false; //발사 된것들이 모두 끝났나? for( unsigned int i(0); m_pFireList.size()>i; i++ ) { if( m_pFireList[i]->IsEnd() == false ) return false; } return true; } bool SFireActMng::Process( DWORD dwTime, unsigned long uProcessBitVector ) { if( m_dwStartTime == 0 ) m_dwStartTime = dwTime; if( dwTime-m_dwStartTime >= m_nInterval ) { m_dwStartTime = dwTime; if( m_nCount > 1 ) { if( m_pReadyList.empty() ) return true; SGameAction* pAct = m_pReadyList.front(); m_pReadyList.pop(); m_pFireList.push_back( pAct ); m_nCount--; } } //지정된 시간에 따라 덩어리를 Active 시킨다. for( unsigned int i(0); m_pFireList.size()>i; i++ ) { //시간이 경과했음에도 불구하고 끝나지 않는 FX는 강제로 끝낸다 if( m_pFireList[i]->CheckTime( dwTime ) ) m_pFireList[i]->SetEnd( true ); if( !m_pFireList[i]->IsEnd() ) m_pFireList[i]->Process( dwTime ); } return true; } bool SFireActMng::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for( unsigned int i(0); m_pFireList.size()>i; i++ ) { if( !m_pFireList[i]->IsEnd() ) m_pFireList[i]->Render( uRenderBitVector, ppViewportList, nViewportCount ); } return true; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////소환 ////연출유형 ID : 1 void SActionRecall::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); m_dwDelayTime = m_pSkill_FX->fStage_Data[0] * 1000; m_nFxPos = m_pSkill_FX->fStage_Data[4]; SetStep( STEP_01 ); //SWork에서 처리된다 SetEnd( true ); } bool SActionRecall::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); return true; } bool SActionRecall::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { return true; } bool SActionRecall::Step01() { if( m_pSubStageFireFxSet ) { m_dwStartTime = m_dwTime; SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionRecall::Step02() { if( m_dwTime - m_dwStartTime > m_dwDelayTime ) { if( !IsEnd() ) { AddFxData( m_target, m_target, m_target, m_pSubStageFireFxSet->nID, m_nFxPos ); SetEnd( true ); } } return true; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////역소환 ////연출유형 ID : 2 void SActionReverseRecall::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); m_dwDelayTime = m_pSkill_FX->fStage_Data[0] * 1000; m_nFxPos = m_pSkill_FX->fStage_Data[4]; SetStep( STEP_01 ); //SWork에서 처리된다 SetEnd( true ); } bool SActionReverseRecall::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); return true; } bool SActionReverseRecall::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { return true; } bool SActionReverseRecall::Step01() { if( m_pSubStageFireFxSet ) { m_dwStartTime = m_dwTime; SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionReverseRecall::Step02() { if( m_dwTime - m_dwStartTime > m_dwDelayTime ) { if( !IsEnd() ) { AddFxData( m_target, m_target, m_target, m_pSubStageFireFxSet->nID, m_nFxPos ); SetEnd( true ); } } return true; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////무기 공격 ////연출유형 ID : 101 void SActionAttkWeapon::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; SetFxData(); } bool SActionAttkWeapon::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); return true; } bool SActionAttkWeapon::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { return true; } bool SActionAttkWeapon::Step01() { if( m_pSubStageHitFxSet || m_pSubStageFireFxSet) { m_dwStartTime = m_dwTime; SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionAttkWeapon::Step02() { if( !IsEnd() ) { if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_pSubStageFireFxSet == NULL && m_pSubStageHitFxSet == NULL ) { SetEnd( true ); } } return true; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////방패 공격 ////연출유형 ID : 111 void SActionAttkShield::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; SetFxData(); } bool SActionAttkShield::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); return true; } bool SActionAttkShield::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { return true; } bool SActionAttkShield::Step01() { if( m_pSubStageHitFxSet || m_pSubStageFireFxSet) { m_dwStartTime = m_dwTime; SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionAttkShield::Step02() { if( !IsEnd() ) { if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_pSubStageFireFxSet == NULL && m_pSubStageHitFxSet == NULL ) { SetEnd( true ); } } return true; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////3분할 모션으로 연타 ////연출유형 ID : 121 void SActionMultiAttkWeapon::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; SetFxData(); } bool SActionMultiAttkWeapon::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); return true; } bool SActionMultiAttkWeapon::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { return true; } bool SActionMultiAttkWeapon::Step01() { if( m_pSubStageHitFxSet || m_pSubStageFireFxSet) { m_dwStartTime = m_dwTime; SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionMultiAttkWeapon::Step02() { if( !IsEnd() ) { if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_pSubStageFireFxSet == NULL && m_pSubStageHitFxSet == NULL ) { SetEnd( true ); } } return true; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////같은 모션으로 2회 이상 연타 ////연출유형 ID : 122 void SActionAboveTwoAttk::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; SetFxData(); } bool SActionAboveTwoAttk::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); return true; } bool SActionAboveTwoAttk::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { return true; } bool SActionAboveTwoAttk::Step01() { if( m_pSubStageHitFxSet || m_pSubStageFireFxSet) { m_dwStartTime = m_dwTime; SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionAboveTwoAttk::Step02() { if( !IsEnd() ) { if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_pSubStageFireFxSet == NULL && m_pSubStageHitFxSet == NULL ) { SetEnd( true ); } } return true; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////히트후 흡수체가 날아온다 ////연출유형 ID : 151 void SActionAttkAbsorber::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; MakeDamageAbsorbe( pMsg, pSkillFx ); SetFxData(); m_iFlyingStyle = m_pSkill_FX->fStage_Data[2]; m_nFxPos = m_pSkill_FX->fStage_Data[4]; } bool SActionAttkAbsorber::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); if( m_pCast ) m_pCast->Process( m_dwTime ); return true; } bool SActionAttkAbsorber::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pCast ) m_pCast->Render( ppViewportList[vit] ); } return true; } bool SActionAttkAbsorber::Step01() { GetMatrixSet( m_pAttack, m_pTarget, EFFECT_POS_DAMAGE ); if( m_pReThrowFxSet ) { if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } if(!CheckDamage(m_pDamage)) { SendSkillDamage( m_pAttack, m_caster, m_caster, m_pDamage ); SetEnd(true); return true; } m_pTarget->Damage(); RunScript(m_pDamage); GetSpeed(); m_dwStartTime = m_dwTime; SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionAttkAbsorber::Step02() { //흡수체 생성 딜레이 if( m_dwTime - m_dwStartTime > m_dwDelayTime ) { if( m_iFlyingStyle == 1 ) SetStep( STEP_04 ); else if( m_iFlyingStyle == 2 ) SetStep( STEP_05 ); else SetStep( STEP_03 ); m_fGravity = 1.0f; GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); m_pCast->SetTransform( m_Matrix ); GetFanShape(); PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pReThrowFxSet->sound_start_file_ID ), m_pReThrowFxSet, &m_DstPos ); } return true; } bool SActionAttkAbsorber::Step03() { if( !AbsorberFlyingStyle01( m_pCast ) ) SetStep( STEP_06 ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet); return true; } bool SActionAttkAbsorber::Step04() { if( !AbsorberFlyingStyle02( m_pCast ) ) SetStep( STEP_06 ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); return true; } bool SActionAttkAbsorber::Step05() { if( !AbsorberFlyingStyle03( m_pCast ) ) SetStep( STEP_06 ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); return true; } bool SActionAttkAbsorber::Step06() { K3DMatrix matTarget; GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetFlyingTime( &m_SrcPos, &m_DstPos ); K3DVectorLerp( m_DstPos, m_DstPos, m_SrcPos, ( m_dwTime - m_dwStartTime ) / m_fFlyingTime ); if( (float)( m_dwTime - m_dwStartTime ) < m_fFlyingTime ) m_pCast->SetPosition( m_DstPos ); else { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); m_pCast->SetTransform( m_Matrix ); m_iPlayStep = 2; if( m_pCastFxSet->IsEffect[m_iPlayStep] ) m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); else { _CID( SETFORCERENDER_FLAG ); m_pCast->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_pCast->PlayAnimation( m_dwTime, "NOT_FOUND" ); } if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( m_pCastFxSet->IsSound[m_iPlayStep] ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pCastFxSet->sound_end_file_ID ), m_pCastFxSet, &m_DstPos ); } SetStep( STEP_07 ); } return true; } bool SActionAttkAbsorber::Step07() { if( !m_pCast->IsPlaying() ) { if( !IsEnd() ) { if( m_pMsgHandler ) m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); AddFxData( m_caster, m_caster, m_caster, m_pReThrowFxSet->nID, m_pSkill_FX->fStage_Data[4] ); SendSkillDamage( m_pAttack, m_caster, m_caster, m_pDamage ); SetEnd( true ); } } return true; } //////////////////////////////////////////////////////////////////////////// ////돌진 ////연출유형 ID : 171 void SActionChargeAttk::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; /* m_vKnockBackPosition = K3DVector( pMsg->vSkillResult[m_iResultIndex].damage_kb.x, pMsg->vSkillResult[m_iResultIndex].damage_kb.y, 0.0f );*/ SetFxData(); SetEnd( TRUE ); } bool SActionChargeAttk::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); return true; } bool SActionChargeAttk::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { /* for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pExplosion ) m_pExplosion->Render( ppViewportList[vit] ); }*/ return true; } bool SActionChargeAttk::Step01() { if( m_pExplosionFxSet ) SetStep( STEP_02 ); else SetEnd( true ); return true; } bool SActionChargeAttk::Step02() { if( !IsEnd() ) { AddFxData( m_target, m_target, m_target, m_pExplosionFxSet->nID, m_pSkill_FX->fStage_Data[4] ); SetEnd( true ); } return true; } //////////////////////////////////////////////////////////////////////////// ////활쏘기 ////연출유형 ID : 201 void SActionShootBow::InitFx( struct SMSG_ATTACK* pMsg ) { m_caster = pMsg->attacker_handle; m_target = pMsg->target_handle; m_pThrowFxSet = GetMotionFxSetDB().GetFXSet( 6001 ); //화살 FX if( m_pThrowFxSet ) { NX3LoadPack loadpack; loadpack.Init(); KSeqModel * pFire = new KSeqModel; // pFire->AddAnimation( pEffectAniKey[0], m_pThrowFxSet->pszGraphic_effect_start_file ); pFire->AddAnimation( pEffectAniKey[1], GetResourceDB().GetEffectResourceName( m_pThrowFxSet->graphic_effect_middle_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); // pFire->AddAnimation( pEffectAniKey[2], m_pThrowFxSet->pszGraphic_effect_end_file ); m_pThrow = pFire; } m_pDamage = new SMSG_DAMAGE; m_pDamage->attacker_handle = pMsg->attacker_handle; m_pDamage->target_handle = pMsg->target_handle; m_pDamage->attack_action = pMsg->attack_action; m_pDamage->attack_flag = pMsg->attack_flag; SGameAvatarEx* pCaster = (SGameAvatarEx *)GetGameObject( pMsg->attacker_handle ); SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( pMsg->target_handle ); SetDamageDisplayName( m_pDamage, pCaster, pTarget ); /// 2012.08.03 코드상으로는 m_iResultIndex가 항상 0이 나와서 pMsg->m_vAttackInfoList.size()를 초과할 경우는 없어 보이지만 /// 어쨌든 예외 처리는 해둠 - prodongi if( !pMsg->m_vAttackInfoList.empty() && m_iResultIndex < (int)pMsg->m_vAttackInfoList.size()) { m_pDamage->nDamage = pMsg->m_vAttackInfoList[m_iResultIndex].damage; m_pDamage->flag = pMsg->m_vAttackInfoList[m_iResultIndex].flag; //// 추가데미지 for( int i(0); CreatureElemental::COUNT>i; i++ ) m_pDamage->elemental_damage[i] = pMsg->m_vAttackInfoList[m_iResultIndex].elemental_damage[i]; } else { m_pDamage->nDamage = 0; m_pDamage->flag = 0; //// 추가데미지 for( int i(0); CreatureElemental::COUNT>i; i++ ) m_pDamage->elemental_damage[i] = 0; } m_pDamage->bBowAttack = true; m_bNormalBow = true; SetStep( STEP_01 ); } //활쏘기 연타 void SActionShootBow::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { if( pMsg->vSkillResult.empty() || (int)pMsg->vSkillResult.size() <= m_iResultIndex ) // #2.3.1.6 sonador SetEnd( true ); else { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->vSkillResult[ m_iResultIndex ].GetTargetHandle(); // 연타 처리 하자 m_bNormalBow = false; MakeDamage( pMsg, pSkillFx ); if( m_pDamage ) m_pDamage->bSphereDamage = true; SetFxData(); } } SActionShootBow::SActionShootBow() { m_pDamage = NULL; } SActionShootBow::~SActionShootBow() { SAFE_DELETE( m_pDamage ); } bool SActionShootBow::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); if( m_pThrow ) m_pThrow->Process( m_dwTime ); return true; } bool SActionShootBow::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pThrow ) m_pThrow->Render( ppViewportList[vit] ); } return true; } bool SActionShootBow::Step01() { GetMatrixSet( m_pAttack, m_pTarget, EFFECT_POS_DAMAGE ); if( m_pThrow && CheckNowState( m_pTarget ) ) { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); GetDirection( m_Matrix, m_SrcPos, m_DstPos ); m_Matrix.SetPosVector( m_SrcPos ); m_pThrow->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); m_pThrow->SetTransform( m_Matrix ); m_velocity = m_DstPos - m_SrcPos; m_acc = K3DVectorLength( m_velocity ); if( m_bNormalBow ) { m_acc = ( m_acc / GameRule::DEFAULT_UNIT_SIZE ) * 30.f; m_fSpeed = 70.f; } else { calsAcc(); GetSpeed(); } PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pThrowFxSet->sound_start_file_ID ), m_pThrowFxSet, &m_SrcPos ); m_dwStartTime = m_dwTime; SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionShootBow::Step02() { K3DMatrix matTarget; GetResultMat( matTarget, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, matTarget ); GetFlyingTime( &m_DstPos, &m_SrcPos ); K3DVectorLerp( m_SrcPos, m_SrcPos, m_DstPos, ( m_dwTime - m_dwStartTime ) / m_fFlyingTime ); SGameAvatarEx* pCaster = (SGameAvatarEx *)GetGameObject( m_caster ); if ( pCaster ) { pCaster->m_vArrowPos = m_SrcPos; } if( (float)( m_dwTime - m_dwStartTime ) < m_fFlyingTime ) { pCaster->m_bArrowTrail = TRUE; m_Matrix.SetPosVector( m_SrcPos ); m_pThrow->SetTransform( m_Matrix ); PlayMiddleAnimation( m_pAttack, m_pThrow, m_pThrowFxSet ); } else { pCaster->m_bArrowTrail = FALSE; GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pThrow->SetPosition( m_DstPos ); m_iPlayStep = 2; if( m_pThrowFxSet->IsEffect[m_iPlayStep] ) m_pThrow->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); else { _CID( SETFORCERENDER_FLAG ); m_pThrow->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_pThrow->PlayAnimation( m_dwTime, "NOT_FOUND" ); } if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( m_pThrowFxSet->IsSound[m_iPlayStep] ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pThrowFxSet->sound_end_file_ID ), m_pThrowFxSet, &m_SrcPos ); } if( m_bNormalBow ) { //기냥 활쏘기 if( m_pDamage ) { m_pTarget->OnDamage( m_caster, m_target, m_pDamage ); if( m_pDamage->flag & TS_ATTACK_EVENT::FLAG_MISS ) { SetEnd(true); return true; } m_pTarget->Damage(); RunScript( m_pDamage ); } } else { //스킬로 활쏘기 if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } if(!CheckDamage(m_pDamage)) { SetEnd(true); return true; } m_pTarget->Damage(); RunScript( m_pDamage ); } m_dwStartTime = m_dwTime; SetStep( STEP_03 ); } return true; } bool SActionShootBow::Step03() { if( !IsEnd() ) { if( !m_pThrow->IsPlaying() ) { if( m_pMsgHandler ) m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); } if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_pSubStageHitFxSet == NULL && m_pSubStageFireFxSet == NULL ) SetEnd( true ); } return true; } //////////////////////////////////////////////////////////////////////////// ////활 발사후 대상이 히트했다면 대상밀려남 ////연출유형 ID : 212 void SActionShootStrongBow::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { if( pMsg->vSkillResult.empty() ) { SetEnd( true ); } else { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->vSkillResult[m_iResultIndex].GetTargetHandle(); if( pMsg->vSkillResult[m_iResultIndex].GetType() == SkillResult::DAMAGE_WITH_KNOCK_BACK ) { m_bKnockBack = true; m_vKnockBackPosition = K3DVector( pMsg->vSkillResult[m_iResultIndex].damage_kb.x, pMsg->vSkillResult[m_iResultIndex].damage_kb.y, 0.0f ); m_fKnockBackSpeed = pMsg->vSkillResult[m_iResultIndex].damage_kb.speed; } else { m_bKnockBack = false; m_fKnockBackSpeed = 0.0f; m_vKnockBackPosition = K3DVector( 0.0f, 0.0f, 0.0f ); } MakeDamage( pMsg, pSkillFx ); if( m_pDamage ) m_pDamage->bSphereDamage = true; SetFxData(); } } bool SActionShootStrongBow::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); if( m_pThrow ) m_pThrow->Process( dwTime ); return true; } bool SActionShootStrongBow::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pThrow ) m_pThrow->Render( ppViewportList[vit] ); } return true; } bool SActionShootStrongBow::Step01() { GetMatrixSet( m_pAttack, m_pTarget, EFFECT_POS_DAMAGE ); if( m_pThrow ) { //현재 타겟이 죽었는가 체크 if( m_pTarget && CheckNowState( m_pTarget ) ) { //살아있다 } else { SetEnd(true); return true; } GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); GetDirection( m_Matrix, m_SrcPos, m_DstPos ); m_Matrix.SetPosVector( m_SrcPos ); m_velocity = m_DstPos - m_SrcPos; m_acc = K3DVectorLength( m_velocity ); calsAcc(); GetSpeed(); m_pThrow->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); m_pThrow->SetTransform( m_Matrix ); PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pThrowFxSet->sound_start_file_ID ), m_pThrowFxSet, &m_SrcPos ); m_dwStartTime = m_dwTime; SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionShootStrongBow::Step02() { K3DMatrix matTarget; GetResultMat( matTarget, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, matTarget ); GetFlyingTime( &m_DstPos, &m_SrcPos ); K3DVectorLerp( m_SrcPos, m_SrcPos, m_DstPos, ( m_dwTime - m_dwStartTime ) / m_fFlyingTime ); if( (float)( m_dwTime - m_dwStartTime ) < m_fFlyingTime ) { m_Matrix.SetPosVector( m_SrcPos ); m_pThrow->SetTransform( m_Matrix ); PlayMiddleAnimation( m_pAttack, m_pThrow, m_pThrowFxSet ); } else { GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pThrow->SetPosition( m_DstPos ); m_iPlayStep = 2; if( m_pThrowFxSet->IsEffect[m_iPlayStep] ) m_pThrow->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); else { _CID( SETFORCERENDER_FLAG ); m_pThrow->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_pThrow->PlayAnimation( m_dwTime, "NOT_FOUND" ); } if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pThrowFxSet->sound_end_file_ID ), m_pThrowFxSet, &m_SrcPos ); } //뎀쥐가 있어야 KNOCKBACK이 된다 if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } if(!CheckDamage(m_pDamage)) { SetEnd(true); return true; } m_pTarget->Damage(); RunScript( m_pDamage ); if( m_bKnockBack ) { //밀기 m_pTarget->SetArObjectStop(); m_pTarget->SetKnockBack( m_vKnockBackPosition, m_fKnockBackSpeed ); } m_dwStartTime = m_dwTime; SetStep( STEP_03 ); } return true; } bool SActionShootStrongBow::Step03() { if( !IsEnd() ) { if( !m_pThrow->IsPlaying() ) { if( m_pMsgHandler ) m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); } if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_pSubStageHitFxSet == NULL && m_pSubStageFireFxSet == NULL ) SetEnd( true ); } return true; } //////////////////////////////////////////////////////////////////////////// ////활 발사후 대상이 히트했다면 흡수체가 날아온다 ////연출유형 ID : 251 void SActionShootAbsorberBow::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; MakeDamageAbsorbe( pMsg, pSkillFx ); SetFxData(); m_iFlyingStyle = m_pSkill_FX->fStage_Data[7]; m_dwDelayTime = m_pSkill_FX->fStage_Data[5] * 1000; } bool SActionShootAbsorberBow::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); if( m_pThrow ) m_pThrow->Process( m_dwTime ); if( m_pReThrow ) m_pReThrow->Process( m_dwTime ); return true; } bool SActionShootAbsorberBow::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pThrow ) m_pThrow->Render( ppViewportList[vit] ); if( m_pReThrow ) m_pReThrow->Render( ppViewportList[vit] ); } return true; } bool SActionShootAbsorberBow::Step01() { GetMatrixSet( m_pAttack, m_pTarget, EFFECT_POS_DAMAGE ); if( m_pThrow && m_pReThrow && m_pExplosionFxSet ) { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); GetDirection( m_Matrix, m_SrcPos, m_DstPos ); m_Matrix.SetPosVector( m_SrcPos ); m_velocity = m_DstPos - m_SrcPos; m_acc = K3DVectorLength( m_velocity ); calsAcc( ); GetSpeed(); m_pThrow->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); m_pThrow->SetTransform( m_Matrix ); PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pThrowFxSet->sound_start_file_ID ), m_pThrowFxSet, &m_SrcPos ); m_dwStartTime = m_dwTime; SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionShootAbsorberBow::Step02() { K3DMatrix matTarget; GetResultMat( matTarget, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, matTarget ); GetFlyingTime( &m_DstPos, &m_SrcPos ); K3DVectorLerp( m_SrcPos, m_SrcPos, m_DstPos, ( m_dwTime - m_dwStartTime ) / m_fFlyingTime ); if( (float)( m_dwTime - m_dwStartTime ) < m_fFlyingTime ) { m_Matrix.SetPosVector( m_SrcPos ); m_pThrow->SetTransform( m_Matrix ); PlayMiddleAnimation( m_pAttack, m_pThrow, m_pThrowFxSet ); } else { GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pThrow->SetPosition( m_DstPos ); if( m_pMsgHandler ) m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); m_iPlayStep = 2; if( m_pThrowFxSet->IsEffect[m_iPlayStep] ) { m_pThrow->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); if( m_pThrowFxSet->IsSound[m_iPlayStep] ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pThrowFxSet->sound_end_file_ID ), m_pThrowFxSet, &m_SrcPos ); } else { _CID( SETFORCERENDER_FLAG ); m_pThrow->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_pThrow->PlayAnimation( m_dwTime, "NOT_FOUND" ); } if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } if(!CheckDamage(m_pDamage)) { SendSkillDamage( m_pAttack, m_caster, m_caster, m_pDamage ); SetEnd(true); return true; } m_pTarget->Damage(); RunScript( m_pDamage ); SetStep( STEP_03 ); m_dwStartTime = m_dwTime; } return true; } bool SActionShootAbsorberBow::Step03() { if( !m_pThrow->IsPlaying() ) { if( m_dwTime - m_dwStartTime > m_dwDelayTime ) { if( m_iFlyingStyle == 1 ) SetStep( STEP_05 ); else if( m_iFlyingStyle == 2 ) SetStep( STEP_06 ); else SetStep( STEP_04 ); m_fGravity = 1.0f; m_iPlayStep = 0; GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pReThrow->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); m_pReThrow->SetTransform( m_Matrix ); m_acc = 15.0f; GetFanShape(); PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pReThrowFxSet->sound_start_file_ID ), m_pReThrowFxSet, &m_DstPos ); } } return true; } bool SActionShootAbsorberBow::Step04() { //UFO형. 대상의 상공으로 살짝 떠올랐다가 시전자에게 가속도가 붙으며 날아와 명중함. if( !AbsorberFlyingStyle01( m_pReThrow ) ) SetStep( STEP_07 ); PlayMiddleAnimation( m_pAttack, m_pReThrow, m_pReThrowFxSet ); return true; } bool SActionShootAbsorberBow::Step05() { if( !AbsorberFlyingStyle02( m_pReThrow ) ) SetStep( STEP_07 ); PlayMiddleAnimation( m_pAttack, m_pReThrow, m_pReThrowFxSet ); return true; } bool SActionShootAbsorberBow::Step06() { if( !AbsorberFlyingStyle03( m_pReThrow ) ) SetStep( STEP_07 ); PlayMiddleAnimation( m_pAttack, m_pReThrow, m_pReThrowFxSet ); return true; } bool SActionShootAbsorberBow::Step07() { K3DMatrix matTarget; GetResultMat( matTarget, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, matTarget ); GetFlyingTime( &m_SrcPos, &m_DstPos ); K3DVectorLerp( m_DstPos, m_DstPos, m_SrcPos, ( m_dwTime - m_dwStartTime ) / m_fFlyingTime ); if( (float)( m_dwTime - m_dwStartTime ) < m_fFlyingTime ) m_pReThrow->SetPosition( m_DstPos ); else { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); m_pReThrow->SetTransform( *m_pCastMat ); m_iPlayStep = 2; if( m_pReThrowFxSet->IsEffect[m_iPlayStep] ) m_pReThrow->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); else { _CID( SETFORCERENDER_FLAG ); m_pReThrow->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_pReThrow->PlayAnimation( m_dwTime, "NOT_FOUND" ); } if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( m_pReThrowFxSet->IsSound[m_iPlayStep] ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pReThrowFxSet->sound_end_file_ID ), m_pReThrowFxSet, &m_DstPos ); } SetStep( STEP_08 ); } return true; } bool SActionShootAbsorberBow::Step08() { if( !m_pReThrow->IsPlaying() ) { if( !IsEnd() ) { if( m_pMsgHandler ) m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); AddFxData( m_caster, m_caster, m_caster, m_pExplosionFxSet->nID, EFFECT_POS_BOTTOM ); SendSkillDamage( m_pAttack, m_caster, m_caster, m_pDamage ); SetEnd( true ); } } return true; } //////////////////////////////////////////////////////////////////////////// ////셀프 스킬 ////연출유형 ID : 301 void SActionSelfSkill::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; MakeDamage( pMsg, pSkillFx ); SetFxData(); } bool SActionSelfSkill::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); return true; } bool SActionSelfSkill::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { return true; } bool SActionSelfSkill::Step01() { if( m_pSubStageFireFxSet || m_pSubStageHitFxSet ) { m_dwStartTime = m_dwTime; assert( m_pSkill_FX->szDeal_Damage == 0 && "SActionSelfSkill::Step01() 셀프 스킬 DealDamage가 == 0 아니다" ); if( m_pSkill_FX->szDeal_Damage == 0) { if(m_pDamage) m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); if(!CheckDamage(m_pDamage)) { SetEnd(true); return true; } } SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionSelfSkill::Step02() { if( !IsEnd() ) { if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_caster, m_caster, m_caster, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_caster, m_caster, m_caster, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_pSubStageFireFxSet == NULL && m_pSubStageHitFxSet == NULL ) { SetEnd( true ); } } return true; } //////////////////////////////////////////////////////////////////////////// ////대상의 몸체에 이펙트를 뿌려준다 ////연출유형 ID : 401 void SActionThrowSkill::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->caster; m_bMultiThrow = false; //szHas_Target이 0이면 셀프 1이면 타겟 존재 //szHas_Target이 0이고 m_pSkill_FX->fStage_Data[0]이 1이면 발동은 셀프 대상은 광역 if(pSkillFx->szHas_Target == 0 && m_pSkill_FX->fStage_Data[0] == 1 ) { m_target = pMsg->caster; m_bMultiThrow = true; } else if( pSkillFx->szHas_Target == 0 ) { m_target = pMsg->caster; } else { if( pMsg->vSkillResult.empty() ) m_target = pMsg->target; else { m_target = pMsg->vSkillResult[m_iResultIndex].GetTargetHandle(); if( m_target == 0 ) { m_target = pMsg->target; if( m_target == 0 ) { m_target = pMsg->caster; } } } } if( m_bMultiAttack ) { MakeDamage( pMsg, pSkillFx ); if( m_pDamage ) m_pDamage->bSphereDamage = true; } else MakeDamageAbsorbe( pMsg, pSkillFx ); SetFxData(); if( IsEnd() ) SetStep( STEP_02 ); } bool SActionThrowSkill::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); return true; } bool SActionThrowSkill::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { return true; } bool SActionThrowSkill::Step01() { if( CheckNowState( m_pTarget ) ) { m_dwStartTime = m_dwTime; //0 대상에 이로운 스킬 1 대상에 해로운 스킬 if( m_bMultiAttack /*m_pSkill_FX->szDeal_Damage != 0*/ ) { if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } if(!CheckDamage(m_pDamage)) { SetEnd(true); // SetStep( STEP_02 ); return true; } m_pTarget->Damage(); } else { if(m_pDamage) { // SGameUISyncMng::ProcUiSyncMsg에서 타겟비교할때 삽질하는걸 막기 위해 땜빵 if ((m_caster == m_target) && m_bMultiThrow) m_pTarget->OnSkillDamage( m_caster, INFINITE_TIME, m_pDamage ); else m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); SendSkillDamage( m_pTarget, m_caster, m_target, m_pDamage ); } if(!CheckDamage(m_pDamage)) { SetEnd(true); /* if( m_bMultiThrow ) SetStep( STEP_03 ); else SetStep( STEP_02 );*/ return true; } } if( m_bMultiThrow ) SetStep( STEP_03 ); else SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionThrowSkill::Step02() { if( !IsEnd() ) { if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_pSubStageHitFxSet == NULL && m_pSubStageFireFxSet == NULL ) SetEnd( true ); } return true; } bool SActionThrowSkill::Step03() { if( !IsEnd() ) { if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { std::vector< SkillResult* >::iterator iter = m_vHPMPSPSkillResult.begin(); for( ; iter != m_vHPMPSPSkillResult.end(); ++iter ) { AR_HANDLE htarget = (*iter)->GetTargetHandle(); AddFxData( htarget, htarget, htarget, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); } m_pSubStageHitFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { std::vector< SkillResult* >::iterator iter = m_vHPMPSPSkillResult.begin(); for( ; iter != m_vHPMPSPSkillResult.end(); ++iter ) { AR_HANDLE htarget = (*iter)->GetTargetHandle(); AddFxData( htarget, htarget, htarget, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); } m_pSubStageFireFxSet = NULL; } } if( m_pSubStageHitFxSet == NULL && m_pSubStageFireFxSet == NULL ) SetEnd( true ); } return true; } //////////////////////////////////////////////////////////////////////////// ////대상의 몸체에 이펙트를 뿌려준다, 히트판정은 딜레이가 있음 ////연출유형 ID : 404 void SActionThrowSkillDelay::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->caster; m_bMultiThrow = false; m_fHittingDelay = m_pSkill_FX->fStage_Data[1]; //szHas_Target이 0이면 셀프 1이면 타겟 존재 //szHas_Target이 0이고 m_pSkill_FX->fStage_Data[0]이 1이면 발동은 셀프 대상은 광역 if(pSkillFx->szHas_Target == 0 && m_pSkill_FX->fStage_Data[0] == 1 ) { m_target = pMsg->caster; m_bMultiThrow = true; } else if( pSkillFx->szHas_Target == 0 ) { m_target = pMsg->caster; } else { if( pMsg->vSkillResult.empty() ) m_target = pMsg->target; else { m_target = pMsg->vSkillResult[m_iResultIndex].GetTargetHandle(); if( m_target == 0 ) { m_target = pMsg->target; if( m_target == 0 ) { m_target = pMsg->caster; } } } } if( m_bMultiAttack ) { MakeDamage( pMsg, pSkillFx ); if( m_pDamage ) m_pDamage->bSphereDamage = true; } else MakeDamageAbsorbe( pMsg, pSkillFx ); SetFxData(); if( IsEnd() ) SetStep( STEP_02 ); } bool SActionThrowSkillDelay::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); return true; } bool SActionThrowSkillDelay::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { return true; } bool SActionThrowSkillDelay::Step01() { if( CheckNowState( m_pTarget ) ) { m_dwStartTime = m_dwTime; if( m_pSubStageHitFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } if( m_pSubStageFireFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } if( m_bMultiThrow ) SetStep( STEP_03 ); else SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionThrowSkillDelay::Step02() { if( !IsEnd() ) { if (m_dwTime - m_dwStartTime > m_fHittingDelay * 1000.0f) { //0 대상에 이로운 스킬 1 대상에 해로운 스킬 if( m_bMultiAttack /*m_pSkill_FX->szDeal_Damage != 0*/ ) { if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } SetEnd(true); m_pTarget->Damage(); } else { if(m_pDamage) { // SGameUISyncMng::ProcUiSyncMsg에서 타겟비교할때 삽질하는걸 막기 위해 땜빵 if ((m_caster == m_target) && m_bMultiThrow) m_pTarget->OnSkillDamage( m_caster, INFINITE_TIME, m_pDamage ); else m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); SendSkillDamage( m_pTarget, m_caster, m_target, m_pDamage ); } SetEnd(true); } } } return true; } bool SActionThrowSkillDelay::Step03() { if( !IsEnd() ) { if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { std::vector< SkillResult* >::iterator iter = m_vHPMPSPSkillResult.begin(); for( ; iter != m_vHPMPSPSkillResult.end(); ++iter ) { AR_HANDLE htarget = (*iter)->GetTargetHandle(); AddFxData( htarget, htarget, htarget, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); } m_pSubStageHitFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { std::vector< SkillResult* >::iterator iter = m_vHPMPSPSkillResult.begin(); for( ; iter != m_vHPMPSPSkillResult.end(); ++iter ) { AR_HANDLE htarget = (*iter)->GetTargetHandle(); AddFxData( htarget, htarget, htarget, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); } m_pSubStageFireFxSet = NULL; } } if( m_pSubStageHitFxSet == NULL && m_pSubStageFireFxSet == NULL ) SetEnd( true ); } return true; } //////////////////////////////////////////////////////////////////////////// ////대상의 몸체에 이펙트를 뿌려준후 흡수체가 날아온다 ////연출유형 ID : 402 void SActionThrowAbsorberSkill::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; MakeDamageAbsorbe( pMsg, pSkillFx ); if( m_caster == m_target ) { std::vector< struct SkillResult* >::iterator iter = m_vHPMPSPSkillResult.begin(); for( ; iter != m_vHPMPSPSkillResult.end(); ++iter ) { m_target = (*iter)->GetTargetHandle(); if( m_caster != m_target ) break; } } SetFxData(); //부가 FX if( m_pSubStageHitFxSet ) { NX3LoadPack loadpack; loadpack.Init(); KSeqModel* pAddHit = new KSeqModel; pAddHit->AddAnimation( pEffectAniKey[0], GetResourceDB().GetEffectResourceName( m_pSubStageHitFxSet->graphic_effect_start_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pAddHit->AddAnimation( pEffectAniKey[1], GetResourceDB().GetEffectResourceName( m_pSubStageHitFxSet->graphic_effect_middle_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pAddHit->AddAnimation( pEffectAniKey[2], GetResourceDB().GetEffectResourceName( m_pSubStageHitFxSet->graphic_effect_end_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); m_pSubStageHit = pAddHit; } m_iFlyingStyle = m_pSkill_FX->fStage_Data[2]; m_nFxPos = m_pSkill_FX->fStage_Data[4]; } SActionThrowAbsorberSkill::~SActionThrowAbsorberSkill() { m_pTarget = (SGameAvatarEx *)GetGameObject( m_target ); if(m_pTarget) m_pTarget->SetReservation(false); } bool SActionThrowAbsorberSkill::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); if( m_pCast ) m_pCast->Process( m_dwTime ); if( m_pSubStageHit ) m_pSubStageHit->Process( m_dwTime ); return true; } bool SActionThrowAbsorberSkill::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pCast ) m_pCast->Render( ppViewportList[vit] ); if( m_pSubStageHit ) m_pSubStageHit->Render( ppViewportList[vit] ); } return true; } bool SActionThrowAbsorberSkill::Step01() { GetMatrixSet( m_pAttack, m_pTarget, m_nFxPos ); if( m_pSubStageHit && m_pReThrowFxSet && m_pCast ) { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); if( m_pTarget->IsDead() || !m_pTarget->IsLive() ) { m_DstPos = *m_pTarget->GetPosition(); K3DMatrixIdentity( m_Matrix ); m_Matrix._41 = m_DstPos.x; m_Matrix._42 = m_DstPos.y; m_Matrix._43 = m_DstPos.z; } else { GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); } m_pSubStageHit->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); m_pSubStageHit->SetTransform( m_Matrix ); GetSpeed(); PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pSubStageHitFxSet->sound_start_file_ID ), m_pSubStageHitFxSet, &m_DstPos ); if(!CheckDamage(m_pDamage)) { if( m_vHPMPSPSkillResult.empty() ) { SetEnd(true); return true; } } SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionThrowAbsorberSkill::Step02() { if( !m_pSubStageHit->IsPlaying() ) { m_iPlayStep++; while( m_iPlayStep < 3) { if( m_pSubStageHitFxSet->IsEffect[m_iPlayStep] ) { m_pSubStageHit->PlayAnimation( m_dwTime , pEffectAniKey[m_iPlayStep] ); if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( m_pSubStageHitFxSet->IsSound[m_iPlayStep] ) { if( m_iPlayStep == 1 ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pSubStageHitFxSet->sound_middle_file_ID ), m_pSubStageHitFxSet, &m_DstPos, true ); else if( m_iPlayStep == 2 ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pSubStageHitFxSet->sound_end_file_ID ), m_pSubStageHitFxSet, &m_DstPos ); } } return true; } else m_iPlayStep++; } _CID( SETFORCERENDER_FLAG ); m_pSubStageHit->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_dwStartTime = m_dwTime; if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } m_pTarget->Damage(); SetStep( STEP_03 ); return true; } return true; } bool SActionThrowAbsorberSkill::Step03() { if( m_dwTime - m_dwStartTime > m_dwDelayTime ) { //비행 타입에 따라 연출 if( m_iFlyingStyle == 1 ) SetStep( STEP_05 ); else if( m_iFlyingStyle == 2 ) SetStep( STEP_06 ); else SetStep( STEP_04 ); m_fGravity = 1.0f; m_iPlayStep = 0; GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); m_pCast->SetTransform( m_Matrix ); GetFanShape(); PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pReThrowFxSet->sound_start_file_ID ), m_pReThrowFxSet, &m_DstPos ); } return true; } bool SActionThrowAbsorberSkill::Step04() { if( !AbsorberFlyingStyle01( m_pCast ) ) SetStep( STEP_07 ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); return true; } bool SActionThrowAbsorberSkill::Step05() { if( !AbsorberFlyingStyle02( m_pCast ) ) SetStep( STEP_07 ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); return true; } bool SActionThrowAbsorberSkill::Step06() { if( !AbsorberFlyingStyle03( m_pCast ) ) SetStep( STEP_07 ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); return true; } bool SActionThrowAbsorberSkill::Step07() { K3DMatrix matTarget; GetResultMat( matTarget, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, matTarget ); GetFlyingTime( &m_SrcPos, &m_DstPos ); K3DVectorLerp( m_DstPos, m_DstPos, m_SrcPos, ( m_dwTime - m_dwStartTime ) / m_fFlyingTime ); if( (float)( m_dwTime - m_dwStartTime ) < m_fFlyingTime ) m_pCast->SetPosition( m_DstPos ); else { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); m_pCast->SetTransform( *m_pCastMat ); m_iPlayStep = 2; if( m_pCastFxSet->IsEffect[m_iPlayStep] ) m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); else { _CID( SETFORCERENDER_FLAG ); m_pCast->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_pCast->PlayAnimation( m_dwTime, "NOT_FOUND" ); } if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( m_pCastFxSet->IsSound[m_iPlayStep] ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pCastFxSet->sound_end_file_ID ), m_pCastFxSet, &m_DstPos ); } SetStep( STEP_08 ); } return true; } bool SActionThrowAbsorberSkill::Step08() { if( !m_pCast->IsPlaying() ) { if( !IsEnd() ) { if( m_pMsgHandler ) m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); AddFxData( m_caster, m_caster, m_caster, m_pReThrowFxSet->nID, m_nFxPos ); SendSkillDamage( m_pAttack, m_caster, m_caster, m_pDamage ); SetEnd( true ); } } return true; } //////////////////////////////////////////////////////////////////////////// ////발사 연출 없이 시전자의 메인 크리처에 힛트 FX & 발동 FX를 뿌리는 동시에 흡수 연출을 보여준다 ////광역 스킬 //아직 구현안됨 ////연출유형 ID : 403 void SActionCreatureAbsorberSkill::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = 0; m_target = 0; MakeDamageAbsorbe( pMsg, pSkillFx ); std::vector< struct SkillResult* >::iterator iter = m_vHPMPSPSkillResult.begin(); for( ; iter != m_vHPMPSPSkillResult.end(); ++iter ) { m_caster = (*iter)->GetTargetHandle(); break; } //RESULT에 있는 핸들이 크리처 핸들 if(m_pDamage) m_target = m_pDamage->skillresult.GetTargetHandle(); SetFxData(); //부가 FX if( m_pSubStageFireFxSet ) { NX3LoadPack loadpack; loadpack.Init(); KSeqModel* pAddCast = new KSeqModel; pAddCast->AddAnimation( pEffectAniKey[0], GetResourceDB().GetEffectResourceName( m_pSubStageFireFxSet->graphic_effect_start_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pAddCast->AddAnimation( pEffectAniKey[1], GetResourceDB().GetEffectResourceName( m_pSubStageFireFxSet->graphic_effect_middle_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); pAddCast->AddAnimation( pEffectAniKey[2], GetResourceDB().GetEffectResourceName( m_pSubStageFireFxSet->graphic_effect_end_file_ID ), KNX3Manager::SEQTYPE_ALL, &loadpack ); m_pSubStageFire = pAddCast; } m_iFlyingStyle = m_pSkill_FX->fStage_Data[2]; m_nFxPos = m_pSkill_FX->fStage_Data[4]; } bool SActionCreatureAbsorberSkill::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); if( m_pCast ) m_pCast->Process( m_dwTime ); if( m_pSubStageFire ) m_pSubStageFire->Process( m_dwTime ); return true; } bool SActionCreatureAbsorberSkill::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pCast ) m_pCast->Render( ppViewportList[vit] ); if( m_pSubStageFire ) m_pSubStageFire->Render( ppViewportList[vit] ); } return true; } bool SActionCreatureAbsorberSkill::Step01() { GetMatrixSet( m_pAttack, m_pTarget, EFFECT_POS_DAMAGE ); if( m_pSubStageFire && m_pReThrowFxSet && m_pCast ) { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pSubStageFire->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); m_pSubStageFire->SetParentTransform( m_pTargetMat, m_pTargetBoneMat ); GetSpeed(); PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pSubStageFireFxSet->sound_start_file_ID ), m_pSubStageFireFxSet, &m_DstPos ); SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionCreatureAbsorberSkill::Step02() { if( !m_pSubStageFire->IsPlaying() ) { m_iPlayStep++; while( m_iPlayStep < 3) { if( m_pSubStageFireFxSet->IsEffect[m_iPlayStep] ) { m_pSubStageFire->PlayAnimation( m_dwTime , pEffectAniKey[m_iPlayStep] ); if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( m_pSubStageFireFxSet->IsSound[m_iPlayStep] ) { if( m_iPlayStep == 1 ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pSubStageFireFxSet->sound_middle_file_ID ), m_pSubStageFireFxSet, &m_DstPos, true ); else if( m_iPlayStep == 2 ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pSubStageFireFxSet->sound_end_file_ID ), m_pSubStageFireFxSet, &m_DstPos ); } } return true; } else m_iPlayStep++; } _CID( SETFORCERENDER_FLAG ); m_pSubStageFire->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_dwStartTime = m_dwTime; /* if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); }*/ m_pTarget->Damage(); SetStep( STEP_03 ); return true; } return true; } bool SActionCreatureAbsorberSkill::Step03() { if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { //비행 타입에 따라 연출 if( m_iFlyingStyle == 1 ) SetStep( STEP_05 ); else if( m_iFlyingStyle == 2 ) SetStep( STEP_06 ); else SetStep( STEP_04 ); m_fGravity = 1.0f; m_iPlayStep = 0; GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); m_pCast->SetTransform( m_Matrix ); m_acc = 15.0f; GetFanShape(); PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pReThrowFxSet->sound_start_file_ID ), m_pReThrowFxSet, &m_DstPos ); } return true; } bool SActionCreatureAbsorberSkill::Step04() { if( !AbsorberFlyingStyle01( m_pCast ) ) SetStep( STEP_07 ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); return true; } bool SActionCreatureAbsorberSkill::Step05() { if( !AbsorberFlyingStyle02( m_pCast ) ) SetStep( STEP_07 ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); return true; } bool SActionCreatureAbsorberSkill::Step06() { if( !AbsorberFlyingStyle03( m_pCast ) ) SetStep( STEP_07 ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); return true; } bool SActionCreatureAbsorberSkill::Step07() { K3DMatrix matTarget; GetResultMat( matTarget, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, matTarget ); GetFlyingTime( &m_SrcPos, &m_DstPos ); K3DVectorLerp( m_DstPos, m_DstPos, m_SrcPos, ( m_dwTime - m_dwStartTime ) / m_fFlyingTime ); if( (float)( m_dwTime - m_dwStartTime ) < m_fFlyingTime ) m_pCast->SetPosition( m_DstPos ); else { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); m_pCast->SetTransform( *m_pCastMat ); m_iPlayStep = 2; if( m_pCastFxSet->IsEffect[m_iPlayStep] ) m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); else { _CID( SETFORCERENDER_FLAG ); m_pCast->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_pCast->PlayAnimation( m_dwTime, "NOT_FOUND" ); } if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( m_pCastFxSet->IsSound[m_iPlayStep] ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pCastFxSet->sound_end_file_ID ), m_pCastFxSet, &m_DstPos ); } SetStep( STEP_08 ); } return true; } bool SActionCreatureAbsorberSkill::Step08() { if( !m_pCast->IsPlaying() ) { if( !IsEnd() ) { if( m_pMsgHandler ) m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); AddFxData( m_caster, m_caster, m_caster, m_pReThrowFxSet->nID, m_nFxPos ); if( m_pDamage && m_pTarget ) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } SendSkillDamage( m_pAttack, m_caster, m_caster, m_pDamage ); SetEnd( true ); } } return true; } //////////////////////////////////////////////////////////////////////////// ////한 대상에게만 스킬을 발사한후 그 대상 주위 대상들까지 히트Fx가 나타난다 ////광역 스킬 ////연출유형 ID : 411 void SActionThrowWideAreaSkill::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; if( m_caster == m_target ) { for(int x = 0; x < (int)pMsg->vSkillResult.size(); x++ ) { if( GetGameObject( pMsg->vSkillResult[x].GetTargetHandle() ) ) { m_target = pMsg->vSkillResult[x].GetTargetHandle(); if( m_caster != m_target ) break; } } } SetFxData(); for(int x = 0; x < (int)pMsg->vSkillResult.size(); x++ ) { if( pMsg->vSkillResult[x].GetType() != SkillResult::NOT_USE && pMsg->vSkillResult[x].GetType() != SkillResult::RUSH ) { SMSG_DAMAGE* pDamage = new SMSG_DAMAGE; pDamage->attacker_handle = pMsg->caster; pDamage->target_handle = pMsg->vSkillResult[x].GetTargetHandle(); pDamage->skillresult = pMsg->vSkillResult[x]; pDamage->nSkillID = pMsg->skill_id; pDamage->nSkillLevel = pMsg->skill_level; SGameAvatarEx* pCaster = (SGameAvatarEx *)GetGameObject( pDamage->attacker_handle ); SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( pDamage->target_handle ); // [sonador][7.7.12] 전투 관련 시스템 메시지 오류 수정 및 추가 SetDamageDisplayName( pDamage, pCaster, pTarget ); // 범위 뎀쥐일경우 pDamage->bSphereDamage = true; TARGET_DATA_LIST targetdata; targetdata.pDamage = pDamage; targetdata.hTarget = pDamage->target_handle; if( !m_pSubStageFireFxSet ) targetdata.bSubFireProcessing = false; if( !m_pSubStageHitFxSet) targetdata.bSubHitProcessing = false; m_vTargetList.push_back( targetdata ); } } } SActionThrowWideAreaSkill::~SActionThrowWideAreaSkill() { std::vector< TARGET_DATA_LIST >::iterator iter = m_vTargetList.begin(); for( ; iter != m_vTargetList.end(); ) { SAFE_DELETE( (*iter).pDamage ); iter = m_vTargetList.erase( iter ); } } bool SActionThrowWideAreaSkill::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckTarget() ) { SetEnd( true ); return true; } (this->*Function_Step[m_nStep])(); return true; } bool SActionThrowWideAreaSkill::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { return true; } bool SActionThrowWideAreaSkill::Step01() { GetMatrixSet( NULL, m_pTarget, m_nFxPos ); if( CheckNowState( m_pTarget ) ) { GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); //현재 타겟이 죽었는가 체크 std::vector< TARGET_DATA_LIST >::iterator iter = m_vTargetList.begin(); for( ; iter != m_vTargetList.end(); ) { SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( (*iter).hTarget ); if( pTarget && CheckNowState( pTarget ) ) ++iter; else { SAFE_DELETE( (*iter).pDamage ); iter = m_vTargetList.erase( iter ); } } m_dwStartTime = m_dwTime; SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionThrowWideAreaSkill::Step02() { if( IsEnd() ) return true; std::vector< TARGET_DATA_LIST >::iterator iter = m_vTargetList.begin(); if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { for( ; iter != m_vTargetList.end(); ++iter ) { SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( (*iter).hTarget ); if( pTarget ) { if( (*iter).bDmgProcessing ) { pTarget->OnSkillDamage( m_caster, (*iter).hTarget, (*iter).pDamage ); if( CheckDamage( (*iter).pDamage ) ) pTarget->Damage(); (*iter).bDmgProcessing = false; } if( (*iter).bSubHitProcessing ) { if( CheckDamage( (*iter).pDamage ) ) AddFxData( (*iter).hTarget, (*iter).hTarget, (*iter).hTarget, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); (*iter).bSubHitProcessing = false; } } else { (*iter).bDmgProcessing = false; (*iter).bSubHitProcessing = false; (*iter).bSubFireProcessing = false; } } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { iter = m_vTargetList.begin(); for( ; iter != m_vTargetList.end(); ) { SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( (*iter).hTarget ); if( pTarget ) { if( (*iter).bSubFireProcessing ) { if( CheckDamage( (*iter).pDamage ) ) AddFxData( (*iter).hTarget, (*iter).hTarget, (*iter).hTarget, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); (*iter).bSubFireProcessing = false; } } if( !(*iter).bDmgProcessing && !(*iter).bSubHitProcessing && !(*iter).bSubFireProcessing ) { SAFE_DELETE( (*iter).pDamage ); iter = m_vTargetList.erase( iter ); } else ++iter; } } if( m_vTargetList.empty() ) SetEnd( true ); return true; } //////////////////////////////////////////////////////////////////////////// ////동시에 여러 대상에게 스킬을 발사한다 히트한 대상들은 히트Fx가 나타난다 ////광역 스킬 ////연출유형 ID : 412 ////( 연출 유형 새로 바뀜 ) void SActionThrowWideAreaMultiSkill::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_dwHitDelay = 0; m_dwStartHitTime = 0; m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; m_nTargetCnt = pMsg->fire.target_count; if( m_caster == m_target ) { for(int x = 0; x < (int)pMsg->vSkillResult.size(); x++ ) { m_target = pMsg->vSkillResult[x].GetTargetHandle(); if( m_caster != m_target ) break; } } SetFxData(); for(int x = 0; x < (int)pMsg->vSkillResult.size(); ++x ) { if( pMsg->vSkillResult[x].GetType() != SkillResult::NOT_USE && pMsg->vSkillResult[x].GetType() != SkillResult::RUSH ) { SMSG_DAMAGE* pDamage = new SMSG_DAMAGE; pDamage->attacker_handle = pMsg->caster; pDamage->target_handle = pMsg->vSkillResult[x].GetTargetHandle(); pDamage->skillresult = pMsg->vSkillResult[x]; pDamage->nSkillID = pMsg->skill_id; pDamage->nSkillLevel = pMsg->skill_level; SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( pDamage->target_handle ); if( pTarget ) { if( pTarget->GetObjType() == TS_ENTER::GAME_MOB || pTarget->GetObjType() == TS_ENTER::GAME_SUMMON || pTarget->GetObjType() == TS_ENTER::GAME_NPC ) pDamage->strTargetName = GetStringDB().GetString( GetMonsterDB().GetTextID( pTarget->GetContentID() ) ); else if( pTarget->GetObjType() == TS_ENTER::GAME_PLAYER ) pDamage->strTargetName = pTarget->GetName(); } else pDamage->strTargetName = GetStringDB().GetString( 88 ); SGameAvatarEx* pCaster = (SGameAvatarEx *)GetGameObject( pDamage->attacker_handle ); if( pCaster ) { if( pCaster->GetObjType() == TS_ENTER::GAME_MOB || pCaster->GetObjType() == TS_ENTER::GAME_SUMMON || pCaster->GetObjType() == TS_ENTER::GAME_NPC ) pDamage->strCasterName = GetStringDB().GetString( GetMonsterDB().GetTextID( pCaster->GetContentID() ) ); else if( pCaster->GetObjType() == TS_ENTER::GAME_PLAYER ) pDamage->strCasterName = pCaster->GetName(); } else pDamage->strCasterName = GetStringDB().GetString( 88 ); // 범위 뎀쥐일경우 pDamage->bSphereDamage = true; TARGET_DATA_LIST targetdata; targetdata.pDamage = pDamage; targetdata.hTarget = pDamage->target_handle; if( !m_pSubStageFireFxSet ) targetdata.bSubFireProcessing = false; if( !m_pSubStageHitFxSet) targetdata.bSubHitProcessing = false; m_vTargetList.push_back( targetdata ); } } m_dwHitDelay = (DWORD)(m_pSkill_FX->fStage_Data[4] * 1000.0f); m_nCasterFxID = m_pSkill_FX->fStage_Data[0]; } SActionThrowWideAreaMultiSkill::~SActionThrowWideAreaMultiSkill() { std::vector< TARGET_DATA_LIST >::iterator iter = m_vTargetList.begin(); for( ; iter != m_vTargetList.end(); ) { SAFE_DELETE( (*iter).pDamage ); iter = m_vTargetList.erase( iter ); } } bool SActionThrowWideAreaMultiSkill::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) { SetEnd( true ); return true; } (this->*Function_Step[m_nStep])(); if( m_pCast ) m_pCast->Process( m_dwTime ); return true; } bool SActionThrowWideAreaMultiSkill::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pCast ) m_pCast->Render( ppViewportList[vit] ); } return true; } bool SActionThrowWideAreaMultiSkill::Step01() { GetMatrixSet( m_pAttack, m_pTarget, m_nFxPos ); if( m_pCast && CheckNowState( m_pTarget ) ) { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[0] ); m_pCast->SetPosition( m_SrcPos ); //현재 타겟이 죽었는가 체크 std::vector< TARGET_DATA_LIST >::iterator iter = m_vTargetList.begin(); for( ; iter != m_vTargetList.end(); ) { SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( (*iter).hTarget ); if( pTarget && CheckNowState( pTarget ) ) ++iter; else { SAFE_DELETE( (*iter).pDamage ); iter = m_vTargetList.erase( iter ); } } m_dwStartTime = m_dwTime; m_dwStartHitTime = m_dwTime; SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionThrowWideAreaMultiSkill::Step02() { if( IsEnd() ) return true; bool bSendFx = true; bool bHit = false; if( m_dwTime - m_dwStartHitTime > m_dwHitDelay ) { m_dwStartHitTime = m_dwTime; bHit = true; } std::vector< TARGET_DATA_LIST >::iterator iter = m_vTargetList.begin(); if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( bHit ) { for( int nTargetCnt = m_nTargetCnt; iter != m_vTargetList.end(); ++iter ) { SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( (*iter).hTarget ); if( pTarget ) { if( (*iter).bDmgProcessing ) { pTarget->OnSkillDamage( m_caster, (*iter).hTarget, (*iter).pDamage ); if( CheckDamage( (*iter).pDamage ) ) pTarget->Damage(); (*iter).bDmgProcessing = false; //시전자 FX if( bSendFx ) { AddFxData( m_caster, m_caster, m_caster, m_nCasterFxID, m_nFxPos ); bSendFx = false; } } if( (*iter).bSubHitProcessing ) { if( CheckDamage( (*iter).pDamage ) ) AddFxData( (*iter).hTarget, (*iter).hTarget, (*iter).hTarget, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); (*iter).bSubHitProcessing = false; } } else { (*iter).bDmgProcessing = false; (*iter).bSubHitProcessing = false; (*iter).bSubFireProcessing = false; } if( --nTargetCnt <= 0 ) break; } } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( bHit ) { iter = m_vTargetList.begin(); for( int nTargetCnt = m_nTargetCnt; iter != m_vTargetList.end(); ) { SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( (*iter).hTarget ); if( pTarget ) { if( (*iter).bSubFireProcessing ) { if( CheckDamage( (*iter).pDamage ) ) AddFxData( (*iter).hTarget, (*iter).hTarget, (*iter).hTarget, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); (*iter).bSubFireProcessing = false; } } if( !(*iter).bDmgProcessing && !(*iter).bSubHitProcessing && !(*iter).bSubFireProcessing ) { SAFE_DELETE( (*iter).pDamage ); iter = m_vTargetList.erase( iter ); } else ++iter; if( --nTargetCnt <= 0 ) break; } } } if( m_vTargetList.empty() ) SetEnd( true ); return true; } //////////////////////////////////////////////////////////////////////////// ////대상 1체에 미사일형 스킬 발사 한번발사될수도 있고 연속으로 발사될수도 있다 ////일정 범위 만큼 데미지를 주는 경우에는 히트FX가 거대하게 폭발한다 ////연출유형 ID : 501 void SActionFireMissle::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; if( pMsg->vSkillResult.empty() || (int)pMsg->vSkillResult.size() <= m_iResultIndex ) m_target = pMsg->target; else m_target = pMsg->vSkillResult[m_iResultIndex].GetTargetHandle(); MakeDamage( pMsg, pSkillFx ); SetFxData(); } bool SActionFireMissle::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); if( m_pCast ) m_pCast->Process( dwTime ); return true; } bool SActionFireMissle::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pCast ) m_pCast->Render( ppViewportList[vit] ); } return true; } bool SActionFireMissle::Step01() { GetMatrixSet( m_pAttack, m_pTarget, EFFECT_POS_DAMAGE ); if( m_pCast ) { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); GetDirection( m_Matrix, m_SrcPos, m_DstPos ); m_Matrix.SetPosVector( m_SrcPos ); m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); m_pCast->SetTransform( m_Matrix ); ShootingFlyingStyle(); PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pCastFxSet->sound_start_file_ID ), m_pCastFxSet, &m_SrcPos ); m_dwStartTime = m_dwTime; } return true; } bool SActionFireMissle::Step02() { K3DMatrix matTarget; GetResultMat( matTarget, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, matTarget ); GetFlyingTime( &m_DstPos, &m_SrcPos ); K3DVectorLerp( m_SrcPos, m_SrcPos, m_DstPos, (m_dwTime - m_dwStartTime) / m_fFlyingTime ); if( (float)(m_dwTime - m_dwStartTime) < m_fFlyingTime ) { if( m_btFlyingState ) { float z = 0.f; WORD wTile=0; GetHeight( m_SrcPos.x, m_SrcPos.y, z,wTile ); m_SrcPos.z = z + (float)GameRule::DEFAULT_UNIT_SIZE; } m_Matrix.SetPosVector( m_SrcPos ); m_pCast->SetTransform( m_Matrix ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); } else { GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pCast->SetPosition( m_DstPos ); m_iPlayStep = 2; if( m_pCastFxSet->IsEffect[m_iPlayStep] ) m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); else { _CID( SETFORCERENDER_FLAG ); m_pCast->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_pCast->PlayAnimation( m_dwTime, "NOT_FOUND" ); } if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( m_pCastFxSet->IsSound[m_iPlayStep] ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pCastFxSet->sound_end_file_ID ), m_pCastFxSet, &m_DstPos ); } if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } if(!CheckDamage(m_pDamage)) { SetEnd(true); return true; } m_pTarget->Damage(); m_dwStartTime = m_dwTime; SetStep( STEP_04 ); } return true; } bool SActionFireMissle::Step03() { if( (m_dwTime - m_dwStartTime) < m_acc ) { float fTime = (float)((m_dwTime - m_dwStartTime) / m_acc ); // K3DVector vTemp = GetParabolaPos( fTime ); K3DMatrix vMatResult = GetParabolaPos( fTime ); /* if( m_btFlyingState ) { float z = GetHeight( vTemp.x, vTemp.y ); vTemp.z = z + (float)GameRule::DEFAULT_UNIT_SIZE; }*/ // m_Matrix.SetPosVector( vTemp ); m_pCast->SetTransform( vMatResult ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); } else { GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pCast->SetPosition( m_DstPos ); m_iPlayStep = 2; if( m_pCastFxSet->IsEffect[m_iPlayStep] ) m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); else { _CID( SETFORCERENDER_FLAG ); m_pCast->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_pCast->PlayAnimation( m_dwTime, "NOT_FOUND" ); } if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( m_pCastFxSet->IsSound[m_iPlayStep] ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pCastFxSet->sound_end_file_ID ), m_pCastFxSet, &m_DstPos ); } if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } if(!CheckDamage(m_pDamage)) { SetEnd(true); return true; } m_pTarget->Damage(); m_dwStartTime = m_dwTime; SetStep( STEP_04 ); } return true; } bool SActionFireMissle::Step04() { if( !IsEnd() ) { if( !m_pCast->IsPlaying() ) { if( m_pMsgHandler ) m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); } if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_pSubStageHitFxSet == NULL && m_pSubStageFireFxSet == NULL ) SetEnd( true ); } return true; } //////////////////////////////////////////////////////////////////////////// ////여러 대상으로 미사일형 스킬 발사 한번발사될수도 있고 연속으로 발사될수도 있다 ////연출유형 ID : 502 void SActionFireMultiMissle::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; if( pMsg->vSkillResult.empty() || (int)pMsg->vSkillResult.size() <= m_iResultIndex ) m_target = pMsg->target; else m_target = pMsg->vSkillResult[m_iResultIndex].GetTargetHandle(); MakeDamage( pMsg, pSkillFx ); if( m_pDamage ) m_pDamage->bSphereDamage = true; SetFxData(); } bool SActionFireMultiMissle::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); if( m_pCast ) m_pCast->Process( dwTime ); return true; } bool SActionFireMultiMissle::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pCast ) m_pCast->Render( ppViewportList[vit] ); } return true; } bool SActionFireMultiMissle::Step01() { GetMatrixSet( m_pAttack, m_pTarget, EFFECT_POS_DAMAGE ); if( CheckNowState( m_pTarget ) && m_pCast ) { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); ShootingFlyingStyle(); GetDirection( m_Matrix, m_SrcPos, m_DstPos ); m_Matrix.SetPosVector( m_SrcPos ); m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); m_pCast->SetTransform( m_Matrix ); PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pCastFxSet->sound_start_file_ID ), m_pCastFxSet, &m_SrcPos ); m_dwStartTime = m_dwTime; } return true; } bool SActionFireMultiMissle::Step02() { K3DMatrix matTarget; GetResultMat( matTarget, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, matTarget ); GetFlyingTime( &m_DstPos, &m_SrcPos ); K3DVectorLerp( m_SrcPos, m_SrcPos, m_DstPos, (m_dwTime - m_dwStartTime) / m_fFlyingTime ); if( (float)(m_dwTime - m_dwStartTime) < m_fFlyingTime ) { if( m_btFlyingState ) { float z = 0.f; WORD wTile=0; GetHeight( m_SrcPos.x, m_SrcPos.y, z,wTile ); m_SrcPos.z = z + (float)GameRule::DEFAULT_UNIT_SIZE; } m_Matrix.SetPosVector( m_SrcPos ); m_pCast->SetTransform( m_Matrix ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); } else { GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pCast->SetPosition( m_DstPos ); m_iPlayStep = 2; if( m_pCastFxSet->IsEffect[m_iPlayStep] ) m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); else { _CID( SETFORCERENDER_FLAG ); m_pCast->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_pCast->PlayAnimation( m_dwTime, "NOT_FOUND" ); } if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( m_pCastFxSet->IsSound[m_iPlayStep] ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pCastFxSet->sound_end_file_ID ), m_pCastFxSet, &m_DstPos ); } if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } if(!CheckDamage(m_pDamage)) { SetEnd(true); return true; } m_pTarget->Damage(); SetStep( STEP_04 ); } return true; } bool SActionFireMultiMissle::Step03() { if( (m_dwTime - m_dwStartTime) < m_acc ) { float fTime = (float)((m_dwTime - m_dwStartTime) / m_acc ); // K3DVector vTemp = GetParabolaPos( fTime ); K3DMatrix vMatResult = GetParabolaPos( fTime ); /* if( m_btFlyingState ) { float z = GetHeight( vTemp.x, vTemp.y ); vTemp.z = z + (float)GameRule::DEFAULT_UNIT_SIZE; }*/ // m_Matrix.SetPosVector( vTemp ); m_pCast->SetTransform( vMatResult ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); } else { GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pCast->SetPosition( m_DstPos ); m_iPlayStep = 2; if( m_pCastFxSet->IsEffect[m_iPlayStep] ) m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); else { _CID( SETFORCERENDER_FLAG ); m_pCast->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_pCast->PlayAnimation( m_dwTime, "NOT_FOUND" ); } if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( m_pCastFxSet->IsSound[m_iPlayStep] ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pCastFxSet->sound_end_file_ID ), m_pCastFxSet, &m_DstPos ); } if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } if(!CheckDamage(m_pDamage)) { SetEnd(true); return true; } m_pTarget->Damage(); m_dwStartTime = m_dwTime; SetStep( STEP_04 ); } return true; } bool SActionFireMultiMissle::Step04() { if( !IsEnd() ) { if( !m_pCast->IsPlaying() ) { if( m_pMsgHandler ) m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); } if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_pSubStageHitFxSet == NULL && m_pSubStageFireFxSet == NULL ) SetEnd( true ); } return true; } //////////////////////////////////////////////////////////////////////////// ////대상 1체에 관통형미사일 스킬 발사 한번발사될수도 있고 연속으로 발사될수도 있다 ////미사일과 대상이 스쳐지나가게 된다면 히트FX를 나타낸다 ////연출유형 ID : 503 void SActionFirePenetratedMissle::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; m_fLength = (float)pMsg->fire.range; SetFxData(); for(short x = 0; x < pMsg->fire.target_count; x++ ) { SMSG_DAMAGE* pDamage = new SMSG_DAMAGE; pDamage->attacker_handle = pMsg->caster; /// 2012.08.03 vSkillResult는 fire.count 개수와 같은데, 루프를 fire.target_count로 돌고 있기 때문에, 유효한지 체크 추가함 /// 관통형 미사일이라서 fire.target_count와 fire.count가 같을 거 같지만 크래쉬가 나는 것 같아서 조건 체크 추가함 - prodongi if (x < (short)pMsg->vSkillResult.size()) { pDamage->target_handle = pMsg->vSkillResult[x].GetTargetHandle(); pDamage->skillresult = pMsg->vSkillResult[x]; } pDamage->nSkillID = pMsg->skill_id; pDamage->nSkillLevel = pMsg->skill_level; SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( pDamage->target_handle ); if( pTarget ) { if( pTarget->GetObjType() == TS_ENTER::GAME_MOB || pTarget->GetObjType() == TS_ENTER::GAME_SUMMON || pTarget->GetObjType() == TS_ENTER::GAME_NPC ) pDamage->strTargetName = GetStringDB().GetString( GetMonsterDB().GetTextID( pTarget->GetContentID() ) ); else if( pTarget->GetObjType() == TS_ENTER::GAME_PLAYER ) pDamage->strTargetName = pTarget->GetName(); } else pDamage->strTargetName = GetStringDB().GetString( 88 ); SGameAvatarEx* pCaster = (SGameAvatarEx *)GetGameObject( pDamage->attacker_handle ); if( pCaster ) { if( pCaster->GetObjType() == TS_ENTER::GAME_MOB || pCaster->GetObjType() == TS_ENTER::GAME_SUMMON || pCaster->GetObjType() == TS_ENTER::GAME_NPC ) pDamage->strCasterName = GetStringDB().GetString( GetMonsterDB().GetTextID( pCaster->GetContentID() ) ); else if( pCaster->GetObjType() == TS_ENTER::GAME_PLAYER ) pDamage->strCasterName = pCaster->GetName(); } else pDamage->strCasterName = GetStringDB().GetString( 88 ); // 범위 뎀쥐일경우 pDamage->bSphereDamage = true; m_DamageList.push_back( pDamage ); //거리 계산땜에 저장한다 TARGET_DATA_LIST pTargetList; pTargetList.pDamage = pDamage; m_vTargetList.push_back( pTargetList ); } } SActionFirePenetratedMissle::SActionFirePenetratedMissle() { } SActionFirePenetratedMissle::~SActionFirePenetratedMissle() { std::vector< TARGET_DATA_LIST >::iterator iter = m_vTargetList.begin(); for(; iter != m_vTargetList.end(); ) iter = m_vTargetList.erase( iter ); m_vTargetList.clear(); } bool SActionFirePenetratedMissle::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); if( m_pCast ) m_pCast->Process( dwTime ); return true; } bool SActionFirePenetratedMissle::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pCast ) m_pCast->Render( ppViewportList[vit] ); } return true; } bool SActionFirePenetratedMissle::Step01() { GetMatrixSet( m_pAttack, m_pTarget, EFFECT_POS_DAMAGE ); if( m_pCast ) { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); GetDirection( m_Matrix, m_SrcPos, m_DstPos ); m_Matrix.SetPosVector( m_SrcPos ); m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); m_pCast->SetPosition( m_SrcPos ); m_velocity = m_DstPos - m_SrcPos; m_velocity.Normalize(); m_DstPos = m_SrcPos + (m_velocity * m_fLength); m_acc = K3DVectorLength( m_DstPos - m_SrcPos ); calsAcc(); PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pCastFxSet->sound_start_file_ID ), m_pCastFxSet, &m_SrcPos ); K3DVector vTemp1 = K3DVector( m_SrcPos.x, m_SrcPos.y, 0.0f ); K3DVector vTemp2 = K3DVector( 0.0f, 0.0f, 0.0f ); std::vector< TARGET_DATA_LIST >::iterator iter = m_vTargetList.begin(); for( ; iter != m_vTargetList.end(); ) { SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( (*iter).pDamage->target_handle ); //죽었는지 체크 if( pTarget && CheckNowState( pTarget ) ) { K3DMatrix* pMat = pTarget->GetTransform(); vTemp2.x = pMat->_41; vTemp2.y = pMat->_42; (*iter).fOldLength = K3DVectorLength( vTemp1 - vTemp2 ); iter++; } else iter = m_vTargetList.erase( iter ); } m_dwStartTime = m_dwTime; SetStep( STEP_02 ); } else SetEnd( true ); return true; } bool SActionFirePenetratedMissle::Step02() { K3DVector vTemp1, vTemp2; K3DVectorLerp( vTemp1, m_SrcPos, m_DstPos, (m_dwTime - m_dwStartTime) / m_acc ); if( (m_dwTime - m_dwStartTime) < m_acc ) { if( m_iFlyingStyle != 0 ) { float z = 0.f; WORD wTile=0; GetHeight( vTemp1.x, vTemp1.y, z,wTile ); vTemp1.z = z + (float)GameRule::DEFAULT_UNIT_SIZE; } m_Matrix.SetPosVector( vTemp1 ); m_pCast->SetTransform( m_Matrix ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); vTemp1 = K3DVector( vTemp1.x, vTemp1.y, 0.0f ); vTemp2 = K3DVector( 0.0f, 0.0f, 0.0f ); std::vector< TARGET_DATA_LIST >::iterator iter = m_vTargetList.begin(); for( ; iter != m_vTargetList.end(); ) { SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( (*iter).pDamage->target_handle ); if( pTarget == NULL ) { iter++; continue; } K3DMatrix* pMat = pTarget->GetTransform(); vTemp2.x = pMat->_41; vTemp2.y = pMat->_42; //대상과의 거리가 20보다 작으면 히트 처리 //서버와의 거리계산이 안맞으면 20보다 작은 값이 나오지 않을수 있기 때문에 전 Length와 비교후 전 Length가 작으면 강제 히트처리 float fLength = K3DVectorLength( vTemp1 - vTemp2 ); if( fLength < 20.0f || (*iter).fOldLength < fLength ) { if((*iter).pDamage) { pTarget->OnSkillDamage( m_caster, (*iter).pDamage->target_handle, (*iter).pDamage ); } if(!CheckDamage((*iter).pDamage)) { iter = m_vTargetList.erase( iter ); continue; } pTarget->Damage(); AddFxData( (*iter).pDamage->target_handle, (*iter).pDamage->target_handle, (*iter).pDamage->target_handle, m_pSubStageHitFxSet->nID, EFFECT_POS_DAMAGE ); iter = m_vTargetList.erase( iter ); } else { (*iter).fOldLength = fLength; iter++; } } } else { m_iPlayStep = 2; if( m_pCastFxSet->IsEffect[m_iPlayStep] ) m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep], KSeqForm::SEQTYPE_LOOP ); if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( m_pCastFxSet->IsSound[m_iPlayStep] ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pCastFxSet->sound_middle_file_ID ), m_pCastFxSet, &m_SrcPos, true ); } m_dwStartTime = m_dwTime; m_SrcPos = m_DstPos; m_DstPos = m_DstPos + ( m_velocity * (float)GameRule::DEFAULT_UNIT_SIZE ); m_velocity = m_DstPos - m_SrcPos; m_velocity.Normalize(); m_DstPos = m_SrcPos + (m_velocity * m_fLength); m_acc = K3DVectorLength( m_DstPos - m_SrcPos ); calsAcc(); SetStep( STEP_03 ); } return true; } bool SActionFirePenetratedMissle::Step03() { K3DVector vTemp; K3DVectorLerp( vTemp, m_SrcPos, m_DstPos, (m_dwTime - m_dwStartTime) / m_acc ); if( (m_dwTime - m_dwStartTime) < m_acc ) { if( m_iFlyingStyle != 0 ) { float z = 0.f; WORD wTile=0; GetHeight( vTemp.x, vTemp.y, z,wTile ); vTemp.z = z + (float)GameRule::DEFAULT_UNIT_SIZE; } m_fVisibility = 1.0f - (float)(m_dwTime - m_dwStartTime) / m_acc; m_Matrix.SetPosVector( vTemp ); m_pCast->SetTransform( m_Matrix ); m_pCast->SetVisibility( m_fVisibility ); } else { if( !IsEnd() ) SetEnd( true ); } return true; } /// 2011.03.23 - prodongi //////////////////////////////////////////////////////////////////////////// ////미사일이 여러 대상을 연쇄적으로 발사 됨 ////연출유형 ID : 504 void SActionFireChainMissile::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_readyNextResult = false; /* m_caster = pMsg->caster; if( pMsg->vSkillResult.empty() || (int)pMsg->vSkillResult.size() <= m_iResultIndex ) m_target = pMsg->target; else m_target = pMsg->vSkillResult[m_iResultIndex].GetTargetHandle(); MakeDamage( pMsg, pSkillFx ); */ setSkillEvent(pMsg); SetFxData(); } bool SActionFireChainMissile::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) return true; if (m_readyNextResult) { float t = ((float)(m_dwTime - m_dwStartTime))/1000.0f; if (m_pSkill_FX->fStage_Data[4] <= t) { setNextChainResultIndex(); m_readyNextResult = false; } } else { (this->*Function_Step[m_nStep])(); } if( m_pCast ) m_pCast->Process( dwTime ); return true; } bool SActionFireChainMissile::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { int a = 0; a = 1; for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pCast ) m_pCast->Render( ppViewportList[vit] ); } return true; } bool SActionFireChainMissile::Step01() { GetMatrixSet( m_pAttack, m_pTarget, EFFECT_POS_DAMAGE ); if( m_pCast ) { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); GetDirection( m_Matrix, m_SrcPos, m_DstPos ); m_Matrix.SetPosVector( m_SrcPos ); m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); m_pCast->SetTransform( m_Matrix ); ShootingFlyingStyle(); PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pCastFxSet->sound_start_file_ID ), m_pCastFxSet, &m_SrcPos ); m_dwStartTime = m_dwTime; } return true; } bool SActionFireChainMissile::Step02() { K3DMatrix matTarget; GetResultMat( matTarget, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, matTarget ); GetFlyingTime( &m_DstPos, &m_SrcPos ); // _oprint("flyingTime:%f, lerpTime:%d\n", m_fFlyingTime, (int)(m_dwTime - m_dwStartTime)); K3DVectorLerp( m_SrcPos, m_SrcPos, m_DstPos, (m_dwTime - m_dwStartTime) / m_fFlyingTime ); if( (float)(m_dwTime - m_dwStartTime) < m_fFlyingTime ) { if( m_btFlyingState ) { float z = 0.f; WORD wTile=0; GetHeight( m_SrcPos.x, m_SrcPos.y, z,wTile ); m_SrcPos.z = z + (float)GameRule::DEFAULT_UNIT_SIZE; } m_Matrix.SetPosVector( m_SrcPos ); m_pCast->SetTransform( m_Matrix ); PlayMiddleAnimation( m_pAttack, m_pCast, m_pCastFxSet ); _CID ( SETRENDER_FLAG ); KMsgSET_RENDERFLAG rendermsg; rendermsg.bRenderFlag = TRUE; m_pCast->Perform( id_SETRENDER_FLAG, rendermsg); } else { GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); m_pCast->SetPosition( m_DstPos ); m_iPlayStep = 2; if( m_pCastFxSet->IsEffect[m_iPlayStep] ) m_pCast->PlayAnimation( m_dwTime, pEffectAniKey[m_iPlayStep] ); else { _CID( SETFORCERENDER_FLAG ); m_pCast->Perform( id_SETFORCERENDER_FLAG, KArg() ); m_pCast->PlayAnimation( m_dwTime, "NOT_FOUND" ); } if( m_pMsgHandler ) { m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); if( m_pCastFxSet->IsSound[m_iPlayStep] ) PlaySoundFx( m_pAttack, GetResourceDB().GetSoundResourceName( m_pCastFxSet->sound_end_file_ID ), m_pCastFxSet, &m_DstPos ); } if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } if(!CheckDamage(m_pDamage)) { SetEnd(true); return true; } m_pTarget->Damage(); m_dwStartTime = m_dwTime; SetStep( STEP_04 ); } return true; } bool SActionFireChainMissile::Step03() { return true; } bool SActionFireChainMissile::Step04() { if( !IsEnd() ) { if( !m_pCast->IsPlaying() ) { if( m_pMsgHandler ) m_pMsgHandler->StopSound( m_strSound.c_str(), m_iSoundIndex ); } if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_target, m_target, m_target, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_pSubStageHitFxSet == NULL && m_pSubStageFireFxSet == NULL ) { m_readyNextResult = true; //setNextChainResultIndex(); } } return true; } void SActionFireChainMissile::setSkillEvent(struct SMSG_SKILL_EVENT const* msg) { m_skillEvent.m_id = msg->skill_id; m_skillEvent.m_level = msg->skill_level; m_skillEvent.m_chainCaster = msg->caster; int resultCount = msg->vSkillResult.size(); for (int i = 0; i < resultCount; ++i) { SkillResult result; memcpy(&result, &msg->vSkillResult[i], sizeof (SkillResult)); m_skillEvent.m_result.push_back(result); } } void SActionFireChainMissile::setCurChainResultIndex(int index) { if (index >= (int)m_skillEvent.m_result.size()) { SetEnd(true); return ; } int casterResult = findValidHandle(index, true); if (0 > casterResult) { SetEnd(true); return ; } int targetResult = findValidHandle(casterResult, false); if (0 > targetResult) { SetEnd(true); return ; } int resultType = m_skillEvent.m_result[casterResult].GetType(); if (SkillResult::CHAIN_DAMAGE == resultType || SkillResult::CHAIN_MAGIC_DAMAGE == resultType) { m_caster = m_skillEvent.m_result[casterResult].chain_damage.hFrom; m_target = m_skillEvent.m_result[targetResult].chain_damage.hTarget; } else if (SkillResult::CHAIN_HEAL == resultType) { m_caster = m_skillEvent.m_result[casterResult].chain_heal.hFrom; m_target = m_skillEvent.m_result[targetResult].chain_heal.hTarget; } MakeChainDamage(m_pSkill_FX, m_skillEvent.m_result[targetResult], m_skillEvent.m_id, m_skillEvent.m_level, m_caster, m_target, m_skillEvent.m_chainCaster); SetStep( STEP_01 ); m_resultIndex = targetResult; m_iPlayStep = 0; if (!m_pSubStageHitFxSet) m_pSubStageHitFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nHit_Fx_Set_Id ); if (!m_pSubStageFireFxSet) m_pSubStageFireFxSet = GetMotionFxSetDB().GetFXSet( m_pSkill_FX->nSub_Fire_Fx_Set_Id ); // _oprint("index:%u, caster:%u, target:%u\n", m_resultIndex, m_caster, m_target); } void SActionFireChainMissile::setNextChainResultIndex() { setCurChainResultIndex(m_resultIndex + 1); } int SActionFireChainMissile::findValidHandle(int startIndex, bool caster) { AR_HANDLE handle; int resultCount = m_skillEvent.m_result.size(); for (int i = startIndex; i < resultCount; ++i) { handle = 0; int resultType = m_skillEvent.m_result[i].GetType(); if (SkillResult::CHAIN_DAMAGE == resultType || SkillResult::CHAIN_MAGIC_DAMAGE == resultType) { if (caster) handle = m_skillEvent.m_result[i].chain_damage.hFrom; else handle = m_skillEvent.m_result[i].chain_damage.hTarget; } else if (SkillResult::CHAIN_HEAL == resultType) { if (caster) handle = m_skillEvent.m_result[i].chain_heal.hFrom; else handle = m_skillEvent.m_result[i].chain_heal.hTarget; } if (handle) { SGameObject* object = GetGameObject(handle); if (object) { return i; } } } return -1; } //////////////////////////////////////////////////////////////////////////// ////대상이 서있는 위치를 기준으로 지역에 지속적으로 데미지 or 회복처리 이펙트 나타낸다 ////광역스킬 ////연출유형 ID : 601, 604, 701 void SActionLastingWideAreaSkill::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->caster; MakeDamage( pMsg, pSkillFx ); if( m_pDamage == NULL ) { MakeAbsorbe(pMsg, pSkillFx); if( m_pDamage ) { m_target = m_pDamage->target_handle; SetStep( STEP_02 ); } } else { SetStep( STEP_01 ); m_target = m_pDamage->target_handle; } SetFxData(); if( m_pDamage ) { m_pDamage->bSphereDamage = true; m_pDamage->skill_type = SMSG_DAMAGE::REGION_FIRE_SKILL; } } bool SActionLastingWideAreaSkill::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; // if( !CheckAttacker() || !CheckTarget() ) if( !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); return true; } bool SActionLastingWideAreaSkill::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { return true; } bool SActionLastingWideAreaSkill::Step01() { if(m_pDamage) { m_pTarget->OnSkillDamage( m_caster, m_target, m_pDamage ); } if(!CheckDamage(m_pDamage)) { SetEnd(true); return true; } m_pTarget->Damage(); // RunScript(m_pDamage); if( m_pExplosionFxSet ) { AddFxData( m_pDamage->target_handle, m_pDamage->target_handle, m_pDamage->target_handle, m_pExplosionFxSet->nID, m_nFxPos ); } SetStep( STEP_03 ); return true; } bool SActionLastingWideAreaSkill::Step02() { SendSkillDamage( m_pTarget, m_caster, m_target, m_pDamage ); if( m_pExplosionFxSet ) { AddFxData( m_pDamage->target_handle, m_pDamage->target_handle, m_pDamage->target_handle, m_pExplosionFxSet->nID, m_nFxPos ); } SetStep( STEP_03 ); return true; } bool SActionLastingWideAreaSkill::Step03() { if( !IsEnd() ) { if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_pDamage->target_handle, m_pDamage->target_handle, m_pDamage->target_handle, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_pDamage->target_handle, m_pDamage->target_handle, m_pDamage->target_handle, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_pSubStageHitFxSet == NULL && m_pSubStageFireFxSet == NULL ) SetEnd( true ); } return true; } //////////////////////////////////////////////////////////////////////////// ////채집 스킬 ////광역스킬 ////연출유형 ID : 1001 void SActionWorkingSkill::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; m_pDamage = new SMSG_DAMAGE; m_pDamage->attacker_handle = pMsg->caster; m_pDamage->nSkillID = pMsg->skill_id; m_pDamage->nSkillLevel = pMsg->skill_level; //m_pDamage->strTargetName = pMsg->target_name; // Fraun performance tweak if( m_iResultIndex < (int)pMsg->vSkillResult.size() ) { m_pDamage->target_handle = pMsg->vSkillResult[m_iResultIndex].GetTargetHandle(); m_pDamage->skillresult = pMsg->vSkillResult[m_iResultIndex]; } SGameAvatarEx* pCaster = (SGameAvatarEx *)GetGameObject( m_pDamage->attacker_handle ); SGameAvatarEx* pTarget = (SGameAvatarEx *)GetGameObject( m_pDamage->target_handle ); SetDamageDisplayName( m_pDamage, pCaster, pTarget ); SetStep( STEP_01 ); } bool SActionWorkingSkill::Process( DWORD dwTime, unsigned long uProcessBitVector) { m_dwTime = dwTime; (this->*Function_Step[m_nStep])(); return true; } bool SActionWorkingSkill::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { return true; } bool SActionWorkingSkill::Step01() { m_pAttack = (SGameAvatarEx *)GetGameObject( m_caster ); if( m_pAttack ) { m_pAttack->OnSkillDamage( m_caster, m_target, m_pDamage ); } SetEnd( true ); return true; } // PathEffect 테스트용 스킬 void SActionPfxTest1::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { if( pMsg->vSkillResult.empty() ) SetEnd( true ); else { m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->vSkillResult[m_iResultIndex].GetTargetHandle(); MakeDamage( pMsg, pSkillFx ); SetFxData(); // 여기 처리해줘야 함 } } bool SActionPfxTest1::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckAttacker() || !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); if( m_pCast ) m_pCast->Process( dwTime ); return true; } bool SActionPfxTest1::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pCast ) m_pCast->Render( ppViewportList[vit] ); } return true; } bool SActionPfxTest1::Step01() { GetMatrixSet( m_pAttack, m_pTarget, EFFECT_POS_DAMAGE ); if( m_pCast ) { GetResultMat( m_Matrix, m_pCastMat, m_pCastBoneMat, m_pCasterAttachMat ); K3DMatrixGetPosVector( m_SrcPos, m_Matrix ); GetResultMat( m_Matrix, m_pTargetMat, m_pTargetBoneMat, m_pTargetAttachMat ); K3DMatrixGetPosVector( m_DstPos, m_Matrix ); //GetDirection( m_Matrix, m_SrcPos, m_DstPos ); //m_Matrix.SetPosVector( m_SrcPos ); KSequencer* pSeq = NULL; KSeqPathEffectChain* pPfxChain = NULL; //pSeq = (KSequencer*) m_pCast->GetCurrentAnimation(); pSeq = (KSequencer*) m_pCast->GetAnimation(pEffectAniKey[1]); if(pSeq) { pPfxChain = (KSeqPathEffectChain*) pSeq->GetSeqObject(0); } if(pPfxChain) { DWORD dwDrawMode = _KSeqPathEffect::DRAW_EMITTER | _KSeqPathEffect::DRAW_POLYLINE; //DWORD dwDrawMode = _KSeqPathEffect::DRAW_POINT | _KSeqPathEffect::DRAW_LINE | _KSeqPathEffect::DRAW_ALLPR // | _KSeqPathEffect::DRAW_EMITTER | _KSeqPathEffect::DRAW_POLYLINE; pPfxChain->SetDrawMode(dwDrawMode); //pPfxChain->SetPos(m_SrcPos); pPfxChain->SetPos(m_SrcPos, m_DstPos); m_acc = pPfxChain->GetInterval().GetLength() / 4.8f; //m_acc = pPfxChain->GetDuration() / 4.8f; pSeq->GetIntervalRef().Expand(pPfxChain->GetInterval()); } m_pCast->PlayAnimation(m_dwTime, pEffectAniKey[1]); //m_pPfxModelForLeftView->PlayAnimation(0, "default", KSeqModel::SEQTYPE_LOOP); //m_pCast->PlayAnimation(m_dwTime, pEffectAniKey[1], KSeqForm::SEQTYPE_LOOP); //m_pCast->SetTransform( m_Matrix ); //ShootingFlyingStyle(); //PlaySoundFx( m_pCastFxSet->pszSound_start_file, m_pCastFxSet, &m_SrcPos ); m_dwStartTime = m_dwTime; SetStep(STEP_02); } else { SetEnd(true); } return true; } bool SActionPfxTest1::Step02() { if( (m_dwTime - m_dwStartTime) < m_acc ) { } else { SetEnd(true); } return true; } //라이트닝 스킬 SActionLightningFx::SActionLightningFx() : m_pLightningFx( NULL ) { } SActionLightningFx::~SActionLightningFx() { SAFE_DELETE( m_pLightningFx ); } void SActionLightningFx::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { // m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; if( m_target == 0 ) { if( !pMsg->vSkillResult.empty() ) { m_target = pMsg->vSkillResult[0].GetTargetHandle(); } } m_pLightningFx = new SGameLightningFx; m_pLightningFx->Init( this, m_caster, pMsg->vSkillResult ); // MakeDamage( pMsg, pSkillFx ); // SetFxData(); SetStep( STEP_01 ); } bool SActionLightningFx::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); m_pLightningFx->Process( m_dwTime ); return true; } bool SActionLightningFx::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; m_pLightningFx->Render( ppViewportList[vit] ); } return true; } bool SActionLightningFx::Step01() { if( m_pLightningFx->IsEnd() ) { SetStep( STEP_02 ); } return true; } bool SActionLightningFx::Step02() { if( !IsEnd() ) { if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_pDamage->target_handle, m_pDamage->target_handle, m_pDamage->target_handle, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_pDamage->target_handle, m_pDamage->target_handle, m_pDamage->target_handle, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_pSubStageHitFxSet == NULL && m_pSubStageFireFxSet == NULL ) SetEnd( true ); } return true; } //힐링 웨이브 SActionHealingWaveFx::SActionHealingWaveFx() : m_pHealingWaveFx( NULL ) { } SActionHealingWaveFx::~SActionHealingWaveFx() { SAFE_DELETE( m_pHealingWaveFx ); } void SActionHealingWaveFx::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { // m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; if( m_target == 0 ) { if( !pMsg->vSkillResult.empty() ) { m_target = pMsg->vSkillResult[0].GetTargetHandle(); } } m_pHealingWaveFx = new SGameHealingWaveFx; m_pHealingWaveFx->Init( this, m_caster, pMsg->vSkillResult ); // MakeDamage( pMsg ); // SetFxData(); SetStep( STEP_01 ); } bool SActionHealingWaveFx::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); m_pHealingWaveFx->Process( m_dwTime ); return true; } bool SActionHealingWaveFx::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; m_pHealingWaveFx->Render( ppViewportList[vit] ); } return true; } bool SActionHealingWaveFx::Step01() { if( m_pHealingWaveFx->IsEnd() ) { SetStep( STEP_02 ); } return true; } bool SActionHealingWaveFx::Step02() { if( !IsEnd() ) { if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_pDamage->target_handle, m_pDamage->target_handle, m_pDamage->target_handle, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_pDamage->target_handle, m_pDamage->target_handle, m_pDamage->target_handle, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_pSubStageHitFxSet == NULL && m_pSubStageFireFxSet == NULL ) SetEnd( true ); } return true; } //축복의 망치 SActionBlessingHammer::SActionBlessingHammer() { m_fHammerZOffSet = 12.0f; m_fHammerDistance = 10.0f; m_fHammerZRotation = 0.0f; m_dwZRotationTime = 1000; m_dwOldZRotationTime = 0; m_fHammerXRotation = 0.0f; m_dwXRotationTime = 500; m_dwOldXRotationTime = 0; m_dwHammerTime = 10000; m_fMovingDistance = (float)3 * GameRule::DEFAULT_UNIT_SIZE; } SActionBlessingHammer::~SActionBlessingHammer() { } void SActionBlessingHammer::InitFx( struct SMSG_SKILL_EVENT* pMsg, struct _SKILL_FX* pSkillFx ) { // m_pSkill_FX = pSkillFx; m_caster = pMsg->caster; m_target = pMsg->target; if( m_target == 0 ) { if( !pMsg->vSkillResult.empty() ) { m_target = pMsg->vSkillResult[0].GetTargetHandle(); } } // MakeDamage( pMsg ); // SetFxData(); NX3LoadPack loadpack; loadpack.Init(); KSeqModel * pFire = new KSeqModel; pFire->AddAnimation( pEffectAniKey[1], "drop_weapon_hammer.nx3", KNX3Manager::SEQTYPE_ALL, &loadpack ); m_pThrow = pFire; SetStep( STEP_01 ); } bool SActionBlessingHammer::Process( DWORD dwTime, unsigned long uProcessBitVector ) { m_dwTime = dwTime; if( !CheckTarget() ) return true; (this->*Function_Step[m_nStep])(); if( m_pThrow ) m_pThrow->Process( dwTime ); return true; } bool SActionBlessingHammer::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount ) { for(int vit = 0; vit < nViewportCount; ++vit) { if( (ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME) == 0) continue; if( m_pThrow ) m_pThrow->Render( ppViewportList[vit] ); } return true; } bool SActionBlessingHammer::Step01() { if( !CheckAttacker() ) { SetEnd( true ); return true; } m_dwOldTime = m_dwTime; m_dwOldHammerTime = m_dwTime; m_dwOldZRotationTime = m_dwTime; m_dwOldXRotationTime = m_dwTime; K3DMatrixIdentity( m_matParent ); m_matParent._41 = m_pAttack->GetPosition()->x; m_matParent._42 = m_pAttack->GetPosition()->y; m_matParent._43 = m_pAttack->GetPosition()->z; m_vPosition = K3DVector( m_fHammerDistance, m_fHammerDistance, 0.0f ); K3DMatrix matTrans; K3DMatrixTranslation( matTrans, m_vPosition.x, m_vPosition.y, m_vPosition.z ); K3DMatrixMultiply( matTrans, matTrans, m_matParent ); m_pThrow->SetTransform( matTrans ); m_pThrow->PlayAnimation( m_dwTime, pEffectAniKey[1] ); SetStep( STEP_02 ); return true; } bool SActionBlessingHammer::Step02() { if( (m_dwTime - m_dwOldZRotationTime) < m_dwZRotationTime ) { float fGap = (float)(m_dwTime - m_dwOldZRotationTime) / m_dwZRotationTime; m_fHammerZRotation = (K3D_PI*2) * fGap; } else { m_dwOldZRotationTime = m_dwTime; m_fHammerZRotation = 0.0f; } if( (m_dwTime - m_dwOldXRotationTime) < m_dwXRotationTime ) { float fGap = (float)(m_dwTime - m_dwOldXRotationTime) / m_dwXRotationTime; m_fHammerXRotation = (K3D_PI*2) * fGap; } else { m_dwOldXRotationTime = m_dwTime; m_fHammerXRotation = 0.0f; } if( (m_dwTime - m_dwOldHammerTime ) < m_dwHammerTime ) { float t = (float)(m_dwTime - m_dwOldHammerTime ) / (float)m_dwHammerTime; float m = m_fHammerDistance + ( t * ( m_fMovingDistance - m_fHammerDistance ) ); m_vPosition.x = m; m_vPosition.y = m; m_vPosition.z = 0.0f; } else { m_vPosition.x = m_fMovingDistance; m_vPosition.y = m_fMovingDistance; m_vPosition.z = 0.0f; SetStep( STEP_03 ); } K3DMatrix mat, matRot, matTrans, matParent; K3DMatrixRotationZ( matRot, m_fHammerXRotation ); K3DMatrixTranslation( matTrans, m_vPosition.x, m_vPosition.y, m_vPosition.z + m_fHammerZOffSet ); K3DMatrixMultiply( matTrans, matRot, matTrans ); K3DMatrixRotationZ( matRot, m_fHammerZRotation ); K3DMatrixMultiply( mat, matTrans, matRot ); K3DMatrixMultiply( mat, mat, m_matParent ); m_pThrow->SetTransform( mat ); return true; } bool SActionBlessingHammer::Step03() { if( !IsEnd() ) { if( m_dwTime - m_dwStartTime > m_dwAddHitDelayTime ) { if( m_pSubStageHitFxSet ) { AddFxData( m_pDamage->target_handle, m_pDamage->target_handle, m_pDamage->target_handle, m_pSubStageHitFxSet->nID, m_nFxSubHitPos ); m_pSubStageHitFxSet = NULL; } } if( m_dwTime - m_dwStartTime > m_dwAddFireDelayTime ) { if( m_pSubStageFireFxSet ) { AddFxData( m_pDamage->target_handle, m_pDamage->target_handle, m_pDamage->target_handle, m_pSubStageFireFxSet->nID, m_nFxSubFirePos ); m_pSubStageFireFxSet = NULL; } } if( m_pSubStageHitFxSet == NULL && m_pSubStageFireFxSet == NULL ) SetEnd( true ); } return true; }