Files
Leviathan/Client/Game/game/GameSystem/SAction.cpp
T
2026-06-01 12:46:52 +02:00

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;
}