DragonNest/GameCommon/DnActorState.cpp
2024-12-20 16:56:44 +08:00

816 lines
No EOL
49 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "DnActorState.h"
#include "DnTableDB.h"
#include "DnActor.h"
#include "DnWeapon.h"
#include "DnItem.h"
#include "MAPartsBody.h"
#include "DnMonsterActor.h"
#include "DnPlayerActor.h"
#include "PerfCheck.h"
#ifndef _GAMESERVER
#include "TaskManager.h"
#include "DnGameTask.h"
#include "DnPvPGameTask.h"
#endif
#ifdef _GAMESERVER
#include "DNGameDataManager.h"
#include "DNUserSession.h"
#include "DNBestFriend.h"
#endif // #ifdef _GAMESERVER
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
int CDnActorState::s_nActorStateIndex[CDnActorState::ActorStateEnum_Amount] = {
CDnActorState::None,
CDnActorState::Stay,
CDnActorState::Move,
CDnActorState::Attack,
CDnActorState::Hit,
CDnActorState::Air,
CDnActorState::Down,
CDnActorState::Stun,
CDnActorState::Stiff,
CDnActorState::IgnoreCantAction,
CDnActorState::IgnoreBackMoveSpeed,
};
char *CDnActorState::s_szActorStateString[CDnActorState::ActorStateEnum_Amount] = {
"None",
"Stay",
"Move",
"Attack",
"Hit",
"Air",
"Down",
"Stun",
"Stiff",
"IgnoreCantAction",
"IgnoreBackMoveSpeed"
};
int CDnActorState::s_nActorCustomStateIndex[CDnActorState::ActorCustomStateEnum_Amount] = {
CDnActorState::Custom_None,
CDnActorState::Custom_Ground,
CDnActorState::Custom_Fly,
CDnActorState::Custom_UnderGround,
CDnActorState::Custom_Fly2,
};
char *CDnActorState::s_szActorCustomStateString[CDnActorState::ActorCustomStateEnum_Amount] = {
"Custom_None",
"Custom_Ground",
"Custom_Fly",
"Custom_UnderGround",
};
float CDnActorState::s_fMaxStiffTime = 3.f;
float CDnActorState::s_fCriticalDamageProb = 2.0f;
CDnActorState::CDnActorState()
{
m_nActorTableID = 0;
m_nLevel = 0;
m_ActorType = (ActorTypeEnum)-1;
m_State = ActorStateEnum::Stay;
m_CustomState = ActorCustomStateEnum::Custom_None;
m_StateEffect = ActorStateEffectEnum::StateEffect_None;
m_Material = ActorMaterialEnum::Flesh;
m_fWeight = 0.f;
m_nHeight = 0;
m_nUnitSize = 0;
m_fRotateAngleSpeed = 720.f;
m_nPressLevel = 0;
/*
m_nStrength = 0;
m_nAgility = 0;
m_nIntelligence = 0;
m_nStamina = 0;
m_nMaxHP = m_nHP = 0;
m_nMaxSP = m_nSP = 0;
m_nMoveSpeed = 0;
m_nAttackP[0] = m_nAttackP[1] = 0;
m_nAttackM[0] = m_nAttackM[1] = 0;
m_nDefenseP = 0;
m_nDefenseM = 0;
m_fDownDelayProb = 0.f;
m_nStiff = 0;
m_nStiffResistance = 0;
m_nCritical = 0;
m_nCriticalResistance = 0;
m_nStun = 0;
m_nStunResistance = 0;
memset( m_fElementAttack, 0, sizeof(m_fElementAttack) );
memset( m_fElementDefense, 0, sizeof(m_fElementDefense) );
*/
m_bHittable = true;
m_bMovable = true;
m_bRotatable = true;
m_pActor = NULL;
m_Press = ActorPressEnum::Press_Circle;
m_nUnitSizeParam1 = 0;
m_nUnitSizeParam2 = 0;
m_StateChangeTime = 0;
#ifdef PRE_ADD_SKILLBUF_RENEW
m_bCopiedFromSummoner = false;
#endif // #ifdef PRE_ADD_SKILLBUF_RENEW
#if defined(PRE_ADD_MULTILANGUAGE)
m_nNameUiStringIndex = 0;
#endif
#ifdef PRE_ADD_BESTFRIEND
m_BFserial = 0;
#endif
}
CDnActorState::~CDnActorState()
{
}
void CDnActorState::Initialize( int nClassID )
{
DNTableFileFormat* pSox = GetDNTable( CDnTableDB::TACTOR );
if( !pSox ) return;
if( nClassID <= 0 ) return;
m_nActorTableID = nClassID;
m_Press = (ActorPressEnum)pSox->GetFieldFromLablePtr( nClassID, "_Press" )->GetInteger();
m_nUnitSizeParam1 = pSox->GetFieldFromLablePtr( nClassID, "_SizeParam1" )->GetInteger();
m_nUnitSizeParam2 = pSox->GetFieldFromLablePtr( nClassID, "_SizeParam2" )->GetInteger();
m_nUnitSize = max(m_nUnitSizeParam1, m_nUnitSizeParam2); // 큰것 저장.
#ifndef _GAMESERVER
#ifdef RENDER_PRESS_hayannal2009
if( m_Press == Press_Circle ) {
float fGap = (float)m_nUnitSizeParam1;
float fGap2 = fGap / 1.414f;
float fYGap = 10.0f;
EtVector3 vCenter(0.0f, fYGap, 0.0f);
for( int i = 0; i < 10; ++i ) m_PressVertices1[i].dwColor = 0xFF00FFFF;
m_PressVertices1[ 0 ].Position = vCenter;
m_PressVertices1[ 1 ].Position = EtVector3( vCenter.x, vCenter.y, vCenter.z + fGap );
m_PressVertices1[ 2 ].Position = EtVector3( vCenter.x + fGap2, vCenter.y, vCenter.z + fGap2 );
m_PressVertices1[ 3 ].Position = EtVector3( vCenter.x + fGap, vCenter.y, vCenter.z );
m_PressVertices1[ 4 ].Position = EtVector3( vCenter.x + fGap2, vCenter.y, vCenter.z - fGap2 );
m_PressVertices1[ 5 ].Position = EtVector3( vCenter.x, vCenter.y, vCenter.z - fGap );
m_PressVertices1[ 6 ].Position = EtVector3( vCenter.x - fGap2, vCenter.y, vCenter.z - fGap2 );
m_PressVertices1[ 7 ].Position = EtVector3( vCenter.x - fGap, vCenter.y, vCenter.z );
m_PressVertices1[ 8 ].Position = EtVector3( vCenter.x - fGap2, vCenter.y, vCenter.z + fGap2 );
m_PressVertices1[ 9 ].Position = EtVector3( vCenter.x, vCenter.y, vCenter.z + fGap );
}
else if( m_Press == Press_Capsule ) {
float fGap = (float)min(m_nUnitSizeParam1, m_nUnitSizeParam2);
float fGap2 = fGap / 1.414f;
float fYGap = 10.0f;
int nSizeX = m_nUnitSizeParam1;
int nSizeZ = m_nUnitSizeParam2;
EtVector3 vCenter1, vCenter2;
if( nSizeX < nSizeZ ) {
vCenter1.x = vCenter2.x = 0.0f;
vCenter1.y = vCenter2.y = fYGap;
vCenter1.z = (float)(nSizeZ - nSizeX);
vCenter2.z = -vCenter1.z;
}
else {
vCenter1.z = vCenter2.z = 0.0f;
vCenter1.y = vCenter2.y = fYGap;
vCenter1.x = (float)(nSizeX - nSizeZ);
vCenter2.x = -vCenter1.x;
}
// 8 1 2
// 7 0 3
// 6 5 4
for( int i = 0; i < 10; ++i ) m_PressVertices1[i].dwColor = 0xFF00FFFF;
m_PressVertices1[ 0 ].Position = vCenter1;
m_PressVertices1[ 1 ].Position = EtVector3( vCenter1.x, vCenter1.y, vCenter1.z + fGap );
m_PressVertices1[ 2 ].Position = EtVector3( vCenter1.x + fGap2, vCenter1.y, vCenter1.z + fGap2 );
m_PressVertices1[ 3 ].Position = EtVector3( vCenter1.x + fGap, vCenter1.y, vCenter1.z );
m_PressVertices1[ 4 ].Position = EtVector3( vCenter1.x + fGap2, vCenter1.y, vCenter1.z - fGap2 );
m_PressVertices1[ 5 ].Position = EtVector3( vCenter1.x, vCenter1.y, vCenter1.z - fGap );
m_PressVertices1[ 6 ].Position = EtVector3( vCenter1.x - fGap2, vCenter1.y, vCenter1.z - fGap2 );
m_PressVertices1[ 7 ].Position = EtVector3( vCenter1.x - fGap, vCenter1.y, vCenter1.z );
m_PressVertices1[ 8 ].Position = EtVector3( vCenter1.x - fGap2, vCenter1.y, vCenter1.z + fGap2 );
m_PressVertices1[ 9 ].Position = EtVector3( vCenter1.x, vCenter1.y, vCenter1.z + fGap );
for( int i = 0; i < 10; ++i ) m_PressVertices2[i].dwColor = 0xFF00FFFF;
m_PressVertices2[ 0 ].Position = vCenter2;
m_PressVertices2[ 1 ].Position = EtVector3( vCenter2.x, vCenter2.y, vCenter2.z + fGap );
m_PressVertices2[ 2 ].Position = EtVector3( vCenter2.x + fGap2, vCenter2.y, vCenter2.z + fGap2 );
m_PressVertices2[ 3 ].Position = EtVector3( vCenter2.x + fGap, vCenter2.y, vCenter2.z );
m_PressVertices2[ 4 ].Position = EtVector3( vCenter2.x + fGap2, vCenter2.y, vCenter2.z - fGap2 );
m_PressVertices2[ 5 ].Position = EtVector3( vCenter2.x, vCenter2.y, vCenter2.z - fGap );
m_PressVertices2[ 6 ].Position = EtVector3( vCenter2.x - fGap2, vCenter2.y, vCenter2.z - fGap2 );
m_PressVertices2[ 7 ].Position = EtVector3( vCenter2.x - fGap, vCenter2.y, vCenter2.z );
m_PressVertices2[ 8 ].Position = EtVector3( vCenter2.x - fGap2, vCenter2.y, vCenter2.z + fGap2 );
m_PressVertices2[ 9 ].Position = EtVector3( vCenter2.x, vCenter2.y, vCenter2.z + fGap );
// 1 2
// 0 3
for( int i = 0; i < 4; ++i ) m_PressVertices3[i].dwColor = 0xFF00FFFF;
if( nSizeX < nSizeZ ) {
m_PressVertices3[ 0 ].Position = m_PressVertices2[ 7 ].Position;
m_PressVertices3[ 1 ].Position = m_PressVertices1[ 7 ].Position;
m_PressVertices3[ 2 ].Position = m_PressVertices1[ 3 ].Position;
m_PressVertices3[ 3 ].Position = m_PressVertices2[ 3 ].Position;
}
else {
m_PressVertices3[ 0 ].Position = m_PressVertices2[ 5 ].Position;
m_PressVertices3[ 1 ].Position = m_PressVertices2[ 1 ].Position;
m_PressVertices3[ 2 ].Position = m_PressVertices1[ 1 ].Position;
m_PressVertices3[ 3 ].Position = m_PressVertices1[ 5 ].Position;
}
}
#endif
#endif
m_fWeight = pSox->GetFieldFromLablePtr( nClassID, "_Weight" )->GetFloat();
m_nHeight = pSox->GetFieldFromLablePtr( nClassID, "_Height" )->GetInteger();
m_Material = (ActorMaterialEnum)pSox->GetFieldFromLablePtr( nClassID, "_Material" )->GetInteger();
m_ActorType = (ActorTypeEnum)pSox->GetFieldFromLablePtr( nClassID, "_Class" )->GetInteger();
m_fRotateAngleSpeed = pSox->GetFieldFromLablePtr( nClassID, "_RotationAngleSpeed" )->GetFloat();
m_nPressLevel = pSox->GetFieldFromLablePtr( nClassID, "_PressLevel" )->GetInteger();
if (m_fWeight == 0.0f) //rlkt_weight
m_fWeight = 1.0f;
RefreshState();
#if defined(PRE_ADD_MISSION_COUPON)
SetHP(m_nMaxHP);
SetSP(m_nMaxSP);
#else
m_nHP = m_nMaxHP;
m_nSP = m_nMaxSP;
#endif
}
#if defined (PRE_ADD_BESTFRIEND)
bool CDnActorState::IsApplyState(CDnActor *pActor, CDnWeapon* pWeapon)
{
if( !pWeapon->IsInfinityDurability() && pWeapon->GetDurability() <= 0 )
return false;
#if defined (_GAMESERVER)
if (pActor && pActor->IsPlayerActor())
{
CDNUserSession* pSession = ((CDnPlayerActor*)pActor)->GetUserSession();
if (pSession)
{
TBestFriendInfo& Info = pSession->GetBestFriend()->GetInfo();
eItemTypeEnum cType = pWeapon->GetItemType();
int* nItemTypeParam = pWeapon->GetTypeParam();
if (cType == ITEMTYPE_PARTS && nItemTypeParam[0] == 10 && nItemTypeParam[1] == 10)
{
if (Info.biItemSerial != pWeapon->GetSerialID())
return false;
}
}
}
#endif
return true;
}
#endif
void CDnActorState::GetStateList( int ListType, CDnState::ValueType Type, std::vector<CDnState *> &VecList )
{
// 기본 셋
if( ( ListType & BaseList ) && m_BaseState.IsExistValueType( Type ) )
VecList.push_back( &m_BaseState );
// 무기 리스트 얻어온다.
if( ListType & WeaponList ) {
for( int i=0; i<2; i++ ) {
DnWeaponHandle hWeapon = m_pActor->CDnActor::GetWeapon(i);
if( !hWeapon ) continue;
#if defined (PRE_ADD_BESTFRIEND)
if (!IsApplyState(m_pActor, hWeapon)) continue;
#else
if( !hWeapon->IsInfinityDurability() && hWeapon->GetDurability() <= 0 ) continue;
#endif
if( m_pActor->IsPlayerActor() ) {
std::vector<int> nVecJobHistory;
if( ((CDnPlayerActor*)m_pActor)->GetJobHistory( nVecJobHistory ) > 0 )
if( hWeapon->IsPermitPlayer( nVecJobHistory ) == false ) continue;
}
if( hWeapon->IsExistValueType( Type ) ) {
VecList.push_back( hWeapon );
}
if( hWeapon->IsActiveEnchant() ) {
if( hWeapon->GetEnchantState() && hWeapon->GetEnchantState()->IsExistValueType( Type ) )
VecList.push_back( hWeapon->GetEnchantState() );
}
if( hWeapon->IsActivePotential() ) {
if( hWeapon->GetPotentialState() && hWeapon->GetPotentialState()->IsExistValueType( Type ) )
VecList.push_back( hWeapon->GetPotentialState() );
}
}
}
// 상태이상 state를 얻어온다.
if( ListType & StateEffectList ) {
BLOW_STATE_LIST_ITER iter = m_listBlowState.begin();
BLOW_STATE_LIST_ITER iter_end = m_listBlowState.end();
for( ; iter != iter_end; ++iter )
{
if( !(*iter)->IsExistValueType( Type ) ) continue;
VecList.push_back( (*iter) );
}
}
// BeforePost 상태효과 state 를 얻어온다.
if( ListType & BeforePostStateEffectList )
{
BLOW_STATE_LIST_ITER iter = m_listBeforePostBlowState.begin();
BLOW_STATE_LIST_ITER iter_end = m_listBeforePostBlowState.end();
for( ; iter != iter_end; ++iter )
{
if( !(*iter)->IsExistValueType( Type ) ) continue;
VecList.push_back( (*iter) );
}
}
// Post 상태이상 state를 얻어온다.
if( ListType & PostStateEffectList ) {
BLOW_STATE_LIST_ITER iter = m_listPostBlowState.begin();
BLOW_STATE_LIST_ITER iter_end = m_listPostBlowState.end();
for( ; iter != iter_end; ++iter )
{
if( !(*iter)->IsExistValueType( Type ) ) continue;
VecList.push_back( (*iter) );
}
}
}
#ifdef PRE_ADD_SKILLBUF_RENEW
void CDnActorState::GetBuffStateList( CDnState::ValueType Type, std::vector<CDnState *> &VecList )
{
BLOW_STATE_LIST_ITER iter = m_listBuffBlowState.begin();
BLOW_STATE_LIST_ITER iter_end = m_listBuffBlowState.end();
for( ; iter != iter_end; ++iter )
{
if( !(*iter)->IsExistValueType( Type ) ) continue;
VecList.push_back( (*iter) );
}
}
#endif // #ifdef PRE_ADD_SKILLBUF_RENEW
void CDnActorState::SetLevel( int nValue )
{
m_nLevel = nValue;
RefreshState();
#if defined(PRE_ADD_TOTAL_LEVEL_SKILL)
OnLevelChange();
#endif // PRE_ADD_TOTAL_LEVEL_SKILL
}
void CDnActorState::RefreshState( RefreshStateExtentEnum Extent, StateTypeEnum Type )
{
if( Extent == RefreshAll ) CalcBaseState( Type );
RefreshAdditionalState( Extent, Type );
CalcState( Extent, Type );
OnRefreshState();
}
float CDnActorState::GetLevelWeightValue()
{
int nIndex = CGlobalWeightTable::LevelWeight + m_nLevel - 1;
#ifdef _GAMESERVER
CDNGameRoom *pRoom = m_pActor->GetGameRoom();
if( pRoom && pRoom->bIsLevelRegulation() ) nIndex = CGlobalWeightTable::PvPLevelWeight;
#else
CDnGameTask *pGameTask = (CDnGameTask*)CTaskManager::GetInstance().GetTask( "GameTask" );
if( pGameTask ) {
switch( pGameTask->GetGameTaskType() ) {
case GameTaskType::PvP:
if( ((CDnPvPGameTask*)pGameTask)->IsUseRegulation() )
nIndex = CGlobalWeightTable::PvPLevelWeight;
break;
case GameTaskType::DarkLair:
nIndex = CGlobalWeightTable::PvPLevelWeight;
break;
}
}
#endif
if( nIndex < 0 || nIndex >= CGlobalWeightTable::Amount ) nIndex = CGlobalWeightTable::LevelWeight;
return CGlobalWeightTable::GetInstance().GetValue( (CGlobalWeightTable::WeightTableIndex)nIndex );
}
bool CDnActorState::IsNeedPvPLevelWeight()
{
bool bPvPLevelWeight = false;
#ifdef _GAMESERVER
CDNGameRoom *pRoom = m_pActor->GetGameRoom();
if( pRoom && pRoom->bIsLevelRegulation() )
bPvPLevelWeight = true;
#else
CDnGameTask *pGameTask = (CDnGameTask*)CTaskManager::GetInstance().GetTask( "GameTask" );
if( pGameTask )
{
switch( pGameTask->GetGameTaskType() )
{
case GameTaskType::PvP:
if( ((CDnPvPGameTask*)pGameTask)->IsUseRegulation() )
bPvPLevelWeight = true;
break;
case GameTaskType::DarkLair:
bPvPLevelWeight = true;
break;
}
}
#endif // #ifdef _GAMESERVER
return bPvPLevelWeight;
}
float CDnActorState::GetDefenseConstant( void )
{
// #33536 이슈에 따라 PlayerCommonLevelTable 에서 상수 값을 가져오도록 변경.
// 기존 Globaltable -> PlayerCommonLevelTable 로 변경. 몬스터든 플레이어든 상관 없음.
float fResult = 0.0f;
bool bPvPLevelWeight = IsNeedPvPLevelWeight();
if( bPvPLevelWeight )
{
fResult = CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::DefenseConstant );
#ifdef PRE_ADD_DWC
if( m_pActor && m_pActor->IsPlayerActor() )
{
if( ((CDnPlayerActor*)m_pActor)->GetAccountLevel() == AccountLevel_DWC )
fResult = CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::DWC_DefenseConstant );
}
#endif
}
else
{
#ifdef _GAMESERVER
TPlayerCommonLevelTableInfo* pPlayerCommonLevelTableInfo = g_pDataManager->GetPlayerCommonLevelTable(GetLevel());
if( pPlayerCommonLevelTableInfo )
fResult = pPlayerCommonLevelTableInfo->fDefense;
#else
DNTableFileFormat* pSoxPlayerCommonLevel = GetDNTable( CDnTableDB::TPLAYERCOMMONLEVEL );
if( pSoxPlayerCommonLevel )
fResult = pSoxPlayerCommonLevel->GetFieldFromLablePtr( GetLevel() , "_Cdefense" )->GetFloat();
#endif
}
return fResult;
}
float CDnActorState::GetCriticalConstant( void )
{
// #33536 이슈에 따라 PlayerCommonLevelTable 에서 상수 값을 가져오도록 변경.
// 기존 Globaltable -> PlayerCommonLevelTable 로 변경. 몬스터든 플레이어든 상관 없음.
float fResult = 0.0f;
bool bPvPLevelWeight = IsNeedPvPLevelWeight();
if( bPvPLevelWeight )
{
fResult = CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::CriticalConstant );
#ifdef PRE_ADD_DWC
if( m_pActor && m_pActor->IsPlayerActor() )
{
if( ((CDnPlayerActor*)m_pActor)->GetAccountLevel() == AccountLevel_DWC )
fResult = CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::DWC_CriticalConstant );
}
#endif
}
else
{
#ifdef _GAMESERVER
TPlayerCommonLevelTableInfo* pPlayerCommonLevelTableInfo = g_pDataManager->GetPlayerCommonLevelTable(GetLevel());
if( pPlayerCommonLevelTableInfo )
fResult = pPlayerCommonLevelTableInfo->fCritical;
#else
DNTableFileFormat* pSoxPlayerCommonLevel = GetDNTable( CDnTableDB::TPLAYERCOMMONLEVEL );
if( pSoxPlayerCommonLevel )
fResult = pSoxPlayerCommonLevel->GetFieldFromLablePtr( GetLevel() , "_Ccritical" )->GetFloat();
#endif
}
return fResult;
}
float CDnActorState::GetFinalDamageConstant( void )
{
// #33536 이슈에 따라 PlayerCommonLevelTable 에서 상수 값을 가져오도록 변경.
// 기존 Globaltable -> PlayerCommonLevelTable 로 변경. 몬스터든 플레이어든 상관 없음.
float fResult = 0.0f;
bool bPvPLevelWeight = IsNeedPvPLevelWeight();
if( bPvPLevelWeight )
{
fResult = CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::FinalDamageConstant );
#ifdef PRE_ADD_DWC
if( m_pActor && m_pActor->IsPlayerActor() )
{
if( ((CDnPlayerActor*)m_pActor)->GetAccountLevel() == AccountLevel_DWC )
fResult = CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::DWC_FinalDamageConstant );
}
#endif
}
else
{
#ifdef _GAMESERVER
TPlayerCommonLevelTableInfo* pPlayerCommonLevelTableInfo = g_pDataManager->GetPlayerCommonLevelTable(GetLevel());
if( pPlayerCommonLevelTableInfo )
fResult = pPlayerCommonLevelTableInfo->fFinalDamage;
#else
DNTableFileFormat* pSoxPlayerCommonLevel = GetDNTable( CDnTableDB::TPLAYERCOMMONLEVEL );
if( pSoxPlayerCommonLevel )
fResult = pSoxPlayerCommonLevel->GetFieldFromLablePtr( GetLevel() , "_Cfinaldamage" )->GetFloat();
#endif
}
return fResult;
}
void CDnActorState::AddBlowState( CDnState *pState, AddBlowStateType eAddBlowStateType , bool bIsBuff )
{
ASSERT(pState&&"CDnActorState::AddBlowState");
if( !pState ) return;
switch( eAddBlowStateType )
{
case Equip_Buff_Level:
{
#ifdef PRE_ADD_SKILLBUF_RENEW
if( bIsBuff )
m_listBuffBlowState.push_back( pState );
else
m_listBlowState.push_back( pState );
#else
m_listBlowState.push_back( pState );
#endif
}
break;
case Equip_Skill_Level:
m_listBeforePostBlowState.push_back( pState );
break;
case Skill_Level:
m_listPostBlowState.push_back( pState );
break;
}
}
void CDnActorState::DelBlowState( CDnState *pState )
{
ASSERT(pState&&"CDnActorState::AddBlowState");
if( !pState ) return;
BLOW_STATE_LIST_ITER iter;
BLOW_STATE_LIST_ITER iter_end;
#ifdef PRE_ADD_SKILLBUF_RENEW
iter = m_listBuffBlowState.begin();
iter_end = m_listBuffBlowState.end();
for( ; iter != iter_end; )
{
if( (*iter) == pState )
{
iter = m_listBuffBlowState.erase(iter);
return;
}
else
{
++iter;
}
}
#endif // #ifdef PRE_ADD_SKILLBUF_RENEW
iter = m_listBlowState.begin();
iter_end = m_listBlowState.end();
for( ; iter != iter_end; )
{
if( (*iter) == pState )
{
iter = m_listBlowState.erase(iter);
return;
}
else
{
++iter;
}
}
iter = m_listPostBlowState.begin();
iter_end = m_listPostBlowState.end();
for( ; iter != iter_end; )
{
if( (*iter) == pState )
{
iter = m_listPostBlowState.erase(iter);
return;
}
else
{
++iter;
}
}
iter = m_listBeforePostBlowState.begin();
iter_end = m_listBeforePostBlowState.end();
for( ; iter != iter_end; )
{
if( (*iter) == pState )
{
iter = m_listBeforePostBlowState.erase( iter );
return;
}
else
{
++iter;
}
}
}
CDnActorState::ActorStateEnum CDnActorState::String2ActorStateEnum( const char *szStr )
{
for( int i=0; i<CDnActorState::ActorStateEnum_Amount; i++ ) {
if ( CDnActorState::s_szActorStateString[i] != NULL )
if( _stricmp( szStr, CDnActorState::s_szActorStateString[i] ) == NULL ) return (CDnActorState::ActorStateEnum)CDnActorState::s_nActorStateIndex[i];
}
return (CDnActorState::ActorStateEnum)CDnActorState::s_nActorStateIndex[0];
}
/*
#ifdef _SHADOW_TEST
bool CDnActorState::IsDie() {
CDnActor *pActor = dynamic_cast<CDnActor *>(this);
if( pActor->IsShadowActor() ) return true;
if( m_nHP <= 0 ) return true;
return false;
}
bool CDnActorState::IsDie() const {
const CDnActor *pActor = dynamic_cast<const CDnActor *>(this);
if( pActor->IsShadowActor() ) return true;
if( m_nHP <= 0 ) return true;
return false;
}
#endif //_SHADOW_TEST
*/
bool CDnActorState::IsDie()
{
#ifdef _SHADOW_TEST
const CDnActor *pActor = dynamic_cast<const CDnActor *>(this);
if( pActor->IsShadowActor() ) return true;
#endif //_SHADOW_TEST
if( m_nHP <= 0 ) return true;
return false;
}
void CDnActorState::CopyStateFromThis( DnActorHandle hActor, bool bDontCopySkillStateEffect/* = false*/ )
{
if( !hActor )
return;
// 중요. 내부적으로 CDnActorState 클래스에서 m_pActor 포인터를 물고 있기 때문에 m_pActor 는 덮어씌워지면 안된다.
CDnActor* pMyActor = m_pActor;
CDnActorState* pActorStateToCopy = static_cast<CDnActorState *>(hActor.GetPointer());
*(static_cast<CDnActorState *>(this)) = *(pActorStateToCopy);
m_pActor = pMyActor;
// 소환자에게 추가되어있던 blowstate 는 삭제한다. (#17931)
m_listBlowState.clear();
#ifdef PRE_ADD_SKILLBUF_RENEW
m_listBuffBlowState.clear();
#endif // #ifdef PRE_ADD_SKILLBUF_RENEW
m_listPostBlowState.clear();
m_listBeforePostBlowState.clear();
m_BaseState = *(pActorStateToCopy->GetBaseState());
// #37841 소환수의 능력치가 복사될 때 소환자의 상태효과로 늘어난 능력치만 제외하고 복사되는 경우가 생김.
if( false == bDontCopySkillStateEffect )
{
// #31011 이슈로 인해 스킬의 상태효과로 부여되는 소환되는 몹의 StateStep[ 1 ] 은 비우도록 하고
// StateStep[ 0 ] 으로 현재 능력치를 몰아주도록 한다.
// 렐릭도 버프 상태효과로 인한 공격력 강화가 적용되게 되는 것.
#ifdef PRE_ADD_SKILLBUF_RENEW
// 스킬 개편으로 버프 상태효과와 스킬 상태효과가 구분되기 때문에 RefreshAll 로 능력치 갱신됨.
// 따라서 StateStep 배열의 내용들은 몬스터의 값으로 덮어씌워지기 때문에
// BaseState 에 몰아주도록 한다. BaseState 는 갱신 안하도록 막아놓았다.
// Step[0]에 BaseState값이 합산된 상태임.
m_BaseState = *(pActorStateToCopy->GetStateStep( 0 ));
m_BaseState += *(pActorStateToCopy->GetStateStep( 1 ));
// RefreshSkill 로 PostStateEffect 만 갱신해줄때 BaseState 값이 포함된 것이 필요하다.
m_StateStep[ 0 ] = *(pActorStateToCopy->GetStateStep( 0 ));
#else
m_StateStep[ 0 ] = *(pActorStateToCopy->GetStateStep( 0 ));
m_StateStep[ 0 ] += *(pActorStateToCopy->GetStateStep( 1 ));
#endif // #ifdef PRE_ADD_SKILLBUF_RENEW
m_StateStep[ 1 ].ResetState();
}
else
{
// 모두 0 으로 만들어놓고
ResetState();
// 상태효과로 주어진 능력치만 제외하고 더해준다.
// Step[0]에 BaseState값이 합산된 상태임. 그래서 baseState는 따로 더할 필요 없음
*(static_cast<CDnState *>(this)) += *const_cast<CDnState*>((pActorStateToCopy->GetStateStep( 0 )));
// 갖고 있는 각 스텝의 값들도 맞춰준다.
#ifdef PRE_ADD_SKILLBUF_RENEW
m_BaseState = *(pActorStateToCopy->GetStateStep( 0 ));
// RefreshSkill 로 PostStateEffect 만 갱신해줄때 BaseState 값이 포함된 것이 필요하다.
m_StateStep[ 0 ] = *(pActorStateToCopy->GetStateStep( 0 ));
#else
m_StateStep[ 0 ] = *(pActorStateToCopy->GetStateStep( 0 ));
#endif // #ifdef PRE_ADD_SKILLBUF_RENEW
m_StateStep[ 1 ].ResetState();
}
#ifdef PRE_ADD_SKILLBUF_RENEW
m_bCopiedFromSummoner = true;
#endif // #ifdef PRE_ADD_SKILLBUF_RENEW
}
void CDnActorState::SetStateChangeTime()
{
if (m_pActor)
m_StateChangeTime = m_pActor->GetLocalTime();
}
#if defined(PRE_ADD_MISSION_COUPON) && (_GAMESERVER)
void CDnActorState::SetHP( INT64 nValue )
{
//hp %를 10구간으로 구분. -> 0~9% 0구간, 10~19 : 1구간 ..
bool bCheck = (m_nHP != 0 && m_nMaxHP != 0);
int nPrevPercent = GetHPPercent()/10 < 10 ? GetHPPercent()/10 : 9; //100% 이상은 9 구간으로
m_nHP = nValue;
m_nHP = (m_nHP < 0) ? 0 : m_nHP;
if( bCheck && nPrevPercent != (GetHPPercent()/10 < 10 ? GetHPPercent()/10 : 9) )
{
if ( GetMaxHP() != 0 && m_pActor && m_pActor->IsPlayerActor())
{
CDNUserSession* pSession = ((CDnPlayerActor*)m_pActor)->GetUserSession();
if (pSession)
pSession->GetEventSystem()->OnEvent( EventSystem::OnHPChanged );
}
}
}
void CDnActorState::SetSP( int nValue )
{
//mp %를 10구간으로 구분. -> 0~9% 0구간, 10~19 : 1구간 ..
bool bCheck = (m_nSP != 0 && m_nMaxSP != 0);
int nPrevPercent = GetSPPercent()/10 < 10 ? GetSPPercent()/10 : 9; //100% 이상은 9 구간으로
m_nSP = nValue;
if( bCheck && nPrevPercent != (GetSPPercent()/10 < 10 ? GetSPPercent()/10 : 9) )
{
if ( GetMaxSP() != 0 && m_pActor && m_pActor->IsPlayerActor())
{
CDNUserSession* pSession = ((CDnPlayerActor*)m_pActor)->GetUserSession();
if (pSession)
pSession->GetEventSystem()->OnEvent( EventSystem::OnMPChanged );
}
}
}
#endif