374 lines
12 KiB
C++
374 lines
12 KiB
C++
#include "stdafx.h"
|
|
#include "MAMultiDamage.h"
|
|
#include "DnPartsMonsterActor.h"
|
|
#include "DnTableDB.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
|
|
#endif
|
|
|
|
MonsterParts::MonsterParts()
|
|
: m_fDestroyDelta( 0.0f )
|
|
{
|
|
m_hSkill.Identity();
|
|
}
|
|
|
|
MonsterParts::~MonsterParts()
|
|
{
|
|
SAFE_RELEASE_SPTR( m_hSkill );
|
|
}
|
|
|
|
bool MonsterParts::Process( const float fDelta )
|
|
{
|
|
// 재생시간이 0보다 작다는 것은 무한이란뜻!
|
|
if( GetPartsOriginalInfo().nHPRefreshTimems < 0 )
|
|
return false;
|
|
|
|
m_fDestroyDelta -= fDelta;
|
|
if( m_fDestroyDelta <= 0.f )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool MonsterParts::Create( const _Info& info)
|
|
{
|
|
m_OriginalInfo = m_Info = info;
|
|
return true;
|
|
}
|
|
|
|
bool MonsterParts::CreateSkill( DnActorHandle hActor )
|
|
{
|
|
if( m_Info.nPassiveSkillIndex > 0 && m_Info.nPassiveSkillLevel > 0 )
|
|
{
|
|
m_hSkill = CDnSkill::CreateSkill( hActor, m_Info.nPassiveSkillIndex, m_Info.nPassiveSkillLevel );
|
|
if( !m_hSkill )
|
|
{
|
|
//g_Log.LogA( "MonsterParts::Create() SkillIndex=%d Level=%d 스킬생성실패!\r\n", m_Info.nPassiveSkillIndex, m_Info.nPassiveSkillLevel );
|
|
return false;
|
|
}
|
|
|
|
if( !hActor->AddSkill( m_hSkill ) )
|
|
return false;
|
|
|
|
SetRefresh( hActor );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool MonsterParts::HasBone( const char* pszBoneName )
|
|
{
|
|
for( size_t i=0 ; i <m_Info.vParts.size() ; ++i )
|
|
{
|
|
if ( strcmp( m_Info.vParts[i].szBoneName.c_str(), pszBoneName ) == 0 )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool MonsterParts::IsLimitAction( const char* pszActionName )
|
|
{
|
|
for( size_t i=0 ; i<m_OriginalInfo.vLimitAction.size() ; ++i )
|
|
{
|
|
if( strcmp( m_OriginalInfo.vLimitAction[i].c_str(), pszActionName ) == 0 )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void MonsterParts::SetRefresh( DnActorHandle hActor )
|
|
{
|
|
m_Info.nHP = m_OriginalInfo.nHP;
|
|
if( m_hSkill && hActor )
|
|
{
|
|
if( m_Info.bIsRefreshUseSkill )
|
|
{
|
|
#if defined( _GAMESERVER )
|
|
hActor->UseSkill( m_hSkill->GetClassID() );
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
void MonsterParts::SetDestroy( DnActorHandle hActor )
|
|
{
|
|
m_Info.nHP = 0;
|
|
m_fDestroyDelta = m_OriginalInfo.nHPRefreshTimems/1000.0f;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------------
|
|
void MAMultiDamage::LoadMultiDamageInfo()
|
|
{
|
|
DNTableFileFormat* pSox = GetDNTable( CDnTableDB::TMONSTER );
|
|
if ( !pSox )
|
|
{
|
|
g_Log.Log( LogType::_FILELOG, L"MonsterTable.ext failed\r\n");
|
|
return;
|
|
}
|
|
|
|
CDnMonsterActor* pMonsterActor = dynamic_cast<CDnMonsterActor*>(this);
|
|
if ( !pMonsterActor )
|
|
return;
|
|
|
|
CDnPartsMonsterActor* pPartsMonsterActor = dynamic_cast<CDnPartsMonsterActor*>(this);
|
|
|
|
int nItemID = pMonsterActor->GetMonsterClassID();
|
|
if( !pSox->IsExistItem( nItemID ) ) return;
|
|
|
|
for ( int i=1 ; i<=5 ; ++i )
|
|
{
|
|
char szLabel[MAX_PATH];
|
|
sprintf_s( szLabel, "_MonsterPartsIndex%d", i );
|
|
int nMultiDamageIdx = pSox->GetFieldFromLablePtr( nItemID, szLabel )->GetInteger();
|
|
if ( nMultiDamageIdx < 1 )
|
|
continue;
|
|
|
|
DNTableFileFormat* pPartsSox = GetDNTable( CDnTableDB::TMONSTERPARTS );
|
|
if ( !pPartsSox )
|
|
return;
|
|
|
|
MonsterParts::_Info info;
|
|
|
|
info.uiMonsterPartsTableID = nMultiDamageIdx;
|
|
info.nHP = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_HP" )->GetInteger();
|
|
info.nHPRefreshTimems = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_HPRefreshTimems" )->GetInteger();
|
|
info.fMainDamageRate = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_MainDamageRate" )->GetFloat();
|
|
info.fDefenseRate = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_DefenseRate" )->GetFloat();
|
|
info.nPassiveSkillIndex = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_PassiveSkillIndex" )->GetInteger();
|
|
info.nPassiveSkillLevel = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_PassiveSkillLevel" )->GetInteger();
|
|
info.nDestroySkillIndex = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_DeadSkillIndex" )->GetInteger();
|
|
info.bIsRefreshUseSkill = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_PassiveSkillLink")->GetInteger() ? true : false;
|
|
|
|
#if defined( _GAMESERVER )
|
|
char* pszRebirthParts = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_PartsHPLink" )->GetString();
|
|
if( pszRebirthParts && strlen(pszRebirthParts) > 0 )
|
|
{
|
|
std::string strString(pszRebirthParts);
|
|
DNVector(std::string) vSplit;
|
|
|
|
boost::algorithm::split( vSplit, strString, boost::algorithm::is_any_of(",") );
|
|
info.vRebirthPartsTableID.reserve( vSplit.size() );
|
|
|
|
for( UINT j=0 ; j<vSplit.size() ; ++j )
|
|
{
|
|
UINT uiTableID = boost::lexical_cast<UINT>(vSplit[j].c_str());
|
|
if( uiTableID )
|
|
info.vRebirthPartsTableID.push_back( uiTableID );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifndef _GAMESERVER
|
|
info.szDeadSkinName = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_DeadSkinName" )->GetString();
|
|
info.szDeadAniName = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_DeadAniName" )->GetString();
|
|
info.szDeadActName = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_DeadActionName" )->GetString();
|
|
info.szAction = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_DeadAction" )->GetString();
|
|
#endif //_GAMESERVER
|
|
|
|
info.szDeadActorActName = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_DeadActorAction" )->GetString();
|
|
info.szDeadActorActBoneName = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_DeadActorActionBoneName" )->GetString();
|
|
info.szDeadActorFixBoneName = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_DeadActorActionFixBoneName" )->GetString();
|
|
|
|
#ifndef _GAMESERVER
|
|
#if defined(PRE_ADD_MULTILANGUAGE)
|
|
info.wszPartsName = GetEtUIXML().GetUIString(CEtUIXML::idCategory1, pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_NameID" )->GetInteger(), MultiLanguage::eDefaultLanguage );
|
|
#else //#if defined(PRE_ADD_MULTILANGUAGE)
|
|
info.wszPartsName = GetEtUIXML().GetUIString(CEtUIXML::idCategory1, pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_NameID" )->GetInteger() );
|
|
#endif //#if defined(PRE_ADD_MULTILANGUAGE)
|
|
info.m_bEnalbeUI = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_PartsHPDisplay")->GetInteger() ? true : false;
|
|
#endif
|
|
|
|
for( int j=1 ; j<=5 ; ++j )
|
|
{
|
|
sprintf_s( szLabel, "_LimitAction%d", j );
|
|
|
|
char* pszLimitAction = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, szLabel )->GetString();
|
|
if( pszLimitAction && strlen(pszLimitAction) )
|
|
info.vLimitAction.push_back( pszLimitAction );
|
|
}
|
|
for ( int j=1 ; j<=20 ; ++j )
|
|
{
|
|
char szLocalLabel[64];
|
|
|
|
sprintf_s( szLocalLabel, "_MeshName%d", j );
|
|
char* pszMeshName = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, szLocalLabel )->GetString();
|
|
sprintf_s( szLocalLabel, "_BoneName%d", j );
|
|
char* pszBoneName = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, szLocalLabel )->GetString();
|
|
sprintf_s( szLocalLabel, "_EffectType%d", j );
|
|
bool bApplyEffect = ( pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, szLocalLabel )->GetInteger() ) ? true : false;
|
|
|
|
if( pszMeshName && pszBoneName && strlen(pszMeshName) && strlen(pszBoneName) )
|
|
info.vParts.push_back( MonsterParts::_PartsInfo( pszMeshName, pszBoneName, bApplyEffect ) );
|
|
}
|
|
|
|
char* pszRequiredPartsID = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_RequiredPartsID" )->GetString();
|
|
char* pszRequiredPartsHP = pPartsSox->GetFieldFromLablePtr( nMultiDamageIdx, "_RequiredPartsHP" )->GetString();
|
|
|
|
if( pszRequiredPartsID && pszRequiredPartsHP && strlen(pszRequiredPartsID) && strlen(pszRequiredPartsHP) )
|
|
{
|
|
std::string strRequiredPartsID(pszRequiredPartsID);
|
|
std::string strRequiredPartsHP(pszRequiredPartsHP);
|
|
std::vector<std::string> vSplitID,vSplitHP;
|
|
|
|
boost::algorithm::split( vSplitID, strRequiredPartsID, boost::algorithm::is_any_of(";") );
|
|
boost::algorithm::split( vSplitHP, strRequiredPartsHP, boost::algorithm::is_any_of(";") );
|
|
|
|
if( vSplitID.size() == vSplitHP.size() )
|
|
{
|
|
MonsterParts::_HitCondition HitCondition;
|
|
for( UINT j=0 ; j<vSplitID.size() ; ++j )
|
|
{
|
|
HitCondition.iRequiredPartsID = atoi(vSplitID[j].c_str());
|
|
HitCondition.iRequiredPartsUnderHP = atoi(vSplitHP[j].c_str());
|
|
|
|
info.vHitCondition.push_back( HitCondition );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(0);
|
|
}
|
|
}
|
|
|
|
_AddMonsterParts( info );
|
|
|
|
#ifdef _GAMESERVER
|
|
if (pPartsMonsterActor)
|
|
pPartsMonsterActor->_OnAddMonsterParts(info);
|
|
#else
|
|
if (pPartsMonsterActor)
|
|
pPartsMonsterActor->OnAddMonsterParts(info);
|
|
#endif
|
|
}
|
|
|
|
for( size_t i=0 ; i<m_Parts.size() ; ++i )
|
|
m_Parts[i].CreateSkill( pMonsterActor->GetActorHandle() );
|
|
}
|
|
|
|
bool MAMultiDamage::_AddMonsterParts( const MonsterParts::_Info& info )
|
|
{
|
|
MonsterParts parts;
|
|
parts.Create( info );
|
|
m_Parts.push_back(parts);
|
|
|
|
return true;
|
|
}
|
|
|
|
void MAMultiDamage::_OnRefreshParts( DnActorHandle hActor, MonsterParts* pParts, int nPartsIndex )
|
|
{
|
|
// 파츠가 다시 살아남. 파괴 이펙트 제거부탁용~
|
|
#ifndef _GAMESERVER
|
|
if( !pParts->GetPartsInfo().szDeadSkinName.empty() || !pParts->GetPartsInfo().szDeadActName.empty() ) {
|
|
for( DWORD i=0; i<pParts->GetPartsInfo().vParts.size(); i++ ) {
|
|
if( pParts->GetPartsInfo().vParts[i].bApplyDeadEffect ) {
|
|
hActor->TSmartPtrSignalImp<DnEtcHandle, EtcObjectSignalStruct>::RemoveSignalHandle( -10000, ( nPartsIndex * 20 ) + i );
|
|
}
|
|
}
|
|
}
|
|
|
|
CDnPartsMonsterActor* pPartsActor = dynamic_cast<CDnPartsMonsterActor*>(this);
|
|
if (pPartsActor != NULL && pParts != NULL)
|
|
pPartsActor->OnRefreshParts(*pParts, nPartsIndex);
|
|
|
|
pParts->SetRefresh( hActor );
|
|
#endif
|
|
}
|
|
|
|
void MAMultiDamage::_OnDestroyParts( DnActorHandle hActor, MonsterParts* pParts, int nPartsIndex )
|
|
{
|
|
// 파츠 파괴. 파괴 이펙트 뿌려주세용~
|
|
#ifndef _GAMESERVER
|
|
if( !pParts->GetPartsInfo().szDeadSkinName.empty() || !pParts->GetPartsInfo().szDeadActName.empty() ) {
|
|
for( DWORD i=0; i<pParts->GetPartsInfo().vParts.size(); i++ ) {
|
|
if( pParts->GetPartsInfo().vParts[i].bApplyDeadEffect ) {
|
|
if( hActor->TSmartPtrSignalImp<DnEtcHandle, EtcObjectSignalStruct>::IsExistSignalHandle( -10000, ( nPartsIndex * 20 ) + i ) ) {
|
|
hActor->TSmartPtrSignalImp<DnEtcHandle, EtcObjectSignalStruct>::RemoveSignalHandle( -10000, ( nPartsIndex * 20 ) + i );
|
|
}
|
|
DnEtcHandle hObject = (new CDnEtcObject)->GetMySmartPtr();
|
|
if( !hObject->Initialize( pParts->GetPartsInfo().szDeadSkinName.c_str(), pParts->GetPartsInfo().szDeadAniName.c_str(), pParts->GetPartsInfo().szDeadActName.c_str() ) ) {
|
|
SAFE_RELEASE_SPTR( hObject );
|
|
return;
|
|
}
|
|
hObject->SetActionQueue( pParts->GetPartsInfo().szAction.c_str() );
|
|
EtcObjectSignalStruct *pResult = hActor->TSmartPtrSignalImp<DnEtcHandle, EtcObjectSignalStruct>::InsertSignalHandle( -10000, ( nPartsIndex * 20 ) + i, hObject );
|
|
|
|
pResult->bDefendenceParent = true;
|
|
pResult->bLinkObject = true;
|
|
pResult->vOffset = EtVector3( 0.f, 0.f, 0.f );
|
|
pResult->vRotate = EtVector3( 0.f, 0.f, 0.f );
|
|
_strcpy( pResult->szBoneName, _countof(pResult->szBoneName), pParts->GetPartsInfo().vParts[i].szBoneName.c_str(), (int)strlen(pParts->GetPartsInfo().vParts[i].szBoneName.c_str()) );
|
|
}
|
|
}
|
|
}
|
|
|
|
CDnPartsMonsterActor* pPartsActor = dynamic_cast<CDnPartsMonsterActor*>(this);
|
|
if (pPartsActor != NULL && pParts != NULL)
|
|
pPartsActor->OnDestroyParts(*pParts, nPartsIndex);
|
|
|
|
pParts->SetDestroy( hActor );
|
|
#endif
|
|
}
|
|
|
|
void MAMultiDamage::OnSetPartsHP( DnActorHandle hActor, const int iPartsTableID, const int iCurHP, const int iHitterID )
|
|
{
|
|
CDnPartsMonsterActor* pMonsterActor = dynamic_cast<CDnPartsMonsterActor*>(this);
|
|
if ( !pMonsterActor )
|
|
return;
|
|
|
|
for( size_t i=0 ; i<m_Parts.size() ; ++i )
|
|
{
|
|
if( m_Parts[i].GetPartsTableID() == iPartsTableID )
|
|
{
|
|
// 파츠에 원래 들어가는 damage 를 주고 각 파츠의 추가 방어 감쇄율을 적용해서 데미지 값을 돌려준다.
|
|
pMonsterActor->OnMultiDamage( m_Parts[i] );
|
|
|
|
int iPrevHP = m_Parts[i].GetHP();
|
|
m_Parts[i].SetHP( iCurHP );
|
|
|
|
//OutputDebug("[PARTSDAMAGE] id:%d : prev HP:%d current HP:%d\n", m_Parts[i].GetPartsTableID(), iPrevHP, iCurHP);
|
|
|
|
#ifndef _GAMESERVER
|
|
if( iPrevHP > 0 && iCurHP <= 0 )
|
|
_OnDestroyParts( hActor, &m_Parts[i], (int)i );
|
|
else if( iPrevHP <= 0 && iCurHP > 0 )
|
|
_OnRefreshParts( hActor, &m_Parts[i], (int)i );
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef PRE_ADD_MONSTER_PARTS_UI_TRIGGER
|
|
int MAMultiDamage::GetPartsIndexFromPartsID( const UINT uiTableID )
|
|
{
|
|
for( UINT i=0 ; i<m_Parts.size() ; ++i )
|
|
{
|
|
if( m_Parts[i].GetPartsTableID() == uiTableID )
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
MonsterParts* MAMultiDamage::GetParts( const UINT uiTableID )
|
|
{
|
|
for( UINT i=0 ; i<m_Parts.size() ; ++i )
|
|
{
|
|
if( m_Parts[i].GetPartsTableID() == uiTableID )
|
|
return &m_Parts[i];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
MonsterParts* MAMultiDamage::GetPartsByIndex(int nIndex)
|
|
{
|
|
if (nIndex < 0 || nIndex >= (int)m_Parts.size())
|
|
return NULL;
|
|
|
|
return &m_Parts[nIndex];
|
|
}
|