6455 lines
169 KiB
C++
6455 lines
169 KiB
C++
#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 <toolkit/XStringUtil.h>
|
|
|
|
#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;
|
|
} |