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

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 주석추가
}
*/