DragonNest/GameCommon/DnStealBuffBlow.cpp
Cussrro 47f7895977 Revert "修复编码问题"
This reverts commit 9e69c01767.
2024-12-21 10:04:04 +08:00

386 lines
11 KiB
C++

#include "StdAfx.h"
#include "DnStealBuffBlow.h"
#include "DnSkill.h"
#if !defined( USE_BOOST_MEMPOOL )
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
#endif // #if !defined( USE_BOOST_MEMPOOL )
CDnStealBuffBlow::CDnStealBuffBlow( DnActorHandle hActor, const char* szValue ) : CDnBlow( hActor )
{
m_StateBlow.emBlowIndex = STATE_BLOW::BLOW_174;
SetValue( szValue );
m_nCount = 0;
m_nNewDelayTime = 0;
m_fScanRange = 0.0f;
std::string str = szValue;//"갯수;지속시간(ms(10000 == 1초))";
std::vector<std::string> tokens;
std::string delimiters = ";";
//1. 상태효과 인덱스 리스트와 적용 레벨 구분
TokenizeA(str, tokens, delimiters);
if (3 == tokens.size())
{
m_nCount = atoi( tokens[0].c_str() );
m_nNewDelayTime = atoi( tokens[1].c_str() );
m_fScanRange = (float)atof(tokens[2].c_str());
}
else
OutputDebug("%s Invalid value!!!\n", __FUNCTION__);
}
CDnStealBuffBlow::~CDnStealBuffBlow(void)
{
}
void CDnStealBuffBlow::OnBegin( LOCAL_TIME LocalTime, float fDelta )
{
__super::OnBegin(LocalTime, fDelta);
#if defined(_GAMESERVER)
StealBuffProcess(LocalTime);
#endif // _GAMESERVER
}
void CDnStealBuffBlow::Process( LOCAL_TIME LocalTime, float fDelta )
{
__super::Process(LocalTime, fDelta);
}
void CDnStealBuffBlow::OnEnd( LOCAL_TIME LocalTime, float fDelta )
{
__super::OnEnd(LocalTime, fDelta);
}
#if defined(_GAMESERVER)
void CDnStealBuffBlow::FindSkillBlowList(DnActorHandle hActor, int skillID, DNVector(DnBlowHandle)& vlBlowList)
{
if (!hActor)
return;
int nStateBlowCount = hActor->GetNumAppliedStateBlow();
for (int i = 0; i < nStateBlowCount; ++i)
{
DnBlowHandle hBlow = hActor->GetAppliedStateBlow(i);
//StealBuff이면 건너뜀.
if (!hBlow || STATE_BLOW::BLOW_174 == hBlow->GetBlowIndex())
continue;
//투명화 상태효과
if (STATE_BLOW::BLOW_073 == hBlow->GetBlowIndex())
continue;
CDnSkill::SkillInfo* pSkillInfo = const_cast<CDnSkill::SkillInfo*>(hBlow->GetParentSkillInfo());
//스킬 정보가 없으면 건너뜀. (스킬 유저가 없을 수 있음..(프랍?에 의해 적용된 상태효과)
if (!pSkillInfo /*|| !pSkillInfo->hSkillUser*/)
continue;
if (pSkillInfo->iSkillID == skillID)
vlBlowList.push_back(hBlow);
}
}
void CDnStealBuffBlow::StealBuffProcess()
{
if (m_nCount <= 0) return;
if (!m_hActor) return;
if (!m_ParentSkillInfo.hSkillUser)
return;
//제거해야할 Blow 리스트
DNVector(DnBlowHandle) vlRemoveBlowList;
typedef std::map<int, int> SKILL_ID_LIST;
SKILL_ID_LIST skillList;
int nLoopCount = m_nCount;
int nStateBlowCount = m_hActor->GetNumAppliedStateBlow();
//1. 스킬 ID를 수집
for (int i = 0; i < nStateBlowCount; ++i)
{
DnBlowHandle hBlow = m_hActor->GetAppliedStateBlow(i);
//StealBuff이면 건너뜀.
if (!hBlow || STATE_BLOW::BLOW_174 == hBlow->GetBlowIndex())
continue;
//투명화 상태효과
if (STATE_BLOW::BLOW_073 == hBlow->GetBlowIndex())
continue;
//스킬 정보가 없거나 buff가 아니면 건너뜀.
CDnSkill::SkillInfo* pSkillInfo = const_cast<CDnSkill::SkillInfo*>(hBlow->GetParentSkillInfo());
if (!pSkillInfo || CDnSkill::DurationTypeEnum::Buff != pSkillInfo->eDurationType )
continue;
//액티브 스킬만..
if (CDnSkill::Active != pSkillInfo->eSkillType)
continue;
skillList.insert(SKILL_ID_LIST::value_type(pSkillInfo->iSkillID, pSkillInfo->iSkillID));
}
//2. 스킬에 부여된 Blow들 수집해서 새로운 캐릭터에 blow부여
SKILL_ID_LIST::iterator iter = skillList.begin();
SKILL_ID_LIST::iterator endIter = skillList.end();
for (; iter != endIter; ++iter)
{
if (nLoopCount == 0)
break;
//해당 스킬의 blow들을 얻어 온다..
DNVector(DnBlowHandle) vlSkillBlowList;
FindSkillBlowList(m_hActor, iter->first, vlSkillBlowList);
int nBlowCount = (int)vlSkillBlowList.size();
for (int n = 0; n < nBlowCount; ++n)
{
DnBlowHandle hBlow = vlSkillBlowList[n];
if (!hBlow)
continue;
CDnSkill::SkillInfo* pSkillInfo = const_cast<CDnSkill::SkillInfo*>(hBlow->GetParentSkillInfo());
if (!pSkillInfo || !pSkillInfo->hSkillUser)
continue;
//스킬 사용한 유저에게서 스킬 핸들을 얻어 온다. 없으면 건너뜀
DnSkillHandle hSkill = pSkillInfo->hSkillUser->FindSkill(pSkillInfo->iSkillID);
if (!hSkill)
continue;
//특정 무기를 필요로 하지 않으면
if (CDnWeapon::EquipTypeEnum_Amount == hSkill->GetNeedEquipType(0) &&
CDnWeapon::EquipTypeEnum_Amount == hSkill->GetNeedEquipType(1))
{
//스킬을 사용한 유저에게 지워지는 상태 효과를 새로운 지속 시간으로 등록한다..
m_ParentSkillInfo.hSkillUser->CmdAddStateEffect(pSkillInfo, hBlow->GetBlowIndex(), m_nNewDelayTime, hBlow->GetValue(), false, false);
}
}
nLoopCount--;
}
}
void CDnStealBuffBlow::StealBuffProcess(LOCAL_TIME LocalTime)
{
DNVector(DnActorHandle) VecList;
m_hActor->ScanActor( m_hActor->GetRoom(), *m_hActor->GetPosition(), m_fScanRange, VecList );
for( DWORD i=0; i<VecList.size(); i++ ) {
if( !VecList[i] || !VecList[i]->IsHittable( m_hActor, LocalTime, NULL ) )
continue;
if (VecList[i]->GetTeam() == m_hActor->GetTeam())
continue;
StealBuffFromActor(VecList[i]);
}
}
void CDnStealBuffBlow::StealBuffFromActor( DnActorHandle hTargetActor )
{
if (m_nCount <= 0) return;
if (!m_hActor) return;
//면역 처리...
if (!hTargetActor || hTargetActor->IsImmuned(m_StateBlow.emBlowIndex)) return;
//제거해야할 Blow 리스트
DNVector(DnBlowHandle) vlRemoveBlowList;
typedef std::map<int, int> SKILL_ID_LIST;
SKILL_ID_LIST skillList;
int nLoopCount = m_nCount;
int nStateBlowCount = hTargetActor->GetNumAppliedStateBlow();
//1. 스킬 ID를 수집
for (int i = 0; i < nStateBlowCount; ++i)
{
DnBlowHandle hBlow = hTargetActor->GetAppliedStateBlow(i);
//StealBuff이면 건너뜀.
if (!hBlow || STATE_BLOW::BLOW_174 == hBlow->GetBlowIndex())
continue;
//투명화 상태효과
if (STATE_BLOW::BLOW_073 == hBlow->GetBlowIndex())
continue;
//스킬 정보가 없거나 buff가 아니면 건너뜀.
CDnSkill::SkillInfo* pSkillInfo = const_cast<CDnSkill::SkillInfo*>(hBlow->GetParentSkillInfo());
if (!pSkillInfo || CDnSkill::DurationTypeEnum::Buff != pSkillInfo->eDurationType )
continue;
//액티브 스킬만..
if (CDnSkill::Active != pSkillInfo->eSkillType)
continue;
skillList.insert(SKILL_ID_LIST::value_type(pSkillInfo->iSkillID, pSkillInfo->iSkillID));
}
//2. 스킬에 부여된 Blow들 수집해서 새로운 캐릭터에 blow부여
SKILL_ID_LIST::iterator iter = skillList.begin();
SKILL_ID_LIST::iterator endIter = skillList.end();
for (; iter != endIter; ++iter)
{
if (nLoopCount == 0)
break;
//해당 스킬의 blow들을 얻어 온다..
DNVector(DnBlowHandle) vlSkillBlowList;
FindSkillBlowList(hTargetActor, iter->first, vlSkillBlowList);
int nBlowCount = (int)vlSkillBlowList.size();
for (int n = 0; n < nBlowCount; ++n)
{
DnBlowHandle hBlow = vlSkillBlowList[n];
if (!hBlow)
continue;
// [2011/03/30 semozz]
// 스킬 유저 액터 확인은 안 하는걸로..(프랍?에 의해서 추가된 상태효과는 스킬 유저 액터가 없음.)
CDnSkill::SkillInfo* pSkillInfo = const_cast<CDnSkill::SkillInfo*>(hBlow->GetParentSkillInfo());
if (!pSkillInfo /*|| !pSkillInfo->hSkillUser*/)
continue;
//스킬 유저 정보가 설정 되어 있을경우
if (pSkillInfo->hSkillUser)
{
//스킬 유저 정보가 있다면 스킬 검사..
DnSkillHandle hSkill = pSkillInfo->hSkillUser->FindSkill(pSkillInfo->iSkillID);
//스킬이 없으면 건너뜀..
if (!hSkill)
continue;
//검색된 스킬이 있으면 특정 무기를 필요로 하는 스킬이면 건너 뜀
if (CDnWeapon::EquipTypeEnum_Amount != hSkill->GetNeedEquipType(0) ||
CDnWeapon::EquipTypeEnum_Amount != hSkill->GetNeedEquipType(1))
continue;
}
//자신에게 적용할 상태효과를 예약한다..
m_hActor->ReserveStealMagicBuff(hTargetActor, pSkillInfo, m_nNewDelayTime, hBlow->GetBlowIndex(), hBlow->GetValue());
}
nLoopCount--;
}
}
#endif // _GAMESERVER
#if defined(PRE_ADD_PREFIX_SYSTE_RENEW)
void CDnStealBuffBlow::AddStateEffectValue(const char* szOrigValue, const char* szAddValue, std::string& szNewValue)
{
char szBuff[128] = {0, };
//파싱에 필요한 변수 선언
std::vector<string> vlTokens[2];
string strArgument[2];
//필요한 값 변수
int nCount[2] = {0, };
int nNewDelayTime[2] = {0, };
float fScanRange[2] = {0.0f, };
//////////////////////////////////////////////////////////////////////////
//첫번째 문자열 파싱.
strArgument[0] = szOrigValue;
TokenizeA( strArgument[0], vlTokens[0], ";" );
if( vlTokens[0].size() == 3 )
{
nCount[0] = atoi( vlTokens[0][0].c_str() );
nNewDelayTime[0] = atoi( vlTokens[0][1].c_str() );
fScanRange[0] = (float)atof( vlTokens[0][2].c_str() );
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//두번째 문자열 파싱
strArgument[1] = szAddValue;
TokenizeA( strArgument[1], vlTokens[1], ";" );
if( vlTokens[1].size() == 3 )
{
nCount[1] = atoi( vlTokens[1][0].c_str() );
nNewDelayTime[1] = atoi( vlTokens[1][1].c_str() );
fScanRange[1] = (float)atof( vlTokens[1][2].c_str() );
}
//////////////////////////////////////////////////////////////////////////
//두 값을 더한다.
int nResultCount = nCount[0] + nCount[1];
int nResultDelayTime = max(nNewDelayTime[0], nNewDelayTime[1]);
float fResultScanRange = max(fScanRange[0], fScanRange[1]);
sprintf_s(szBuff, "%d;%d;%f", nResultCount, nResultDelayTime, fResultScanRange);
szNewValue = szBuff;
}
void CDnStealBuffBlow::RemoveStateEffectValue(const char* szOrigValue, const char* szAddValue, std::string& szNewValue)
{
char szBuff[128] = {0, };
//파싱에 필요한 변수 선언
std::vector<string> vlTokens[2];
string strArgument[2];
//필요한 값 변수
int nCount[2] = {0, };
int nNewDelayTime[2] = {0, };
float fScanRange[2] = {0.0f, };
//////////////////////////////////////////////////////////////////////////
//첫번째 문자열 파싱.
strArgument[0] = szOrigValue;
TokenizeA( strArgument[0], vlTokens[0], ";" );
if( vlTokens[0].size() == 3 )
{
nCount[0] = atoi( vlTokens[0][0].c_str() );
nNewDelayTime[0] = atoi( vlTokens[0][1].c_str() );
fScanRange[0] = (float)atof( vlTokens[0][2].c_str() );
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//두번째 문자열 파싱
strArgument[1] = szAddValue;
TokenizeA( strArgument[1], vlTokens[1], ";" );
if( vlTokens[1].size() == 3 )
{
nCount[1] = atoi( vlTokens[1][0].c_str() );
nNewDelayTime[1] = atoi( vlTokens[1][1].c_str() );
fScanRange[1] = (float)atof( vlTokens[1][2].c_str() );
}
//////////////////////////////////////////////////////////////////////////
//두 값을 더한다.
int nResultCount = nCount[0] - nCount[1];
int nResultDelayTime = min(nNewDelayTime[0], nNewDelayTime[1]);
float fResultScanRange = min(fScanRange[0], fScanRange[1]);
sprintf_s(szBuff, "%d;%d;%f", nResultCount, nResultDelayTime, fResultScanRange);
szNewValue = szBuff;
}
#endif // PRE_ADD_PREFIX_SYSTE_RENEW