931 lines
30 KiB
C++
931 lines
30 KiB
C++
#include "stdafx.h"
|
|
#include "SGameCreature.h"
|
|
|
|
#include "KSeqAvatarEx.h"
|
|
|
|
#include "SCreatureDB.h"
|
|
#include "SSkillDB.h"
|
|
|
|
//#include "Util.h"
|
|
#include "SGameAniType.h"
|
|
#include "SGameWork.h"
|
|
#include "SGameMessage.h"
|
|
#include "SSkillStageType.h"
|
|
#include "SGameUtil.h"
|
|
|
|
|
|
#include "SMonsterDB.h"
|
|
#include "SAvatarProperty.h"
|
|
|
|
#include "SDebug_Util.h"
|
|
|
|
#include "SMotionDB.h"
|
|
#include "KSeqAvatar.h"
|
|
|
|
#include "SUIChattingWnd.h"
|
|
|
|
|
|
SGameCreature::SGameCreature( ENC_INT nCreatureID, unsigned char ucEnhance )
|
|
: SGameAvatarEx(nCreatureID)
|
|
, m_dwIdleTime( 0 ) // sonaodr 1.8.13 아바타 IDLE 모션 동작 구현
|
|
, m_ucEnhance( ucEnhance ) // floyd 2010. 4. 14 크리쳐 강화
|
|
{
|
|
m_bIsUseSkill_complete = true;
|
|
m_nCreatureRideType = 0;
|
|
|
|
m_fPlayRate = DEFAULT_ANI_PLAY_RATE;
|
|
m_fStandardWalkPlayRate = DEFAULT_ANI_PLAY_RATE;
|
|
m_fStandardRunPlayRate = DEFAULT_ANI_PLAY_RATE;
|
|
m_fRdbScale = 1.0f;
|
|
m_fWalkSpeed = (float)DEF_SPEED;
|
|
|
|
_SUMMON_INFO_FILE* pSummonInfo = GetCreatureDB().GetCreatureData( nCreatureID );
|
|
if( pSummonInfo )
|
|
{
|
|
m_fStandardWalkPlayRate = (float)pSummonInfo->standard_walk_speed / 7.0f;
|
|
m_fStandardRunPlayRate = (float)pSummonInfo->standard_run_speed / 7.0f;
|
|
m_fRdbScale = pSummonInfo->scale;
|
|
m_fWalkSpeed = (float)((pSummonInfo->standard_walk_speed + pSummonInfo->standard_run_speed) / 2.0f) / 7.0f;
|
|
|
|
SetScale( pSummonInfo->scale );
|
|
}
|
|
}
|
|
|
|
SGameCreature::~SGameCreature()
|
|
{
|
|
}
|
|
|
|
void SGameCreature::OnNetInput( struct SGameMessage * pMsg )
|
|
{
|
|
if( !m_pStateVM ) return;
|
|
m_pStateVM->OnNetInput( pMsg );
|
|
}
|
|
AR_UNIT SGameCreature::GetSize()
|
|
{
|
|
// AziaMafia SKin pet
|
|
if (m_pProperty->InnContentID())
|
|
{
|
|
return GetCreatureDB().GetSize(m_pProperty->InnContentID()) ;
|
|
}
|
|
else
|
|
return GetCreatureDB().GetSize(m_pProperty->ContentID()) ;
|
|
|
|
}
|
|
AR_UNIT SGameCreature::GetScale()
|
|
{
|
|
return m_fScale; // sonador 1.8.16 크리쳐 스케일 오류 수정
|
|
}
|
|
// state
|
|
void SGameCreature::OnChangeState( SObjectState::ID stateid, const SStateInfo &info )
|
|
{
|
|
if( m_pStateVM == NULL ) return;
|
|
|
|
AR_HANDLE target = m_pStateVM->GetCurrentStateInfo().hTarget;
|
|
|
|
switch( stateid )
|
|
{
|
|
case SObjectState::STATE_IDLE :
|
|
{
|
|
if( GetCurrAnimationID() == ANI_RUN ||
|
|
GetCurrAnimationID() == ANI_WALK )
|
|
{
|
|
Default();
|
|
}
|
|
|
|
if( !IsPlaying() && ( CurrentlyAnimationIsAttack() || CurrentlyAnimationIsDamage() ) )
|
|
Default();
|
|
|
|
break; //기본 상태
|
|
}
|
|
case SObjectState::STATE_ATTACK :
|
|
{
|
|
// _oprint( "공격 상태 시간 : %d\n", m_dwTime );
|
|
|
|
SetViewVector( info.vTargetPos ); //몸통 방향 바꾸기
|
|
|
|
//일반 공격
|
|
OnAttack( info );
|
|
}
|
|
break; // 공격 (1회)
|
|
|
|
case SObjectState::STATE_MOVE :
|
|
{
|
|
if( info.dwSpeed == 0 )
|
|
{
|
|
//달리다 죽은 것이므로 Ani 처리는 스킵한다.
|
|
return;
|
|
}
|
|
|
|
//SetViewVector( info.vTargetPos );
|
|
|
|
SetAniLock( false );
|
|
if(info.dwSpeed < m_fWalkSpeed)
|
|
{
|
|
CalcCreatureWalkPlayRate( (float)info.dwSpeed );
|
|
Walk(true);
|
|
}
|
|
else
|
|
{
|
|
CalcCreatureRunPlayRate( (float)info.dwSpeed );
|
|
Run();
|
|
}
|
|
}
|
|
break; // 이동
|
|
|
|
case SObjectState::STATE_CHASE :
|
|
if( info.dwSpeed >= m_fWalkSpeed )
|
|
{
|
|
CalcCreatureRunPlayRate( (float)info.dwSpeed );
|
|
Run();
|
|
}
|
|
else
|
|
{
|
|
CalcCreatureWalkPlayRate( (float)info.dwSpeed );
|
|
Walk(true);
|
|
}
|
|
|
|
SetViewVector( info.vTargetPos );
|
|
break; // 추격
|
|
|
|
case SObjectState::STATE_MOUNT :
|
|
SetUnHold();
|
|
break;
|
|
|
|
case SObjectState::STATE_CAST :
|
|
{
|
|
//_oprint( "SKILL - SObjectState::STATE_CAST\n" );
|
|
|
|
//_oprint( "*****상태 머신 : 캐스팅\n" );
|
|
|
|
|
|
m_bIsUseSkill_complete = false;
|
|
|
|
//캐스팅 표시
|
|
if( IsLocalCreature() )
|
|
UseSkill( GetArID(), info.nSkillID, info.nSkillLv, info.dwSpeed );
|
|
|
|
//캐스팅 관련 연출 설정
|
|
//1) 애니메이션 연출 -> 설정 된 애니메이션의 이벤트 핸들 처리
|
|
//2) FX 출력
|
|
//New Process
|
|
_SKILL_FX* pSkillFXDB = GetSkillStageDB().GetSkillStageData( info.nSkillID );
|
|
|
|
if( !pSkillFXDB )
|
|
{
|
|
_oprint( "스킬 연출 데이타 없음!!! [스킬ID:%d]\n", info.nSkillID );
|
|
// assert( 0 && "스킬 연출 데이타 없음!!!" );
|
|
return;
|
|
}
|
|
|
|
_SKILL_FX* pSkillFX = new _SKILL_FX;
|
|
*pSkillFX = *pSkillFXDB;
|
|
|
|
float fRate = 1.f;
|
|
if( pSkillFX->nCasting_Type_Id != 1 && (pSkillFX->nCasting_Start_Motion_Id !=0 || pSkillFX->nCasting_Middle_Motion_Id != 0) )
|
|
{
|
|
pSkillFX->nCasting_Start_Motion_Id = 110;
|
|
pSkillFX->nCasting_Middle_Motion_Id = 111;
|
|
|
|
std::string strAniKey;
|
|
int nBoneCount = 0;
|
|
DWORD dwMinTime, dwMaxTime, totalTime;
|
|
dwMinTime = 0;
|
|
dwMaxTime = 0;
|
|
totalTime = 0;
|
|
|
|
if( pSkillFX->nCasting_Start_Motion_Id != 0 )
|
|
{
|
|
strAniKey = GetAniKey( GetObjType(), pSkillFX->nCasting_Start_Motion_Id, true );
|
|
if( m_pSeqAvatar )
|
|
m_pSeqAvatar->GetFrameInfo( ANIPART_BIPED, strAniKey.c_str(), nBoneCount, dwMinTime, dwMaxTime );
|
|
|
|
totalTime = dwMaxTime;
|
|
}
|
|
|
|
if( pSkillFX->nCasting_Middle_Motion_Id )
|
|
{
|
|
strAniKey = GetAniKey( GetObjType(), pSkillFX->nCasting_Middle_Motion_Id, true );
|
|
if( m_pSeqAvatar )
|
|
m_pSeqAvatar->GetFrameInfo( ANIPART_BIPED, strAniKey.c_str(), nBoneCount, dwMinTime, dwMaxTime );
|
|
|
|
totalTime += dwMaxTime;
|
|
}
|
|
|
|
float fAttack = GetAttackSpeed( info.dwSpeed*10 );
|
|
//기본 배율
|
|
fRate = GetAniPlayRate( fAttack, totalTime, false );
|
|
}
|
|
else if( pSkillFX->nCasting_Type_Id == 1 )
|
|
{
|
|
pSkillFX->nCasting_Start_Motion_Id = 70;
|
|
pSkillFX->nCasting_Middle_Motion_Id = 80;
|
|
}
|
|
|
|
//switch( pSkillFX->nCasting_Type_Id )
|
|
//{
|
|
//case _SKILL_FX::SKILLTYPE_NOACT : break;
|
|
//case _SKILL_FX::SKILLTYPE_MAGIC : break;
|
|
//case _SKILL_FX::SKILLTYPE_INSTANT : break;
|
|
//case _SKILL_FX::SKILLTYPE_INSTANT_CONTINUE : break;
|
|
//case _SKILL_FX::SKILLTYPE_CHARGE : break;
|
|
//case _SKILL_FX::SKILLTYPE_CHARGE_CONTINUE : break;
|
|
//}
|
|
|
|
//pSkillFX->nCasting_Start_Motion_Id; //시작
|
|
//pSkillFX->nCasting_Middle_Motion_Id; //시작 Loop
|
|
|
|
SNewSkill * pSkill_Cast = NULL;
|
|
SGameAvatarEx * pTarget = NULL;
|
|
|
|
if( info.hTarget )
|
|
{
|
|
pTarget = (SGameAvatarEx *)GetGameObject( info.hTarget );
|
|
}
|
|
|
|
switch( pSkillFX->nStage_Type_Id )
|
|
{
|
|
case SS_TYPE_001 : { SWorkSummonCall * pSkill = new SWorkSummonCall( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_002 : { SWorkSummonReCall * pSkill = new SWorkSummonReCall( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_101 : { SWorkWeaponSwingHit * pSkill = new SWorkWeaponSwingHit( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_111 : { SWorkShieldSwingHit * pSkill = new SWorkShieldSwingHit( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_121 : { SWorkWeaponSwing_3Motion * pSkill = new SWorkWeaponSwing_3Motion( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_122 : { SWorkWeaponSwing_ContinuousHits * pSkill = new SWorkWeaponSwing_ContinuousHits( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_123 : { SWorkWeaponSwing_Zeal * pSkill = new SWorkWeaponSwing_Zeal( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_151 : { SWorkWeaponSwing_Leech * pSkill = new SWorkWeaponSwing_Leech( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
// case SS_TYPE_171 : { //TODO : 밀기 - 서버 메세지 처리 넣어야 함. SWorkRush_Shove* pSkill = new SWorkRush_Shove( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
//// case SS_TYPE_172 : { break;
|
|
//// case SS_TYPE_173 : { break;
|
|
//// case SS_TYPE_174 : { break;
|
|
case SS_TYPE_201 : { SWorkBowShoot* pSkill = new SWorkBowShoot( this, pSkillFX ); pSkill_Cast = pSkill; fRate = 1.f; } break;
|
|
case SS_TYPE_212 : { SWorkBowShoot* pSkill = new SWorkBowShoot( this, pSkillFX ); pSkill_Cast = pSkill; fRate = 1.f; } break;
|
|
case SS_TYPE_251 : { SWorkBowShoot* pSkill = new SWorkBowShoot( this, pSkillFX ); pSkill_Cast = pSkill; fRate = 1.f; } break;
|
|
//// case SS_TYPE_211 : { break;
|
|
// case SS_TYPE_212 : { SWorkBowShoot_Shove * pSkill = new SWorkBowShoot_Shove( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
// case SS_TYPE_251 : { SWorkBowShoot_Leech * pSkill = new SWorkBowShoot_Leech( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_301 : { SWorkSelf * pSkill = new SWorkSelf( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_401 :
|
|
case SS_TYPE_404 :
|
|
{ SWorkMotion * pSkill = new SWorkMotion( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_402 : { SWorkMotion_Leech * pSkill = new SWorkMotion_Leech( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_403 : { SWorkMotion_SummonMotion_Leech * pSkill = new SWorkMotion_SummonMotion_Leech( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_411 : { SWorkMotion_FXMotion * pSkill = new SWorkMotion_FXMotion( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_412 : { SWorkMotion_FXMotionMultiple * pSkill = new SWorkMotion_FXMotionMultiple( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_501 : { SWorkShoot_FXShoot * pSkill = new SWorkShoot_FXShoot( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_502 : { SWorkShoot_FXShootMultiple * pSkill = new SWorkShoot_FXShootMultiple( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_503 : { SWorkShoot_FXShootPenetrate * pSkill = new SWorkShoot_FXShootPenetrate( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
/// 2011.03.23 - prodongi
|
|
case SS_TYPE_504 : { SWorkShoot_FXShootChain * pSkill = new SWorkShoot_FXShootChain( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
case SS_TYPE_601 : { SWorkGround_FXContinue * pSkill = new SWorkGround_FXContinue( this, pSkillFX ); pSkill_Cast = pSkill; } break;
|
|
// case SS_TYPE_602 : break;
|
|
// case SS_TYPE_603 : break;
|
|
// case SS_TYPE_701 : break;
|
|
default:
|
|
{
|
|
_oprint( "This skill is on hold. Please check with the planning team whether it should be used, and then confirm with the programming team whether it will be implemented.\n" );
|
|
// assert( 0 && "구현 보류 중인 스킬입니다.기획팀에 사용 여부를 확인 후, 프로그램 팀에 구현 여부를 확인 바랍니다.\n" );
|
|
}
|
|
break;
|
|
}
|
|
|
|
if( pSkill_Cast )
|
|
{ //변경 되었으면, PlayRate 수정
|
|
if( fRate != 1.f && pSkillFX->nCasting_Type_Id != 1 ) //마법류는 PlayRate 수정 하지 않는다.
|
|
pSkill_Cast->SetPlayRate( fRate/4.8f );
|
|
if( pTarget )
|
|
{
|
|
pSkill_Cast->SetTarget( info.hTarget, pTarget );
|
|
// 2010.05.25 - prodongi
|
|
//흡수체 스킬류
|
|
if(pSkillFX->nStage_Type_Id == SS_TYPE_402 )
|
|
{
|
|
//대상이 삭제될수 있으이 보류시킨다
|
|
pTarget->SetReservation(true);
|
|
}
|
|
}
|
|
pSkill_Cast->SetStartTime( m_dwTime );
|
|
pSkill_Cast->SetSkillMode( SNewSkill::SKILLMODE_CAST );
|
|
m_vCastSkillList.push_back( pSkill_Cast );
|
|
|
|
m_nWeaponSwing_RepeatMotion = 0;
|
|
}
|
|
else
|
|
SAFE_DELETE( pSkillFX );
|
|
|
|
break; // 캐스팅
|
|
}
|
|
case SObjectState::STATE_FIRE :
|
|
{
|
|
//_oprint( "SKILL - SObjectState::STATE_FIRE\n" );
|
|
// _oprint( "*****상태 머신 : 발사\n" );
|
|
|
|
//SkillResult가 0이면 Fire실패 Default모션으로
|
|
if(info.vSkillResult.empty())
|
|
{
|
|
m_bIsUseSkill_complete = true;
|
|
|
|
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
|
|
m_vCastSkillList[i]->ForceEnd();
|
|
|
|
SetAniLock( false );
|
|
Default();
|
|
|
|
return;
|
|
}
|
|
|
|
//New Process
|
|
//Cast 관련 사운드 끄기
|
|
//Cast 관련 이펙트 끄기
|
|
|
|
_SKILL_FX* pSkillFXDB = GetSkillStageDB().GetSkillStageData( info.nSkillID );
|
|
|
|
if( !pSkillFXDB )
|
|
{
|
|
_oprint( "스킬 연출 데이타 없음!!! [스킬ID:%d]\n", info.nSkillID );
|
|
// assert( 0 && "스킬 연출 데이타 없음!!!" );
|
|
return;
|
|
}
|
|
|
|
_SKILL_FX* pSkillFX = new _SKILL_FX;
|
|
*pSkillFX = *pSkillFXDB;
|
|
|
|
if( pSkillFX->nCasting_Type_Id == 1 )
|
|
pSkillFX->nFire_Motion_Id = 90;
|
|
else
|
|
pSkillFX->nFire_Motion_Id = 112;
|
|
|
|
|
|
SNewSkill * pSkill_Fire = NULL;
|
|
SGameAvatarEx * pTarget = NULL;
|
|
|
|
if( info.hTarget )
|
|
{
|
|
pTarget = (SGameAvatarEx *)GetGameObject( info.hTarget );
|
|
}
|
|
|
|
switch( pSkillFX->nStage_Type_Id )
|
|
{
|
|
case SS_TYPE_001 : { SWorkSummonCall * pSkill = new SWorkSummonCall( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_002 : { SWorkSummonReCall * pSkill = new SWorkSummonReCall( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_101 : { SWorkWeaponSwingHit * pSkill = new SWorkWeaponSwingHit( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_111 : { SWorkShieldSwingHit * pSkill = new SWorkShieldSwingHit( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_121 : { SWorkWeaponSwing_3Motion * pSkill = new SWorkWeaponSwing_3Motion( this, pSkillFX ); pSkill_Fire = pSkill; pSkill->SetCurHitCount( m_nWeaponSwing_RepeatMotion ); } break;
|
|
case SS_TYPE_122 : { SWorkWeaponSwing_ContinuousHits * pSkill = new SWorkWeaponSwing_ContinuousHits( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_123 : { SWorkWeaponSwing_Zeal * pSkill = new SWorkWeaponSwing_Zeal( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_151 : { SWorkWeaponSwing_Leech * pSkill = new SWorkWeaponSwing_Leech( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_171 : break; // sonador 11.0.1 돌진 스킬 연출 오류 수정
|
|
// case SS_TYPE_171 : { //TODO : 밀기 - 서버 메세지 처리 넣어야 함. SWorkRush_Shove* pSkill = new SWorkRush_Shove( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
// case SS_TYPE_172 : { break;
|
|
// case SS_TYPE_173 : { break;
|
|
// case SS_TYPE_174 : { break;
|
|
case SS_TYPE_201 : { SWorkBowShoot* pSkill = new SWorkBowShoot( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_212 : { SWorkBowShoot* pSkill = new SWorkBowShoot( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_251 : { SWorkBowShoot* pSkill = new SWorkBowShoot( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
// case SS_TYPE_211 : { break;
|
|
// case SS_TYPE_212 : { SWorkBowShoot_Shove * pSkill = new SWorkBowShoot_Shove( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
// case SS_TYPE_251 : { SWorkBowShoot_Leech * pSkill = new SWorkBowShoot_Leech( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_301 : { SWorkSelf * pSkill = new SWorkSelf( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_401 :
|
|
case SS_TYPE_404 :
|
|
{ SWorkMotion * pSkill = new SWorkMotion( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_402 : { SWorkMotion_Leech * pSkill = new SWorkMotion_Leech( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_403 : { SWorkMotion_SummonMotion_Leech * pSkill = new SWorkMotion_SummonMotion_Leech( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_411 : { SWorkMotion_FXMotion * pSkill = new SWorkMotion_FXMotion( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_412 : { SWorkMotion_FXMotionMultiple * pSkill = new SWorkMotion_FXMotionMultiple( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_501 : { SWorkShoot_FXShoot * pSkill = new SWorkShoot_FXShoot( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_502 : { SWorkShoot_FXShootMultiple * pSkill = new SWorkShoot_FXShootMultiple( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_503 : { SWorkShoot_FXShootPenetrate * pSkill = new SWorkShoot_FXShootPenetrate( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
/// 2011.03.23 - prodongi
|
|
case SS_TYPE_504 : { SWorkShoot_FXShootChain * pSkill = new SWorkShoot_FXShootChain( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
case SS_TYPE_601 : { SWorkGround_FXContinue * pSkill = new SWorkGround_FXContinue( this, pSkillFX ); pSkill_Fire = pSkill; } break;
|
|
// case SS_TYPE_602 : break;
|
|
// case SS_TYPE_603 : break;
|
|
// case SS_TYPE_701 : break;
|
|
default:
|
|
{
|
|
_oprint( "구현 보류 중인 스킬입니다.기획팀에 사용 여부를 확인 후, 프로그램 팀에 구현 여부를 확인 바랍니다.\n" );
|
|
// assert( 0 && "구현 보류 중인 스킬입니다.기획팀에 사용 여부를 확인 후, 프로그램 팀에 구현 여부를 확인 바랍니다.\n" );
|
|
|
|
SAFE_DELETE( pSkillFX );
|
|
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if( pSkillFX->nStage_Type_Id == SS_TYPE_121 )
|
|
{
|
|
//최대 연타 수 ( DB에 정의됨 )
|
|
if( m_nWeaponSwing_RepeatMotion < pSkillFXDB->fStage_Data[9] )
|
|
++m_nWeaponSwing_RepeatMotion;
|
|
else
|
|
m_nWeaponSwing_RepeatMotion = 0;
|
|
}
|
|
else
|
|
m_nWeaponSwing_RepeatMotion = 0;
|
|
|
|
if( pSkill_Fire )
|
|
{
|
|
//SAction에서 데미지 처리하고 있기 때문에 데미지 표시가 2번뜬다
|
|
switch( pSkillFX->nStage_Type_Id )
|
|
{
|
|
case SS_TYPE_001 :
|
|
case SS_TYPE_002 :
|
|
case SS_TYPE_101 :
|
|
case SS_TYPE_111 :
|
|
case SS_TYPE_121 :
|
|
case SS_TYPE_122 :
|
|
case SS_TYPE_123 : pSkill_Fire->SetDamegeInfo( &info );
|
|
break;
|
|
// AziaMAfiaSkillFix Animation
|
|
/*default:
|
|
pSkill_Fire->SetActionSkillEvent( &info );
|
|
break;*/
|
|
}
|
|
|
|
|
|
//돌고 있는 케스팅은 모두 강제 끝
|
|
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
|
|
m_vCastSkillList[i]->ForceEnd();
|
|
|
|
if( pSkillFX->nCasting_Type_Id == 1 ) //마법류 스킬이면
|
|
{
|
|
//5번 타인에게 사용하는 해로운 스킬
|
|
pSkill_Fire->SetFireMotionID( 90 ); //나쁜 스킬 설정
|
|
|
|
//1번 소환/역소환 스킬이면
|
|
if( pSkillFX->nStage_Type_Id == 1 || pSkillFX->nStage_Type_Id == 2 )
|
|
pSkill_Fire->SetFireMotionID( 94 ); //소환 스킬은 없을듯
|
|
else
|
|
{
|
|
SkillBaseEx * pSkill = GetSkillDB().GetSkillData( info.nSkillID );
|
|
if( pSkill )
|
|
{
|
|
//2번 자신에게만 주는 이로운 스킬
|
|
if( (pSkill->GetSkillTargetType() == 1 || pSkill->GetSkillTargetType() == 4 || pSkill->GetSkillTargetType() == 31 ) && info.hTarget == GetArID() )
|
|
{
|
|
pSkill_Fire->SetFireMotionID( 90 );
|
|
}
|
|
else
|
|
{
|
|
//3번 자신의 주변에 영향을 주는 스킬
|
|
if( info.hTarget == GetArID() )
|
|
pSkill_Fire->SetFireMotionID( 90 );
|
|
else
|
|
{
|
|
//4번 타인에게 사용하는 이로운 스킬
|
|
if( !pSkill->IsHarmful() )
|
|
pSkill_Fire->SetFireMotionID( 90 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( pTarget )
|
|
pSkill_Fire->SetTarget( info.hTarget, pTarget );
|
|
pSkill_Fire->SetStartTime( m_dwTime );
|
|
pSkill_Fire->SetSkillMode( SNewSkill::SKILLMODE_FIRE );
|
|
m_vFireSkillList.push_back( pSkill_Fire );
|
|
}
|
|
else
|
|
{
|
|
if( pSkillFX->nStage_Type_Id != SS_TYPE_171 )
|
|
{
|
|
SAFE_DELETE( pSkillFX );
|
|
return;
|
|
}
|
|
}
|
|
|
|
//RUSH, KNOCK_BACK, DAMAGE 처리
|
|
if( pSkillFX->nStage_Type_Id != SS_TYPE_171 ) return;
|
|
|
|
std::vector<SkillResult>::const_iterator it;
|
|
for( it = info.vSkillResult.begin(); it != info.vSkillResult.end(); it++ )
|
|
{
|
|
_SKILL_FX* ptSkillFX = new _SKILL_FX;
|
|
*ptSkillFX = *pSkillFXDB;
|
|
|
|
if( SkillResult::RUSH == (*it).GetType() )
|
|
{
|
|
if( (*it).rush.bResult )
|
|
{
|
|
SWorkRush_Shove* pRushShove = new SWorkRush_Shove( this, ptSkillFX, &info );
|
|
m_vFireSkillList.push_back( pRushShove );
|
|
return;
|
|
}
|
|
}
|
|
else if( SkillResult::DAMAGE_WITH_KNOCK_BACK == (*it).GetType() )
|
|
{
|
|
SWorkKnockBack* pWorkKnockBack = new SWorkKnockBack( this, ptSkillFX, &(*it) );
|
|
pWorkKnockBack->SetStartTime( m_dwTime );
|
|
m_vFireSkillList.push_back( pWorkKnockBack );
|
|
}
|
|
else if( SkillResult::DAMAGE == (*it).GetType() )
|
|
{
|
|
SChargeAttack* pChargerAttack = new SChargeAttack( this, ptSkillFX, &(*it) );
|
|
pChargerAttack->SetStartTime( m_dwTime );
|
|
m_vFireSkillList.push_back( pChargerAttack );
|
|
}
|
|
}
|
|
}
|
|
break; // 캐스팅
|
|
|
|
case SObjectState::STATE_SKILL_END :
|
|
{
|
|
//_oprint( "SKILL - SObjectState::STATE_SKILL_END\n" );
|
|
m_bIsUseSkill_complete = true;
|
|
|
|
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
|
|
m_vCastSkillList[i]->ForceEnd();
|
|
|
|
// for( unsigned int i(0); m_vFireSkillList.size()>i; i++ )
|
|
// m_vFireSkillList[i]->ForceEnd();
|
|
|
|
break;
|
|
}
|
|
case SObjectState::STATE_CAST_CANCEL :
|
|
{
|
|
//_oprint( "SKILL - SObjectState::STATE_CAST_CANCEL\n" );
|
|
m_bIsUseSkill_complete = true;
|
|
|
|
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
|
|
m_vCastSkillList[i]->ForceEnd();
|
|
|
|
// for( unsigned int i(0); m_vFireSkillList.size()>i; i++ )
|
|
// m_vFireSkillList[i]->ForceEnd();
|
|
|
|
Default();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SGameCreature::MotionCancel()
|
|
{
|
|
if( m_vAttackEventList.empty() && m_vCastSkillList.empty() && m_vFireSkillList.empty() )
|
|
{
|
|
m_bIsUseSkill_complete = true;
|
|
|
|
SetIng(false);
|
|
SetAniLock( false );
|
|
Default();
|
|
|
|
return true;
|
|
}
|
|
|
|
//애니메이션 진행과 상관없이 히트 후 바로 캔슬 가능
|
|
/*
|
|
int nBoneCnt = 0;
|
|
DWORD dwMinTime = 0, dwMaxTime = 0;
|
|
DWORD dwCurAniTime = 0;
|
|
GetCurrentAnimationInfo( nBoneCnt, dwMinTime, dwMaxTime, dwCurAniTime );
|
|
dwMaxTime = dwMaxTime / 160;
|
|
dwCurAniTime = (dwCurAniTime / 160) * 4.8f;
|
|
|
|
float fPlayProgress = (dwCurAniTime / (float)dwMaxTime);
|
|
//80프로 애니메이션 진행되면 모션 캔슬 가능
|
|
if( fPlayProgress < 0.13f )
|
|
return;
|
|
*/
|
|
|
|
//데미지 처리 완료했는지 체크
|
|
for( unsigned int i(0); m_vAttackEventList.size()>i; i++)
|
|
{
|
|
if( !m_vAttackEventList[i]->ProcessingDamage() )
|
|
return false;
|
|
}
|
|
|
|
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
|
|
{
|
|
if( !m_vCastSkillList[i]->ProcessingDamage() )
|
|
return false;
|
|
}
|
|
|
|
for( unsigned int i(0); m_vFireSkillList.size()>i; i++ )
|
|
{
|
|
if( !m_vFireSkillList[i]->ProcessingDamage() )
|
|
return false;
|
|
}
|
|
|
|
for( unsigned int i(0); m_vAttackEventList.size()>i; i++)
|
|
m_vAttackEventList[i]->ForceEnd();
|
|
|
|
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
|
|
m_vCastSkillList[i]->ForceEnd();
|
|
|
|
for( unsigned int i(0); m_vFireSkillList.size()>i; i++ )
|
|
m_vFireSkillList[i]->ForceEnd();
|
|
|
|
m_bIsUseSkill_complete = true;
|
|
SetIng(false);
|
|
SetAniLock( false );
|
|
Default();
|
|
|
|
return true;
|
|
}
|
|
|
|
void SGameCreature::SetMountMode()
|
|
{
|
|
if( m_pStateVM )
|
|
m_pStateVM->SetMode( SObjectStateMachine::MODE_MOUNT );
|
|
}
|
|
|
|
void SGameCreature::SetAttackMode()
|
|
{
|
|
if( m_pStateVM )
|
|
m_pStateVM->SetMode( SObjectStateMachine::MODE_ATTACK );
|
|
}
|
|
|
|
void SGameCreature::SetNormalMode()
|
|
{
|
|
if( m_pStateVM )
|
|
m_pStateVM->SetMode( SObjectStateMachine::MODE_NORMAL );
|
|
}
|
|
|
|
void SGameCreature::Damage()
|
|
{
|
|
if( _damage() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//이미 공격 중이면, 모션 플레이 안됨.
|
|
if( GetAttackAniLock() )
|
|
return;
|
|
|
|
////이동 중, 공격 중 에는 영향 안 받는다.
|
|
if( GetCurrAnimationID() == ANI_WALK ||
|
|
GetCurrAnimationID() == ANI_RUN ||
|
|
GetCurrAnimationID() == ANI_DEAD01 ) return;
|
|
|
|
if( GetCurrAnimationID() == ANI_DEFAULT01 || GetCurrAnimationID() == ANI_IDLE ) // sonaodr 1.8.13 아바타 IDLE 모션 동작 구현
|
|
NPlayAnimation( ANI_DAMAGE01, SEQTYPE_NORMAL );
|
|
|
|
if( GetCurrAnimationID() == ANI_DAMAGE01 && !IsPlaying() )
|
|
{
|
|
NPlayAnimation( ANI_DAMAGE01, SEQTYPE_NORMAL );
|
|
}
|
|
else if( GetCurrAnimationID() == ANI_DAMAGE02 && !IsPlaying() )
|
|
{
|
|
NPlayAnimation( ANI_DAMAGE02, SEQTYPE_NORMAL );
|
|
}
|
|
}
|
|
|
|
void SGameCreature::Default( bool bForce/*=false*/ )
|
|
{
|
|
// if( GetHP() <= 0 )
|
|
// return;
|
|
|
|
if( CurrentlyAnimationIsAttack() && IsPlaying() )
|
|
return;
|
|
|
|
// sonador 1.8.8 크리쳐 전투중 디폴트 모션 개선
|
|
if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_ATTACK )
|
|
{
|
|
if( GetCurrAnimationID() != ANI_DEFAULT02 )
|
|
NPlayAnimation( ANI_DEFAULT02, SEQTYPE_LOOP );
|
|
}
|
|
else if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_NORMAL )
|
|
{ //
|
|
_resetIdleTime(); // sonaodr 1.8.13 아바타 IDLE 모션 동작 구현
|
|
if( GetCurrAnimationID() != ANI_DEFAULT01 )
|
|
NPlayAnimation( ANI_DEFAULT01, SEQTYPE_LOOP );
|
|
}
|
|
else
|
|
{
|
|
if( GetCurrAnimationID() != ANI_DEFAULT01 )
|
|
NPlayAnimation( ANI_DEFAULT01, SEQTYPE_LOOP );
|
|
}
|
|
}
|
|
|
|
void SGameCreature::Walk( bool bLoop )
|
|
{
|
|
if( GetCurrAnimationID() != ANI_WALK || m_fCurPlayRate != m_fPlayRate )
|
|
NPlayAnimation( ANI_WALK, SEQTYPE_LOOP, m_fPlayRate );
|
|
}
|
|
|
|
void SGameCreature::Run( bool bAutoRun, int nAniType )
|
|
{
|
|
if( GetCurrAnimationID() != nAniType || m_fCurPlayRate != m_fPlayRate )
|
|
NPlayAnimation( nAniType, SEQTYPE_LOOP, m_fPlayRate );
|
|
}
|
|
|
|
// sonaodr 1.8.13 아바타 IDLE 모션 동작 구현
|
|
void SGameCreature::_processIdle()
|
|
{
|
|
if( GetCurrAnimationID() == ANI_IDLE )
|
|
{
|
|
if( !IsPlaying() )
|
|
NPlayAnimation( ANI_DEFAULT01, SEQTYPE_LOOP );
|
|
}
|
|
else if( GetCurrAnimationID() == ANI_DEFAULT01 )
|
|
{
|
|
int timeDiff = m_dwTime - m_dwIdleTime;
|
|
int rand = XFastRandom( 1, 10000000 );
|
|
if( rand < (int)timeDiff )
|
|
{
|
|
NPlayAnimation( ANI_IDLE, SEQTYPE_NORMAL );
|
|
_resetIdleTime();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SGameCreature::Process( DWORD time, unsigned long uProcessBitVector ) // sonador 1.8.15 다른 플레이어의 크리처 스킬 연출 오류 수정
|
|
{
|
|
SGameAvatarEx::Process( time, uProcessBitVector );
|
|
|
|
_processIdle(); // sonaodr 1.8.13 아바타 IDLE 모션 동작 구현
|
|
|
|
if( !m_vCastSkillList.empty() )
|
|
CheckWorkDel( m_vCastSkillList );
|
|
|
|
if( !m_vFireSkillList.empty() )
|
|
CheckWorkDel( m_vFireSkillList );
|
|
|
|
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
|
|
m_vCastSkillList[i]->Process( m_dwTime );
|
|
|
|
for( unsigned int i(0); m_vFireSkillList.size()>i; i++ )
|
|
m_vFireSkillList[i]->Process( m_dwTime );
|
|
|
|
return true;
|
|
}
|
|
|
|
void SGameCreature::SetViewVectorForMount( const K3DVector &tpos )
|
|
{
|
|
m_fTargetRoll = atan2( tpos.y, tpos.x );
|
|
m_dwPrevTime = m_dwTime;
|
|
m_bUseRot = true;
|
|
|
|
StandingDegreeForMount();
|
|
}
|
|
|
|
void SGameCreature::CalcCreatureRunPlayRate( float fSpeed )
|
|
{
|
|
//#ifdef _DEBUG
|
|
m_fPlayRate = DEFAULT_ANI_PLAY_RATE * ( (fSpeed / m_fStandardRunPlayRate) / m_fRdbScale );
|
|
//#else
|
|
// m_fPlayRate = DEFAULT_ANI_PLAY_RATE;
|
|
//#endif
|
|
|
|
}
|
|
|
|
void SGameCreature::CalcCreatureWalkPlayRate( float fSpeed )
|
|
{
|
|
//#ifdef _DEBUG
|
|
m_fPlayRate = DEFAULT_ANI_PLAY_RATE * ( (fSpeed / m_fStandardWalkPlayRate) / m_fRdbScale );
|
|
//#else
|
|
// m_fPlayRate = DEFAULT_ANI_PLAY_RATE;
|
|
//#endif
|
|
}
|
|
|
|
|
|
bool SGameCreature::ExistAnimation( int ani_id)
|
|
{
|
|
const char * pAni = NULL;
|
|
|
|
if( GetInnObjType() == TS_ENTER::GAME_SUMMON)
|
|
{
|
|
//몹디비에서 해당 모션의 이름을 꺼내본다
|
|
_MONSTER_INFO_FILE * pMonster = GetMonsterDB().GetMonsterData( GetInnContentID() );
|
|
if( pMonster )
|
|
pAni = GetMonsterMotionSetDB().GetAni( pMonster->motion_file_id, ani_id );
|
|
|
|
if (pAni != NULL)
|
|
{
|
|
std::string strAniKey;
|
|
KSeqObject* ani = NULL;
|
|
|
|
CStringUtil::GetStrKey( pAni, '_', strAniKey );
|
|
// 여기까지 해서 모션의 이름을 꺼내본뒤에
|
|
// 아래에서 아바타의 BIPED 부분에서 그 애니메이션이 있는지 꺼내본다
|
|
if (m_pSeqAvatar != NULL)
|
|
ani = m_pSeqAvatar->getAvatarPart(ANIPART_BIPED)->GetAnimation( strAniKey.c_str() );
|
|
|
|
if ( ani == NULL)
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int SGameCreature::GetAnimationLength(int ani_id)
|
|
{
|
|
const char * pAni = NULL;
|
|
|
|
if( GetInnObjType() == TS_ENTER::GAME_SUMMON)
|
|
{
|
|
//몹디비에서 해당 모션의 이름을 꺼내본다
|
|
_MONSTER_INFO_FILE * pMonster = GetMonsterDB().GetMonsterData( GetInnContentID() );
|
|
if( pMonster )
|
|
pAni = GetMonsterMotionSetDB().GetAni( pMonster->motion_file_id, ani_id );
|
|
|
|
std::string strAniKey;
|
|
KSeqObject* new_ani = NULL;
|
|
|
|
if (pAni != NULL)
|
|
{
|
|
CStringUtil::GetStrKey( pAni, '_', strAniKey );
|
|
// 여기까지 해서 모션의 이름을 꺼내본뒤에
|
|
// 아래에서 아바타의 BIPED 부분에서 그 애니메이션이 있는지 꺼내본다
|
|
if (m_pSeqAvatar != NULL)
|
|
new_ani = m_pSeqAvatar->getAvatarPart(ANIPART_BIPED)->GetAnimation( strAniKey.c_str() );
|
|
}
|
|
|
|
if (new_ani == NULL) // 없으면 -1
|
|
{
|
|
return -1;
|
|
}
|
|
else // 있으면
|
|
{
|
|
return new_ani->GetInterval().GetLength();
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void SGameCreature::RefreshTextureGroup( vec_cobset* pCobSet )
|
|
{
|
|
if (pCobSet == NULL || m_pSeqAvatar == NULL || pCobSet->empty()) return;
|
|
|
|
assert(GetInnObjType() == TS_ENTER::GAME_SUMMON);
|
|
|
|
_SUMMON_INFO_FILE* pSummon = GetCreatureDB().GetCreatureData(GetInnContentID());
|
|
if (pSummon == NULL)
|
|
return;
|
|
|
|
int texture_group_index = pSummon->texture_group;
|
|
|
|
if (m_ucEnhance > 0)
|
|
{
|
|
if (ENV().IsExist("c_enhance"))
|
|
{
|
|
texture_group_index = m_ucEnhance;
|
|
}
|
|
else
|
|
{
|
|
texture_group_index = 1;
|
|
}
|
|
|
|
EnableMTE(true);
|
|
}
|
|
|
|
_RefreshTextureGroup(texture_group_index, pCobSet);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* {
|
|
if ( pCobSet == NULL || m_pSeqAvatar == NULL || pCobSet->empty() ) return;
|
|
|
|
assert( GetInnObjType() == TS_ENTER::GAME_SUMMON );
|
|
|
|
_SUMMON_INFO_FILE* pSummon = GetCreatureDB().GetCreatureData( GetInnContentID() );
|
|
if( pSummon == NULL )
|
|
return;
|
|
|
|
int texture_group_index = pSummon->texture_group; // sonador 1.8.10 아바타 텍스쳐 그룹 적용(페이스 컷 포함)
|
|
|
|
|
|
/* AziaMafia MTE backup
|
|
if (m_ucEnhance > 0) // floyd 2010. 4. 14 크리쳐 강화, 강화된 크리쳐의 텍스쳐 변경
|
|
{
|
|
texture_group_index = 1;
|
|
|
|
//gmpbigsun( 2012_1213 ) : mte적용 // AziaMafia MTE
|
|
EnableMTE(true);
|
|
}
|
|
|
|
|
|
//Edit
|
|
texture_group_index = m_ucEnhance ;
|
|
|
|
if (m_ucEnhance == 5 )
|
|
{
|
|
EnableMTE(true);
|
|
}
|
|
*/
|
|
/*
|
|
if (m_ucEnhance > 0 ) // floyd 2010. 4. 14 크리쳐 강화, 강화된 크리쳐의 텍스쳐 변경
|
|
{
|
|
texture_group_index = 1;
|
|
|
|
//gmpbigsun( 2012_1213 ) : mte적용 // AziaMafia MTE
|
|
EnableMTE(true);
|
|
}
|
|
|
|
if (m_nDisguise == NONE_DISGUISE ) // m_disguiseEnhance
|
|
_RefreshTextureGroup( texture_group_index, pCobSet ); // 크리처 강화시 텍스처를 다시 찾는다(0 -> 1 단계로 강화에만 텍스처 바뀜) servantes 2011.03.15 주석추가
|
|
|
|
|
|
}
|
|
|
|
*/ |