#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 &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 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 &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(this); if( pActor->IsShadowActor() ) return true; if( m_nHP <= 0 ) return true; return false; } bool CDnActorState::IsDie() const { const CDnActor *pActor = dynamic_cast(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(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(hActor.GetPointer()); *(static_cast(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(this)) += *const_cast((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