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

431 lines
No EOL
13 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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; i<m_VecDropItemList.size(); i++ ) {
// CDnDropItem::PreInitializeItem( GetRoom(), m_VecDropItemList[i].nItemID );
// }
//}
//*/
if( GetData() ) {
BrokenStruct *pStruct = (BrokenStruct *)GetData();
m_nDurability = pStruct->nDurability;
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()){
// <20><><EFBFBD><EFBFBD><EFBFBD>α<EFBFBD>
// g_pLogConnection->QueryLogStage(GetRoom()->GetRoomID(), pTask->GetMapTableID(), 0, 0, nTableID); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>α<EFBFBD> 090226
}
else {
for( DWORD i=0; i<m_VecDropItemList.size(); i++ ) {
#if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
if( CDnDropItem::PreInitializeItem( GetRoom(), m_VecDropItemList[i].nItemID, m_VecDropItemList[i].nEnchantID ) == false )
#else // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
if( CDnDropItem::PreInitializeItem( GetRoom(), m_VecDropItemList[i].nItemID ) == false )
#endif // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
{
m_VecDropItemList.erase( m_VecDropItemList.begin() + i );
i--;
continue;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>α<EFBFBD>
// g_pLogConnection->QueryLogStage(GetRoom()->GetRoomID(), pTask->GetMapTableID(), 0, m_VecDropItemList[i].nItemID, nTableID); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>α<EFBFBD> 090226
}
}
}
}
}
return true;
}
bool CDnWorldBrokenProp::Initialize( CEtWorldSector *pParentSector, const char *szPropName, EtVector3 &vPos, EtVector3 &vRotate, EtVector3 &vScale )
{
// FSM <20><> BrokenProp<6F><70> <20>°<EFBFBD> <20>ʱ<EFBFBD>ȭ <20><><EFBFBD>ش<EFBFBD>..
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -1 <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> broken<65><6E> <20>ƴ<EFBFBD>..
if( -1 == m_nDurability )
return true;
// state <20><><EFBFBD><EFBFBD>
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<CDnPropStateDoAction*>(pHitActionState)->AddActionName( "Hit" );
m_pBrokenActionState = static_cast<CDnPropStateDoAction*>(pBrokenActionState);
static_cast<CDnPropStateTrigger*>(pTriggerState)->SetFuncName( "CDnWorldProp::OnBrokenProp" );
m_pTriggerActionState = static_cast<CDnPropStateTrigger*>(pTriggerState);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
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<CDnPropCondiDurability*>(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<CDnPlayerActor *>(hActor.GetPointer());
pPlayer->UpdatePropBreak();
}
else
if( CDnActorState::Cannon == hActor->GetActorType() )
{
CDnCannonMonsterActor* pCannonMonsterActor = static_cast<CDnCannonMonsterActor*>(hActor.GetPointer());
DnActorHandle hPlayerActor = pCannonMonsterActor->GetMasterPlayerActor();
if( hPlayerActor && hPlayerActor->IsPlayerActor() )
{
CDnPlayerActor* pPlayer = static_cast<CDnPlayerActor*>(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: Ʈ<><C6AE><EFBFBD>ſ<EFBFBD><C5BF><EFBFBD> IsBroken() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.. <20>ٸ<EFBFBD> <20>Լ<EFBFBD><D4BC>鵵 üũ<C3BC>غ<EFBFBD><D8BA><EFBFBD> <20>ҵ<EFBFBD>.
// Ʈ<><C6AE><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> <20><>Ȳ<EFBFBD><C8B2> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD> <20><><EFBFBD>ٷ<EFBFBD> <20><><EFBFBD><EFBFBD> üũ<C3BC><C5A9> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
if( m_nDurability <= 0 )
{
m_bBroken = true;
//<2F><>ȯ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>͸<EFBFBD> ã<>Ƽ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ؾ<EFBFBD> <20><>.
DnActorHandle hHitterActor;
if (pHitter)
hHitterActor = pHitter->GetActorHandle();
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
if (hHitterActor && hHitterActor->IsMonsterActor())
{
DnActorHandle hMasterActor;
CDnMonsterActor* pMonsterActor = NULL;
pMonsterActor = static_cast<CDnMonsterActor*>(hHitterActor.GetPointer());
if (pMonsterActor)
hMasterActor = pMonsterActor->GetSummonerPlayerActor();
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>͸<EFBFBD> ã<><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, hHitterActor<6F><72> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ͷ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
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 );
// }
// // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>~
// DropItems();
//}
//else {
// SetActionQueue( "Hit" );
//}
if( HitParam.hWeapon ) {
if( HitParam.hWeapon->GetWeaponType() & CDnWeapon::Projectile ) {
CDnProjectile *pProjectile = static_cast<CDnProjectile *>(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 );
// <20><> <20>κе<CEBA> MPTransAction <20><> <20><><EFBFBD>ӹް<D3B9> <20>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD> <20><>¿ <20><> <20><><EFBFBD><EFBFBD>..
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 <20><> <20><><EFBFBD>Խÿ<D4BD><C3BF><EFBFBD> <20><><EFBFBD>߾<EFBFBD><DFBE>ָ<EFBFBD> <20>ȴ<EFBFBD>.
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 );
}