#include "StdAfx.h" #include "DnWorldBrokenProp.h" #include "DnTableDB.h" #include "DnWorld.h" #include "DnWeapon.h" #include "DnDamageBase.h" #include "DnProjectile.h" #include "TaskManager.h" #include "DnPartyTask.h" #include "DnItemTask.h" #include "DNUserSession.h" #include "DnPropState.h" #include "DnPropCondition.h" #include "DnPropStateDoAction.h" #include "DnPropStateTrigger.h" #include "DnPropCondiDurability.h" #include "DNLogConnection.h" #include "DNGameTask.h" #include "DnPlayerActor.h" #include "DnCannonMonsterActor.h" #include "DnMonsterActor.h" #include "DnStateBlow.h" CDnWorldBrokenProp::CDnWorldBrokenProp( CMultiRoom *pRoom ) : CDnWorldActProp( pRoom ) //, CDnDamageBase( DamageObjectTypeEnum::Prop ) { m_nDurability = 0; //m_nBreakActionCount = 0; m_bHittable = false; m_bNoDamage = false; m_nItemDropGroupTableID = 0; m_pLastHitObject = NULL; m_bBroken = false; m_nLastHitUniqueID = -1; m_iLastRandomSeed = 0; m_bHitted = false; m_pBrokenActionState = NULL; m_pTriggerActionState = NULL; m_LastDamageTime = 0; } CDnWorldBrokenProp::~CDnWorldBrokenProp() { SAFE_DELETE_VEC( m_VecDropItemList ); ReleasePostCustomParam(); } bool CDnWorldBrokenProp::InitializeTable( int nTableID ) { if( CDnWorldActProp::InitializeTable( nTableID ) == false ) return false; //* //DNTableFileFormat* pSox = GetDNTable( CDnTableDB::TPROP ); //m_nDurability = pSox->GetFieldFromLablePtr( nTableID, "_Durability" )->GetInteger(); //m_nItemDropTableID = pSox->GetFieldFromLablePtr( nTableID, "_ItemDropTableIndex" )->GetInteger(); //if( m_nItemDropTableID > 0 ) { // CDnDropItem::CalcDropItemList( GetRoom(), m_nItemDropTableID, m_VecDropItemList ); // for( DWORD i=0; inDurability; if( -1 != m_nDurability ) { if( 0 == m_nDurability ) m_nDurability = 1; m_nItemDropGroupTableID = pStruct->nItemDropGroupTableID; if( m_nItemDropGroupTableID > 0 ) { CDnDropItem::CalcDropItemList( GetRoom(), Dungeon::Difficulty::Max, m_nItemDropGroupTableID, m_VecDropItemList ); if (m_VecDropItemList.empty()){ // ÇÁ¶ø·Î±× // g_pLogConnection->QueryLogStage(GetRoom()->GetRoomID(), pTask->GetMapTableID(), 0, 0, nTableID); // ½ºÅ×ÀÌÁö ·Î±× 090226 } else { for( DWORD i=0; iQueryLogStage(GetRoom()->GetRoomID(), pTask->GetMapTableID(), 0, m_VecDropItemList[i].nItemID, nTableID); // ½ºÅ×ÀÌÁö ·Î±× 090226 } } } } } return true; } bool CDnWorldBrokenProp::Initialize( CEtWorldSector *pParentSector, const char *szPropName, EtVector3 &vPos, EtVector3 &vRotate, EtVector3 &vScale ) { // FSM À» BrokenProp¿¡ ¸Â°Ô ÃʱâÈ­ ÇØÁØ´Ù.. // ³»±¸µµ°¡ -1 ÀÎ ÇÁ¶øÀº brokenÀÌ ¾Æ´Ô.. if( -1 == m_nDurability ) return true; // state »ý¼º CDnPropState* pNormalState = CDnPropState::Create( GetMySmartPtr(), CDnPropState::NORMAL ); CDnPropState* pHitActionState = CDnPropState::Create( GetMySmartPtr(), CDnPropState::DO_ACTION ); CDnPropState* pItemDropState = CDnPropState::Create( GetMySmartPtr(), CDnPropState::ITEM_DROP ); CDnPropState* pTriggerState = CDnPropState::Create( GetMySmartPtr(), CDnPropState::TRIGGER ); CDnPropState* pBrokenActionState = CDnPropState::Create( GetMySmartPtr(), CDnPropState::DO_ACTION ); static_cast(pHitActionState)->AddActionName( "Hit" ); m_pBrokenActionState = static_cast(pBrokenActionState); static_cast(pTriggerState)->SetFuncName( "CDnWorldProp::OnBrokenProp" ); m_pTriggerActionState = static_cast(pTriggerState); // Á¶°Ç »ý¼º CDnPropCondition* pHitCondition = CDnPropCondition::Create( GetMySmartPtr(), CDnPropCondition::IS_HIT ); CDnPropCondition* pNULLCondition = CDnPropCondition::Create( GetMySmartPtr(), CDnPropCondition::NULL_CONDITION ); CDnPropCondition* pDurabilityCondition = CDnPropCondition::Create( GetMySmartPtr(), CDnPropCondition::COMPARE_DURABILITY ); static_cast(pDurabilityCondition)->Initialize( 0, CDnPropCondiDurability::LESS_EQUAL ); m_pFSM->AddCondition( pHitCondition ); m_pFSM->AddCondition( pNULLCondition ); m_pFSM->AddCondition( pDurabilityCondition ); m_pFSM->AddState( pNormalState ); m_pFSM->AddState( pHitActionState ); m_pFSM->AddState( pItemDropState ); m_pFSM->AddState( pTriggerState); m_pFSM->AddState( pBrokenActionState ); pNormalState->AddTransitState( pHitActionState, pHitCondition ); pHitActionState->AddTransitState( pNormalState, pNULLCondition ); pNormalState->AddTransitState( pTriggerState, pDurabilityCondition ); pTriggerState->AddTransitState( pItemDropState, pNULLCondition ); pItemDropState->AddTransitState( pBrokenActionState, pNULLCondition ); m_pFSM->SetEntryState( pNormalState ); bool bResult = CDnWorldActProp::Initialize( pParentSector, szPropName, vPos, vRotate, vScale ); if( !bResult ) return false; return true; } bool CDnWorldBrokenProp::CreateObject() { bool bResult = CDnWorldActProp::CreateObject(); if( m_pBrokenActionState ) { if( -1 == m_nDurability ) return true; if( bResult ) { char szTemp[16]; for( int i=0; ; i++ ) { sprintf_s( szTemp, "Break_%c", 'a' + i ); if( IsExistAction( szTemp ) == false ) break; m_pBrokenActionState->AddActionName( szTemp ); //m_nBreakActionCount++; } } } return bResult; } void CDnWorldBrokenProp::UpdatePropBreakToHitter( CDnDamageBase* pHitter ) { if( pHitter ) { DnActorHandle hActor = pHitter->GetActorHandle(); if( hActor ) { if ( hActor->IsPlayerActor() ) { CDnPlayerActor *pPlayer = static_cast(hActor.GetPointer()); pPlayer->UpdatePropBreak(); } else if( CDnActorState::Cannon == hActor->GetActorType() ) { CDnCannonMonsterActor* pCannonMonsterActor = static_cast(hActor.GetPointer()); DnActorHandle hPlayerActor = pCannonMonsterActor->GetMasterPlayerActor(); if( hPlayerActor && hPlayerActor->IsPlayerActor() ) { CDnPlayerActor* pPlayer = static_cast(hPlayerActor.GetPointer()); pPlayer->UpdatePropBreak(); } } } } } void CDnWorldBrokenProp::CalcDamage( CDnDamageBase *pHitter, CDnDamageBase::SHitParam &HitParam ) { // if( m_nDurability <= 0 ) return; if( m_bDestroy == true ) return; if( m_bBroken ) return; m_pLastHitObject = pHitter; m_LastDamageTime = HitParam.RemainTime; m_nLastHitUniqueID = HitParam.iUniqueID; m_nDurability -= (int)( HitParam.fDurability * 100.f ); // NOTE: Æ®¸®°Å¿¡¼­ IsBroken() »ç¿ëÇÔ.. ´Ù¸¥ ÇÔ¼öµéµµ Ã¼Å©ÇØºÁ¾ß ÇÒµí. // Æ®¸®°Å °ü·ÃÇØ¼± »óȲÀÌ º¯°æµÇÀÚ¸¶ÀÚ °ð¹Ù·Î ÀüÀÌ Ã¼Å©¸¦ µ¹·Á¾ß ÇÑ´Ù. if( m_nDurability <= 0 ) { m_bBroken = true; //¼Òȯ ¸ó½ºÅÍÀÏ °æ¿ì ÁÖÀÎ ¾×Å͸¦ ã¾Æ¼­ ¼³Á¤ ÇØ¾ß ÇÔ. DnActorHandle hHitterActor; if (pHitter) hHitterActor = pHitter->GetActorHandle(); //¸ó½ºÅÍ ¾×ÅÍÀÎ °æ¿ì if (hHitterActor && hHitterActor->IsMonsterActor()) { DnActorHandle hMasterActor; CDnMonsterActor* pMonsterActor = NULL; pMonsterActor = static_cast(hHitterActor.GetPointer()); if (pMonsterActor) hMasterActor = pMonsterActor->GetSummonerPlayerActor(); //Á¤»óÀûÀÎ ÁÖÀÎ ¾×Å͸¦ ã¾ÒÀ¸¸é, hHitterActor¸¦ ÁÖÀÎ ¾×ÅÍ·Î º¯°æÇÑ´Ù. if (hMasterActor) hHitterActor = hMasterActor; } m_pTriggerActionState->AddFuncParam( "LastBrokenPropActor", hHitterActor ? hHitterActor->GetUniqueID() : -1 ); m_pFSM->Process( 0, 0.0f ); UpdatePropBreakToHitter( pHitter ); // SetLastAccessActor( pHitter->GetActorHandle() ); } //if( m_nDurability <= 0 ) { // CDnWorld::GetInstance(GetRoom()).OnTriggerEventCallback( "CDnWorldProp::OnBrokenProp", m_LocalTime, 0.f ); // m_bBroken = true; // m_nDurability = 0; // if( m_nBreakActionCount > 0 ) { // char szTemp[32]; // sprintf_s( szTemp, "Break_%c", 'a' + _rand(GetRoom())%m_nBreakActionCount ); // SetActionQueue( szTemp ); // } // // ¾ÆÀÌÅÛ µå¶ø ÇØÁÖÀÚ~ // DropItems(); //} //else { // SetActionQueue( "Hit" ); //} if( HitParam.hWeapon ) { if( HitParam.hWeapon->GetWeaponType() & CDnWeapon::Projectile ) { CDnProjectile *pProjectile = static_cast(HitParam.hWeapon.GetPointer()); if( pProjectile ) pProjectile->OnDamageSuccess( CDnActor::Identity(), HitParam ); else HitParam.hWeapon->SetDestroy(); } } DnActorHandle hHitterActor; if (pHitter) hHitterActor = pHitter->GetActorHandle(); if (hHitterActor && hHitterActor->IsAppliedThisStateBlow(STATE_BLOW::BLOW_179)) { DnActorHandle hTargetActor; DNVector(DnBlowHandle) vlhBlows; hHitterActor->GetStateBlow()->GetStateBlowFromBlowIndex( STATE_BLOW::BLOW_179, vlhBlows ); int iNumBlow = (int)vlhBlows.size(); for( int i = 0; i < iNumBlow; ++i ) { DnBlowHandle hBlow = vlhBlows.at(i); if (hBlow) hBlow->OnTargetHit(hTargetActor); } } } void CDnWorldBrokenProp::OnDamage( CDnDamageBase *pHitter, CDnDamageBase::SHitParam &HitParam ) { if( -1 == m_nDurability ) return; int nSeed = CRandom::Seed(GetRoom()); _srand( GetRoom(), nSeed ); m_iLastRandomSeed = nSeed; CalcDamage( pHitter, HitParam ); // ÀÌ ºÎºÐµµ MPTransAction À» »ó¼Ó¹Þ°í ÀÖ´ÂÁö¶ó ¾î¿ ¼ö ¾ø³×.. switch( pHitter->GetDamageObjectType() ) { case CDnDamageBase::DamageObjectTypeEnum::Actor: { DnActorHandle hActor = pHitter->GetActorHandle(); if( !hActor ) break; // Request Damage BYTE pBuffer[128]; CPacketCompressStream Stream( pBuffer, 128 ); DWORD dwUniqueID = hActor->GetUniqueID(); DWORD dwWeaponUniqueID = -1; INT64 nWeaponSerialID = -1; bool bSendWeaponSerialID = false; if( HitParam.hWeapon ) { if( HitParam.hWeapon->GetSerialID() == -1 ) dwWeaponUniqueID = HitParam.hWeapon->GetUniqueID(); else { bSendWeaponSerialID = true; nWeaponSerialID = HitParam.hWeapon->GetSerialID(); } } Stream.Write( &nSeed, sizeof(int) ); Stream.Write( &dwUniqueID, sizeof(DWORD) ); Stream.Write( &m_nDurability, sizeof(int) ); Stream.Write( &bSendWeaponSerialID, sizeof(bool) ); if( bSendWeaponSerialID ) Stream.Write( &nWeaponSerialID, sizeof(INT64) ); else Stream.Write( &dwWeaponUniqueID, sizeof(DWORD) ); Stream.Write( &HitParam.vPosition, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); Stream.Write( &HitParam.vViewVec, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT ); OnDamageWriteAdditionalPacket( HitParam, &Stream ); Send( eProp::SC_ONDAMAGE, &Stream ); } break; case CDnDamageBase::DamageObjectTypeEnum::Prop: break; } m_bHitted = true; } bool CDnWorldBrokenProp::IsHittedAndReset( void ) { bool bResult = m_bHitted; m_bHitted = false; return bResult; } bool CDnWorldBrokenProp::IsHittable( CDnDamageBase *pHitter, LOCAL_TIME LocalTime, int iHitUniqueID /*= -1*/ ) { if( m_bBroken ) return false; if( false == IsShow() ) return false; if( m_pLastHitObject == pHitter ) { if( -1 != m_nLastHitUniqueID ) { if( m_nLastHitUniqueID == iHitUniqueID ) { if( m_LastDamageTime > LocalTime ) return false; } } else if( m_LastDamageTime > LocalTime ) return false; } if( m_bNoDamage ) return false; return m_bHittable; } void CDnWorldBrokenProp::OnSignal( SignalTypeEnum Type, void *pPtr, LOCAL_TIME LocalTime, LOCAL_TIME SignalStartTime, LOCAL_TIME SignalEndTime, int nSignalIndex ) { switch( Type ) { case STE_CanHit: { CanHitStruct *pStruct = (CanHitStruct *)pPtr; m_bHittable = ( pStruct->bHittable == TRUE ) ? true : false; } break; } CDnWorldActProp::OnSignal( Type, pPtr, LocalTime, SignalStartTime, SignalEndTime, nSignalIndex ); } // BrokenProp Àº ³­ÀԽÿ¡¸¸ ¸ÂÃß¾îÁÖ¸é µÈ´Ù. void CDnWorldBrokenProp::OnSyncComplete( CDNUserSession* pBreakIntoGameSession/*=NULL*/ ) { if( !pBreakIntoGameSession ) return; CmdShow( true, pBreakIntoGameSession ); CDnWorldActProp::OnSyncComplete( pBreakIntoGameSession ); } void CDnWorldBrokenProp::_OnLifeTimeEnd( LOCAL_TIME LocalTime, float fDelta ) { m_nDurability = 0; m_bBroken = true; m_pBrokenActionState->UseCmdAction( true ); m_pFSM->Process( 0, 0.0f ); }