DragonNest/GameCommon/DnPlagueBlow.cpp
2024-12-19 09:48:26 +08:00

275 lines
No EOL
6.8 KiB
C++

#include "StdAfx.h"
#include "DnPlagueBlow.h"
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
const LOCAL_TIME PLAGUE_DAMAGE_INTERVAL = 2000;
CDnPlagueBlow::CDnPlagueBlow( DnActorHandle hActor, const char* szValue ) : CDnBlow( hActor ),
m_IntervalChecker( hActor, GetMySmartPtr() ),
m_fDamageProb( 0.f ),
m_nPlageProbability( 0 ),
m_fDamageAbsolute( 0.f ),
m_fPlagueRange( 0.f ),
m_fEffectLength( 0.f ),
m_bEffecting( false )
#ifdef _GAMESERVER
,m_fIntervalDamage( 0.0f )
#endif
{
m_StateBlow.emBlowIndex = STATE_BLOW::BLOW_136;
SetValue( szValue );
std::vector<std::string> tokens;
TokenizeA( szValue, tokens , ";" );
if( tokens.size() == 2 )
{
m_nPlageProbability = 100;
m_fDamageProb = (float)atof( tokens[0].c_str() );
m_fPlagueRange = (float)atof( tokens[1].c_str() );
}
else if( tokens.size() == 4 )
{
m_nPlageProbability = (float)atof( tokens[0].c_str() ) * 100.f;
m_fDamageProb = (float)atof( tokens[1].c_str() );
m_fDamageAbsolute = (float)atof( tokens[2].c_str() );
m_fPlagueRange = (float)atof( tokens[3].c_str() );
}
#ifdef _GAMESERVER
// 전염되어온 경우 데미지 비율이 1.0 을 넘을 것이다. 이 경우엔 그대로 데미지 적용해주면 된다.
if( m_fDamageProb < 1.0f )
m_fIntervalDamage = (m_hActor->GetLastDamage() * m_fDamageProb) + m_fDamageAbsolute;
else
m_fIntervalDamage = m_fDamageProb;
#endif
#ifndef _GAMESERVER
UseTableDefinedGraphicEffect( false );
#endif
}
CDnPlagueBlow::~CDnPlagueBlow(void)
{
}
#ifdef _GAMESERVER
bool CDnPlagueBlow::CanBegin( void )
{
return true;
}
#endif
bool CDnPlagueBlow::OnCustomIntervalProcess( void )
{
#ifdef _GAMESERVER
if( 0.0f < m_fIntervalDamage )
{
#if defined(PRE_FIX_61382)
DnActorHandle hActor = CDnActor::GetOwnerActorHandle(m_hActor);
if (hActor &&
hActor->IsDie() == false)
{
m_hActor->RequestDamageFromStateBlow(GetMySmartPtr(), (int)m_fIntervalDamage);
}
#else
if (m_hActor->IsDie() == false)
{
m_hActor->RequestDamageFromStateBlow(GetMySmartPtr(), (int)m_fIntervalDamage);
}
#endif // PRE_FIX_61382
}
// 주변에 옮길만한 대상이 있는지 아군중에서 찾는다.
// 옮기게 되면 같은 데미지로 처리되도록 한다.
DNVector( DnActorHandle ) vlActorsInRange;
CDnActor::ScanActor( m_hActor->GetRoom(), *m_hActor->GetPosition(), m_fPlagueRange, vlActorsInRange );
// 가장 가까운 대상에게 옮김. 이미 전염병 상태효과가 걸린 대상에게는 옮기지 않는다.
float fShortestLengthSQ = FLT_MAX;
int iNumActorsInRange = (int)vlActorsInRange.size();
DnActorHandle hResultTarget;
for( int i = 0; i < iNumActorsInRange; ++i )
{
DnActorHandle hActor = vlActorsInRange.at( i );
// 아군에게만.
if( hActor->GetTeam() == m_hActor->GetTeam() )
{
// 이미 전염된 상태인 애들 빼고.
if( false == hActor->IsAppliedThisStateBlow( STATE_BLOW::BLOW_136 ) )
{
int iRandVal = _rand(GetRoom()) % 100;
if( iRandVal < m_nPlageProbability )
{
EtVector3 vLength = *hActor->GetPosition() - *m_hActor->GetPosition();
float fLengthSQ = EtVec3LengthSq( &vLength );
if( fLengthSQ < fShortestLengthSQ )
{
fShortestLengthSQ = fLengthSQ;
hResultTarget = hActor;
break;
}
}
}
}
}
if( hResultTarget )
{
// 결과로 나온 액터가 있다면 전염병 상태효과 추가.
// 공격 당해서 걸리는 게 아니라 전염되는 것이므로 결정된 데미지를 그대로 전달한다.
char acBuf[ STATE_BLOW_ARGUMENT_MAX_SIZE ] = { 0 };
sprintf_s( acBuf, sizeof(acBuf), "%2.2f;%2.2f", m_fIntervalDamage, m_fPlagueRange );
hResultTarget->CmdAddStateEffect( &m_ParentSkillInfo, m_StateBlow.emBlowIndex,
int(m_fOriginalDurationTime*1000.0f), acBuf );
}
#else
_AttachGraphicEffect();
if( m_hEtcObjectEffect )
{
CEtActionBase::ActionElementStruct* pStruct = m_hEtcObjectEffect->GetElement( "Idle" );
if( pStruct )
{
m_fEffectLength = (float)pStruct->dwLength / 1000.0f;
}
_SetDiffuse( 0.0f, 1.0f, 0.0f, 1.0f );
m_bEffecting = true;
}
#endif
return true;
}
void CDnPlagueBlow::OnBegin( LOCAL_TIME LocalTime, float fDelta )
{
#ifdef _GAMESERVER
if( m_fIntervalDamage < 1.0f )
{
SetState( STATE_BLOW::STATE_END );
OutputDebug( "CDnPlagueBlow::OnBegin - Damage is too small. ( < 1) Plague Fail\n" );
}
#endif
m_IntervalChecker.OnBegin( LocalTime, PLAGUE_DAMAGE_INTERVAL );
m_fEffectLength = 0.0f;
m_bEffecting = false;
m_fOriginalDurationTime = m_StateBlow.fDurationTime;
}
void CDnPlagueBlow::Process( LOCAL_TIME LocalTime, float fDelta )
{
CDnBlow::Process( LocalTime, fDelta );
#ifndef _GAMESERVER
if( m_bEffecting )
{
m_fEffectLength -= fDelta;
if( m_fEffectLength < 0.0f )
{
m_fEffectLength = 0.0f;
_SetDiffuse( 1.0f, 1.0f, 1.0f, 1.0f );
m_bEffecting = false;
}
}
#endif
// 내부에서 Die 처리가 되기 때문에 본인이 Die 되는 경우도 있으므로 본인의 이 상태효과가 무효화 될 수 있다.
// 따라서 맨 마지막에 두도록한다.
m_IntervalChecker.Process( LocalTime, fDelta );
}
void CDnPlagueBlow::OnEnd( LOCAL_TIME LocalTime, float fDelta )
{
// LocalTime 이 0으로 호출되면 삭제, 중첩처리 등을 위한 강제 종료임.
if( LocalTime != 0 )
m_IntervalChecker.OnEnd( LocalTime, fDelta );
#ifndef _GAMESERVER
_SetDiffuse( 1.0f, 1.0f, 1.0f, 1.0f );
_DetachGraphicEffect();
#endif
}
#if defined(_GAMESERVER)
void CDnPlagueBlow::OnDuplicate( const STATE_BLOW& StateBlowInfo )
{
// TODO: 중첩되었을 때 어떻게 할까?
}
#endif
#if defined(PRE_ADD_PREFIX_SYSTE_RENEW)
void CDnPlagueBlow::AddStateEffectValue(const char* szOrigValue, const char* szAddValue, std::string& szNewValue)
{
std::string strArgument[2];
strArgument[0] = szOrigValue;
strArgument[1] = szAddValue;
std::vector<string> vlOriginTokens, vlNewTokens;
TokenizeA( strArgument[0], vlOriginTokens, ";" );
TokenizeA( strArgument[1], vlNewTokens, ";" );
if( vlOriginTokens.size() == vlNewTokens.size() )
{
std::string strResult;
for( DWORD i=0; i<vlOriginTokens.size(); i++ )
{
strResult += FormatA( "%f" , ( (float)atof( vlOriginTokens[i].c_str() ) + (float)atof( vlNewTokens[i].c_str() ) ) );
if( i < vlOriginTokens.size()-1 )
{
strResult += ';';
}
}
szNewValue = strResult.c_str();
}
}
void CDnPlagueBlow::RemoveStateEffectValue(const char* szOrigValue, const char* szAddValue, std::string& szNewValue)
{
std::string strArgument[2];
strArgument[0] = szOrigValue;
strArgument[1] = szAddValue;
std::vector<string> vlOriginTokens, vlNewTokens;
TokenizeA( strArgument[0], vlOriginTokens, ";" );
TokenizeA( strArgument[1], vlNewTokens, ";" );
if( vlOriginTokens.size() == vlNewTokens.size() )
{
std::string strResult;
for( DWORD i=0; i<vlOriginTokens.size(); i++ )
{
strResult += FormatA( "%f" , ( (float)atof( vlOriginTokens[i].c_str() ) - (float)atof( vlNewTokens[i].c_str() ) ) );
if( i < vlOriginTokens.size()-1 )
{
strResult += ';';
}
}
szNewValue = strResult.c_str();
}
}
#endif // PRE_ADD_PREFIX_SYSTE_RENEW