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

4581 lines
123 KiB
C++
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "stdafx.h"
#include "SGameWork.h"
#include "SGameMessage.h"
#include "GameDefine.h"
#include "SGame.h"
#include "SMotionDB.h"
#include "SStringDB.h"
#include "SMonsterDB.h"
#include "SCreatureDB.h"
#include "SNpcDB.h"
#include "SGameUtil.h"
#include "SItemDB.h"
#include "SGameAvatarEx.h"
#include "SSkillStageType.h"
#include "SGameOtherEffectMng.h"
#include "LuaVM.h"
#include <toolkit/XStringUtil.h>
#include "SSoundResourceDB.h"
#include "SDebug_Util.h"
#include "SGameWorld.h"
#include "SGameSystem.h"
#include "CommonUtil.h"
#include "SGameScript.h" // Fraun performance tweak
extern SGameSystem * g_pCurrentGameSystem;
namespace
{
const char* szNX3Name[3][2] =
{
{ "gam.nx3", "gaf.nx3", },
{ "dem.nx3", "def.nx3", },
{ "asm.nx3", "asf.nx3", },
};
const char* GetNX3Name( int nRace, int nSex )
{
short race = 0;
if( nRace == GCLAN_GAIA ) race = 0;
else if( nRace == GCLAN_DEVA ) race = 1;
else if( nRace == GCLAN_ASURA ) race = 2;
else
{
assert( false && "유효하지 않는 종족" );
return "";
}
short sex = 0;
if( nSex == SEX_MALE ) sex = 0;
else if( nSex == SEX_FEMALE ) sex = 1;
else
{
assert( false && "유효하지 않는 성별" );
return "";
}
return szNX3Name[race][sex];
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SGameWork::SGameWork( SGameAvatarEx *pOwner, int nCount, DWORD dwKeepTime )
: m_nCount(nCount), m_dwStartTime(0), m_dwKeepTime(dwKeepTime), m_dwTime(0), m_pOwner(pOwner), m_bEnd(FALSE), m_nStep(STEP_00), m_nWorkType( WORK_NONE )
{
}
SGameWork::~SGameWork()
{
}
void SGameWork::Process( DWORD dwTime )
{
}
void SGameWork::_setEvent( KEventKeyRes<Key_EVENT_NEW>* srcEvent, KEventKeyRes<Key_EVENT_NEW>* & dstEvent )
{
dstEvent = NULL;
if( srcEvent )
{
dstEvent = new KEventKeyRes<Key_EVENT_NEW>;
dstEvent->SetKeyCount( srcEvent->GetKeyCount(), srcEvent->GetLength() );
for( int i(0); srcEvent->GetKeyCount()>i; i++ )
dstEvent->SetKey( i, &srcEvent->GetKey(i) );
}
}
void SGameWork::SetDamageDisplayName( SMSG_DAMAGE* pDamage, SGameAvatarEx* pTarget )
{
// Fraun performance tweak
if( m_pOwner )
{
switch (m_pOwner->GetObjType())
{
case TS_ENTER::GAME_PLAYER:
{
pDamage->strCasterName = m_pOwner->GetName();
break;
}
case TS_ENTER::GAME_MOB:
{
pDamage->strCasterName = GetStringDB().GetString(GetMonsterDB().GetTextID(m_pOwner->GetContentID()));
break;
}
case TS_ENTER::GAME_SUMMON:
{
pDamage->strCasterName = GetStringDB().GetString(GetCreatureDB().GetTextID(m_pOwner->GetContentID()));
break;
}
case TS_ENTER::GAME_NPC:
{
pDamage->strCasterName = GetStringDB().GetString(GetNpcDB().GetTextID(m_pOwner->GetContentID()));
break;
}
}
}
if( pTarget )
{
switch (m_pOwner->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;
}
}
}
}
void SGameWork::SetWorkType( WORK_TYPE nWorkType )
{
m_nWorkType = nWorkType;
}
// 2010.06.14 - prodongi
void SGameWork::SetStep(int nStep)
{
m_nStep = nStep;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//캐릭터 이모션 관련
SWorkEmotion::SWorkEmotion( class SGameAvatarEx * pOwner, struct SGameMessage * pMsg )
: SGameWork( pOwner )
{
if( pMsg )
{
//TODO : 서버에서 처리 해주면 추가 가능.
}
m_nEmotionID = -1;
SetStep(STEP_01);
}
SWorkEmotion::~SWorkEmotion()
{
if( m_pOwner ) m_pOwner->HideWeapon( TRUE );
}
bool SWorkEmotion::SetEmotion( int nEmotionID )
{
if( m_pOwner->GetCurrAnimationID() == nEmotionID )
{
SetEnd( true );
return false;
}
m_nEmotionID = nEmotionID;
return true;
}
void SWorkEmotion::Process( DWORD dwTime )
{
if( IsEnd() ) return;
if( m_pOwner->GetInnObjType() != m_pOwner->GetObjType() )
{
SetEnd( true );
return;
}
if( m_nEmotionID == -1 )
{ //초기화 안 됐음
SetEnd(TRUE);
return;
}
if( GetStep() == STEP_01 )
{
//Emotion이 가능 한가 검사
if( m_pOwner->IsAniLock() || m_pOwner->GetAttackAniLock() )
{
SetEnd(TRUE);
return;
}
if( !m_pOwner->CheckAllState() )
{
SetEnd(TRUE);
return;
}
if( m_nEmotionID == ANI_PRAY && IsRamadanPrayRoom() == false ) // 기도실이 아니면 기도는 할 수 없다
{
SetEnd(TRUE);
return ;
}
//FALSE가 무기 숨김
//TRUE가 무기 보여줌
if( ANI_CHEER != m_nEmotionID ) m_pOwner->HideWeapon( FALSE );
SetStep(STEP_02);
}
else if( GetStep() == STEP_02 )
{
m_pOwner->NPlayAnimation( m_nEmotionID );
SetStep(STEP_03);
}
else if( GetStep() == STEP_03 )
{
if( !m_pOwner->IsPlaying() && m_pOwner->GetCurrAnimationID() == m_nEmotionID )
{
m_pOwner->HideWeapon( TRUE );
m_pOwner->Default();
SetEnd(TRUE);
}
if( m_pOwner->GetCurrAnimationID() != m_nEmotionID )
{
m_pOwner->HideWeapon( TRUE );
SetEnd(TRUE);
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SWorkAttackEx
SWorkAttackEx::SWorkAttackEx( class SGameAvatarEx * pOwner, const AR_HANDLE target, float fAttackPlayRate )
: SGameWork( pOwner )
{
m_Target = target; //타겟
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_Target );
if( !m_pTarget )
{
SetEnd(TRUE);
return;
}
// _oprint( "SWorkAttackEx : fRate[%f]\n", m_fAttackRate );
ZeroMemory( m_pDamageSet, sizeof( m_pDamageSet ) );
m_nHitCount = 0;
m_nSwingCnt = 0;
m_nMaxHitCount = 0;
m_fAttackPlayRate = fAttackPlayRate;
pOwner->SetVisibleWeaponTrail( true );
SetWorkType( WORK_ATTACKEX );
}
SWorkAttackEx::~SWorkAttackEx()
{
if( !m_vFX_List.empty() )
{
if( m_pOwner )
{
for( unsigned int i(0); m_vFX_List.size()>i; i++ )
m_pOwner->DelEffect(m_vFX_List[i]);
}
m_vFX_List.erase( m_vFX_List.begin(), m_vFX_List.end() );
}
if( m_pOwner ) m_pOwner->SetAttackAniLock( false );
if( m_pOwner )
{
//처리가 안된 데미지 처리한다
while( m_nHitCount > 0 )
{
SGameAvatarEx* pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_Target );
if( pTarget )
{
SMSG_DAMAGE *pDamage = m_pDamageSet[m_nMaxHitCount-m_nHitCount];
_processDamage( pDamage, m_nHitCount, SMotionEventHanderDB::EV_HIT, -1 );
}
else
{
break;
}
}
}
for( short i = 0; i < 4; i++ )
{
SAFE_DELETE( m_pDamageSet[i] );
}
SAFE_DELETE( m_pEventHandle06 );
SAFE_DELETE( m_pEventHandle05 );
SAFE_DELETE( m_pEventHandle04 );
SAFE_DELETE( m_pEventHandle03 );
SAFE_DELETE( m_pEventHandle02 );
SAFE_DELETE( m_pEventHandle01 );
SAFE_DELETE( m_pEventHandle00_sound );
SAFE_DELETE( m_pEventHandle00_effect );
SAFE_DELETE( m_pEventHandle00_motion_effect );
}
void SWorkAttackEx::SetEventHandle( const DWORD dwStartTime, const unsigned short attack_speed, KEventKeyRes<Key_EVENT_NEW>* pEvent00_eff, KEventKeyRes<Key_EVENT_NEW>* pEvent00_sound, KEventKeyRes<Key_EVENT_NEW>* pEvent00_motion_effect,
KEventKeyRes<Key_EVENT_NEW>* pEvent01,
KEventKeyRes<Key_EVENT_NEW>* pEvent02,
KEventKeyRes<Key_EVENT_NEW>* pEvent03,
KEventKeyRes<Key_EVENT_NEW>* pEvent04,
KEventKeyRes<Key_EVENT_NEW>* pEvent05,
KEventKeyRes<Key_EVENT_NEW>* pEvent06 )
{
m_dwStartTime = dwStartTime; //공격 시작 시간
m_dwMaxTime = attack_speed; //공격 전체 시간
_setEvent( pEvent00_eff , m_pEventHandle00_effect );
_setEvent( pEvent00_sound, m_pEventHandle00_sound );
_setEvent( pEvent00_motion_effect, m_pEventHandle00_motion_effect );
_setEvent( pEvent01, m_pEventHandle01 );
_setEvent( pEvent02, m_pEventHandle02 );
_setEvent( pEvent03, m_pEventHandle03 );
_setEvent( pEvent04, m_pEventHandle04 );
_setEvent( pEvent05, m_pEventHandle05 );
_setEvent( pEvent06, m_pEventHandle06 );
int nLength = 0;
if( pEvent00_eff ) nLength = pEvent00_eff->GetLength();
else if( pEvent00_sound ) nLength = pEvent00_sound->GetLength();
else if( pEvent00_motion_effect ) nLength = pEvent00_motion_effect->GetLength();
else if( pEvent01 ) nLength = pEvent01->GetLength();
else if( pEvent02 ) nLength = pEvent02->GetLength();
else if( pEvent03 ) nLength = pEvent03->GetLength();
else if( pEvent04 ) nLength = pEvent04->GetLength();
else if( pEvent05 ) nLength = pEvent05->GetLength();
else if( pEvent06 ) nLength = pEvent06->GetLength();
float fAttack = m_pOwner->GetAttackSpeed( attack_speed );
float fRate = GetAniPlayRate( fAttack, nLength );
// _oprint( "SGameAttackEx : total[%d], fAttack[%f], fRate[%f]\n", attack_speed, fAttack, fRate );
m_fAttackRate = fRate; //진행 배속
//#ifndef NDEBUG
// if( m_pOwner && m_pOwner->IsLocalPlayer() )
// _oprint( "Work Attack Speed : %d, %f\n", attack_speed, 4.8f / fRate );
//#endif
//Half 시간 설정
if( m_pOwner->GetObjType() == TS_ENTER::GAME_MOB ||
m_pOwner->GetObjType() == TS_ENTER::GAME_SUMMON )
{
//Mouvement de dégâts possible lorsque la progression est supérieure à 50 %
m_dwHalfTime = (nLength/fRate)/2.f;
}
else if( m_pOwner->GetObjType() == TS_ENTER::GAME_PLAYER )
{
//Le mouvement des dégâts est possible lorsque la progression est supérieure à 70 %
m_dwHalfTime = (nLength / fRate) - ((nLength / fRate) * 0.3f);
}
//assert( m_dwHalfTime && "공격 시간이 이상함!!!" );
m_dwHalfTime += dwStartTime;
//이번 공격이 끝날 시점
m_dwMaxTime += dwStartTime; //현재 시간을 더해서 끝날 시간을 생성
}
void SWorkAttackEx::SetDamegeMsg( struct SMSG_ATTACK * pAttackMsg )
{
for( short i(0); i < 4; i++ )
{
SAFE_DELETE( m_pDamageSet[i] );
}
SGameAvatarEx* pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_Target );
for( m_nMaxHitCount = 0; m_nMaxHitCount < pAttackMsg->count; m_nMaxHitCount++ )
{
m_pDamageSet[m_nMaxHitCount] = new SMSG_DAMAGE;
m_pDamageSet[m_nMaxHitCount]->attacker_handle = pAttackMsg->attacker_handle;
m_pDamageSet[m_nMaxHitCount]->target_handle = pAttackMsg->target_handle;
m_pDamageSet[m_nMaxHitCount]->attack_action = pAttackMsg->attack_action;
m_pDamageSet[m_nMaxHitCount]->attack_flag = pAttackMsg->attack_flag;
m_pDamageSet[m_nMaxHitCount]->flag = pAttackMsg->m_vAttackInfoList[m_nMaxHitCount].flag;
m_pDamageSet[m_nMaxHitCount]->nDamage = pAttackMsg->m_vAttackInfoList[m_nMaxHitCount].damage;
SetDamageDisplayName( m_pDamageSet[m_nMaxHitCount], pTarget );
for( int count(0); CreatureElemental::ElementalType::COUNT>count; count++ )
m_pDamageSet[m_nMaxHitCount]->elemental_damage[count] = pAttackMsg->m_vAttackInfoList[m_nMaxHitCount].elemental_damage[count];
}
m_nSwingCnt = m_nHitCount = m_nMaxHitCount;
}
void SWorkAttackEx::SetDamegeInfo( const struct SStateInfo * pStateInfo )
{
for( short i(0); i < 4; i++ )
{
SAFE_DELETE( m_pDamageSet[i] );
}
SGameAvatarEx* pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_Target );
for( m_nMaxHitCount = 0; m_nMaxHitCount < pStateInfo->count; m_nMaxHitCount++ )
{
m_pDamageSet[m_nMaxHitCount] = new SMSG_DAMAGE;
m_pDamageSet[m_nMaxHitCount]->attacker_handle = pStateInfo->hSelf;
m_pDamageSet[m_nMaxHitCount]->target_handle = pStateInfo->hTarget;
m_pDamageSet[m_nMaxHitCount]->attack_action = pStateInfo->attack_action;
m_pDamageSet[m_nMaxHitCount]->attack_flag = pStateInfo->attack_flag;
m_pDamageSet[m_nMaxHitCount]->flag = pStateInfo->vAttackInfoList[m_nMaxHitCount].flag;
m_pDamageSet[m_nMaxHitCount]->nDamage = pStateInfo->vAttackInfoList[m_nMaxHitCount].damage;
SetDamageDisplayName( m_pDamageSet[m_nMaxHitCount], pTarget );
for( int count(0); CreatureElemental::ElementalType::COUNT>count; count++ )
m_pDamageSet[m_nMaxHitCount]->elemental_damage[count] = pStateInfo->vAttackInfoList[m_nMaxHitCount].elemental_damage[count];
}
m_nSwingCnt = m_nHitCount = m_nMaxHitCount;
}
bool SWorkAttackEx::ProcessingDamage()
{
if( m_nHitCount > 0 )
return false;
return true;
}
void SWorkAttackEx::_ondamage( struct SMSG_DAMAGE * pDamage, int & nHitCnt, int nKeyHandleID, int nKeyTime )
{
// Fraun performance tweak
if( pDamage && nHitCnt > 0)
{
AR_HANDLE ownerHandle = m_pOwner->GetArID();
AR_HANDLE targetHandle = m_pTarget->GetArID();
m_pOwner->OnDamage(ownerHandle, targetHandle, pDamage);
if (!(pDamage->flag & TS_ATTACK_EVENT::FLAG_MISS))
{
int nMaterial = 0;
int nWeaponClass = 0;
bool bCrit = pDamage->flag & TS_ATTACK_EVENT::FLAG_CRITICAL;
bool bBlock = pDamage->flag & TS_ATTACK_EVENT::FLAG_BLOCK;
SGame* pGame = g_pCurrentGameSystem->GetGame();
if (pGame)
{
SGameObject* pPlayer = pGame->GetGameObject(targetHandle);
if (pPlayer)
{
nMaterial = pPlayer->GetMaterial();
nWeaponClass = pPlayer->GetItemClass();
}
}
Noscript_PlayFX(ownerHandle, ownerHandle, targetHandle, nMaterial, nWeaponClass, bCrit, bBlock, nKeyHandleID, nKeyTime);
//void Noscript_PlayFX(AR_HANDLE owner_handle, AR_HANDLE attack_handle, AR_HANDLE target_handle, int nMaterial, int nWeaponClass, bool bIsCritical, bool bIsBlock, int nKeyHandleID, int nKeyTime)
m_pTarget->Damage();
}
nHitCnt--;
}
}
void SWorkAttackEx::_processDamage( struct SMSG_DAMAGE * pDamage, int & nHitCnt, int nKeyHandleID, int nKeyTime )
{
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_Target );
if( !m_pTarget )
{
SetEnd(TRUE);
return;
}
if( pDamage ) _ondamage( pDamage, nHitCnt, nKeyHandleID, nKeyTime );
}
void SWorkAttackEx::_processEvent( KEventKeyRes<Key_EVENT_NEW>* event, DWORD eventTime )
{
if( event )
{
Key_EVENT_NEW * pKey1 = NULL;
Key_EVENT_NEW * pKey2 = NULL;
event->GetData( eventTime, pKey1, pKey2 );
if( pKey1 && !pKey1->bUse )
{
pKey1->bUse = true;
//std::string strScript;
//힛팅임.
if( pKey1->nHandleID == SMotionEventHanderDB::EV_HIT ||
pKey1->nHandleID == SMotionEventHanderDB::EV_LEFT_HAND_HIT ||
pKey1->nHandleID == SMotionEventHanderDB::EV_RIGHT_HAND_HIT ||
pKey1->nHandleID == SMotionEventHanderDB::EV_TWO_HAND_HIT)
{
if( m_nHitCount )
_processDamage( m_pDamageSet[m_nMaxHitCount-m_nHitCount], m_nHitCount, pKey1->nHandleID, pKey1->time );
}
else
{
if( m_nSwingCnt && (pKey1->nHandleID == SMotionEventHanderDB::EV_SHOOT || pKey1->nHandleID == SMotionEventHanderDB::EV_SWING) )
{
m_nSwingCnt--;
//XStringUtil::Format( strScript, "%s( %u, %u )", "call_fx_ch_weapone_attack", m_pOwner->GetArID(), m_pTarget->GetArID() );
}
}
// Fraun performance tweak (TODO: return it back; testing purposes!)
//if( strScript.length() )
// LUA()->RunString( strScript.c_str() );
}
}
}
void SWorkAttackEx::Process( DWORD dwTime )
{
if( IsEnd() )
return;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_Target );
if( !m_pTarget )
{
SetEnd(TRUE);
return;
}
if( dwTime >= m_dwHalfTime )
{ //공격 시간이 50% 지났다.
m_pOwner->SetAttackAniLock( false );
}
if( dwTime >= m_dwMaxTime )
{ //시간이 모두 지났다.
// _oprint( "SWorkAttackEx 종료 02\n" );
m_pOwner->SetAttackAniLock( false );
SetEnd(TRUE);
return;
}
DWORD eventTime = ((dwTime - m_dwStartTime) * m_fAttackRate);
//_oprint( " 공격 : %d\n", eventTime );
if( m_pEventHandle00_effect )
{
//시작 되자 마자 나오는 Effect
Key_EVENT_NEW * pKey1 = NULL;
Key_EVENT_NEW * pKey2 = NULL;
m_pEventHandle00_effect->GetData( 0, pKey1, pKey2 );
if( pKey1 && !pKey1->bUse )
{
pKey1->bUse = true;
m_pOwner->FindMotionAddOnFx( pKey1 );
switch(pKey1->nSpeedType)
{
case 0:
{
m_pOwner->AddEffect( &FX_DATA_EX( pKey1->strEffect.c_str(), pKey1->followflag, m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), pKey1->nEffPos, false, pKey1->nSpeedType, m_fAttackPlayRate ) );
}
break;
case 2:
{
if(!pKey1->strEffect.empty())
{
m_pOwner->AddEffect( &FX_DATA_EX( pKey1->strEffect.c_str(), pKey1->followflag, m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), pKey1->nEffPos, false, pKey1->nSpeedType, m_fAttackPlayRate ) );
}
//검 잔상
m_pOwner->ActivateFxSwordSlashForSkill();
}
break;
}
}
}
if( m_pEventHandle00_sound )
{
Key_EVENT_NEW * pKey1 = NULL;
Key_EVENT_NEW * pKey2 = NULL;
m_pEventHandle00_sound->GetData( eventTime, pKey1, pKey2 );
if( pKey1 && !pKey1->bUse )
{
pKey1->bUse = true;
if( pKey1->nSound_play_probability != 100 )
{
int nRatio = rand()%100;
if( nRatio < pKey1->nSound_play_probability )
m_pOwner->StartSound( m_pOwner, pKey1->strSound.c_str(), *m_pOwner->GetPosition(), true, pKey1->nSoundVolume, false, pKey1->SoundOption );
}
else
{
m_pOwner->StartSound( m_pOwner, pKey1->strSound.c_str(), *m_pOwner->GetPosition(), true, pKey1->nSoundVolume, false, pKey1->SoundOption );
}
}
}
if( m_pEventHandle00_motion_effect )
{
Key_EVENT_NEW * pKey1 = NULL;
Key_EVENT_NEW * pKey2 = NULL;
m_pEventHandle00_motion_effect->GetData( eventTime, pKey1, pKey2 );
if( pKey1 && pKey1->bUse == false )
{
pKey1->bUse = true; //사용.
FX_DATA fxdata;
fxdata.nFX_ID = pKey1->nFXsetID;
fxdata.nEffPos = pKey1->nEffPos;
fxdata.owner = m_pOwner->GetArID();
fxdata.attack = m_pOwner->GetArID();
fxdata.target = m_pOwner->GetArID();
fxdata.fPlayRate = pKey1->fPlayRate;
fxdata.nPlayID = 0;//한번
fxdata.nMode = 0;//기본
m_pOwner->AddEffect( &fxdata );
}
}
_processEvent( m_pEventHandle01, eventTime );
_processEvent( m_pEventHandle02, eventTime );
_processEvent( m_pEventHandle03, eventTime );
_processEvent( m_pEventHandle04, eventTime );
_processEvent( m_pEventHandle05, eventTime );
_processEvent( m_pEventHandle06, eventTime );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SWorkWarp
SWorkWarp::SWorkWarp( class SGameAvatarEx * pOwner, struct SCMSG_WARP * pMsg ) : SGameWork( pOwner )
{
// _oprint( "SWorkWarp::SWorkWarp\n" );
m_pWarpMsg = new SCMSG_WARP;
m_pWarpMsg->x = pMsg->x;
m_pWarpMsg->y = pMsg->y;
m_pWarpMsg->z = pMsg->z;
m_pWarpMsg->layer = pMsg->layer;
}
SWorkWarp::~SWorkWarp()
{
if( m_pOwner ) m_pOwner->InputThawing();
SAFE_DELETE( m_pWarpMsg );
}
void SWorkWarp::Process( DWORD dwTime )
{
// _oprint( "SWorkWarp::Process\n" );
m_pOwner->SetArObjectPos( m_pWarpMsg->x, m_pWarpMsg->y, m_pWarpMsg->z, m_pWarpMsg->layer );
float fHeight = 0.f;
WORD wTile=0;
m_pOwner->GetHeight(m_pWarpMsg->x,m_pWarpMsg->y,fHeight,wTile);
m_pOwner->SetPosition( K3DVector(m_pWarpMsg->x,m_pWarpMsg->y, fHeight) );
SGameAvatarEx* pTransportCreature = (SGameAvatarEx*)m_pOwner->GetGameTransportCreatureObject( m_pOwner->GetCreatureMountHandle() );
if( pTransportCreature )
{
m_pOwner->SetMountMode();
pTransportCreature->SetMountMode();
pTransportCreature->SetArObjectPos( m_pWarpMsg->x, m_pWarpMsg->y, m_pWarpMsg->z, m_pWarpMsg->layer );
pTransportCreature->SetPosition( K3DVector(m_pWarpMsg->x,m_pWarpMsg->y, fHeight) );
int nDefaultAniType;
switch( pTransportCreature->GetCreatureMountType() )
{
case SGameAvatarEx::RIDE_LOW_TYPE:
nDefaultAniType = ANI_M_DEFAULT01_LOW;
break;
case SGameAvatarEx::RIDE_HIGH_TYPE:
nDefaultAniType = ANI_M_DEFAULT01_HIGH;
break;
case SGameAvatarEx::RIDE_QILIN_TYPE:
nDefaultAniType = ANI_M_DEFAULT01_QILIN;
break;
case SGameAvatarEx::RIDE_WHITE_TYPE:
nDefaultAniType = ANI_M_DEFAULT01_WHITE;
break;
case SGameAvatarEx::RIDE_UNICORN_TYPE:
nDefaultAniType = ANI_M_DEFAULT01_UNICORN;
break;
/// 2011.02.08 - prodongi
case SGameAvatarEx::RIDE_BEAKHO_TYPE:
nDefaultAniType = ANI_M_DEFAULT01_BEAKHO;
break;
default:
nDefaultAniType = ANI_M_DEFAULT01_HIGH;
break;
}
m_pOwner->NPlayAnimation( nDefaultAniType, SEQTYPE_LOOP );
pTransportCreature->NPlayAnimation( ANI_DEFAULT01, SEQTYPE_LOOP );
}
else
{
//마운트 모드가 아닐때 기본 상태로
// if( !m_pOwner->IsMountMode() )
SGameAvatarEx* pCreature = (SGameAvatarEx*)m_pOwner->GetGameObject( m_pOwner->GetCreatureMountHandle() );
if( pCreature )
{
pCreature->SetAniLock( false );
pCreature->Default();
}
m_pOwner->SetAniLock( false );
m_pOwner->Default();
}
m_pOwner->SetAttackAniLock( false );
m_pOwner->WarpComplete( m_pWarpMsg );
m_pOwner->InputThawing();
SetEnd( TRUE );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SWorkAttack
SWorkAttack::SWorkAttack( SGameAvatarEx * pOwner, K3DVector & targetpos, AR_HANDLE targetID, int nDamage, int nRest_hp, int nAttackMsec ) : SGameWork(pOwner)
{
// _oprint( "호호호 : SWorkAttack::SWorkAttack %0x8d \n", targetID );
m_TargetPos = targetpos;
m_TargetID = targetID;
m_nDamage = nDamage;
m_nRest_hp = nRest_hp;
m_nAttackMsec = nAttackMsec;
}
SWorkAttack::~SWorkAttack()
{
}
void SWorkAttack::Process( DWORD dwTime )
{
// _oprint( "SWorkAttack Damage : %d, RestHP : %d\n", m_nDamage, m_nRest_hp );
m_pOwner->SetViewVector( m_TargetPos );
// m_pOwner->SetDamage( m_TargetID, m_nDamage, m_nRest_hp );
// m_pOwner->Attack( m_TargetID, m_TargetPos, m_nAttackMsec );
SetEnd(TRUE);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SWorkGoodPosSearch
SWorkGoodPosSearch::SWorkGoodPosSearch( class SGameAvatarEx * pOwner, AR_HANDLE hMaster ): SGameWork(pOwner)
{
// _oprint( "SWorkGoodPosSearch::SWorkGoodPosSearch\n" );
m_hMaster = hMaster; //주인님
SetStep(STEP_01);
}
SWorkGoodPosSearch::~SWorkGoodPosSearch()
{
}
void SWorkGoodPosSearch::Process( DWORD dwTime )
{
//성공 할때까지, 자동으로 해준다.
//공격하는 Object에서 떨어진다.
//적절한 위치라 함은, 어딜까???
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SWorkPickUp::SWorkPickUp( class SGameAvatarEx * pOwner, class SGameAvatarEx* pItem ) : SGameWork(pOwner)
{
m_dwStartTime = 0;
m_pOwner->SetViewVector( *pItem->GetPosition() );
SetStep( STEP_00 );
}
SWorkPickUp::~SWorkPickUp()
{
}
void SWorkPickUp::Process( DWORD dwTime )
{
if( IsEnd() ) return;
//마운트 상태에서는 줍기 모션 생략
if( m_pOwner->IsMountMode() )
{
SetEnd( TRUE );
return;
}
if( m_dwStartTime == 0 )
m_dwStartTime = dwTime;
if( !m_pOwner->IsMoving() )
{
if( GetStep() == STEP_00 )
{
m_dwStartTime = dwTime;
m_pOwner->SetAniLock( false );
m_pOwner->PickUpEx();
m_pOwner->SetAniLock( true );
SetStep( STEP_01 );
}
else if( GetStep() == STEP_01 )
{
if( !m_pOwner->IsPlaying() &&
m_pOwner->GetCurrAnimationID() == ANI_PICKUP01 )
{
m_pOwner->SetAniLock( false );
m_pOwner->StandUp();
SetEnd( TRUE );
}
}
//줍는 도중 이동 및 공격 모션으로 바뀌었을 경우 검사한다
if( m_pOwner->IsPlaying() && m_pOwner->GetCurrAnimationID() != ANI_PICKUP01 )
{
m_pOwner->SetIng(false);
m_pOwner->SetAniLock( false );
SetEnd( TRUE );
}
}
//10초가 경과했는데도 끝나지 않았다면
if( dwTime - m_dwStartTime > 10000 )
{
//줍는 모션중이라면
if( m_pOwner->GetCurrAnimationID() == ANI_PICKUP01 )
{
m_pOwner->StandUp();
}
m_pOwner->SetIng(false);
m_pOwner->SetAniLock( false );
SetEnd( TRUE );
}
}
//////////////////////////////////////////////////////////////////////////
SWorkAniSit::SWorkAniSit( class SGameAvatarEx * pOwner, DWORD dwTime ) : SGameWork(pOwner)
{
m_dwStartTime = dwTime;
SetStep( STEP_00 );
}
SWorkAniSit::~SWorkAniSit()
{
}
void *SWorkAniSit::PerformMsg( struct SGameMessage * pMsg )
{
return (void*)0;
}
void SWorkAniSit::Process( DWORD dwTime )
{
//if( GetStep() != STEP_00 )
//{
// if( dwTime - m_dwStartTime > 3000 )
// { //3000 초 이후에는 강제 종료
// SetEnd( TRUE );
// }
//}
if( GetStep() == STEP_00 )
{
m_dwStartTime = dwTime;
m_pOwner->SetAniLock( false );
m_pOwner->SitProcess( ANI_SITDOWN );
m_pOwner->SetAniLock( true );
SetStep( STEP_01 );
}
else if( GetStep() == STEP_01 )
{
if( !m_pOwner->IsPlaying() && m_pOwner->GetCurrAnimationID() == ANI_SITDOWN )
{
m_pOwner->SetIng(false);
m_pOwner->SetAniLock( false );
m_pOwner->SitProcess( ANI_SIT, SEQTYPE_LOOP );
SetEnd( TRUE );
}
else
{
if( dwTime - m_dwStartTime > 3000 )
SetEnd( TRUE );
}
}
}
//////////////////////////////////////////////////////////////////////////
SWorkAniStandUp::SWorkAniStandUp( class SGameAvatarEx * pOwner, DWORD dwTime ) : SGameWork(pOwner)
{
m_dwStartTime = dwTime;
SetStep( STEP_00 );
}
SWorkAniStandUp::~SWorkAniStandUp()
{
}
void SWorkAniStandUp::Process( DWORD dwTime )
{
if( GetStep() == STEP_00 )
{
m_pOwner->SitProcess( ANI_SITUP );
SetStep( STEP_01 );
}
else if( GetStep() == STEP_01 )
{
if( !m_pOwner->IsPlaying() && m_pOwner->GetCurrAnimationID() == ANI_SITUP )
{
m_pOwner->SetAniLock( false );
m_pOwner->StandUp();
SetEnd( TRUE );
m_pOwner->SetIng(false);
}
}
//2초 후에는 무조건 종료
if( (dwTime - m_dwStartTime) > 2000 )
{
//일어서는 도중 애니메이션이 바뀌었는지 검사한다( 일어서는 도중 이동 및 공격 할수있기 때문 )
if( m_pOwner->GetCurrAnimationID() == ANI_SITUP )
{
m_pOwner->StandUp();
}
m_pOwner->SetAniLock( false );
SetEnd( TRUE );
m_pOwner->SetIng(false);
}
}
//////////////////////////////////////////////////////////////////////////
SWorkAimingBow::SWorkAimingBow( class SGameAvatarEx * pOwner, AR_HANDLE hTarger, char bowtype ) : SGameWork(pOwner)
{
m_hTarget = hTarger;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
SetEnd( TRUE );
return;
}
m_nTypeBow = 0;
// Arrow casting and shooting effect IDs
// 3049 Normal Arrow_Cast Asura (Female Only)
// 3050 Normal Arrow_Cast Asura (Male Only)
// 3051 Normal Arrow_Cast Deva (Female Only)
// 3052 Normal Arrow_Cast Deva (Male Only)
m_nEffectID[0] = -1;
m_nEffectID[1] = -1;
if( bowtype & TS_ATTACK_EVENT::ATTACK_FLAG_CROSS_BOW )
{
m_strFX_01 = "rcfx_cross_arrowattack_start_lv01_";
m_strFX_02 = "rcfx_cross_arrowattack_loop_lv01_";
}
else
{
m_strFX_01 = "rcfx_arrowattack_start_lv01_";
m_strFX_02 = "rcfx_arrowattack_loop_lv01_";
}
const char* szName = GetNX3Name( pOwner->GetRace(), pOwner->GetSex() );
m_strFX_01 += szName;
m_strFX_02 += szName;
SetStep( STEP_00 );
SetWorkType( WORK_AIMINGBOW );
pOwner->SetVisibleWeaponTrail( true );
}
SWorkAimingBow::~SWorkAimingBow()
{
if( m_pOwner )
{
if( m_nEffectID[0] != -1 ) m_pOwner->DelEffect( m_nEffectID[0] );
if( m_nEffectID[1] != -1 ) m_pOwner->DelEffect( m_nEffectID[1] );
}
}
void SWorkAimingBow::ForceEnd()
{
m_bEnd = TRUE;
if( m_nEffectID[0] != -1 ) m_pOwner->DelEffect( m_nEffectID[0] );
if( m_nEffectID[1] != -1 ) m_pOwner->DelEffect( m_nEffectID[1] );
}
void SWorkAimingBow::Process( DWORD dwTime )
{
if( IsEnd() ) return;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( m_pTarget == NULL )
{
m_pOwner->SetIng(false);
m_pOwner->SetAniLock( false );
m_pOwner->Default();
SetEnd( TRUE );
return;
}
m_pOwner->SetViewVector( *m_pTarget->GetPosition() );
////////////////////////////////////////////////////////////////////////////
if( GetStep() == STEP_00 )
{
m_pOwner->SetIng(true);
m_pOwner->SetAniLock( false );
m_pOwner->NPlayAnimation( ANI_BOW_ATTACK01_A ); //장전
m_nEffectID[0] = m_pOwner->AddEffect( &FX_DATA_EX( m_strFX_01.c_str(), 2, m_pOwner->GetArID(), m_pOwner->GetArID(), m_hTarget, EFFECT_POS_DAMAGE, true ) );
m_pOwner->SetAniLock( true );
SetStep( STEP_01 );
}
else if( GetStep() == STEP_01 )
{
if( !m_pOwner->IsPlaying() )
{
m_pOwner->SetAniLock( false );
m_pOwner->NPlayAnimation( ANI_BOW_ATTACK01_B, SEQTYPE_LOOP ); //겨누기
m_nEffectID[1] = m_pOwner->AddEffect( &FX_DATA_EX( m_strFX_02.c_str(), 2, m_pOwner->GetArID(), m_pOwner->GetArID(), m_hTarget, EFFECT_POS_DAMAGE, true, SEQTYPE_LOOP ) );
m_pOwner->SetAniLock( true );
SetStep( STEP_04 );
}
}
//장전 및 겨누기 이외 모션이 재생될 경우 끝낸다
if( m_pOwner->GetCurrAnimationID() != ANI_BOW_ATTACK01_A &&
m_pOwner->GetCurrAnimationID() != ANI_BOW_ATTACK01_B )
{
m_pOwner->SetIng(false);
SetEnd(TRUE);
}
}
//////////////////////////////////////////////////////////////////////////
SWorkShootingBow::SWorkShootingBow( class SGameAvatarEx * pOwner, AR_HANDLE hTarger, char bowtype ) : SGameWork(pOwner)
{
m_hTarget = hTarger;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
SetEnd( TRUE );
return;
}
m_pAttackMsg = NULL;
m_nTypeBow = 0;
m_nEffectID = -1;
m_strFX_03 = "rcfx_arrowattack_end_lv01_";
m_strFX_03 += GetNX3Name( pOwner->GetRace(), pOwner->GetSex() );
SetStep( STEP_00 );
SetWorkType( WORK_SHOOTINGBOW );
}
SWorkShootingBow::~SWorkShootingBow()
{
SAFE_DELETE( m_pAttackMsg );
if( m_nEffectID != -1 )
{
if( m_pOwner )
m_pOwner->DelEffect( m_nEffectID );
}
}
void SWorkShootingBow::SetDamegeInfo( const struct SStateInfo * pStateInfo )
{
SAFE_DELETE( m_pAttackMsg );
SMSG_ATTACK * pAttackMsg = new SMSG_ATTACK;
pAttackMsg->attacker_handle = pStateInfo->hSelf;
pAttackMsg->target_handle = pStateInfo->hTarget;
pAttackMsg->attack_action = pStateInfo->attack_action;
pAttackMsg->attack_flag = pStateInfo->attack_flag;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
pAttackMsg->attack_speed = pStateInfo->dwSpeed;
pAttackMsg->count = pStateInfo->count;
for( int i = 0; i < pStateInfo->count; i++ )
{
pAttackMsg->m_vAttackInfoList.push_back( pStateInfo->vAttackInfoList[i] );
}
pAttackMsg->nTypeBow = m_nTypeBow;
m_pAttackMsg = pAttackMsg;
}
bool SWorkShootingBow::ProcessingDamage()
{
if( GetStep() != STEP_02 )
return false;
return true;
}
void SWorkShootingBow::Process( DWORD dwTime )
{
// Fraun performance tweak
if( IsEnd() ) return;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject(m_hTarget);
if( m_pTarget == NULL )
{
m_pOwner->SetIng(false);
m_pOwner->SetAniLock(false);
m_pOwner->Default();
SetEnd(TRUE);
return;
}
int nCurrtStep = GetStep();
switch (nCurrtStep)
{
case STEP_00:
{
m_pOwner->SetViewVector(*m_pTarget->GetPosition());
// Shoot after the characters direction has been set
if (m_pAttackMsg && !m_pOwner->IsRotation())
{
m_pOwner->SetIng(true);
m_pOwner->SetAniLock(false);
m_pOwner->NPlayAnimation(ANI_BOW_ATTACK01_C); // Shooting
m_nEffectID = m_pOwner->AddEffect(&FX_DATA_EX(m_strFX_03.c_str(), 2, m_pOwner->GetArID(), m_pOwner->GetArID(), m_hTarget, EFFECT_POS_DAMAGE, true));
m_pOwner->SetAniLock(true);
m_pOwner->AddAction(m_pAttackMsg);
SetStep(STEP_02);
}
else
{
SetStep(STEP_01);
}
break;
}
case STEP_01:
{
if (m_pAttackMsg && !m_pOwner->IsRotation())
{
m_pOwner->SetIng(true);
m_pOwner->SetAniLock(false);
m_pOwner->NPlayAnimation(ANI_BOW_ATTACK01_C);
m_nEffectID = m_pOwner->AddEffect(&FX_DATA_EX(m_strFX_03.c_str(), 2, m_pOwner->GetArID(), m_pOwner->GetArID(), m_hTarget, EFFECT_POS_DAMAGE, true));
m_pOwner->SetAniLock(true);
m_pOwner->AddAction(m_pAttackMsg);
SetStep(STEP_02);
}
}
case STEP_02:
{
if (!m_pOwner->IsPlaying())
{
m_pOwner->SetIng(false);
m_pOwner->SetAniLock(false);
m_pOwner->Default(); // Return to the default pose
SetEnd(TRUE);
}
}
}
// End if any motion other than the shooting motion is played
if(GetStep() == STEP_02 && m_pOwner->GetCurrAnimationID() != ANI_BOW_ATTACK01_C )
{
m_pOwner->SetIng(false);
SetEnd(TRUE);
}
}
//==============================================================================================
//New Skill 시스템
SNewSkill::SNewSkill( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SGameWork( pOwner ), m_pSkillFX(pSkillFX)
{
// SetEnd( true );
m_fPlayRate = 1.f; //1배
m_fPlayRateAfterFire = 1.0f;
m_hTarget = 0;
m_pTarget = NULL;
m_pEventSet = NULL;
m_pDamage = NULL;
m_pSkillEvent = NULL;
m_nCurHitIndex = 0;
m_nHitCnt = 0;
m_dwStartTime = 0;
m_nFireMotionID = pSkillFX->nFire_Motion_Id;
m_nFxID = -1;
//1이면 타겟형
//0이면 셀프형
if( m_pSkillFX->szHas_Target > 0 )
m_bIsSelfSkill = false;
else
m_bIsSelfSkill = true;
m_dwCatingTime = 0;
m_pActionSkillEvent = NULL;
m_bIsMeleeSkill = false;
}
SNewSkill::~SNewSkill()
{
if(m_nFxID != -1)
{
if( m_pOwner )
m_pOwner->EndLoopFx(m_nFxID);
}
if( !m_vFX_List.empty() )
{
if( m_pOwner )
{
for( unsigned int i(0); m_vFX_List.size()>i; i++ )
m_pOwner->DelEffect(m_vFX_List[i]);
}
m_vFX_List.erase( m_vFX_List.begin(), m_vFX_List.end() );
}
if( m_pOwner )
{
//힛팅 처리 안된 것들 처리
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( m_pTarget )
{
while(m_nHitCnt > 0)
_processDamage();
}
}
//Event handle 처리
if( m_pEventSet )
{
m_pEventSet->event_clear();
SAFE_DELETE( m_pEventSet );
}
SAFE_DELETE( m_pSkillEvent );
SAFE_DELETE( m_pDamage );
SAFE_DELETE( m_pSkillFX );
if( m_pActionSkillEvent )
{
if( m_pOwner ) m_pOwner->AddAction( m_pActionSkillEvent );
SAFE_DELETE( m_pActionSkillEvent );
}
}
void SNewSkill::ForceEnd()
{
if(m_nFxID != -1)
{
m_pOwner->EndLoopFx(m_nFxID);
}
m_bEnd = TRUE;
}
void SNewSkill::SetDamegeInfo( const struct SStateInfo * pStateInfo )
{
SAFE_DELETE( m_pSkillEvent );
SAFE_DELETE( m_pDamage );
//데미지 일반 데미지 때릴때 사용
m_pDamage = new SMSG_DAMAGE;
m_pDamage->attacker_handle = pStateInfo->hSelf;
m_pDamage->target_handle = pStateInfo->hTarget;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_pDamage->target_handle );
if( !m_pTarget )
{
SetEnd(true);
return;
}
SetDamageDisplayName( m_pDamage, m_pTarget );
//스킬 이벤트 -> Action 에 날릴때 사용
m_pSkillEvent = new SMSG_SKILL_EVENT;
m_pSkillEvent->skill_id = pStateInfo->nSkillID;
m_pSkillEvent->skill_level = pStateInfo->nSkillLv;
m_pSkillEvent->caster = m_pOwner->GetArID();
m_pSkillEvent->target = pStateInfo->hTarget;
m_pSkillEvent->fire.count = pStateInfo->nRepeat;
m_pSkillEvent->fire.bMultiple = pStateInfo->bMultiple;
m_pSkillEvent->fire.range = pStateInfo->range;
m_pSkillEvent->fire.target_count = pStateInfo->target_count;
m_pSkillEvent->fire.fire_count = pStateInfo->fire_count;
m_pDamage->nSkillID = pStateInfo->nSkillID;
m_pDamage->nSkillLevel = pStateInfo->nSkillLv;
m_nCount = (int)pStateInfo->vSkillResult.size();
m_nCurHitIndex = 0;
m_nHitCnt = m_nCount;
//스킬 결과 데미지
for( unsigned int i(0); pStateInfo->vSkillResult.size()>i; i++ )
m_pSkillEvent->vSkillResult.push_back( pStateInfo->vSkillResult[i] );
_oprint( "Server skill result %d\n", pStateInfo->vSkillResult.size() );
}
void SNewSkill::SetActionSkillEvent( const struct SStateInfo * pStateInfo )
{
//스킬 이벤트 -> Action 에 날릴때 사용
m_pActionSkillEvent = new SMSG_SKILL_EVENT;
m_pActionSkillEvent->status_type = TS_SC_SKILL::FIRE;
m_pActionSkillEvent->skill_id = pStateInfo->nSkillID;
m_pActionSkillEvent->skill_level = pStateInfo->nSkillLv;
m_pActionSkillEvent->caster = m_pOwner->GetArID();
m_pActionSkillEvent->target = pStateInfo->hTarget;
//m_pActionSkillEvent->target_name = pStateInfo->target_name; // Fraun performance tweak
m_pActionSkillEvent->fire.count = pStateInfo->nRepeat;
m_pActionSkillEvent->fire.bMultiple = pStateInfo->bMultiple;
m_pActionSkillEvent->fire.range = pStateInfo->range;
m_pActionSkillEvent->fire.target_count = pStateInfo->target_count;
m_pActionSkillEvent->fire.fire_count = pStateInfo->fire_count;
//스킬 결과 데미지
for( unsigned int i(0); pStateInfo->vSkillResult.size()>i; i++ )
m_pActionSkillEvent->vSkillResult.push_back( pStateInfo->vSkillResult[i] );
}
void SNewSkill::SetTarget( AR_HANDLE handle, class SGameAvatarEx* pTarget )
{
m_hTarget = handle;
m_pTarget = pTarget;
}
void SNewSkill::SetSkillMode( SKILL_MODE bMode )
{
m_nMode = bMode;
if( m_nMode == SKILLMODE_CAST )
{
_processView();
}
}
void SNewSkill::SetPlayRate( float fPlayRate )
{
m_fPlayRate = fPlayRate;
}
void SNewSkill::SetStartTime( DWORD dwStartTime )
{
m_dwStartTime = dwStartTime;
}
void SNewSkill::SetFireMotionID( int nFireMotionID )
{
m_nFireMotionID = nFireMotionID;
}
void SNewSkill::SetCastingTime( DWORD time )
{
m_dwCatingTime = time;
}
bool SNewSkill::ProcessingDamage()
{
if( m_nHitCnt > 0 || GetSkillMode() != SKILLMODE_FIRE )
return false;
return true;
}
void SNewSkill::_processDamage()
{
if( m_nHitCnt > 0 )
{
m_pDamage->skillresult = m_pSkillEvent->vSkillResult[m_nCount - m_nHitCnt];
if( m_pTarget )
{
int nBlock = 0;
int nCritical = 0;
if(m_pDamage->skillresult.damage.flag & TS_ATTACK_EVENT::FLAG_CRITICAL) nCritical = 1;
if(m_pDamage->skillresult.damage.flag & TS_ATTACK_EVENT::FLAG_BLOCK) nBlock = 1;
m_pOwner->OnDamage( m_pOwner->GetArID(), m_pTarget->GetArID(), m_pDamage );
std::string strScript;
int resultType = m_pDamage->skillresult.GetType();
if( (resultType == SkillResult::DAMAGE || resultType == SkillResult::MAGIC_DAMAGE ||
resultType == SkillResult::CHAIN_DAMAGE || resultType == SkillResult::CHAIN_MAGIC_DAMAGE)
&& !(m_pDamage->skillresult.damage.flag & SkillResult::MISS) )
{
m_pTarget->Damage();
// Fraun performance tweak (TODO: return it back; testing purposes!)
//XStringUtil::Format( strScript, "%s( %u, %u, %d, %d )", "avatar_basic_hit", m_pOwner->GetArID(), m_pTarget->GetArID(), nCritical, nBlock );
}
else if( m_pDamage->skillresult.GetType() == SkillResult::DAMAGE_WITH_KNOCK_BACK
&& !(m_pDamage->skillresult.damage.flag & SkillResult::MISS) )
{
if( m_pTarget->GetHP() > 0 )
{
m_pTarget->SetAniLock( false );
m_pTarget->NPlayAnimation( ANI_DAMAGE01, SEQTYPE_LOOP );
}
K3DVector vKnockBackPosition = K3DVector( m_pDamage->skillresult.damage_kb.x, m_pDamage->skillresult.damage_kb.y, 0.f );
m_pTarget->SetKnockBack( vKnockBackPosition , m_pDamage->skillresult.damage_kb.speed );
m_pTarget->Damage();
// Fraun performance tweak (TODO: return it back; testing purposes!)
//XStringUtil::Format( strScript, "%s( %u, %u, %d, %d )", "avatar_basic_hit", m_pOwner->GetArID(), m_pTarget->GetArID(), nCritical, nBlock );
}
// Fraun performance tweak (TODO: return it back; testing purposes!)
//if( strScript.length() )
// LUA()->RunString( strScript.c_str() );
}
--m_nHitCnt;
}
}
void SNewSkill::_processDamageMulti()
{
if( m_nHitCnt > 0 )
{
m_pDamage->skillresult = m_pSkillEvent->vSkillResult[m_nCount - m_nHitCnt];
SGameAvatarEx* pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_pDamage->skillresult.GetTargetHandle() );
if( pTarget )
{
int nBlock = 0;
int nCritical = 0;
if(m_pDamage->skillresult.damage.flag & TS_ATTACK_EVENT::FLAG_CRITICAL) nCritical = 1;
if(m_pDamage->skillresult.damage.flag & TS_ATTACK_EVENT::FLAG_BLOCK) nBlock = 1;
m_pOwner->OnDamage( m_pOwner->GetArID(), pTarget->GetArID(), m_pDamage );
std::string strScript;
if( (m_pDamage->skillresult.GetType() == SkillResult::DAMAGE || m_pDamage->skillresult.GetType() == SkillResult::MAGIC_DAMAGE)
&& !(m_pDamage->skillresult.damage.flag & SkillResult::MISS) )
{
pTarget->Damage();
XStringUtil::Format( strScript, "%s( %u, %u, %d, %d )", "avatar_basic_hit", m_pOwner->GetArID(), pTarget->GetArID(), nCritical, nBlock );
}
else if( m_pDamage->skillresult.GetType() == SkillResult::DAMAGE_WITH_KNOCK_BACK
&& !(m_pDamage->skillresult.damage.flag & SkillResult::MISS) )
{
if( pTarget->GetHP() > 0 )
{
pTarget->SetAniLock( false );
pTarget->NPlayAnimation( ANI_DAMAGE01, SEQTYPE_LOOP );
}
K3DVector vKnockBackPosition = K3DVector( m_pDamage->skillresult.damage_kb.x, m_pDamage->skillresult.damage_kb.y, 0.f );
pTarget->SetKnockBack( vKnockBackPosition , m_pDamage->skillresult.damage_kb.speed );
pTarget->Damage();
// Fraun performance tweak (TODO: return it back; testing purposes!)
//XStringUtil::Format( strScript, "%s( %u, %u, %d, %d )", "avatar_basic_hit", m_pOwner->GetArID(), pTarget->GetArID(), nCritical, nBlock );
}
// Fraun performance tweak (TODO: return it back; testing purposes!)
//if( strScript.length() )
// LUA()->RunString( strScript.c_str() );
}
--m_nHitCnt;
}
}
void SNewSkill::Process( DWORD dwTime )
{
m_dwTime = dwTime;
if( IsEnd() ) return;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
SetEnd(true);
return;
}
if( GetSkillMode() == SKILLMODE_CAST )
{
_processDefCast( dwTime );
}
else if( GetSkillMode() == SKILLMODE_FIRE )
{
_processDefFire( dwTime );
}
DWORD eventTime = ((dwTime - m_dwStartTime) * m_fPlayRate);
_processEventSet( eventTime );
}
void SNewSkill::_processEventSet( DWORD eventTime )
{
if( !m_pEventSet ) return;
if( m_pEventSet->pCurEvent00_effect )
{
//시작 되자 마자 나오는 Effect
Key_EVENT_NEW * pKey1 = NULL;
Key_EVENT_NEW * pKey2 = NULL;
m_pEventSet->pCurEvent00_effect->GetData( 0, pKey1, pKey2 );
if( pKey1 && !pKey1->bUse )
{
pKey1->bUse = true;
m_pOwner->FindMotionAddOnFx( pKey1 );
switch(pKey1->nSpeedType)
{
case 0:
{
float fPlayRate = m_pOwner->GetCurPlayRate();
m_pOwner->AddEffect( &FX_DATA_EX( pKey1->strEffect.c_str(), pKey1->followflag, m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), pKey1->nEffPos, false, pKey1->nSpeedType, fPlayRate ) );
}
break;
case 2:
{
if(!pKey1->strEffect.empty())
{
float fPlayRate = m_pOwner->GetCurPlayRate();
m_pOwner->AddEffect( &FX_DATA_EX( pKey1->strEffect.c_str(), pKey1->followflag, m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), pKey1->nEffPos, false, pKey1->nSpeedType, fPlayRate ) );
}
//검 잔상
m_pOwner->ActivateFxSwordSlashForSkill();
}
break;
}
}
}
if( m_pEventSet->pCurEvent00_sound )
{
Key_EVENT_NEW * pKey1 = NULL;
Key_EVENT_NEW * pKey2 = NULL;
m_pEventSet->pCurEvent00_sound->GetData( eventTime, pKey1, pKey2 );
if( pKey1 && !pKey1->bUse )
{
pKey1->bUse = true;
if( pKey1->nSound_play_probability != 100 )
{
int nRatio = rand()%100;
if( nRatio < pKey1->nSound_play_probability )
m_pOwner->StartSound( m_pOwner, pKey1->strSound.c_str(), *m_pOwner->GetPosition(), true, pKey1->nSoundVolume, false, pKey1->SoundOption );
}
else
{
m_pOwner->StartSound( m_pOwner, pKey1->strSound.c_str(), *m_pOwner->GetPosition(), true, pKey1->nSoundVolume, false, pKey1->SoundOption );
}
}
}
if( m_pEventSet->pCurEvent00_motion_effect )
{
Key_EVENT_NEW * pKey1 = NULL;
Key_EVENT_NEW * pKey2 = NULL;
m_pEventSet->pCurEvent00_motion_effect->GetData( eventTime, pKey1, pKey2 );
if( pKey1 && pKey1->bUse == false )
{
pKey1->bUse = true; //사용.
FX_DATA fxdata;
fxdata.nFX_ID = pKey1->nFXsetID;
fxdata.nEffPos = pKey1->nEffPos;
fxdata.owner = m_pOwner->GetArID();
fxdata.attack = m_pOwner->GetArID();
fxdata.target = m_pOwner->GetArID();
fxdata.fPlayRate = pKey1->fPlayRate;
fxdata.nPlayID = 0;//한번
fxdata.nMode = 0;//기본
m_pOwner->AddEffect( &fxdata );
}
}
if( GetSkillMode() == SKILLMODE_CAST )
return;
// _processEvent( , eventTime );
// _processEvent( , eventTime );
_processEvent( m_pEventSet->pCurEvent01 , eventTime );
_processEvent( m_pEventSet->pCurEvent02 , eventTime );
_processEvent( m_pEventSet->pCurEvent03 , eventTime );
_processEvent( m_pEventSet->pCurEvent04 , eventTime );
_processEvent( m_pEventSet->pCurEvent05 , eventTime );
_processEvent( m_pEventSet->pCurEvent06 , eventTime );
}
void SNewSkill::_processEvent( KEventKeyRes<Key_EVENT_NEW>* event, DWORD eventTime )
{
if( event )
{
Key_EVENT_NEW * pKey1 = NULL;
Key_EVENT_NEW * pKey2 = NULL;
event->GetData( eventTime, pKey1, pKey2 );
if( pKey1 && !pKey1->bUse )
{
pKey1->bUse = true;
std::string strScript;
//힛팅임.
if( pKey1->nHandleID == SMotionEventHanderDB::EV_HIT ||
pKey1->nHandleID == SMotionEventHanderDB::EV_LEFT_HAND_HIT ||
pKey1->nHandleID == SMotionEventHanderDB::EV_RIGHT_HAND_HIT ||
pKey1->nHandleID == SMotionEventHanderDB::EV_TWO_HAND_HIT )
{
assert( GetSkillMode() != SKILLMODE_CAST && "캐스팅 모션에 힛팅 연출 모션이 설정 되어 있음." );
OnEventHit();
}
else if( pKey1->nHandleID == SMotionEventHanderDB::EV_SHOOT || pKey1->nHandleID == SMotionEventHanderDB::EV_SWING )
{
// 이것도 따로 처리해야 해야 할듯
OnEventSwing();
XStringUtil::Format( strScript, "%s( %u, %u )", "call_fx_ch_weapone_attack", m_pOwner->GetArID(), m_pTarget->GetArID() );
}
else
{
if( pKey1->nHandleID != 0 )
{
_MOTION_EVENT_HANDER * pHandler = GetMotionEventHanderDB().GetScript( pKey1->nHandleID );
if( pHandler )
{
OnEventEtc();
XStringUtil::Format( strScript, "%s( %u )", pHandler->szScript, m_pOwner->GetArID(), m_pTarget->GetArID() );
}
}
}
if( pKey1->nHandleID == SMotionEventHanderDB::EV_HIT ||
pKey1->nHandleID == SMotionEventHanderDB::EV_LEFT_HAND_HIT ||
pKey1->nHandleID == SMotionEventHanderDB::EV_RIGHT_HAND_HIT ||
pKey1->nHandleID == SMotionEventHanderDB::EV_TWO_HAND_HIT ||
pKey1->nHandleID == SMotionEventHanderDB::EV_SHOOT )
{
//이펙트 출력
if( GetSkillMode() == SKILLMODE_FIRE )
{
if( m_pActionSkillEvent )
{
if( m_pOwner->GetObjType() != TS_ENTER::GAME_MOB ) assert( false );
m_pOwner->AddAction( m_pActionSkillEvent );
SAFE_DELETE( m_pActionSkillEvent );
}
}
}
// Fraun performance tweak (TODO: return it back; testing purposes!)
//if( strScript.length() )
// LUA()->RunString( strScript.c_str() );
}
}
}
void SNewSkill::_getEventSet()
{
//Ani 변경 되어서, 시작 시간 다시 설정
m_dwStartTime = m_dwTime;
//Event handle 처리
if( m_pEventSet )
{
m_pEventSet->event_clear();
SAFE_DELETE( m_pEventSet );
}
m_pEventSet = new EVENT_SET;
EVENT_SET event_set;
m_pOwner->GetCurSeqEvent( event_set );
_setEvent( event_set.pCurEvent00_effect, m_pEventSet->pCurEvent00_effect );
_setEvent( event_set.pCurEvent00_sound , m_pEventSet->pCurEvent00_sound );
_setEvent( event_set.pCurEvent00_motion_effect, m_pEventSet->pCurEvent00_motion_effect );
_setEvent( event_set.pCurEvent01, m_pEventSet->pCurEvent01 );
_setEvent( event_set.pCurEvent02, m_pEventSet->pCurEvent02 );
_setEvent( event_set.pCurEvent03, m_pEventSet->pCurEvent03 );
_setEvent( event_set.pCurEvent04, m_pEventSet->pCurEvent04 );
_setEvent( event_set.pCurEvent05, m_pEventSet->pCurEvent05 );
_setEvent( event_set.pCurEvent06, m_pEventSet->pCurEvent06 );
}
void SNewSkill::_processDefCast( DWORD dwTime )
{
if( GetStep() == STEP_00 )
{ //손 올리기
if( m_pSkillFX->nCasting_Start_Motion_Id != 0 )
{
m_pOwner->NPlayAnimation( m_pSkillFX->nCasting_Start_Motion_Id, SEQTYPE_NORMAL, m_fPlayRate*4.8f );
_addEffect( m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), m_pSkillFX->nCasting_Fx_Set_Id, EFFECT_POS_BOTTOM, SEQTYPE_LOOP );
_getEventSet();
}
// m_pOwner->OnSkillDamage( m_pOwner->GetArID(), m_pOwner->GetArID(), )
SetStep(STEP_01);
}
else if( GetStep() == STEP_01 )
{ //손 올리고 대기
if( m_pSkillFX->nCasting_Start_Motion_Id != 0 )
{
if( m_pOwner->GetCurrAnimationID() == m_pSkillFX->nCasting_Start_Motion_Id && !m_pOwner->IsPlaying() )
{
//밀리스킬과 마법스킬을 구분해서 마법스킬만 skill_b를 루프
if (m_bIsMeleeSkill)
m_pOwner->NPlayAnimation( m_pSkillFX->nCasting_Middle_Motion_Id, SEQTYPE_NORMAL, m_fPlayRate*4.8 );
else
m_pOwner->NPlayAnimation( m_pSkillFX->nCasting_Middle_Motion_Id, SEQTYPE_LOOP, 4.8f );
// _addEffect( m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), m_pSkillFX->nCasting_Fx_Set_Id, EFFECT_POS_BOTTOM, SEQTYPE_LOOP );
_getEventSet();
SetStep(STEP_02);
}
}
else if( m_pSkillFX->nCasting_Start_Motion_Id == 0 )
{
if( m_pSkillFX->nCasting_Middle_Motion_Id != 0 )
{
//밀리스킬과 마법스킬을 구분해서 마법스킬만 skill_b를 루프
if (m_bIsMeleeSkill)
m_pOwner->NPlayAnimation( m_pSkillFX->nCasting_Middle_Motion_Id, SEQTYPE_NORMAL, m_fPlayRate*4.8 );
else
m_pOwner->NPlayAnimation( m_pSkillFX->nCasting_Middle_Motion_Id, SEQTYPE_LOOP, 4.8f );
if( m_nFxID == -1 )
_addEffect( m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), m_pSkillFX->nCasting_Fx_Set_Id, EFFECT_POS_BOTTOM, SEQTYPE_LOOP );
_getEventSet();
}
SetStep(STEP_02);
}
}
else if( GetStep() == STEP_02 )
{
if( m_bIsMeleeSkill && !m_pOwner->IsPlaying() )
{
if (m_nFireMotionID != 0)
{
m_pOwner->NPlayAnimation( m_nFireMotionID , SEQTYPE_NORMAL, m_fPlayRateAfterFire * 4.8f );
if( m_pSkillFX->nFire_Fx_Set_Id != 0 )
_addEffect( m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), m_pSkillFX->nFire_Fx_Set_Id , EFFECT_POS_BOTTOM, SEQTYPE_NORMAL );
_oprint("강제로 fire애니 재생\n");
}
}
// SetEnd(TRUE);
}
}
void SNewSkill::_processDefFire( DWORD dwTime )
{
if( GetStep() == STEP_00 )
{
_oprint("Fire animation started: %d\n", m_nFireMotionID);
if( m_nFireMotionID != 0 )
{
if ( m_bIsMeleeSkill && m_pOwner->IsPlaying() && (m_pOwner->GetCurrAnimationID() == m_nFireMotionID))
{ // 밀리스킬이고 재생중이고 재생중인게 파이어모션이면
} // 아무것도 하지않음
else if (m_nFireMotionID == ANI_ATTACK01)
{ // 스킬이지만 평타모션으로 나가고 있을 경우도 아무것도 하지 않음
}
else // 아니면 파이어모션 출력
{
m_pOwner->NPlayAnimation( m_nFireMotionID , SEQTYPE_NORMAL, m_fPlayRateAfterFire * 4.8f );
//시전시 동반 되는 이펙트
if( m_pSkillFX->nFire_Fx_Set_Id != 0 )
_addEffect( m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), m_pSkillFX->nFire_Fx_Set_Id , EFFECT_POS_BOTTOM, SEQTYPE_NORMAL );
}
_getEventSet();
}
SetStep(STEP_01);
}
else if( GetStep() == STEP_01 )
{
if( m_nFireMotionID != 0 )
{
if( m_pOwner->GetCurrAnimationID() == m_nFireMotionID && !m_pOwner->IsPlaying() )
{ //시전 연출 끝났음.
SetStep(STEP_02);
}
}
else if( m_nFireMotionID == 0 )
{ //시전 모션 없음.
SetStep(STEP_02);
}
}
else if( GetStep() == STEP_02 )
{
m_pOwner->EndUseSkill( m_pSkillFX->nID );
m_pOwner->Default();
SetEnd(TRUE);
}
//이미 스킬이 완료 되었고
if( m_pOwner->IsUseSkill_complete() == true )
{ //기존 애니메이션이 다르면, 종료
if( m_nFireMotionID != 0 && m_pOwner->GetCurrAnimationID() != m_nFireMotionID )
{
_oprint( "Fire ended because the animation was different. [cur:%d] [fire:%d]\n", m_pOwner->GetCurrAnimationID(), m_nFireMotionID );
SetEnd( TRUE );
return;
}
}
}
// AziaMafia FixSkill
void SNewSkill::_processView()
{
if (IsEnd()) return;
if (m_pTarget && !m_bIsSelfSkill)
{
if (m_pTarget->GetArID() != m_pOwner->GetArID())
{
if (GetSkillMode() == SKILLMODE_FIRE && m_pOwner->GetCurrAnimationID() != m_nFireMotionID)
return;
m_pOwner->SetViewVector(*m_pTarget->GetPosition());
}
else
m_bIsSelfSkill = true;
}
}
void SNewSkill::_addEffect( const AR_HANDLE & owner, const AR_HANDLE & attack, const AR_HANDLE & target, const int & nFX_ID, const int & nFX_pos, int nAnitype, float fPlayRate )
{
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 위치
fx_data.fPlayRate = fPlayRate;
if(nAnitype == SEQTYPE_LOOP ) fx_data.bIsLoop = true;
m_nFxID = m_pOwner->AddEffect( &fx_data );
}
void SNewSkill::_addEffect( const AR_HANDLE & target, const int & nFX_ID, const int & nFX_pos )
{
FX_DATA fx_data;
fx_data.owner = target;
fx_data.attack = target;
fx_data.target = target;
fx_data.nFX_ID = nFX_ID; //시전(타격)연출 보조FX ID
fx_data.nEffPos = nFX_pos; //시전(타격)연출 보조FX 위치
m_nFxID = m_pTarget->AddEffect( &fx_data );
}
void SNewSkill::_addFX( int nStage_Type )
{
if( nStage_Type == SS_TYPE_121 )
{
if( m_pSkillFX->fStage_Data[7] == 0 ) return;
_addEffect( m_pOwner->GetArID(), m_pOwner->GetArID(), m_pTarget->GetArID(), m_pSkillFX->fStage_Data[7], m_pSkillFX->fStage_Data[8], SEQTYPE_NORMAL, m_pSkillFX->fStage_Data[1]*4.8f );
}
else if( nStage_Type == SS_TYPE_122 )
{
if( m_pSkillFX->fStage_Data[2] == 0 ) return;
_addEffect( m_pOwner->GetArID(), m_pOwner->GetArID(), m_pTarget->GetArID(), m_pSkillFX->fStage_Data[2], m_pSkillFX->fStage_Data[3], SEQTYPE_NORMAL, m_pSkillFX->fStage_Data[1]*4.8f );
if( m_pSkillFX->fStage_Data[4] == 0 ) return;
_addEffect( m_pOwner->GetArID(), m_pOwner->GetArID(), m_pTarget->GetArID(), m_pSkillFX->fStage_Data[4], m_pSkillFX->fStage_Data[5], SEQTYPE_NORMAL, m_pSkillFX->fStage_Data[1]*4.8f );
}
else if( nStage_Type == SS_TYPE_123 )
{
if( m_pSkillFX->fStage_Data[7] == 0 ) return;
_addEffect( m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), m_pSkillFX->fStage_Data[7], m_pSkillFX->fStage_Data[8], SEQTYPE_NORMAL, m_pSkillFX->fStage_Data[1]*4.8f );
}
else if( nStage_Type == SS_TYPE_171)
{
if( m_pSkillFX->fStage_Data[7] == 0 ) return;
_addEffect( m_pOwner->GetArID(), m_pOwner->GetArID(), m_pTarget->GetArID(), m_pSkillFX->fStage_Data[7], m_pSkillFX->fStage_Data[8], SEQTYPE_NORMAL, m_pSkillFX->fStage_Data[1]*4.8f );
}
}
float SNewSkill::CalcCurrentAniTimeTime( SGameAvatarEx* pAvatar )
{
if( pAvatar == NULL ) return 0.0f;
int nBoneCnt = 0;
DWORD dwMinTime = 0, dwMaxTime = 0;
DWORD dwCurAniTime = 0;
pAvatar->GetCurrentAnimationInfo( nBoneCnt, dwMinTime, dwMaxTime, dwCurAniTime );
float fMaxTime = (float)dwMaxTime / 160.0f;
float fMinTime = (float)dwMinTime / 160.0f;
fMaxTime = ((fMaxTime * 4.8f) / 100.0f ) * 1000.0f;
fMinTime = ((fMinTime * 4.8f) / 100.0f ) * 1000.0f;
return fMaxTime - fMinTime;
}
//==============================================================================================
//추후에 소환 연출 개개별로 만들 필요 있음.
SWorkSummonCall::SWorkSummonCall( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
//마법 모션임.
pSkillFX->nCasting_Start_Motion_Id; //시작
pSkillFX->nCasting_Middle_Motion_Id; //대기
pSkillFX->nFire_Motion_Id; //시전
SetStep(STEP_00);
// 2010.08.31 - prodongi
m_nFXID = -1;
}
SWorkSummonCall::~SWorkSummonCall()
{
// 2010.08.31 - prodongi
//if( m_nFXID != 0 )
if( m_nFXID != 0 && -1 != m_nFXID)
{
if( m_pOwner )
m_pOwner->EndOtherEffect( m_nFXID );
}
}
void SWorkSummonCall::Process( DWORD dwTime )
{
if( IsEnd() ) return;
if( GetStep() == STEP_00 && GetSkillMode() == SKILLMODE_CAST )
{
int fxid = 5081;
m_nFXID = m_pOwner->AddOtherEffect( SGameOtherEffectMng::FX_CAST_SUMMONING_CREATURE, &OtherFxData( m_pOwner->GetArID(), 0,fxid, m_dwCatingTime, &m_vPos ) );
}
else if( GetStep() == STEP_00 && GetSkillMode() == SKILLMODE_FIRE )
{
// 2010.08.31 소환 주문서 사용 경우에 캐스팅 시간이 0이므로 SKILLMODE_CAST에 들어가지 않아서 이펙트가 출력 안될때가 만다
// 그래서 SKILLMODE_FIRE에서 출력하도록 해줌 - prodongi
if (-1 == m_nFXID && 0 == m_dwCatingTime)
{
AR_HANDLE handle = m_pOwner->GetArID();
FX_DATA fx_data;
fx_data.attack = handle;
fx_data.owner = handle;
fx_data.target = handle;
fx_data.fPlayRate = 1.f;
fx_data.nEffPos = EFFECT_POS_BOTTOM;
fx_data.nPlayID = 0;
fx_data.nFX_ID = 5081;
m_pOwner->AddEffect(&fx_data);
m_nFXID = 0;
}
m_pOwner->OnUISync( m_pOwner->GetArID(), m_pOwner->GetArID() );
}
SNewSkill::Process( dwTime );
m_pOwner->SetViewVector( m_vPos );
}
//==============================================================================================
//추후에 역소환 연출 개개별로 만들 필요 있음.
SWorkSummonReCall::SWorkSummonReCall( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
//마법 모션임.
pSkillFX->nCasting_Start_Motion_Id; //시작
pSkillFX->nCasting_Middle_Motion_Id; //대기
pSkillFX->nFire_Motion_Id; //시전
}
SWorkSummonReCall::~SWorkSummonReCall()
{
}
void SWorkSummonReCall::Process( DWORD dwTime )
{
if( IsEnd() ) return;
if( GetStep() == STEP_00 && GetSkillMode() == SKILLMODE_FIRE )
{
m_pOwner->OnUISync( m_pOwner->GetArID(), m_pOwner->GetArID() );
}
SNewSkill::Process( dwTime );
}
//==============================================================================================
SWorkWeaponSwingHit::SWorkWeaponSwingHit( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
//물리 스킬
// pSkillFX->nCasting_Start_Motion_Id; //시작
// pSkillFX->nCasting_Middle_Motion_Id; //대기
// pSkillFX->nFire_Motion_Id; //시전
if( m_pSkillFX->fStage_Data[0] == 0 )
m_bMultiAttack = false;
else
m_bMultiAttack = true;
SetStep(STEP_00);
}
SWorkWeaponSwingHit::~SWorkWeaponSwingHit()
{
if( m_pOwner )
{
//처리가 안됐다면
if( m_bMultiAttack )
{
while( m_nHitCnt > 0 ) //_processDamageMulti() 여기서 --m_nHitCnt 무조건 수행하므로 무한 루프 가능성은 없음
{
_processDamageMulti();
}
}
}
}
void SWorkWeaponSwingHit::OnEventHit()
{
/// 2010.10.07 epic6에서 적용 안된 것 추가
/*
//대상 1
if( !m_bMultiAttack )
{
_processDamage();
}
else //광역
{
while( m_nHitCnt > 0 ) //_processDamageMulti() 여기서 --m_nHitCnt 무조건 수행하므로 무한 루프 가능성은 없음
{
_processDamageMulti();
}
}
*/
if( m_bMultiAttack )
_processDamage();
else
{
while( m_nHitCnt > 0 ) //_processDamageMulti() 여기서 --m_nHitCnt 무조건 수행하므로 무한 루프 가능성은 없음
{
_processDamageMulti();
}
}
}
void SWorkWeaponSwingHit::OnEventSwing()
{
}
void SWorkWeaponSwingHit::OnEventEtc()
{
}
/// 2010.10.07 epic6에서 적용 안되서 추가함 - prodongi
/*
void SWorkWeaponSwingHit::_processDamage()
{
if( m_pTarget )
{
if( m_pSkillFX->nHit_Fx_Set_Id != 0 )
_addEffect( m_pTarget->GetArID(), m_pTarget->GetArID(), m_pTarget->GetArID(), m_pSkillFX->nHit_Fx_Set_Id, m_pSkillFX->nHit_Fx_Set_Position_Id );
}
SNewSkill::_processDamage();
}
*/
void SWorkWeaponSwingHit::Process( DWORD dwTime )
{
if( IsEnd() ) return;
SNewSkill::Process( dwTime );
_processView();
}
//==============================================================================================
SWorkShieldSwingHit::SWorkShieldSwingHit( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
//물리 스킬
pSkillFX->nCasting_Start_Motion_Id; //시작
pSkillFX->nCasting_Middle_Motion_Id; //대기
pSkillFX->nFire_Motion_Id; //시전
if( m_pSkillFX->fStage_Data[0] == 0 )
m_bMultiAttack = false;
else
m_bMultiAttack = true;
}
SWorkShieldSwingHit::~SWorkShieldSwingHit()
{
if( m_pOwner )
{
//처리가 안됐다면
if( m_bMultiAttack )
{
while( m_nHitCnt > 0 ) //_processDamageMulti() 여기서 --m_nHitCnt 무조건 수행하므로 무한 루프 가능성은 없음
{
_processDamageMulti();
}
}
else
_processDamage();
}
}
void SWorkShieldSwingHit::Process( DWORD dwTime )
{
if( IsEnd() ) return;
SNewSkill::Process( dwTime );
_processView();
}
void SWorkShieldSwingHit::OnEventHit()
{
//대상 1
if( !m_bMultiAttack )
{
_processDamage();
}
else //광역
{
while( m_nHitCnt > 0 ) //_processDamage() 여기서 --m_nHitCnt 무조건 수행하므로 무한 루프 가능성은 없음
{
_processDamageMulti();
}
}
}
void SWorkShieldSwingHit::OnEventSwing()
{
}
void SWorkShieldSwingHit::OnEventEtc()
{
}
//==============================================================================================
//스킬 연출 유형 121
SWorkWeaponSwing_3Motion::SWorkWeaponSwing_3Motion( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
int nFX1 = pSkillFX->fStage_Data[0];//모션배분 (0:순차 1:랜덤)
int nFX2 = pSkillFX->fStage_Data[1];//모션속도변화 (1=100%, 클수록 빨라짐)
int nFX3 = pSkillFX->fStage_Data[2];//시전(타격)모션1 ID
int nFX4 = pSkillFX->fStage_Data[3];//시전(타격)모션2 ID
int nFX5 = pSkillFX->fStage_Data[4];//시전(타격)모션3 ID
int nFX6 = pSkillFX->fStage_Data[5];//시전(타격)연출 보조FX ID
int nFX7 = pSkillFX->fStage_Data[6];//시전(타격)연출 보조FX 위치
m_fPlayRate = pSkillFX->fStage_Data[1]; //재생 배속
// m_nLocalFireMotionID[0] = pSkillFX->fStage_Data[2];
// m_nLocalFireMotionID[1] = pSkillFX->fStage_Data[3];
// m_nLocalFireMotionID[2] = pSkillFX->fStage_Data[4];
m_nCurHitCount = 0;
m_cMaxHitCount = (int)pSkillFX->fStage_Data[9];
if( m_cMaxHitCount <= 0 )
m_cMaxHitCount = 3;
m_pLocalFireMotionID = new int[m_cMaxHitCount];
for( unsigned char cMaxHitCount = 0; cMaxHitCount < m_cMaxHitCount; ++cMaxHitCount )
m_pLocalFireMotionID[cMaxHitCount] = pSkillFX->fStage_Data[2+cMaxHitCount]; //시전(타격)모션
}
SWorkWeaponSwing_3Motion::~SWorkWeaponSwing_3Motion()
{
if( m_pOwner )
{
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( m_pTarget )
{
while(m_nHitCnt > 0)
_processDamage();
}
}
SAFE_DELETE_ARRAY( m_pLocalFireMotionID );
}
void SWorkWeaponSwing_3Motion::OnEventHit()
{
_processDamage();
}
void SWorkWeaponSwing_3Motion::OnEventSwing()
{
// _oprint( "스윙 이벤트\n" );
}
void SWorkWeaponSwing_3Motion::OnEventEtc()
{
// _oprint( "그외 이벤트\n" );
}
bool SWorkWeaponSwing_3Motion::ProcessingDamage()
{
//마지막 연타가 m_nCurHitCount == 2
//히트 카운트가 m_nHitCnt == 0
//SkillMode는 GetSkillMode() == SKILLMODE_FIRE
if( m_nCurHitCount != 2 || m_nHitCnt > 0 || GetSkillMode() != SKILLMODE_FIRE )
return false;
return true;
}
void SWorkWeaponSwing_3Motion::_processDamage()
{
//타겟 만큼 순차적으로 데미지 처리
for( unsigned char target_count = 0; target_count < m_pSkillEvent->fire.target_count; ++target_count )
{
if( m_nHitCnt > 0 )
{
m_pDamage->skillresult = m_pSkillEvent->vSkillResult[m_nCount - m_nHitCnt];
SGameAvatarEx* pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_pDamage->skillresult.GetTargetHandle() );
if( pTarget )
{
int nBlock = 0;
int nCritical = 0;
if(m_pDamage->skillresult.damage.flag & TS_ATTACK_EVENT::FLAG_CRITICAL) nCritical = 1;
if(m_pDamage->skillresult.damage.flag & TS_ATTACK_EVENT::FLAG_BLOCK) nBlock = 1;
m_pOwner->OnDamage( m_pOwner->GetArID(), pTarget->GetArID(), m_pDamage );
if( (m_pDamage->skillresult.GetType() == SkillResult::DAMAGE || m_pDamage->skillresult.GetType() == SkillResult::MAGIC_DAMAGE)
&& !(m_pDamage->skillresult.damage.flag & SkillResult::MISS) )
{
pTarget->Damage();
// Fraun performance tweak (TODO: return it back; testing purposes!)
//std::string strScript;
//XStringUtil::Format( strScript, "%s( %u, %u, %d, %d )", "avatar_basic_hit", m_pOwner->GetArID(), pTarget->GetArID(), nCritical, nBlock );
//if( strScript.length() )
// LUA()->RunString( strScript.c_str() );
if( m_pSkillFX->nSub_Fire_Fx_Set_Id != 0 )
_addEffect( m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), m_pSkillFX->nSub_Fire_Fx_Set_Id, m_pSkillFX->nSub_Fire_Fx_Position );
if( m_pSkillFX->nHit_Fx_Set_Id != 0 )
_addEffect( pTarget->GetArID(), pTarget->GetArID(), pTarget->GetArID(), m_pSkillFX->nHit_Fx_Set_Id, m_pSkillFX->nHit_Fx_Set_Position_Id );
}
}
--m_nHitCnt;
}
}
}
void SWorkWeaponSwing_3Motion::SetCurHitCount( int nCurHitCount )
{
m_nCurHitCount = nCurHitCount;
}
void SWorkWeaponSwing_3Motion::Process( DWORD dwTime )
{
if( IsEnd() ) return;
m_dwTime = dwTime;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
SetEnd(true);
return;
}
_processView();
if( GetSkillMode() == SKILLMODE_CAST )
{
if( GetStep() == STEP_00 )
{
_addFX( m_pSkillFX->nStage_Type_Id );
}
_processDefCast( dwTime );
}
else if( GetSkillMode() == SKILLMODE_FIRE )
{
if( GetStep() == STEP_00 )
{
if( m_nCurHitCount < m_cMaxHitCount && m_pLocalFireMotionID[m_nCurHitCount] != 0 )
{
m_pOwner->NPlayAnimation( m_pLocalFireMotionID[m_nCurHitCount], SEQTYPE_NORMAL, m_fPlayRate * 4.8f );
_getEventSet();
if( m_nCurHitCount == 0 )
_addFX( m_pSkillFX->nStage_Type_Id );
SetStep( STEP_01 );
}
else
{
m_pOwner->EndUseSkill( m_pSkillFX->nID );
m_pOwner->Default();
SetEnd(TRUE);
return;
}
}
else if( GetStep() == STEP_01 )
{
int nAniType = m_pOwner->GetCurrAnimationID();
if( !m_pOwner->IsPlaying() || !CurrentlyAnimationIsFire() )
{
m_pOwner->EndUseSkill( m_pSkillFX->nID );
m_pOwner->Default();
SetEnd(TRUE);
return;
}
}
}
DWORD eventTime = ((dwTime - m_dwStartTime) * m_fPlayRate);
_processEventSet( eventTime );
}
bool SWorkWeaponSwing_3Motion::CurrentlyAnimationIsFire()
{
int nCurrentAniID = m_pOwner->GetCurrAnimationID();
for( unsigned char cMaxHitCount = 0; cMaxHitCount < m_cMaxHitCount; ++cMaxHitCount )
{
if( nCurrentAniID == m_pLocalFireMotionID[cMaxHitCount] )
return true;
}
return false;
}
//==============================================================================================
//스킬 연출 유형 122
SWorkWeaponSwing_ContinuousHits::SWorkWeaponSwing_ContinuousHits( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
m_nFireMotionID = pSkillFX->fStage_Data[0]; //시전모션 ID
m_nEndFireMotionID = pSkillFX->fStage_Data[6];
m_fPlayRate = pSkillFX->fStage_Data[1]; //모션속도변화 (1=100%, 클수록 빨라짐)
//pSkillFX->nStage_Data_03;
//pSkillFX->nStage_Data_04;
//pSkillFX->nStage_Data_05;//시전(타격)연출 보조FX(2) ID
//pSkillFX->nStage_Data_06;//시전(타격)연출 보조FX(2) 위치
}
SWorkWeaponSwing_ContinuousHits::~SWorkWeaponSwing_ContinuousHits()
{
if( m_pOwner )
{
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( m_pTarget )
{
while(m_nHitCnt > 0)
_processDamage();
}
}
}
//Snewskill에서 처리 하지 말고 여기서 처리한다 ( 추가될수 있으이 )
bool SWorkWeaponSwing_ContinuousHits::ProcessingDamage()
{
if( m_nHitCnt > 0 || GetSkillMode() != SKILLMODE_FIRE )
return false;
return true;
}
void SWorkWeaponSwing_ContinuousHits::Process( DWORD dwTime )
{
if( IsEnd() ) return;
m_dwTime = dwTime;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
SetEnd(true);
return;
}
_processView();
if( GetSkillMode() == SKILLMODE_CAST )
{
_processDefCast( dwTime );
}
else if( GetSkillMode() == SKILLMODE_FIRE )
{
if( GetStep() == STEP_00 )
{
if( m_nFireMotionID != 0 )
{
m_pOwner->NPlayAnimation( m_nFireMotionID, SEQTYPE_NORMAL, m_fPlayRate * 4.8f );
_addFX( m_pSkillFX->nStage_Type_Id );
_getEventSet();
SetStep( STEP_01 );
}
else
SetStep( STEP_02 );
}
else if( GetStep() == STEP_01 )
{
if( !m_pOwner->IsPlaying() )
{
SetStep( STEP_02 );
}
else if( m_pOwner->GetCurrAnimationID() != m_nFireMotionID )
{
if( m_nHitCnt > 0 )
{
m_pOwner->SetAniLock( false );
m_pOwner->NPlayAnimation( m_nFireMotionID, SEQTYPE_NORMAL, m_fPlayRate * 4.8f );
m_pOwner->SetAniLock( true );
_getEventSet();
}
else
{
SetStep( STEP_02 );
return;
}
}
}
else if( GetStep() == STEP_02 )
{
m_pOwner->EndUseSkill( m_pSkillFX->nID );
m_pOwner->Default();
SetEnd(TRUE);
return;
}
}
DWORD eventTime = ((dwTime - m_dwStartTime) * m_fPlayRate );
_processEventSet( eventTime );
}
void SWorkWeaponSwing_ContinuousHits::OnEventHit()
{
_processDamage();
}
void SWorkWeaponSwing_ContinuousHits::OnEventSwing()
{
}
void SWorkWeaponSwing_ContinuousHits::OnEventEtc()
{
}
void SWorkWeaponSwing_ContinuousHits::_processDamage()
{
//타겟 만큼 순차적으로 데미지 처리
for( unsigned char target_count = 0; target_count < m_pSkillEvent->fire.target_count; ++target_count )
{
if( m_nHitCnt > 0 )
{
m_pDamage->skillresult = m_pSkillEvent->vSkillResult[m_nCount - m_nHitCnt];
SGameAvatarEx* pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_pDamage->skillresult.GetTargetHandle() );
if( pTarget )
{
int nBlock = 0;
int nCritical = 0;
if(m_pDamage->skillresult.damage.flag & TS_ATTACK_EVENT::FLAG_CRITICAL) nCritical = 1;
if(m_pDamage->skillresult.damage.flag & TS_ATTACK_EVENT::FLAG_BLOCK) nBlock = 1;
m_pOwner->OnDamage( m_pOwner->GetArID(), pTarget->GetArID(), m_pDamage );
if( (m_pDamage->skillresult.GetType() == SkillResult::DAMAGE || m_pDamage->skillresult.GetType() == SkillResult::MAGIC_DAMAGE)
&& !(m_pDamage->skillresult.damage.flag & SkillResult::MISS) )
{
pTarget->Damage();
// Fraun performance tweak (TODO: return it back; testing purposes!)
//std::string strScript;
//XStringUtil::Format( strScript, "%s( %u, %u, %d, %d )", "avatar_basic_hit", m_pOwner->GetArID(), pTarget->GetArID(), nCritical, nBlock );
//if( strScript.length() )
// LUA()->RunString( strScript.c_str() );
if( m_pSkillFX->nSub_Fire_Fx_Set_Id != 0 )
_addEffect( m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), m_pSkillFX->nSub_Fire_Fx_Set_Id, m_pSkillFX->nSub_Fire_Fx_Position );
if( m_pSkillFX->nHit_Fx_Set_Id != 0 )
_addEffect( pTarget->GetArID(), pTarget->GetArID(), pTarget->GetArID(), m_pSkillFX->nHit_Fx_Set_Id, m_pSkillFX->nHit_Fx_Set_Position_Id );
}
}
--m_nHitCnt;
}
}
}
//==============================================================================================
//스킬 연출 유형 123
SWorkWeaponSwing_Zeal::SWorkWeaponSwing_Zeal( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
// m_nLocalFireMotionID[0] = pSkillFX->fStage_Data[2];//시전(타격)모션1 ID
// m_nLocalFireMotionID[1] = pSkillFX->fStage_Data[3];//시전(타격)모션2 ID
// m_nLocalFireMotionID[2] = pSkillFX->fStage_Data[4];//시전(타격)모션3 ID
m_fPlayRate = pSkillFX->fStage_Data[1];//재생 배속
m_nCurMotionID = -1;
m_cMaxHitCount = (int)pSkillFX->fStage_Data[9];
if( m_cMaxHitCount <= 0 )
{
m_cMaxHitCount = 3;
}
m_pLocalFireMotionID = new int[m_cMaxHitCount];
for( unsigned char cMaxHitCount = 0; cMaxHitCount < m_cMaxHitCount; ++cMaxHitCount )
m_pLocalFireMotionID[cMaxHitCount] = pSkillFX->fStage_Data[2+cMaxHitCount]; //시전(타격)모션
}
SWorkWeaponSwing_Zeal::~SWorkWeaponSwing_Zeal()
{
if( m_pOwner )
{
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( m_pTarget )
{
while(m_nHitCnt > 0)
_processDamage();
}
}
SAFE_DELETE_ARRAY( m_pLocalFireMotionID );
}
void SWorkWeaponSwing_Zeal::OnEventHit()
{
_processDamage();
}
bool SWorkWeaponSwing_Zeal::ProcessingDamage()
{
if( m_nHitCnt > 0 || GetSkillMode() != SKILLMODE_FIRE )
return false;
return true;
}
void SWorkWeaponSwing_Zeal::_processDamage()
{
for( unsigned char target_count = 0; target_count < m_pSkillEvent->fire.target_count; ++target_count )
{
if( m_nHitCnt > 0 )
{
m_pDamage->skillresult = m_pSkillEvent->vSkillResult[m_nCount - m_nHitCnt];
SGameAvatarEx* pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_pDamage->skillresult.GetTargetHandle() );
if( pTarget )
{
int nBlock = 0;
int nCritical = 0;
if(m_pDamage->skillresult.damage.flag & TS_ATTACK_EVENT::FLAG_CRITICAL) nCritical = 1;
if(m_pDamage->skillresult.damage.flag & TS_ATTACK_EVENT::FLAG_BLOCK) nBlock = 1;
m_pOwner->OnDamage( m_pOwner->GetArID(), pTarget->GetArID(), m_pDamage );
if( (m_pDamage->skillresult.GetType() == SkillResult::DAMAGE || m_pDamage->skillresult.GetType() == SkillResult::MAGIC_DAMAGE)
&& !(m_pDamage->skillresult.damage.flag & SkillResult::MISS) )
{
pTarget->Damage();
// Fraun performance tweak (TODO: return it back; testing purposes!)
//std::string strScript;
//XStringUtil::Format( strScript, "%s( %u, %u, %d, %d )", "avatar_basic_hit", m_pOwner->GetArID(), pTarget->GetArID(), nCritical, nBlock );
//if( strScript.length() )
// LUA()->RunString( strScript.c_str() );
if( m_pSkillFX->nSub_Fire_Fx_Set_Id != 0 )
_addEffect( m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), m_pSkillFX->nSub_Fire_Fx_Set_Id, m_pSkillFX->nSub_Fire_Fx_Position );
if( m_pSkillFX->nHit_Fx_Set_Id != 0 )
_addEffect( pTarget->GetArID(), pTarget->GetArID(), pTarget->GetArID(), m_pSkillFX->nHit_Fx_Set_Id, m_pSkillFX->nHit_Fx_Set_Position_Id );
}
}
--m_nHitCnt;
}
}
}
void SWorkWeaponSwing_Zeal::Process( DWORD dwTime )
{
if( IsEnd() ) return;
m_dwTime = dwTime;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
SetEnd(true);
return;
}
_processView();
if( GetSkillMode() == SKILLMODE_CAST )
{
_processDefCast( dwTime );
}
else if( GetSkillMode() == SKILLMODE_FIRE )
{
if( GetStep() == STEP_00 )
{
//1이면 랜덤 0이면 순차
if( m_pSkillFX->fStage_Data[0] > 0.0f)
m_nCurMotionID = rand() % m_cMaxHitCount;
else
{
++m_nCurMotionID;
if( m_nCurMotionID >= m_cMaxHitCount )
m_nCurMotionID = 0;
}
m_pOwner->SetAniLock( false );
m_pOwner->NPlayAnimation( m_pLocalFireMotionID[m_nCurMotionID], SEQTYPE_NORMAL, m_fPlayRate * 4.8f );
m_pOwner->SetAniLock( true );
_addFX( m_pSkillFX->nStage_Type_Id );
_getEventSet();
SetStep( STEP_01 );
}
else if( GetStep() == STEP_01 )
{
if( !m_pOwner->IsPlaying() )
{
if( m_nHitCnt > 0 )
{
//1이면 랜덤 0이면 순차
if( m_pSkillFX->fStage_Data[0] > 0.0f )
m_nCurMotionID = rand() % m_cMaxHitCount;
else
{
++m_nCurMotionID;
if( m_nCurMotionID >= m_cMaxHitCount )
m_nCurMotionID = 0;
}
m_pOwner->SetAniLock( false );
m_pOwner->NPlayAnimation( m_pLocalFireMotionID[m_nCurMotionID], SEQTYPE_NORMAL, m_fPlayRate * 4.8f );
m_pOwner->SetAniLock( true );
_getEventSet();
}
else
{
SetStep( STEP_02 );
return;
}
}
else if( !CurrentlyAnimationIsFire() ) //연타 관련 모션을 재생중이지 않다면 끝낸다
{
if( m_nHitCnt > 0 )
{
m_pOwner->SetAniLock( false );
m_pOwner->NPlayAnimation( m_pLocalFireMotionID[m_nCurMotionID], SEQTYPE_NORMAL, m_fPlayRate * 4.8f );
m_pOwner->SetAniLock( true );
_getEventSet();
}
else
{
SetStep( STEP_02 );
return;
}
}
}
else if( GetStep() == STEP_02 )
{
m_pOwner->SetAniLock( false );
m_pOwner->EndUseSkill( m_pSkillFX->nID );
m_pOwner->Default();
SetEnd(TRUE);
return;
}
}
DWORD eventTime = ((dwTime - m_dwStartTime) * m_fPlayRate );
_processEventSet( eventTime );
}
bool SWorkWeaponSwing_Zeal::CurrentlyAnimationIsFire()
{
int nCurrentAniID = m_pOwner->GetCurrAnimationID();
for( unsigned char cMaxHitCount = 0; cMaxHitCount < m_cMaxHitCount; ++cMaxHitCount )
{
if( nCurrentAniID == m_pLocalFireMotionID[cMaxHitCount] )
return true;
}
return false;
}
//==============================================================================================
SWorkWeaponSwing_Leech::SWorkWeaponSwing_Leech( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
pSkillFX->fStage_Data[0];//흡수체생성딜레이(초)
pSkillFX->fStage_Data[1];//흡수체FX ID
pSkillFX->fStage_Data[2];//흡수체FX 비행스타일 (0~2)
pSkillFX->fStage_Data[3];//추가발동(회복) FX ID
pSkillFX->fStage_Data[4];//추가발동(회복) FX 위치
}
SWorkWeaponSwing_Leech::~SWorkWeaponSwing_Leech()
{
}
void SWorkWeaponSwing_Leech::Process( DWORD dwTime )
{
if( IsEnd() ) return;
SNewSkill::Process( dwTime );
_processView();
}
void SWorkWeaponSwing_Leech::OnEventHit()
{
_processDamage();
}
void SWorkWeaponSwing_Leech::OnEventSwing()
{
}
void SWorkWeaponSwing_Leech::OnEventEtc()
{
}
//==============================================================================================
SWorkBowShoot::SWorkBowShoot( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
pSkillFX->fStage_Data[0];//연타연출타입 (0,1)
pSkillFX->fStage_Data[1];//범위연출타입 (0,1)
pSkillFX->fStage_Data[2];//슈팅형 발사체FX ID
pSkillFX->fStage_Data[3];//슈팅형 발사체FX 비행속도 (-1,1~9)
pSkillFX->fStage_Data[4];//연사간격(초)
m_nEffectID[0] = -1;
m_nEffectID[1] = -1;
m_nEffectID[2] = -1;
struct _MOTION_FX_SET* m_pFxSet = NULL;
if( pSkillFX->nStage_Type_Id == SS_TYPE_201 )
{
m_pFxSet = GetMotionFxSetDB().GetFXSet( pSkillFX->fStage_Data[5] );
}
else if( pSkillFX->nStage_Type_Id == SS_TYPE_212 )
{
m_pFxSet = GetMotionFxSetDB().GetFXSet( pSkillFX->fStage_Data[6] );
}
// From ZONE source; dual crossbows
bool bIsCrossBow = false;
<<<<<<< HEAD
if (ItemBase::CLASS_CROSSBOW == pOwner->GetItemClass()) //Double Crossbow
=======
if (ItemBase::CLASS_CROSSBOW == pOwner->GetItemClass())
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
bIsCrossBow = true;
// AziaMafia Double Crossbow
//if (ItemBase::CLASS_CROSSBOW == pOwner->GetItemClass())
// (ItemBase::CLASS_CROSSBOW || ItemBase::CLASS_DOUBLE_CROSSBOW == pOwner->GetItemClass())
// bIsCrossBow = true;
if( m_pFxSet )
{
m_strFX_01 = GetResourceDB().GetEffectResourceName( m_pFxSet->graphic_effect_start_file_ID );
m_strFX_02 = GetResourceDB().GetEffectResourceName( m_pFxSet->graphic_effect_middle_file_ID );
m_strFX_03 = GetResourceDB().GetEffectResourceName( m_pFxSet->graphic_effect_end_file_ID );
if( bIsCrossBow )
{
<<<<<<< HEAD
//Double Crossbow
m_strFX_01 += "cba_";
m_strFX_02 += "cba_";
m_strFX_03 += "cba_";
=======
// AziaMafia Double Crossbow
//m_strFX_01 += "cba_";
//m_strFX_02 += "cba_";
//m_strFX_03 += "cba_";
m_strFX_01 += "cbt_";
m_strFX_02 += "cbt_";
m_strFX_03 += "cbt_";
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
}
else
{
m_strFX_01 += "bwa_";
m_strFX_02 += "bwa_";
m_strFX_03 += "bwa_";
}
}
else
{
if( bIsCrossBow )
{
m_strFX_01 = "rcfx_cross_arrowattack_start_lv01_";
m_strFX_02 = "rcfx_cross_arrowattack_loop_lv01_";
m_strFX_03 = "rcfx_cross_arrowattack_end_lv01_";
}
else
{
m_strFX_01 = "rcfx_arrowattack_start_lv01_";
m_strFX_02 = "rcfx_arrowattack_loop_lv01_";
m_strFX_03 = "rcfx_arrowattack_end_lv01_";
/*m_strFX_01 = "rcfx_pillaroffirearrow_start_lv01_bwa_"; //Alucard Need test this if this from higher epic
m_strFX_02 = "rcfx_pillaroffirearrow_loop_lv01_bwa_";
m_strFX_03 = "rcfx_pillaroffirearrow_end_lv01_bwa_";*/
}
}
const char* szName = GetNX3Name( pOwner->GetRace(), pOwner->GetSex() );
m_strFX_01 += szName;
m_strFX_02 += szName;
m_strFX_03 += szName;
}
SWorkBowShoot::~SWorkBowShoot()
{
if( m_pOwner )
{
if( m_nEffectID[0] != -1 ) m_pOwner->DelEffect( m_nEffectID[0] );
if( m_nEffectID[1] != -1 ) m_pOwner->DelEffect( m_nEffectID[1] );
// if( m_nEffectID[2] != -1 ) m_pOwner->DelEffect( m_nEffectID[2] );
}
}
bool SWorkBowShoot::ProcessingDamage()
{
if( GetSkillMode() != SKILLMODE_FIRE || GetStep() != STEP_01 )
return false;
return true;
}
void SWorkBowShoot::Process( DWORD dwTime )
{
if( IsEnd() ) return;
m_dwTime = dwTime;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
SetEnd(true);
return;
}
_processView();
if( GetSkillMode() == SKILLMODE_CAST )
{
_processDefCast( dwTime );
//우선 애니메이션 체크로 화살 이펙트를 출력하자
if( m_pOwner->GetCurrAnimationID() == ANI_BOW_ATTACK01_A && m_nEffectID[0] == -1)
m_nEffectID[0] = m_pOwner->AddEffect( &FX_DATA_EX( m_strFX_01.c_str(), 2, m_pOwner->GetArID(), m_pOwner->GetArID(), m_hTarget, EFFECT_POS_DAMAGE, true, SEQTYPE_NORMAL, m_fPlayRate*4.8f ) );
else if( m_pOwner->GetCurrAnimationID() == ANI_BOW_ATTACK01_B && m_nEffectID[1] == -1)
m_nEffectID[1] = m_pOwner->AddEffect( &FX_DATA_EX( m_strFX_02.c_str(), 2, m_pOwner->GetArID(), m_pOwner->GetArID(), m_hTarget, EFFECT_POS_DAMAGE, true, SEQTYPE_LOOP, m_fPlayRate*4.8f ) );
}
else if( GetSkillMode() == SKILLMODE_FIRE )
{
if( GetStep() == STEP_00 )
{
//m_pOwner->AddAction( m_pSkillEvent );
if( m_nEffectID[2] == -1 )
m_nEffectID[2] = m_pOwner->AddEffect( &FX_DATA_EX( m_strFX_03.c_str(), 2, m_pOwner->GetArID(), m_pOwner->GetArID(), m_hTarget, EFFECT_POS_DAMAGE, true, SEQTYPE_NORMAL, m_fPlayRate*4.8f ) );
}
_processDefFire( dwTime );
}
DWORD eventTime = ((dwTime - m_dwStartTime) * m_fPlayRate);
_processEventSet( eventTime );
}
//==============================================================================================
SWorkBowShoot_Shove::SWorkBowShoot_Shove( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
pSkillFX->fStage_Data[0];//연타연출타입 (0,1)
pSkillFX->fStage_Data[1];//범위연출타입 (0,1)
pSkillFX->fStage_Data[2];//슈팅형 발사체FX ID
pSkillFX->fStage_Data[3];//슈팅형 발사체FX 비행속도 (-1,1~9)
pSkillFX->fStage_Data[4];//연사간격(초)
pSkillFX->fStage_Data[5];//밀려나는속도 (1~9)
SetEnd( true );
}
SWorkBowShoot_Shove::~SWorkBowShoot_Shove()
{
}
//==============================================================================================
SWorkBowShoot_Leech::SWorkBowShoot_Leech( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
pSkillFX->fStage_Data[0];//연타연출타입 (0,1)
pSkillFX->fStage_Data[1];//범위연출타입 (0,1)
pSkillFX->fStage_Data[2];//슈팅형 발사체FX ID
pSkillFX->fStage_Data[3];//슈팅형 발사체FX 비행속도 (-1,1~9)
pSkillFX->fStage_Data[4];//연사간격(초)
pSkillFX->fStage_Data[5];//흡수체생성딜레이(초)
pSkillFX->fStage_Data[6];//흡수체FX 파일명
pSkillFX->fStage_Data[7];//흡수체FX 비행스타일 (0~2)
pSkillFX->fStage_Data[8];//추가발동(회복) FX ID
pSkillFX->fStage_Data[9];//추가발동(회복) FX 위치
SetEnd( true );
}
SWorkBowShoot_Leech::~SWorkBowShoot_Leech()
{
}
//==============================================================================================
SWorkSelf::SWorkSelf( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
}
SWorkSelf::~SWorkSelf()
{
}
void SWorkSelf::Process( DWORD dwTime )
{
if( IsEnd() ) return;
SNewSkill::Process( dwTime );
}
//==============================================================================================
SWorkMotion::SWorkMotion( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
}
SWorkMotion::~SWorkMotion()
{
}
bool SWorkMotion::ProcessingDamage()
{
if( GetSkillMode() != SKILLMODE_FIRE || GetStep() != STEP_01 )
return false;
return true;
}
void SWorkMotion::Process( DWORD dwTime )
{
if( IsEnd() ) return;
m_dwTime = dwTime;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
SetEnd(true);
return;
}
_processView();
if( GetSkillMode() == SKILLMODE_CAST )
{
_processDefCast( dwTime );
}
else if( GetSkillMode() == SKILLMODE_FIRE )
{
if( GetStep() == STEP_00 )
{
if( m_pSkillEvent )
m_pOwner->AddAction( m_pSkillEvent );
}
_processDefFire( dwTime );
}
DWORD eventTime = ((dwTime - m_dwStartTime) * m_fPlayRate);
_processEventSet( eventTime );
}
//==============================================================================================
SWorkMotion_Leech::SWorkMotion_Leech( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
pSkillFX->fStage_Data[0];//흡수체생성딜레이(초)
pSkillFX->fStage_Data[1];//흡수체FX ID
pSkillFX->fStage_Data[2];//흡수체FX 비행스타일 (0~2)
pSkillFX->fStage_Data[3];//추가발동(회복) FX ID
pSkillFX->fStage_Data[4];//추가발동(회복) FX 위치
}
SWorkMotion_Leech::~SWorkMotion_Leech()
{
}
bool SWorkMotion_Leech::ProcessingDamage()
{
if( GetSkillMode() != SKILLMODE_FIRE || GetStep() != STEP_01 )
return false;
return true;
}
void SWorkMotion_Leech::Process( DWORD dwTime )
{
if( IsEnd() ) return;
m_dwTime = dwTime;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
SetEnd(true);
return;
}
_processView();
if( GetSkillMode() == SKILLMODE_CAST )
{
_processDefCast( dwTime );
}
else if( GetSkillMode() == SKILLMODE_FIRE )
{
_processDefFire( dwTime );
if( GetStep() == STEP_00 )
{
m_pOwner->AddAction( m_pSkillEvent );
}
}
DWORD eventTime = ((dwTime - m_dwStartTime) * m_fPlayRate);
_processEventSet( eventTime );
}
//==============================================================================================
SWorkMotion_SummonMotion_Leech::SWorkMotion_SummonMotion_Leech( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
pSkillFX->fStage_Data[0];//흡수체생성딜레이(초)
pSkillFX->fStage_Data[1];//흡수체FX ID
pSkillFX->fStage_Data[2];//흡수체FX 비행스타일 (0~2)
pSkillFX->fStage_Data[3];//추가발동(회복) FX ID
pSkillFX->fStage_Data[4];//추가발동(회복) FX 위치
}
SWorkMotion_SummonMotion_Leech::~SWorkMotion_SummonMotion_Leech()
{
}
void SWorkMotion_SummonMotion_Leech::Process( DWORD dwTime )
{
if( IsEnd() ) return;
SNewSkill::Process( dwTime );
_processView();
}
//==============================================================================================
SWorkMotion_FXMotion::SWorkMotion_FXMotion( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
pSkillFX->fStage_Data[0];//발동형 발사체FX ID
pSkillFX->fStage_Data[1];//발동형 발사체FX 위치
pSkillFX->fStage_Data[2];//발동형 발사체 FX 방향 랜덤처리 (0:한방향 1:랜덤방향)
pSkillFX->fStage_Data[3];//연사간격(초)
pSkillFX->fStage_Data[4];//힛트타이밍(초)
}
SWorkMotion_FXMotion::~SWorkMotion_FXMotion()
{
}
void SWorkMotion_FXMotion::Process( DWORD dwTime )
{
if( IsEnd() ) return;
SNewSkill::Process( dwTime );
_processView();
}
//==============================================================================================
SWorkMotion_FXMotionMultiple::SWorkMotion_FXMotionMultiple( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
pSkillFX->fStage_Data[0];//발동형 발사체FX ID
pSkillFX->fStage_Data[1];//발동형 발사체FX 위치
pSkillFX->fStage_Data[2];//발동형 발사체 FX 방향 랜덤처리 (0:한방향 1:랜덤방향)
pSkillFX->fStage_Data[3];//연사간격(초)
pSkillFX->fStage_Data[4];//힛트타이밍(초)
}
SWorkMotion_FXMotionMultiple::~SWorkMotion_FXMotionMultiple()
{
}
void SWorkMotion_FXMotionMultiple::Process( DWORD dwTime )
{
if( IsEnd() ) return;
SNewSkill::Process( dwTime );
_processView();
}
//==============================================================================================
SWorkShoot_FXShoot::SWorkShoot_FXShoot( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
pSkillFX->fStage_Data[0];//슈팅형 발사체FX ID
pSkillFX->fStage_Data[1];//슈팅형 발사체 비행 타입 (0~)
pSkillFX->fStage_Data[2];//슈팅형 발사체 비행속도 (1~9)
pSkillFX->fStage_Data[3];//슈팅형 발사체 비행 가속 (0~9)
pSkillFX->fStage_Data[4];//연사간격(초)
}
SWorkShoot_FXShoot::~SWorkShoot_FXShoot()
{
}
void SWorkShoot_FXShoot::Process( DWORD dwTime )
{
if( IsEnd() ) return;
SNewSkill::Process( dwTime );
_processView();
}
//==============================================================================================
SWorkShoot_FXShootMultiple::SWorkShoot_FXShootMultiple( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
pSkillFX->fStage_Data[0];//슈팅형 발사체FX ID
pSkillFX->fStage_Data[1];//슈팅형 발사체 비행 타입 (0~)
pSkillFX->fStage_Data[2];//슈팅형 발사체 비행속도 (1~9)
pSkillFX->fStage_Data[3];//슈팅형 발사체 비행 가속 (0~9)
pSkillFX->fStage_Data[4];//연사간격(초)
}
SWorkShoot_FXShootMultiple::~SWorkShoot_FXShootMultiple()
{
}
void SWorkShoot_FXShootMultiple::Process( DWORD dwTime )
{
if( IsEnd() ) return;
SNewSkill::Process( dwTime );
_processView();
}
//==============================================================================================
SWorkShoot_FXShootPenetrate::SWorkShoot_FXShootPenetrate( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
pSkillFX->fStage_Data[0];//슈팅형 발사체FX ID
pSkillFX->fStage_Data[1];//슈팅형 발사체 비행 타입 (0~)
pSkillFX->fStage_Data[2];//슈팅형 발사체 비행속도 (1~9)
pSkillFX->fStage_Data[3];//슈팅형 발사체 비행 가속 (0~9)
pSkillFX->fStage_Data[4];//연사간격(초)
}
SWorkShoot_FXShootPenetrate::~SWorkShoot_FXShootPenetrate()
{
}
void SWorkShoot_FXShootPenetrate::Process( DWORD dwTime )
{
if( IsEnd() ) return;
SNewSkill::Process( dwTime );
_processView();
}
/// 2011.03.23 - prodongi
//==============================================================================================
SWorkShoot_FXShootChain::SWorkShoot_FXShootChain( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
pSkillFX->fStage_Data[0];//슈팅형 발사체FX ID
pSkillFX->fStage_Data[1];//슈팅형 발사체 비행 타입 (0~)
pSkillFX->fStage_Data[2];//슈팅형 발사체 비행속도 (1~9)
pSkillFX->fStage_Data[3];//슈팅형 발사체 비행 가속 (0~9)
pSkillFX->fStage_Data[4];//연사간격(초)
}
SWorkShoot_FXShootChain::~SWorkShoot_FXShootChain()
{
}
void SWorkShoot_FXShootChain::Process( DWORD dwTime )
{
if( IsEnd() ) return;
SNewSkill::Process( dwTime );
_processView();
}
//==============================================================================================
SWorkGround_FXContinue::SWorkGround_FXContinue( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
{
pSkillFX->fStage_Data[0];//지속발동체FX ID
}
SWorkGround_FXContinue::~SWorkGround_FXContinue()
{
}
void SWorkGround_FXContinue::Process( DWORD dwTime )
{
if( IsEnd() ) return;
SNewSkill::Process( dwTime );
_processView();
}
//==============================================================================================
//==============================================================================================
SWorkKnockBack::SWorkKnockBack( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX, const SkillResult* pSkillResult ) : SNewSkill( pOwner, pSkillFX )
{
m_pDamage = NULL;
m_hTarget = pSkillResult->damage_kb.hTarget;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
SetEnd( TRUE );
return;
}
//타겟이 이동중일경우 정지명령을 내린다
m_pTarget->SetArObjectStop();
m_nFireMotionID = pSkillFX->fStage_Data[6];
m_nFxSubHitID = pSkillFX->nHit_Fx_Set_Id;
m_nFxSubFireID = pSkillFX->nSub_Fire_Fx_Set_Id;
m_dwAddHitDelayTime = pSkillFX->nSub_Hit_Fx_OutPut_Delay * 1000;
m_dwAddFireDelayTime = pSkillFX->nFire_Fx_OutPut_Delay * 1000;
m_nFxSubHitPos = pSkillFX->nHit_Fx_Set_Position_Id;
m_nFxSubFirePos = pSkillFX->nSub_Fire_Fx_Position;
m_vKnockBackPosition = K3DVector( pSkillResult->damage_kb.x, pSkillResult->damage_kb.y, 0.0f );
m_fKnockBackSpeed = pSkillResult->damage_kb.speed;
m_pDamage = new SMSG_DAMAGE;
m_pDamage->attacker_handle = pOwner->GetArID();
m_pDamage->target_handle = m_hTarget;
m_pDamage->nDamage = pSkillResult->damage_kb.damage;
m_pDamage->flag = pSkillResult->damage_kb.flag;
m_pDamage->nHittingAdd_FxID = pSkillFX->nSub_Stage_On_Hit_Id;
m_pDamage->skillresult = *pSkillResult;
m_pDamage->nSkillID = pSkillFX->nID; /// 2011.05.16 - prodongi
SetDamageDisplayName( m_pDamage, m_pTarget );
SetStep( STEP_00 );
}
SWorkKnockBack::~SWorkKnockBack()
{
SAFE_DELETE( m_pDamage );
}
bool SWorkKnockBack::ProcessingDamage()
{
if( GetStep() != STEP_02 )
return false;
return true;
}
void SWorkKnockBack::Process( DWORD dwTime )
{
if( IsEnd() ) return;
// Fraun performance tweak
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
SetEnd( TRUE );
return;
}
int nStep = GetStep();
switch (nStep)
{
case STEP_00:
{
if (m_nFireMotionID != 0)
{
m_pOwner->NPlayAnimation(m_nFireMotionID);
_getEventSet();
}
if (m_pDamage)
{
m_pTarget->OnDamage(m_pOwner->GetArID(), m_hTarget, m_pDamage);
if (!(m_pDamage->flag & TS_ATTACK_EVENT::FLAG_MISS) && m_pDamage->nDamage > 0)
{
_addFX(m_pSkillFX->nStage_Type_Id);
if (m_pTarget->GetHP() > 0)
{
m_pTarget->SetAniLock(false);
m_pTarget->NPlayAnimation(ANI_DAMAGE01, SEQTYPE_LOOP);
}
m_pTarget->Damage();
// Removed FX in case of performance
//std::string strScript;
//XStringUtil::Format( strScript, "%s( %u, %u, %d, %d )", "avatar_basic_hit", m_pOwner->GetArID(), m_pTarget->GetArID(),
// ( m_pDamage->flag & TS_ATTACK_EVENT::FLAG_CRITICAL ),
// ( m_pDamage->flag & TS_ATTACK_EVENT::FLAG_BLOCK ) );
//if( strScript.length() )
// LUA()->RunString( strScript.c_str() );
}
}
SetStep(STEP_01);
break;
}
case STEP_01:
{
m_pTarget->SetKnockBack(m_vKnockBackPosition, m_fKnockBackSpeed);
SetStep(STEP_02);
break;
}
case STEP_02:
{
if (!m_pOwner->IsPlaying() || m_pOwner->GetCurrAnimationID() != m_nFireMotionID)
{
m_pOwner->Default();
SetEnd(TRUE);
return;
}
break;
}
}
if( m_nFxSubHitID > 0 )
{
if( ( dwTime - m_dwStartTime ) > m_dwAddHitDelayTime )
{
_addEffect( m_pTarget->GetArID(),
m_nFxSubHitID,
m_nFxSubHitPos );
m_nFxSubHitID = -1;
}
}
if( m_nFxSubFireID > 0 )
{
if( ( dwTime - m_dwStartTime ) > m_dwAddFireDelayTime )
{
_addEffect( m_pTarget->GetArID(),
m_nFxSubFireID,
m_nFxSubFirePos );
m_nFxSubFireID = -1;
}
}
DWORD eventTime = ((dwTime - m_dwStartTime) * m_fPlayRate);
_processEventSet( eventTime );
}
//==============================================================================================
SWorkRush_Shove::SWorkRush_Shove( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX, const struct SStateInfo * pStateInfo ) : SGameWork( pOwner )
{
m_nFireMotionID = pSkillFX->fStage_Data[0]; //돌진모션 ID
m_fPlayRate = pSkillFX->fStage_Data[1] * 4.8f;//모션속도변화 (1=100%, 클수록 빨라짐)
m_pOwner->SetViewVector( pStateInfo->vTargetPos );
m_pOwner->SetAniLock( false );
m_pOwner->Rush( m_nFireMotionID, m_fPlayRate );
if( pSkillFX->fStage_Data[2] != 0 )
{
FX_DATA fx_data;
fx_data.owner = m_pOwner->GetArID();
fx_data.attack = m_pOwner->GetArID();
fx_data.target = m_pOwner->GetArID();
fx_data.nFX_ID = pSkillFX->fStage_Data[2];
fx_data.nEffPos = pSkillFX->fStage_Data[3];
m_pOwner->AddEffect( &fx_data );
}
m_pSkillFX = pSkillFX;
SetEnd( TRUE );
}
SWorkRush_Shove::~SWorkRush_Shove()
{
SAFE_DELETE( m_pSkillFX );
}
void SWorkRush_Shove::Process( DWORD dwTime )
{
if( IsEnd() ) return;
}
//==============================================================================================
//돌진공격
SChargeAttack::SChargeAttack( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX, const SkillResult* pSkillResult ) : SNewSkill( pOwner, pSkillFX )
{
m_pDamage = NULL;
m_hTarget = pSkillResult->damage.hTarget;
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
SetEnd( TRUE );
return;
}
m_nFireMotionID = pSkillFX->fStage_Data[6];
m_nFxSubHitID = pSkillFX->nHit_Fx_Set_Id;
m_nFxSubFireID = pSkillFX->nSub_Fire_Fx_Set_Id;
m_dwAddHitDelayTime = pSkillFX->nSub_Hit_Fx_OutPut_Delay * 1000;
m_dwAddFireDelayTime = pSkillFX->nFire_Fx_OutPut_Delay * 1000;
m_nFxSubHitPos = pSkillFX->nHit_Fx_Set_Position_Id;
m_nFxSubFirePos = pSkillFX->nSub_Fire_Fx_Position;
m_pDamage = new SMSG_DAMAGE;
m_pDamage->attacker_handle = pOwner->GetArID();
m_pDamage->target_handle = m_hTarget;
m_pDamage->nDamage = pSkillResult->damage.damage;
m_pDamage->flag = pSkillResult->damage.flag;
m_pDamage->nHittingAdd_FxID = pSkillFX->nSub_Stage_On_Hit_Id;
m_pDamage->skillresult = *pSkillResult;
SetDamageDisplayName( m_pDamage, m_pTarget );
SetStep( STEP_00 );
}
SChargeAttack::~SChargeAttack()
{
SAFE_DELETE( m_pDamage );
}
void SChargeAttack::Process( DWORD dwTime )
{
if( IsEnd() ) return;
// Fraun performance tweak
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
SetEnd( TRUE );
return;
}
int nStep = GetStep();
switch (nStep)
{
case STEP_00:
{
if (m_nFireMotionID != 0)
{
m_pOwner->NPlayAnimation(m_nFireMotionID);
_getEventSet();
}
if (m_pDamage)
{
m_pTarget->OnDamage(m_pOwner->GetArID(), m_hTarget, m_pDamage);
if (!(m_pDamage->flag & TS_ATTACK_EVENT::FLAG_MISS) && m_pDamage->nDamage > 0)
{
_addFX(m_pSkillFX->nStage_Type_Id);
if (m_pTarget->GetHP() > 0)
{
m_pTarget->SetAniLock(false);
m_pTarget->NPlayAnimation(ANI_DAMAGE01, SEQTYPE_LOOP);
}
m_pTarget->Damage();
// Removed FX in case of performance
//std::string strScript;
//XStringUtil::Format( strScript, "%s( %u, %u, %d, %d )", "avatar_basic_hit", m_pOwner->GetArID(), m_pTarget->GetArID(),
// (m_pDamage->flag & TS_ATTACK_EVENT::FLAG_CRITICAL),
// (m_pDamage->flag & TS_ATTACK_EVENT::FLAG_BLOCK) );
//if( strScript.length() )
// LUA()->RunString( strScript.c_str() );
}
}
SetStep(STEP_01);
break;
}
case STEP_01:
{
if (!m_pOwner->IsPlaying() || m_pOwner->GetCurrAnimationID() != m_nFireMotionID)
{
m_pOwner->Default();
SetEnd(TRUE);
return;
}
break;
}
}
if( m_nFxSubHitID > 0 )
{
if( ( dwTime - m_dwStartTime ) > m_dwAddHitDelayTime )
{
_addEffect( m_pTarget->GetArID(),
m_nFxSubHitID,
m_nFxSubHitPos );
m_nFxSubHitID = -1;
}
}
if( m_nFxSubFireID > 0 )
{
if( ( dwTime - m_dwStartTime ) > m_dwAddFireDelayTime )
{
_addEffect( m_pTarget->GetArID(),
m_nFxSubFireID,
m_nFxSubFirePos );
m_nFxSubFireID = -1;
}
}
DWORD eventTime = ((dwTime - m_dwStartTime) * m_fPlayRate);
_processEventSet( eventTime );
}
bool SChargeAttack::ProcessingDamage()
{
if( GetStep() != STEP_01 )
return false;
return true;
}
//==============================================================================================
//타기
SWorkMount::SWorkMount( class SGameAvatarEx * pOwner, AR_HANDLE hTarger ) : SGameWork( pOwner )
, m_pCreature( NULL )
{
m_hCreatrue = hTarger;
m_dwOldTime = 0;
/// 2011.09.06 바로 탑승하도록 수정 - prodongi
//SetStep( STEP_00 );
SetStep( STEP_01 );
}
SWorkMount::~SWorkMount()
{
if( m_pOwner )
{
m_pCreature = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hCreatrue );
if( m_pCreature )
{
m_pOwner->SetRiderCreatureInfo( &SGameAvatarEx::RiderCreatureInfo( m_hCreatrue, EFFECT_POS_SADDLE, m_pCreature->GetCreatureMountType() ) );
m_pOwner->SetMountMode();
m_pCreature->SetMountMode();
}
else
{
m_pOwner->SetRiderCreatureInfo( &SGameAvatarEx::RiderCreatureInfo( m_hCreatrue, EFFECT_POS_SADDLE ) );
}
}
}
void SWorkMount::Process( DWORD dwTime )
{
if( IsEnd() ) return;
// Fraun performance tweak
if( m_dwOldTime == 0 ) m_dwOldTime = dwTime;
m_pCreature = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hCreatrue );
int nStep = GetStep();
switch (nStep)
{
case STEP_00:
{
// If movement occurs with the mount motion in Step 0, immediately switch to Step 1 (this can happen to other players)
if (m_pOwner->IsMoving() && (m_pOwner->CurrentlyAnimationIsMWalk() || m_pOwner->CurrentlyAnimationIsMRun())) // sonador #2.1.6
{
SetStep(STEP_01);
return;
}
// If movement to the position sent by the server has finished…
if (!m_pOwner->IsMoving())
{
m_pOwner->SetMotionBlend(false);
m_pOwner->SetIng(true);
if (m_pCreature)
{
int nAniType;
switch (m_pCreature->GetCreatureMountType())
{
case SGameAvatarEx::RIDE_HIGH_TYPE:
nAniType = ANI_M_MOUNT_HIGH;
break;
case SGameAvatarEx::RIDE_LOW_TYPE:
nAniType = ANI_M_MOUNT_LOW;
break;
case SGameAvatarEx::RIDE_WHITE_TYPE:
nAniType = ANI_M_MOUNT01_WHITE;
break;
case SGameAvatarEx::RIDE_UNICORN_TYPE:
nAniType = ANI_M_MOUNT01_UNICORN;
break;
default:
nAniType = ANI_M_MOUNT_HIGH;
break;
}
m_pOwner->SetAniLock(false);
m_pOwner->NPlayAnimation(nAniType);
m_pOwner->SetAniLock(true);
// Rotate the creature to face the player
m_pCreature->SetViewVectorForMount(m_pOwner->GetViewVector());
m_pCreature->SetIng(true);
m_pCreature->SetAniLock(false);
m_pCreature->NPlayAnimation(nAniType);
m_pCreature->SetAniLock(true);
}
SetStep(STEP_01);
}
break;
}
case STEP_01:
{
// Has the mounting animation finished?
// If movement occurs before the mounting animation finishes, link immediately
// (this can happen for other players as well)
// If the mounting animation differs from the currently playing animation, link immediately
if (!m_pOwner->IsPlaying() || m_pOwner->IsMoving() || !m_pOwner->CurrentlyAnimationIsMount())
{
m_pOwner->SetIng(false);
m_pOwner->SetAniLock(false);
if (m_pCreature)
{
m_pOwner->SetRiderCreatureInfo(&SGameAvatarEx::RiderCreatureInfo(m_hCreatrue, EFFECT_POS_SADDLE, m_pCreature->GetCreatureMountType()));
// 2011.09.06 Modified to mount immediately prodongi
m_pOwner->SetMotionBlend(false);
if (m_pOwner->IsMoving()) m_pOwner->NPlayAnimation( m_pOwner->GetPlayerMRunAniID(), SEQTYPE_LOOP );
else m_pOwner->NPlayAnimation( m_pOwner->GetPlayerMDefAniID(), SEQTYPE_LOOP );
m_pCreature->SetIng(false);
m_pCreature->SetAniLock(false);
m_pCreature->StandingDegree();
m_pCreature->SetViewVectorForMount(m_pOwner->GetViewVector());
if (m_pCreature->IsMoving()) m_pCreature->NPlayAnimation( ANI_RUN, SEQTYPE_LOOP );
else m_pCreature->NPlayAnimation( ANI_DEFAULT01, SEQTYPE_LOOP );
// 2011.09.06 Play mount effect prodongi
// Normally, the effect ID should be obtained from the riding persistent effect,
// but since mount-type creatures dont have related persistent effects, it is hardcoded.
FX_DATA fxdata;
fxdata.nFX_ID = 18015;
fxdata.nEffPos = EFFECT_POS_BOTTOM;
fxdata.owner = m_pOwner->GetArID();
fxdata.attack = m_pOwner->GetArID();
fxdata.target = m_pOwner->GetArID();
fxdata.fPlayRate = 4.8f;
fxdata.nPlayID = 0;//한번
fxdata.nMode = 0;//기본
m_pOwner->AddEffect(&fxdata);
}
SetStep(STEP_02);
}
break;
}
case STEP_02:
{
// 2011.09.06 Modified so that mounting happens immediately prodongi
SetEnd(TRUE);
return;
break;
}
}
// If 10 seconds have passed and its still in Step 0, immediately link and finish it
if( dwTime - m_dwOldTime > 10000 && nStep == STEP_00 )
{
m_pOwner->SetIng( false );
m_pOwner->SetAniLock( false );
if( m_pCreature )
{
m_pOwner->SetRiderCreatureInfo( &SGameAvatarEx::RiderCreatureInfo( m_hCreatrue, EFFECT_POS_SADDLE, m_pCreature->GetCreatureMountType() ) );
m_pCreature->SetIng( false );
m_pCreature->SetAniLock( false );
m_pCreature->StandingDegree();
if( m_pOwner->IsMoving() ) m_pOwner->NPlayAnimation( m_pOwner->GetPlayerMRunAniID(), SEQTYPE_LOOP );
else m_pOwner->NPlayAnimation( m_pOwner->GetPlayerMDefAniID(), SEQTYPE_LOOP );
if( m_pCreature->IsMoving() ) m_pCreature->NPlayAnimation( ANI_RUN, SEQTYPE_LOOP );
else m_pCreature->NPlayAnimation( ANI_DEFAULT01, SEQTYPE_LOOP );
}
SetStep( STEP_02 );
}
}
//==============================================================================================
// Dismount
SWorkUnMount::SWorkUnMount( class SGameAvatarEx * pOwner, AR_HANDLE hTarger, char Flag ) : SGameWork( pOwner )
, m_pCreature( NULL )
{
m_hCreatrue = hTarger;
m_Flag = Flag;
m_dwOldTime = 0;
SetStep( STEP_01 );
}
SWorkUnMount::~SWorkUnMount()
{
if( m_pOwner )
{
m_pOwner->SetRiderCreatureInfo();
m_pOwner->SetDefaultView();
m_pOwner->SetNormalMode();
m_pCreature = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hCreatrue );
if( m_pCreature )
{
m_pCreature->SetNormalMode();
}
}
}
void SWorkUnMount::Process( DWORD dwTime )
{
if( IsEnd() ) return;
// Fraun performance tweak
if( m_dwOldTime == 0 ) m_dwOldTime = dwTime;
m_pCreature = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hCreatrue );
int nStep = GetStep();
switch (nStep)
{
case STEP_00:
{
// When the character falls off the creature or SP reaches 0 and the creature is summoned
switch (m_Flag)
{
case TS_SC_UNMOUNT_SUMMON::FALL:
case TS_SC_UNMOUNT_SUMMON::UNSUMMON:
{
m_pOwner->NPlayAnimation(ANI_DEFAULT01, SEQTYPE_LOOP); // t needs to be changed to a stun motion
// Unlink
m_pOwner->SetRiderCreatureInfo();
m_pOwner->SetIng(false);
m_pOwner->SetMotionBlend(true);
m_pOwner->SetAniLock(false);
m_pOwner->UnMountFallUnSummon();
if (m_pCreature)
{
m_pCreature->SetIng(false);
m_pCreature->SetAniLock(false);
m_pCreature->Default();
m_pCreature->SetBestPosition(); // Moving the creature
m_pCreature->UnMountFallUnSummon();
}
SetEnd(TRUE);
break;
}
case TS_SC_UNMOUNT_SUMMON::NORMAL:
{
if (!m_pOwner->IsMoving()) // The animation must play while in a standing state
{
m_pOwner->SetRiderCreatureInfo(); // Unlink
m_pOwner->SetIng(true); // It is in the process of descending
m_pOwner->SetMotionBlend(false); // Disable motion interpolation
if (m_pCreature)
{
int nAniType;
switch (m_pCreature->GetCreatureMountType())
{
case SGameAvatarEx::RIDE_HIGH_TYPE:
nAniType = ANI_M_UNMOUNT_HIGH;
break;
case SGameAvatarEx::RIDE_LOW_TYPE:
nAniType = ANI_M_UNMOUNT_LOW;
break;
case SGameAvatarEx::RIDE_WHITE_TYPE:
nAniType = ANI_M_UNMOUNT01_WHITE;
break;
case SGameAvatarEx::RIDE_UNICORN_TYPE:
nAniType = ANI_M_UNMOUNT01_UNICORN;
break;
default:
nAniType = ANI_M_UNMOUNT_HIGH;
break;
}
m_pCreature->SetIng(true);
m_pOwner->SetAniLock(false);
m_pOwner->NPlayAnimation(nAniType);
m_pOwner->SetAniLock(true);
m_pCreature->SetAniLock(false);
m_pCreature->NPlayAnimation(nAniType);
m_pCreature->SetAniLock(true);
}
SetStep(STEP_01);
}
else
{
m_pOwner->SetRiderCreatureInfo();
m_pOwner->SetIng(false);
m_pOwner->SetAniLock(false);
m_pOwner->Default();
if (m_pCreature)
{
m_pCreature->SetIng(false);
m_pCreature->SetAniLock(false);
m_pCreature->SetBestPosition(); //Moving the creature
m_pCreature->Default();
}
SetEnd(TRUE); // If moving, immediately disconnect the link (it must not descend while moving).
}
break;
}
}
break;
}
case STEP_01:
{
// If the descending motion has finished
// If movement occurred even though the descending animation hasnt finished, switch to the default animation
// (other players might see the character standing up)
// If the descending animation and the currently playing animation are different, switch to the default animation
m_pOwner->SetIng(false);
m_pOwner->SetMotionBlend(true);
m_pOwner->SetAniLock(false);
if (m_pOwner->IsMoving()) m_pOwner->Run();
else m_pOwner->Default();
if (m_pCreature)
{
m_pCreature->SetIng(false);
m_pCreature->SetAniLock(false);
if (m_pCreature->IsMoving()) m_pCreature->Run();
else m_pCreature->Default();
m_pCreature->SetBestPosition(); // Moving the creature
/// 2011.09.06 탑승 이펙트 출력 - prodongi
/// 원래는 이펙트 id를 라이딩 지속효과에서 갖고 와야 되나, 탑승형 크리처는 관련된 지속효과가 없기 때문에, 하드코딩으로 해줌
FX_DATA fxdata;
fxdata.nFX_ID = 18015;
fxdata.nEffPos = EFFECT_POS_BOTTOM;
fxdata.owner = m_pOwner->GetArID();
fxdata.attack = m_pOwner->GetArID();
fxdata.target = m_pOwner->GetArID();
fxdata.fPlayRate = 4.8f;
fxdata.nPlayID = 0; // Once
fxdata.nMode = 0; // Default
m_pOwner->AddEffect(&fxdata);
}
SetEnd(TRUE);
}
}
// If 10 seconds have passed and its still stuck at step 0, immediately switch to step 1
if( dwTime - m_dwOldTime > 10000 && nStep == STEP_00 )
{
m_pOwner->SetRiderCreatureInfo();
m_pOwner->SetIng( false );
m_pOwner->SetAniLock( false );
m_pOwner->Default();
if( m_pCreature )
{
m_pCreature->SetIng( false );
m_pCreature->SetAniLock( false );
m_pCreature->SetBestPosition();
m_pCreature->Default();
}
SetEnd( TRUE );
}
}
//==============================================================================================
//애니 없이 타기
SWorkMountWithOutAnimation::SWorkMountWithOutAnimation( class SGameAvatarEx * pOwner, AR_HANDLE hTarger, int nFXID, int nFXPos ) : SGameWork( pOwner )
, m_hCreatrue( hTarger )
, m_nFXID( nFXID )
, m_nFXPos( nFXPos )
, m_pCreature( NULL )
{
SetStep( STEP_00 );
}
SWorkMountWithOutAnimation::~SWorkMountWithOutAnimation()
{
if( m_pOwner )
{
m_pOwner->SetMotionBlend( true );
m_pCreature = (SGameAvatarEx*)m_pOwner->GetGameTransportCreatureObject( m_hCreatrue ); // sonador #2.1.6 크리쳐 기린(spirit_qilin) 테스트
if( m_pCreature )
{
m_pOwner->SetRiderCreatureInfo( &SGameAvatarEx::RiderCreatureInfo( m_hCreatrue, EFFECT_POS_SADDLE, m_pCreature->GetCreatureMountType(), true ) );
m_pOwner->SetMountMode();
m_pCreature->SetVisibility( 1.0f );
m_pCreature->SetMountMode();
}
else
m_pOwner->SetRiderCreatureInfo( &SGameAvatarEx::RiderCreatureInfo( m_hCreatrue, EFFECT_POS_SADDLE, 2, true ) );
}
}
void SWorkMountWithOutAnimation::Process( DWORD dwTime )
{
if( IsEnd() ) return;
m_pCreature = (SGameAvatarEx*)m_pOwner->GetGameTransportCreatureObject( m_hCreatrue );
if( m_pCreature == NULL ) return;
int nStep = GetStep();
if( nStep == STEP_00 )
{
if( m_pCreature->IsInit() && m_pCreature->Activate() )
{
// sonador #2.1.6
m_pOwner->SetRiderCreatureInfo( &SGameAvatarEx::RiderCreatureInfo( m_hCreatrue, EFFECT_POS_SADDLE, m_pCreature->GetCreatureMountType(), true ) );
int nRunAniType = m_pOwner->GetPlayerMRunAniID();
int nDefaultAniType = m_pOwner->GetPlayerMDefAniID();
m_pOwner->SetMotionBlend( false );
if( m_pOwner->IsMoving() ) m_pOwner->NPlayAnimation( nRunAniType, SEQTYPE_LOOP );
else m_pOwner->NPlayAnimation( nDefaultAniType, SEQTYPE_LOOP );
//크리처를 플레이어 방향으로 돌리자
m_pCreature->StandingDegree();
m_pCreature->SetViewVectorForMount( m_pOwner->GetViewVector() );
if( m_pOwner->IsMoving() ) m_pCreature->NPlayAnimation( ANI_RUN, SEQTYPE_LOOP );
else m_pCreature->NPlayAnimation( ANI_DEFAULT01, SEQTYPE_LOOP );
m_pCreature->SetViewVectorStateIdle( K3DVector( 0.0f, 0.0f, 0.0f ) );
m_pCreature->SetVisibility( 1.0f );
m_pOwner->SetMountMode();
m_pCreature->SetMountMode();
if( m_nFXID != 0 )
{
FX_DATA fxdata;
fxdata.nFX_ID = m_nFXID;
fxdata.nEffPos = m_nFXPos;
fxdata.owner = m_pOwner->GetArID();
fxdata.attack = m_pOwner->GetArID();
fxdata.target = m_pOwner->GetArID();
fxdata.fPlayRate = 4.8f;
fxdata.nPlayID = 0;//한번
fxdata.nMode = 0;//기본
m_pOwner->AddEffect( &fxdata );
}
SetEnd( TRUE );
}
}
}
//==============================================================================================
//애니 없이 내리기
SWorkUnMountWithOutAnimation::SWorkUnMountWithOutAnimation( class SGameAvatarEx * pOwner, AR_HANDLE hTarger, int nFXID, int nFXPos ) : SGameWork( pOwner )
, m_nFXID( nFXID )
, m_nFXPos( nFXPos )
, m_pCreature( NULL )
{
m_pOwner->SetMotionBlend( false );
m_pOwner->SetNormalMode();
m_pOwner->SetRiderCreatureInfo();
m_pOwner->SetDefaultView();
if( m_pOwner->IsMoving() )
m_pOwner->Run();
else
m_pOwner->Default();
FX_DATA fxdata;
fxdata.nFX_ID = m_nFXID;
fxdata.nEffPos = m_nFXPos;
fxdata.owner = m_pOwner->GetArID();
fxdata.attack = m_pOwner->GetArID();
fxdata.target = m_pOwner->GetArID();
fxdata.fPlayRate = 4.8f;
fxdata.nPlayID = 0;//한번
fxdata.nMode = 0;//기본
m_pOwner->AddEffect( &fxdata );
SetEnd( TRUE );
}
SWorkUnMountWithOutAnimation::~SWorkUnMountWithOutAnimation()
{
if( m_pOwner )
{
m_pOwner->SetMotionBlend( true );
m_pOwner->SetNormalMode();
}
}
void SWorkUnMountWithOutAnimation::Process( DWORD dwTime )
{
/* if( IsEnd() == false )
{
m_pOwner->SetMotionBlend( true );
m_pOwner->SetNormalMode();
SetEnd( TRUE );
}*/
}
//==============================================================================================
//광역 공격
SWorkMultiAttack::SWorkMultiAttack( class SGameAvatarEx * pOwner ) : SGameWork( pOwner )
, m_vStartDir( K3DVector( 0.0f, 0.0f, 0.0f ) )
, m_dwOldTime( 0 )
, m_dwRotationTime( 300 )
, m_fCheckAngle( 0.95f )
{
m_fRangeAngle = K3D_PI*2.0f; //범위 각도
}
SWorkMultiAttack::~SWorkMultiAttack()
{
if( m_pOwner )
{
std::vector< TargetInfo >::iterator iter = m_vTargetInfo.begin();
for( ; iter != m_vTargetInfo.end(); ++iter )
{
//처리가 안된넘들 체크
SGameAvatarEx* pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( (*iter).hTarget );
if( pTarget )
{
//데미지 처리
pTarget->NPlayAnimation( ANI_DAMAGE01 );
}
}
}
m_vTargetInfo.clear();
}
void SWorkMultiAttack::SetTargetList( std::vector< AR_HANDLE > & vTargetList )
{
std::vector< AR_HANDLE >::iterator iter = vTargetList.begin();
for( ; iter != vTargetList.end(); ++iter )
{
TargetInfo target( (*iter) );
m_vTargetInfo.push_back( target );
}
}
void SWorkMultiAttack::Process( DWORD dwTime )
{
if( m_dwOldTime == 0 ) m_dwOldTime = dwTime;
int nStep = GetStep();
if( nStep == STEP_00 )
{
K3DVector vView = m_pOwner->GetViewVector();
K3DVector vUp = K3DVector( 0.0f, 0.0f, 1.0f );
m_vStartDir = CrossProduct( vView, vUp );
//타겟 정리
std::vector< TargetInfo >::iterator iter = m_vTargetInfo.begin();
for( ; iter != m_vTargetInfo.end(); ++iter )
{
SGameAvatarEx* pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( (*iter).hTarget );
if( pTarget )
{
K3DVector vTarget;
vTarget.x = pTarget->GetPosition()->x - m_pOwner->GetPosition()->x;
vTarget.y = pTarget->GetPosition()->y - m_pOwner->GetPosition()->y;
vTarget.z = 0.0f;
K3DVectorNormalize( vTarget, vTarget );
K3DVector vCross = CrossProduct( m_vStartDir, vTarget );
if( vCross.z >= 0.0f )
{
(*iter).bCheckDamage = true;
}
}
}
m_pOwner->NPlayAnimation( ANI_ATTACK01 );
SetStep( STEP_01 );
}
else if( nStep == STEP_01 )
{
float fRotation = 0.0f;
if( (dwTime - m_dwOldTime) <= m_dwRotationTime )
{
float fGap = (float)(dwTime - m_dwOldTime) / m_dwRotationTime;
fRotation = m_fRangeAngle * fGap;
}
else
{
fRotation = m_fRangeAngle;
SetEnd( true );
}
K3DMatrix matResult, matRot, matTrans;
K3DMatrixRotationZ( matRot, fRotation );
K3DMatrixTranslation( matTrans, m_vStartDir.x, m_vStartDir.y, m_vStartDir.z );
K3DMatrixMultiply( matResult, matTrans, matRot );
K3DVector vOut( matResult._41, matResult._42, matResult._43 );
K3DVectorNormalize( vOut, vOut );
std::vector< TargetInfo >::iterator iter = m_vTargetInfo.begin();
for( ; iter != m_vTargetInfo.end(); )
{
SGameAvatarEx* pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( (*iter).hTarget );
if( pTarget )
{
K3DVector vTarget;
vTarget.x = pTarget->GetPosition()->x - m_pOwner->GetPosition()->x;
vTarget.y = pTarget->GetPosition()->y - m_pOwner->GetPosition()->y;
vTarget.z = 0.0f;
K3DVectorNormalize( vTarget, vTarget );
if( CheckCrash( vOut, vTarget ) )
{
//데미지 처리
pTarget->NPlayAnimation( ANI_DAMAGE01 );
iter = m_vTargetInfo.erase( iter );
}
else
{
K3DVector vCross = CrossProduct( vOut, vTarget );
if( (*iter).bCheckDamage )
{
if( vCross.z <= 0.0f )
{
//데미지 처리
pTarget->NPlayAnimation( ANI_DAMAGE01 );
iter = m_vTargetInfo.erase( iter );
continue;
}
}
else
{
if( vCross.z >= 0.0f )
{
(*iter).bCheckDamage = true;
}
}
++iter;
}
}
else
{
iter = m_vTargetInfo.erase( iter );
}
}
if( m_vTargetInfo.empty() )
SetEnd( true );
}
}
bool SWorkMultiAttack::CheckCrash( const K3DVector & vView, const K3DVector & vTarget )
{
float fDot = DotProduct( vView, vTarget );
if( fDot >= m_fCheckAngle )
{
return true;
}
return false;
}
//==============================================================================================
//노동기술
SWorkingSkill::SWorkingSkill( class SGameAvatarEx * pOwner, _SKILL_FX* pSkillFX ) : SNewSkill( pOwner, pSkillFX )
, m_szSwapWeaponName( NULL )
, m_bHideWeapon( false )
{
_MOTION_FX_SET* pFxSet = GetMotionFxSetDB().GetFXSet( pSkillFX->fStage_Data[0] );
if( pFxSet )
{
m_szSwapWeaponName = GetResourceDB().GetEffectResourceName( pFxSet->graphic_effect_start_file_ID );
}
else
{
if( pSkillFX->fStage_Data[1] != 0 )
{
m_bHideWeapon = true;
}
}
}
SWorkingSkill::~SWorkingSkill()
{
}
void SWorkingSkill::CastCancel()
{
ForceEnd();
if( GetSkillMode() == SKILLMODE_CAST )
{
HideNSwapWeapon();
}
}
bool SWorkingSkill::ProcessingDamage()
{
return false;
}
void SWorkingSkill::Process( DWORD dwTime )
{
m_dwTime = dwTime;
if( IsEnd() ) return;
// Fraun performance tweak
m_pTarget = (SGameAvatarEx*)m_pOwner->GetGameObject( m_hTarget );
if( !m_pTarget )
{
HideNSwapWeapon();
m_pOwner->Default();
SetEnd(true);
return;
}
int nSkillMode = GetSkillMode();
switch (nSkillMode)
{
case SKILLMODE_CAST:
{
int nStep = GetStep();
switch (nStep)
{
case STEP_00:
{
if (m_bHideWeapon)
{
m_pOwner->HideWeapon(FALSE);
}
else
{
if (m_szSwapWeaponName != NULL)
{
m_pOwner->AddMeshPart(ANIPART_WEAPON_LEFT, MPART_L_WEAPON, "");
m_pOwner->AddMeshPart(ANIPART_WEAPON_RIGHT, MPART_R_WEAPON, m_szSwapWeaponName);
}
}
_processDefCast(dwTime);
break;
}
}
break;
}
case SKILLMODE_FIRE:
{
int nStep = GetStep();
switch (nStep)
{
case STEP_00:
{
if (m_nFireMotionID != 0)
{
bool bPlayNextAnimation = false;
int nAniType = m_pOwner->GetCurrentlyAniType();
if (nAniType == SEQTYPE_NORMAL ||
nAniType == SEQTYPE_LASTPAGE ||
nAniType == SEQTYPE_REVERSE)
{
if (!m_pOwner->IsPlaying())
bPlayNextAnimation = true;
}
else
{
if (m_pOwner->CurrentlyAnimationIsLoopWrap())
bPlayNextAnimation = true;
}
if (bPlayNextAnimation)
{
m_pOwner->NPlayAnimation(m_nFireMotionID);
//시전시 동반 되는 이펙트
if (m_pSkillFX->nFire_Fx_Set_Id != 0)
_addEffect(m_pOwner->GetArID(), m_pOwner->GetArID(), m_pOwner->GetArID(), m_pSkillFX->nFire_Fx_Set_Id, EFFECT_POS_BOTTOM, SEQTYPE_NORMAL);
_getEventSet();
SetStep(STEP_01);
}
}
else
{
SetStep(STEP_01);
}
break;
}
case STEP_01:
{
if (m_nFireMotionID != 0)
{
if (m_pOwner->GetCurrAnimationID() == m_nFireMotionID && !m_pOwner->IsPlaying())
{ //시전 연출 끝났음.
SetStep(STEP_02);
}
}
else if (m_nFireMotionID == 0)
{ //시전 모션 없음.
SetStep(STEP_02);
}
break;
}
case STEP_02:
{
HideNSwapWeapon();
m_pOwner->EndUseSkill(m_pSkillFX->nID);
m_pOwner->Default();
SetEnd(TRUE);
break;
}
default:
{
if (m_pOwner->IsUseSkill_complete())
{
if (m_nFireMotionID != 0 && m_pOwner->GetCurrAnimationID() != m_nFireMotionID)
{
HideNSwapWeapon();
SetEnd(TRUE);
return;
}
}
break;
}
}
break;
}
}
DWORD eventTime = ((dwTime - m_dwStartTime) * m_fPlayRate);
_processEventSet( eventTime );
_processView();
}
void SWorkingSkill::HideNSwapWeapon()
{
if( m_bHideWeapon )
{
m_pOwner->HideWeapon( TRUE );
}
else if (m_szSwapWeaponName != NULL)
{
int nRace = m_pOwner->GetInnRace();
int nSex = m_pOwner->GetInnSex();
std::string strRightHand = GetItemDB().GetFileName(nRace, nSex, m_pOwner->GetItemCode(ItemBase::WEAR_WEAPON), m_pOwner->GetItemLevel(ItemBase::WEAR_WEAPON));
std::string strLeftHand = GetItemDB().GetFileName(nRace, nSex, m_pOwner->GetItemCode(ItemBase::WEAR_SHIELD), m_pOwner->GetItemLevel(ItemBase::WEAR_SHIELD));
strRightHand += ".nx3";
strLeftHand += ".nx3";
ItemBase::ItemClass nRItemClass = m_pOwner->GetItemClass(ItemBase::WEAR_WEAPON);
if (nRItemClass == ItemBase::CLASS_LIGHT_BOW || nRItemClass == ItemBase::CLASS_HEAVY_BOW)
{
m_pOwner->AddMeshPart(ANIPART_WEAPON_RIGHT, MPART_R_WEAPON, "");
m_pOwner->AddMeshPart(ANIPART_WEAPON_LEFT, MPART_L_WEAPON, strRightHand.c_str());
}
<<<<<<< HEAD
else if (nRItemClass == ItemBase::CLASS_CROSSBOW) //Double Crossbow
=======
// AziaMafia Double Crossbow // From ZONE source; dual crossbows
else if (nRItemClass == ItemBase::CLASS_CROSSBOW)
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
{
m_pOwner->AddMeshPart(ANIPART_WEAPON_RIGHT, MPART_R_WEAPON, strRightHand.c_str());
m_pOwner->AddMeshPart(ANIPART_WEAPON_LEFT, MPART_L_WEAPON, "");
}
else
{
m_pOwner->AddMeshPart( ANIPART_WEAPON_RIGHT, MPART_R_WEAPON, strRightHand.c_str() );
ItemBase::ItemClass nLItemClass = m_pOwner->GetItemClass( ItemBase::WEAR_SHIELD );
if( nLItemClass == ItemBase::CLASS_ONEHAND_SWORD || nLItemClass == ItemBase::CLASS_DAGGER || nLItemClass == ItemBase::CLASS_ONEHAND_AXE) // From ZONE source; dual crossbows
//if( nLItemClass == ItemBase::CLASS_ONEHAND_SWORD || nLItemClass == ItemBase::CLASS_DAGGER || nLItemClass == ItemBase::CLASS_ONEHAND_AXE || nLItemClass == ItemBase::CLASS_CROSSBOW)
{
if( strLeftHand.length() > 5 )
strLeftHand.replace( strLeftHand.size() - 4, 1, "_L." );
}
m_pOwner->AddMeshPart( ANIPART_WEAPON_LEFT, MPART_L_WEAPON, strLeftHand.c_str() );
}
m_pOwner->RefreshDeform();
}
}