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

2564 lines
No EOL
81 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 "DnMonsterActor.h"
#include "DnWorld.h"
#include "DnWeapon.h"
#include "MAAiBase.h"
#include "DnTableDB.h"
#include "DnDropItem.h"
#include "DnPartyTask.h"
#include "DnGameTask.h"
#include "TaskManager.h"
#include "DnItemTask.h"
#include "DnBlow.h"
#include "DNGameRoom.h"
#include "DNUserSession.h"
#include "DnWorldTrapProp.h"
#include "DnStateBlow.h"
#include "navigationcell.h"
#include "navigationmesh.h"
#include "navigationpath.h"
#include "DnPlayerActor.h"
#include "DNLogConnection.h"
#include "MAWalkMovementNav.h"
#include "DNMissionSystem.h"
#include "DnProjectile.h"
#include "MAAiScript.h"
#include "DNMonsterAggroSystem.h"
#include "GameSendPacket.h"
#include "MAScanner.h"
#include "MasterRewardSystem.h"
#include "DnBlockBlow.h"
#include "DnParryBlow.h"
#include "DnCannonMonsterActor.h"
#if defined(PRE_ADD_WEEKLYEVENT)
#include "DNGameDataManager.h"
#endif
int CDnMonsterActor::s_nPositionRevisionTime = 3000;
CDnMonsterActor::CDnMonsterActor( CMultiRoom *pRoom, int nClassID )
:CDnActor( pRoom, nClassID )
,m_nMonsterClassID(0)
,m_AIDifficult( Dungeon::Difficulty::Easy )
,m_pszCanBumpActionName(NULL)
{
CDnActionBase::Initialize( this );
m_nDestroyTime = 0;
m_bTimeMonster = false;
m_fScale = 1.f;
m_nMonsterWeightTableID = -1;
m_eElementType = ElementEnum_Amount;
m_bNoDamage = false;
m_LastSendMoveMsg = 0;
m_fRotateResistance = 1.f;
m_nPartyComboCount = 0;
m_nPartyComboDelay = 0;
m_bIsTriggerMonster = false;
m_iTriggerRandomSeed = 0;
m_hProp = CDnWorldProp::Identity();
m_uiForcePositionRevisionTick = 0;
m_uiPrevForcePositionRevisionTick = 0;
m_bEnableDropItem = true;
m_nBirthAreaHandle = -1;
m_dwSummonerActorID = 0;
m_bSuicideWhenSummonerDie = false;
m_bFollowSummonerStage = false;
m_iSummonGroupID = 0;
m_fLimitSummonerDistanceSQ = 0.0f;
m_bSummoned = false;
m_bReCreatedFollowStageMonster = false;
#ifdef PRE_ADD_MONSTER_CATCH
m_iCatchedActorActionIndex = 0;
#endif // #ifdef PRE_ADD_MONSTER_CATCH
#if defined( PRE_FIX_MOVEBACK )
m_bNearMoveBack = false;
m_bPrevMoveBack = false;
#endif
m_nAutoRecallRange = 0;
#if defined(PRE_FIX_51048)
m_EnablePassiveStateEffect = false;
#endif // PRE_FIX_51048
m_bChangeAxisOnFinishAction = false;
m_isPuppetSummonMonster = false;
#ifdef PRE_MOD_DARKLAIR_RECONNECT
m_nEventAreaUniqueID = -1;
#endif // PRE_MOD_DARKLAIR_RECONNECT
#ifdef PRE_ADD_TRANSFORM_MONSTER_ACTOR
m_nSwapActorID = -1;
#endif
}
CDnMonsterActor::~CDnMonsterActor()
{
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ų <20><><EFBFBD><EFBFBD>.
if( IsEnabledAuraSkill() )
OnSkillAura( m_hAuraSkill, false );
SAFE_DELETE_VEC( m_VecDropItemList );
}
bool CDnMonsterActor::Initialize()
{
CalcMonsterWeightIndex();
CDnMonsterState::Initialize( m_nClassID );
MAAiReceiver::Initialize( m_nMonsterClassID, GetAIFileName().c_str() );
CDnActor::Initialize();
if( m_fWeight == 0.f ) m_fRevisionWeight = 0.f;
else m_fRevisionWeight = m_fWeight + ( ( m_fScale - 1.f ) * CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::ScaleWeightValue ) );
GenerationDropItem();
if( m_hObject ) {
m_hObject->SetCollisionGroup( COLLISION_GROUP_DYNAMIC( 1 ) );
m_hObject->SetTargetCollisionGroup( COLLISION_GROUP_STATIC( 1 ) | COLLISION_GROUP_DYNAMIC( 2 ) );
}
DNTableFileFormat* pSox = GetDNTable( CDnTableDB::TMONSTER );
int nStrElementType = pSox->GetFieldFromLablePtr( m_nMonsterClassID, "_Element_Str_Type" )->GetInteger();
if( nStrElementType != -1 )
m_eElementType = (ElementEnum)nStrElementType;
_ASSERT( m_pAggroSystem == NULL );
m_pAggroSystem = new CDNMonsterAggroSystem( GetActorHandle() );
_ASSERT( m_pAggroSystem != NULL );
return true;
}
void CDnMonsterActor::ProcessLook( LOCAL_TIME LocalTime, float fDelta )
{
if( bIsAILook() && bIsTurnOnAILook() )
{
Look( *m_pAi->GetAILook() );
}
else
{
bool bNaviMode = IsNaviMode();
// bool bLockTarget = IsSignalRange( STE_LockTargetLook );
#if defined( PRE_MOD_LOCK_TARGET_LOOK )
if( false == bNaviMode && 0 != m_nLockLookEventArea && true == m_bLockLookTarget )
{
if( GetLookTarget() )
ResetLook();
if( NULL != GetGameRoom() && NULL != GetGameRoom()->GetWorld() )
{
std::vector<CEtWorldEventArea *> vecArea;
GetGameRoom()->GetWorld()->FindEventAreaFromCreateUniqueID( m_nLockLookEventArea, &vecArea );
if( false == vecArea.empty() )
{
EtVector3 vAreaPosition = vecArea[0]->GetOBB()->Center;
EtVector3 * vMonsterPosition = GetPosition();
EtVector2 vDir;
vDir.x = vAreaPosition.x - vMonsterPosition->x;
vDir.y = vAreaPosition.z - vMonsterPosition->z;
EtVec2Normalize( &vDir, &vDir );
CmdLook( vDir );
}
}
}
else
#endif // #if defined( PRE_MOD_LOCK_TARGET_LOOK )
if( !bNaviMode && m_bLockLookTarget && GetAggroTarget() )
{
if( !GetLookTarget() && GetLookTarget() != GetAggroTarget() )
LookTarget( GetAggroTarget() );
}
else
{
if( GetLookTarget() )
ResetLook();
}
}
if( !IsSignalRange( STE_RotateResistance ) ) m_fRotateResistance = 1.f;
}
void CDnMonsterActor::Process( LOCAL_TIME LocalTime, float fDelta )
{
m_bLockLookTarget = false;
m_pszCanBumpActionName = NULL;
m_uiPrevForcePositionRevisionTick = m_uiForcePositionRevisionTick;
m_uiForcePositionRevisionTick = 0;
#if defined( PRE_MOD_LOCK_TARGET_LOOK )
m_nLockLookEventArea = 0;
#endif // #if defined( PRE_MOD_LOCK_TARGET_LOOK )
CDnActor::Process( LocalTime, fDelta );
PROFILE_TIME_TEST_BLOCK_START( "CDnMonsterActor::Process" );
ProcessLook( LocalTime, fDelta );
SetMoveVectorX( m_Cross.m_vXAxis );
SetMoveVectorZ( m_Cross.m_vZAxis );
if ( m_bTimeMonster && !IsDie() )
{
m_nDestroyTime -= (LOCAL_TIME)(fDelta*1000.0f);
if( m_nDestroyTime <= 0 )
CmdSuicide( false, false );
}
// <20><>ȯ<EFBFBD>ڰ<EFBFBD> <20>׾<EFBFBD><D7BE><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20>׵<EFBFBD><D7B5><EFBFBD> <20>Ǿ<EFBFBD><C7BE>ִٸ<D6B4> üũ<C3BC>ؼ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>״´<D7B4>.
if( m_bSuicideWhenSummonerDie )
{
// <20><>ȯ<EFBFBD><C8AF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ü<EFBFBD><C3BC> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ų<EFBFBD> <20>׾<EFBFBD><D7BE><EFBFBD> <20><>..
if( !m_hSummonerPlayerActor ||
m_hSummonerPlayerActor->IsDie() )
{
CmdSuicide( false, false );
}
}
// <20><><EFBFBD><EFBFBD> <20>Ÿ<EFBFBD> <20>̻<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>װ<EFBFBD> <20>Ǿ<EFBFBD><C7BE>ִٸ<D6B4> <20>׷<EFBFBD><D7B7><EFBFBD> ó<><C3B3><EFBFBD>Ѵ<EFBFBD>.
if( 0.0f < m_fLimitSummonerDistanceSQ )
{
if( m_hSummonerPlayerActor && false == m_hSummonerPlayerActor->IsDie() )
{
EtVector3 vSummonerPos = *m_hSummonerPlayerActor->GetPosition();
float fNowDistanceSQ = EtVec3LengthSq( &(vSummonerPos - *GetPosition()) );
if( m_fLimitSummonerDistanceSQ < fNowDistanceSQ )
{
CmdSuicide( false, false );
}
}
}
ProcessPositionRevision( fDelta );
ProcessPartyCombo( LocalTime, fDelta );
#ifdef PRE_ADD_MONSTER_CATCH
ProcessCatchActor( LocalTime, fDelta );
#endif // #ifdef PRE_ADD_MONSTER_CATCH
Process_AutoRecallRange();
PROFILE_TIME_TEST_BLOCK_END();
}
void CDnMonsterActor::ProcessAI(LOCAL_TIME LocalTime, float fDelta)
{
if( MATransAction::GetGameRoom() )
{
MAAiReceiver::Process( LocalTime, fDelta );
}
}
void CDnMonsterActor::OnDamage( CDnDamageBase *pHitter, SHitParam &HitParam, HitStruct *pHitStruct )
{
int nSeed = CRandom::Seed(GetRoom());
_srand( GetRoom(), nSeed );
INT64 nTemp = GetHP();
CDnActor::OnDamage( pHitter, HitParam, pHitStruct );
INT64 nDamage = nTemp - GetHP();
switch( pHitter->GetDamageObjectType() )
{
case DamageObjectTypeEnum::Actor:
{
// Aggro Process
//DnActorHandle hActor = dynamic_cast<CDnActor*>(pHitter)->GetMySmartPtr();
DnActorHandle hActor = pHitter->GetActorHandle();
if( m_pAggroSystem )
m_pAggroSystem->OnDamageAggro( hActor, HitParam, (int)nDamage );
ResetCustomAction();
// ȭ<><EFBFBD><ECB0B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><20>ÿ<EFBFBD><C3BF>̵Ǹ鼭 <20>߻<EFBFBD><DFBB>DZ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Hit <20><> Idle <20><> <20><><EFBFBD>ش<EFBFBD>.
if( GetWeapon() ) {
if( GetWeapon()->GetElementIndex( "Idle" ) != -1 )
GetWeapon()->SetActionQueue( "Idle" );
}
if( HitParam.HitType != CDnWeapon::Defense )
OnPartyCombo( hActor, pHitStruct->nPartyComboDelay );
}
break;
case DamageObjectTypeEnum::Prop:
break;
}
RequestDamage( pHitter, nSeed, nDamage );
}
void CDnMonsterActor::OnDie( DnActorHandle hHitter )
{
CDnActor::OnDie( hHitter );
CDnPartyTask *pTask = (CDnPartyTask *)CTaskManager::GetInstance(GetRoom()).GetTask( "PartyTask" );
if( !pTask ) return;
#ifdef PRE_FIX_REMOVE_AURA_ONDIE
if (IsEnabledAuraSkill())
OnSkillAura(m_hAuraSkill, false);
#endif
if( m_hSummonerPlayerActor )
{
_ASSERT( m_hSummonerPlayerActor->IsPlayerActor() );
if( m_hSummonerPlayerActor->IsPlayerActor() )
{
CDnPlayerActor* pPlayerActor = static_cast<CDnPlayerActor*>(m_hSummonerPlayerActor.GetPointer());
pPlayerActor->OnDieSummonedMonster( GetMySmartPtr() );
}
}
CDnPlayerActor* pMasterPlayerActor = NULL;
if (hHitter)
{
if (hHitter->IsPlayerActor())
pMasterPlayerActor = static_cast<CDnPlayerActor*>(hHitter.GetPointer());
else if (hHitter->IsMonsterActor())
{
CDnMonsterActor* pMonster = static_cast<CDnMonsterActor*>(hHitter.GetPointer());
if (pMonster && pMonster->IsCannonMonsterActor())
{
CDnCannonMonsterActor* pCannonMonster = static_cast<CDnCannonMonsterActor*>(hHitter.GetPointer());
if (pCannonMonster && pCannonMonster->GetMasterPlayerActor() && pCannonMonster->GetMasterPlayerActor()->IsPlayerActor())
pMasterPlayerActor = static_cast<CDnPlayerActor*>(pCannonMonster->GetMasterPlayerActor().GetPointer());
}
}
}
int nPartyCount = pTask->GetRoom()->GetUserCount() - pTask->GetRoom()->GetGMCount();
// <20><><EFBFBD><EFBFBD>ġ <20>й<EFBFBD><D0B9><EFBFBD><EFBFBD>ֽð<D6BD>. <20><><EFBFBD><EFBFBD> Add <20><><EFBFBD>ֽð<D6BD>..
// float fValue = ( ( 1.f + ( 0.9f * ( nPartyCount - 1 ) ) ) / nPartyCount );
float fExpPenalty;
float fExp;
int nValue;
float fCompleteExp;
float fItemExp = 0.f;
float fGuildRewardExp = 0.f;
float fDeadDurabilityRevision = CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::MonsterDeadDurabilityRevision );
int nDeadDurability = (int)( ( GetDeadDurability() * ( 1.f + ( fDeadDurabilityRevision * ( nPartyCount - 1 ) ) ) ) / nPartyCount );
int nFinalDeadDurability = nDeadDurability;
for( int i=0; i<nPartyCount; i++ )
{
CDNUserSession *pSession = pTask->GetRoom()->GetUserData(i);
if( !pSession )
continue;
// <20><EFBFBD>ڳ<EFBFBD><DAB3><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD> <20>ʰ<EFBFBD> <20><><EFBFBD>ش<EFBFBD>.
if( pSession->bIsGMTrace() )
continue;
DnActorHandle hActor = pSession->GetActorHandle();
if( !hActor ) continue;
pSession->GetEventSystem()->OnEvent( EventSystem::OnKillMonster2, 1, EventSystem::MonsterID, GetMonsterClassID() );
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ġ
nValue = hActor->GetLevel() - GetLevel();
fExpPenalty = 1.f - ( ( pow( max( nValue - 1, 0.f ), CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::ExpPenaltyValue1 ) ) ) *
CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::ExpPenaltyValue2 ) );
fExpPenalty = max( fExpPenalty, CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::ExpPenaltyMin ) );
float fExpPartyBonus = CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::ExpPartyBonus );
fExp = GetDeadExperience() * ( 1.f + ( fExpPartyBonus * ( nPartyCount - 1 ) ) ) / nPartyCount * fExpPenalty;
float fEventBonusExp = pTask->GetRoom()->GetEventExpWhenMonsterDie(fExp, pSession->GetFriendBonus(), pSession->GetClassID(), pSession->GetUserJob());
#ifdef PRE_ADD_BEGINNERGUILD
fEventBonusExp += (pTask->GetRoom()->GetPartyStructData().bPartyBeginnerGuild == true && pSession->CheckBegginerGuild()) ? (float)((fExp * (float)((float)(BeginnerGuild::Common::PartyBonusRate)/100)) + 0.5f) : 0;
#endif //#ifdef PRE_ADD_BEGINNERGUILD
#if defined(PRE_ADD_TOTAL_LEVEL_SKILL)
float fIncExpRate = 0.0f;
if (hActor && hActor->IsAppliedThisStateBlow(STATE_BLOW::BLOW_255))
{
DNVector(DnBlowHandle) vlBlows;
hActor->GatherAppliedStateBlowByBlowIndex(STATE_BLOW::BLOW_255, vlBlows);
{
int nCount = (int)vlBlows.size();
for (int i = 0; i < nCount; ++i)
{
DnBlowHandle hBlow = vlBlows[i];
if (hBlow && hBlow->IsEnd() == false)
{
fIncExpRate += hBlow->GetFloatValue();
}
}
}
}
float fAddBlowExp = fExp * fIncExpRate;
fEventBonusExp += fAddBlowExp;
#endif // PRE_ADD_TOTAL_LEVEL_SKILL
#if defined(PRE_ADD_WEEKLYEVENT)
if (CDnWorld::GetInstance(GetRoom()).GetMapSubType() != EWorldEnum::MapSubTypeNest){
int nThreadID = GetGameRoom()->GetServerID();
if (pTask->GetRoom()->GetPartyUpkeepCount() > 0){
float fEventValue = g_pDataManager->GetWeeklyEventValuef(WeeklyEvent::Player, pSession->GetClassID(), WeeklyEvent::Event_6, nThreadID);
if (fEventValue != 0)
fEventBonusExp += fEventValue;
}
if (pSession->GetFriendBonus()){
float fEventValue = g_pDataManager->GetWeeklyEventValuef(WeeklyEvent::Player, pSession->GetClassID(), WeeklyEvent::Event_7, nThreadID);
if (fEventValue != 0)
fEventBonusExp += fEventValue;
}
}
#endif // #if defined(PRE_ADD_WEEKLYEVENT)
// <20>Ϸ<EFBFBD><CFB7><EFBFBD> <20><><EFBFBD><EFBFBD>ġ ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
fCompleteExp = GetCompleteExperience() * ( 1.f + ( fExpPartyBonus * ( nPartyCount - 1 ) ) ) / nPartyCount * fExpPenalty;
CDnPlayerActor *pPlayer = static_cast<CDnPlayerActor *>(hActor.GetPointer());
if( pPlayer->GetAddExp() > 0.f )
fItemExp = GetDeadExperience()*pPlayer->GetAddExp();
float fGuildCompleteExp = 0.f;
int nGuildRewardValue = pSession->GetGuildRewardItemValue(GUILDREWARDEFFECT_TYPE_EXTRAEXP);
if( nGuildRewardValue > 0 )
{
fGuildRewardExp = (float)(GetDeadExperience() * (nGuildRewardValue * 0.01));
fGuildCompleteExp = (float)(fCompleteExp * (nGuildRewardValue * 0.01));
}
else
fGuildRewardExp = 0;
fCompleteExp += ( (fCompleteExp*pPlayer->GetAddExp()) + fGuildCompleteExp );
pPlayer->AddCompleteExperience((int)fCompleteExp);
if (hActor->IsDie())
continue;
MasterSystem::CRewardSystem* pMasterRewardSystem = pSession->GetGameRoom()->GetMasterRewardSystem();
if( pMasterRewardSystem )
{
float fBonusRate = pMasterRewardSystem->GetExpRewardRate( pSession );
if( fBonusRate > 0.f )
{
fEventBonusExp += (fExp*fBonusRate);
int iMasterAddExp = 0;
iMasterAddExp = pMasterRewardSystem->GetMasterSystemAddExp(pSession, fExp, false);
fEventBonusExp += iMasterAddExp;
#if defined( _WORK )
WCHAR wszBuf[MAX_PATH];
wsprintf( wszBuf, L"[<5B><><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD><EFBFBD>] <20>߰<EFBFBD> <20><><EFBFBD><EFBFBD>ġ %d, <20><><EFBFBD><EFBFBD>:%d", static_cast<int>(fExp*fBonusRate), iMasterAddExp );
pSession->SendDebugChat( wszBuf );
#endif // #if defined( _WORK )
}
}
if( pSession->GetPeriodExpItemRate() > 0 )
{
fEventBonusExp += (fExp* (float)(pSession->GetPeriodExpItemRate()/100.0f));
#if defined( _WORK )
WCHAR wszBuf[MAX_PATH];
wsprintf( wszBuf, L"[<5B><><EFBFBD><EFBFBD>ġ<EFBFBD>߰<EFBFBD><DFB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>] <20>߰<EFBFBD> <20><><EFBFBD><EFBFBD>ġ %d", static_cast<int>(fExp* (float)(pSession->GetPeriodExpItemRate()/100.0f)) );
pSession->SendDebugChat( wszBuf );
#endif // #if defined( _WORK )
}
float fPcBangExp = 0.0f;
if (pSession->IsPCBang() && pSession->GetPcBangBonusExp() > 0 && fExp > 0.f )
fPcBangExp = (float)((fExp * (float)((float)(pSession->GetPcBangBonusExp())/100)) + 0.5f);
float fPromotionBonusExp = 0.0f;
if( fExp > 0.f )
fPromotionBonusExp = (float)((fExp * (float)((float)(pSession->GetPromotionValue(PROMOTIONTYPE_MONSTERKILL))/100)) + 0.5f);
float fVIPExp = 0.0f;
#if defined(PRE_ADD_VIP)
if (pSession->IsVIP() && pSession->GetVIPBonusExp() > 0 && fExp > 0.f )
fVIPExp = (float)((fExp * (float)((float)(pSession->GetVIPBonusExp())/100)) + 0.5f);
#endif // #if defined(PRE_ADD_VIP)
TExpData ExpData;
ExpData.set( fExp, fEventBonusExp, fPcBangExp, fVIPExp, fPromotionBonusExp, fItemExp, fGuildRewardExp );
#if defined( PRE_USA_FATIGUE )
pPlayer->CmdAddExperience( ExpData, DBDNWorldDef::CharacterExpChangeCode::DungeonMonster, pPlayer->GetUserSession()->GetPartyID() );
#else
pPlayer->CmdAddExperience( ExpData, DBDNWorldDef::CharacterExpChangeCode::Dungeon, pPlayer->GetUserSession()->GetPartyID() );
#endif // #if defined( PRE_USA_FATIGUE )
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ʽ<EFBFBD> <20><><EFBFBD><EFBFBD>ġ<EFBFBD>Դϴ<D4B4>. <20>ݵ<EFBFBD><DDB5><EFBFBD> <20><><EFBFBD><EFBFBD> <20>߰<EFBFBD><DFB0>Ǹ<EFBFBD> <20><><EFBFBD><20><><EFBFBD>ؼ<EFBFBD> <20><><EFBFBD>ּ<EFBFBD><D6BC><EFBFBD>.
pPlayer->UpdateMaxLevelGainExperience( (int)( fExp + fEventBonusExp + fPcBangExp ) );
int nGuildRewardItemValue = pSession->GetGuildRewardItemValue(GUILDREWARDEFFECT_TYPE_REDUCEDURABILITYRATIO);
if( nGuildRewardItemValue > 0 )
nFinalDeadDurability -= (int)(nFinalDeadDurability * nGuildRewardItemValue * 0.01);
// <20><>Ƽ<EFBFBD><C6BC> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
pPlayer->OnDecreaseEquipDurability( nFinalDeadDurability, false );
if (pMasterPlayerActor)
{
pSession->GetEventSystem()->OnEvent( EventSystem::OnKillMonster, 3,
EventSystem::MonsterID, GetMonsterClassID(),
EventSystem::MonsterGrade, GetGrade(),
EventSystem::MonsterRaceID, GetRaceID());
}
}
// pTask->GetRoom()->AddCompleteExperience( GetCompleteExperience() );
if( m_bEnableDropItem )
DropItems();
if( IsSlowByDie() ) {
CDnGameTask *pGameTask = (CDnGameTask *)CTaskManager::GetInstance(GetRoom()).GetTask( "GameTask" );
if( pGameTask ) pGameTask->RequestChangeGameSpeed( 0.2f, 3000 );
}
if (m_pAggroSystem)
{
int wholeAggro = m_pAggroSystem->GetAggroSum();
std::list<CDNAggroSystem::AggroStruct>& aggroList = m_pAggroSystem->GetAggroList();
std::list<CDNAggroSystem::AggroStruct>::iterator iter = aggroList.begin();
for( ; iter!=aggroList.end() ; ++iter)
{
CDNAggroSystem::AggroStruct& curAggro = *iter;
if (curAggro.hActor && curAggro.hActor->IsPlayerActor())
{
CDnPlayerActor* pActor = static_cast<CDnPlayerActor*>(curAggro.hActor.GetPointer());
pActor->UpdateAssistScore(curAggro.iAggro, wholeAggro);
}
}
}
if (GetGameRoom())
{
GetGameRoom()->OnDie(GetActorHandle(), hHitter);
}
#ifdef PRE_ADD_MONSTER_CATCH
if( false == m_vlCatchedActors.empty() )
{
ReleaseAllActor();
}
#endif // #ifdef PRE_ADD_MONSTER_CATCH
}
void CDnMonsterActor::ProcessDie( LOCAL_TIME LocalTime, float fDelta )
{
CDnActor::ProcessDie( LocalTime, fDelta );
}
void CDnMonsterActor::DropItems()
{
DNVector(CDnItem::RealDropItemStruct) vRealDropItemList;
vRealDropItemList.reserve( m_VecDropItemList.size() );
int iPercent = HackPenanty::Common::MaxRate - GetGameRoom()->GetHackPenalty();
for( DWORD i=0; i<m_VecDropItemList.size(); i++ )
{
CDnItem::DropItemStruct *pStruct = &m_VecDropItemList[i];
int nRotate = (int)( ( ( pStruct->nSeed % 360 ) / (float)m_VecDropItemList.size() ) * i );
if( _rand(GetRoom())%HackPenanty::Common::MaxRate < iPercent )
{
vRealDropItemList.push_back( CDnItem::RealDropItemStruct(*pStruct, nRotate) );
}
else
{
g_Log.Log(LogType::_DROPITEMPENALTY, L"[%d] RoomID=%d HackPenalty=%d ItemID=%d Miss!!!\n", g_Config.nManagedID, GetGameRoom()->GetRoomID(), GetGameRoom()->GetHackPenalty(), pStruct->nItemID );
}
}
#if defined( PRE_FATIGUE_DROPITEM_PENALTY )
if( CDnWorld::GetInstance(GetRoom()).GetMapSubType() == EWorldEnum::MapSubTypeNone)
{
int iFatigueDropPercent = GetGameRoom()->GetFatigueDropRate();
if( iFatigueDropPercent < 100 )
{
for( UINT i=0 ; i<vRealDropItemList.size() ; ++i )
{
if( _roomrand(GetRoom())%100 >= iFatigueDropPercent )
{
vRealDropItemList.erase( vRealDropItemList.begin()+i );
--i;
}
}
}
}
#endif // #if defined( PRE_FATIGUE_DROPITEM_PENALTY )
EtVector3 vPos = *GetPosition();
for( DWORD i=0 ; i<vRealDropItemList.size() ; ++i )
{
CDnItem::RealDropItemStruct* pStruct = &vRealDropItemList[i];
#if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
CDnDropItem::DropItem( GetRoom(), vPos, pStruct->dwUniqueID, pStruct->nItemID, pStruct->nSeed, pStruct->cOption, pStruct->nCount, pStruct->nRotate, -1, pStruct->nEnchantID );
#else // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
CDnDropItem::DropItem( GetRoom(), vPos, pStruct->dwUniqueID, pStruct->nItemID, pStruct->nSeed, pStruct->cOption, pStruct->nCount, pStruct->nRotate );
#endif // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
}
if( !vRealDropItemList.empty() )
{
for( DWORD i=0; i<GetGameRoom()->GetUserCount(); i++ )
{
CDNUserSession* pGameSession = GetGameRoom()->GetUserData(i);
if( pGameSession && pGameSession->GetState() == SESSION_STATE_GAME_PLAY )
SendGameDropItemList( pGameSession, vPos, vRealDropItemList );
}
}
SAFE_DELETE_VEC( m_VecDropItemList );
}
void CDnMonsterActor::OnDrop( float fCurVelocity )
{
if( IsAir() ) {
if( !IsHit() ) {
char szStr[64];
sprintf_s( szStr, "%s_Landing", GetCurrentAction() );
if( IsExistAction( szStr ) )
{
SetActionQueue( szStr, 0, 2.f, 0.f, true, false );
// <20><>ų <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD> ü<>ξ׼<CEBE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
if( m_hProcessSkill )
{
m_hProcessSkill->AddUseActionName( szStr );
m_hProcessSkill->OnChainInput( szStr );
}
}
SetMovable( false );
}
else if( !IsDie() ) {
std::string szAction;
float fBlendFrame = 2.f;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ӵ<EFBFBD><D3B5><EFBFBD> 10<31>̻<EFBFBD><CCBB≯<EFBFBD> bigBounce<63><65> <20>ѹ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
if( fCurVelocity < -6.f && m_HitParam.vVelocity.y != 0.f && abs(m_HitParam.vVelocity.y) > 0.1f ) {
if( m_HitParam.vVelocity.y > 0.f ) {
m_HitParam.vVelocity.y *= 0.6f;
SetVelocityY( m_HitParam.vVelocity.y );
}
else { // <20><><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٴ<EFBFBD><D9B4><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><ECBFA1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
m_HitParam.vVelocity.y *= -0.6f;
if( m_HitParam.vResistance.y > 0.f )
m_HitParam.vResistance.y *= -1.f;
SetVelocityY( m_HitParam.vVelocity.y );
if( m_HitParam.vVelocity.y > 0 && m_HitParam.vResistance.y <= 0 )
SetResistanceY( -15.0f );
else
SetResistanceY( m_HitParam.vResistance.y );
}
szAction = "Hit_AirBounce";
}
else {
szAction = "Down_SmallBounce";
fBlendFrame = 0.f;
}
SetActionQueue( szAction.c_str(), 0, fBlendFrame, 0.f, true, false );
}
}
}
void CDnMonsterActor::OnStop( EtVector3 &vPosition )
{
if( IsDie() ) return;
if( IsMove() ) CmdStop( "Stand" );
if( m_pAi ) m_pAi->OnStop(vPosition);
}
void CDnMonsterActor::OnBeginNaviMode()
{
if( IsDie() ) return;
std::string strPrevAction = m_hActor->GetCurrentAction();
bool bPrevIsMove = false;
if( IsMove() && !IsNaviMode() )
{
bPrevIsMove = true;
CmdStop( "Stand" );
}
if( m_pAi )
m_pAi->OnBeginNaviMode( strPrevAction.c_str(), bPrevIsMove );
}
void CDnMonsterActor::CmdMove( EtVector3 &vPos, const char *szActionName, int nLoopCount, float fBlendFrame )
{
if( !IsMovable() ) return;
MovePos( vPos, true );
if( SetActionQueue( szActionName, nLoopCount, fBlendFrame, 0.f, true ) == false ) return;
BYTE pBuffer[128];
CPacketCompressStream Stream( pBuffer, 128 );
int nActionIndex = GetElementIndex( szActionName );
Stream.Write( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT );
Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Write( &vPos, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Write( &EtVec3toVec2( *GetMoveVectorZ() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Write( &EtVec3toVec2( *GetLookDir() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Write( &nLoopCount, sizeof(int), CPacketCompressStream::INTEGER_CHAR );
Send( eActor::SC_CMDMOVE, &Stream );
ResetPositionRevision();
}
void CDnMonsterActor::CmdMove( DnActorHandle hActor, float fMinDistance, const char *szActionName, int nLoopCount, float fBlendFrame )
{
if( !IsMovable() )
return;
bool bIsNaviMode = m_hActor->IsNaviMode();
MoveTarget( hActor, fMinDistance );
if( SetActionQueue( szActionName, nLoopCount, fBlendFrame, 0.f, !bIsNaviMode ) == false )
return;
BYTE pBuffer[128];
CPacketCompressStream Stream( pBuffer, 128 );
int nActionIndex = GetElementIndex( szActionName );
DWORD dwUniqueID = hActor->GetUniqueID();
Stream.Write( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT );
Stream.Write( &dwUniqueID, sizeof(DWORD) );
Stream.Write( &fMinDistance, sizeof(float), CPacketCompressStream::FLOAT_SHORT, 1.f );
Stream.Write( &EtVec3toVec2( *GetMoveVectorZ() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Write( &EtVec3toVec2( *GetLookDir() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Write( &nLoopCount, sizeof(int), CPacketCompressStream::INTEGER_CHAR );
Send( eActor::SC_CMDMOVETARGET, &Stream );
ResetPositionRevision();
}
bool CDnMonsterActor::_bIsCheckVaildPosition( EtVector3& vTargetPos )
{
// Ÿ<><C5B8> <20>׺<EFBFBD><D7BA><EFBFBD><EFBFBD>̼<EFBFBD> <20><><EFBFBD><EFBFBD> <20>˻<EFBFBD>
CEtWorldGrid* pGrid = INSTANCE(CDnWorld).GetGrid();
if( IsMovable() && pGrid )
{
NavigationMesh* pNavMesh = pGrid->GetNavMesh( vTargetPos );
if( pNavMesh )
{
NavigationCell* pCurCell = pNavMesh->FindClosestCell( vTargetPos );
if( pCurCell && pCurCell->IsPointInCellCollumn( vTargetPos ) )
return true;
}
}
if( !IsDie() ) CmdStop( "Stand" );
return false;
}
void CDnMonsterActor::_SendCmdMoveNavi( EtVector3& vTargetPos, float fMinDistance, const char* szActionName, int nLoopCount )
{
BYTE pBuffer[128];
CPacketCompressStream Stream( pBuffer, 128 );
int nActionIndex = GetElementIndex( szActionName );
Stream.Write( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT );
Stream.Write( &vTargetPos, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Write( &fMinDistance, sizeof(float), CPacketCompressStream::FLOAT_SHORT, 1.f );
Stream.Write( &EtVec3toVec2( *GetMoveVectorZ() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Write( &EtVec3toVec2( *GetLookDir() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Write( &nLoopCount, sizeof(int), CPacketCompressStream::INTEGER_CHAR );
Send( eActor::SC_CMDMOVETARGET_NAVI, &Stream );
}
void CDnMonsterActor::CmdMoveNavi( DnActorHandle hActor, float fMinDistance, const char *szActionName, int nLoopCount, float fBlendFrame )
{
// Ÿ<><C5B8><EFBFBD><EFBFBD> <20>׺<EFBFBD><D7BA><EFBFBD><EFBFBD>̼<EFBFBD> <20>ۿ<EFBFBD> <20>ִ<EFBFBD><D6B4><EFBFBD> <20>˻<EFBFBD>
if( !_bIsCheckVaildPosition( *hActor->GetPosition() ) )
return;
//
bool bAlreadyNaviMode = m_hActor->IsNaviMode();
MoveTargetNavi( hActor, fMinDistance, szActionName );
if( !m_hActor->IsNaviMode() )
return CmdStop( "Stand" );
if( (bAlreadyNaviMode && GetWayPointSize() <= 2) )
return CmdStop( "Stand" );
if( SetActionQueue( szActionName, -1, fBlendFrame, 0.f, !bAlreadyNaviMode ) == false )
return;
// <20><>Ŷ
_SendCmdMoveNavi( *hActor->GetPosition(), fMinDistance, szActionName, nLoopCount );
ResetPositionRevision();
}
void CDnMonsterActor::CmdMoveNavi( EtVector3& vTargetPos, float fMinDistance, const char *szActionName, int nLoopCount, float fBlendFrame )
{
// Ÿ<><C5B8><EFBFBD><EFBFBD> <20>׺<EFBFBD><D7BA><EFBFBD><EFBFBD>̼<EFBFBD> <20>ۿ<EFBFBD> <20>ִ<EFBFBD><D6B4><EFBFBD> <20>˻<EFBFBD>
if( !_bIsCheckVaildPosition( vTargetPos ) )
return;
//
bool bAlreadyNaviMode = m_hActor->IsNaviMode();
MoveTargetNavi( vTargetPos, fMinDistance, szActionName );
if( !m_hActor->IsNaviMode() )
return CmdStop( "Stand" );
if( SetActionQueue( szActionName, -1, fBlendFrame, 0.f, !bAlreadyNaviMode ) == false )
return;
// <20><>Ŷ
_SendCmdMoveNavi( vTargetPos, fMinDistance, szActionName, nLoopCount );
ResetPositionRevision();
}
void CDnMonsterActor::CmdStop( const char *szActionName, int nLoopCount, float fBlendFrame, float fStartFrame )
{
if( SetActionQueue( szActionName, nLoopCount, fBlendFrame, fStartFrame, true ) == false ) return;
ResetMove();
ResetLook();
BYTE pBuffer[128];
CPacketCompressStream Stream( pBuffer, 128 );
int nActionIndex = GetElementIndex( szActionName );
Stream.Write( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT );
Stream.Write( &nLoopCount, sizeof(int), CPacketCompressStream::INTEGER_CHAR );
Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Send( eActor::SC_CMDSTOP, &Stream );
ResetPositionRevision();
}
void CDnMonsterActor::CmdAction( const char *szActionName, int nLoopCount /*= 0*/, float fBlendFrame /*= 3.f*/,
bool bCheckOverlapAction /*= true*/, bool bFromStateBlow /*= false */, bool bSkillChain/* = false*/ )
{
// mp <20>Ҹ<EFBFBD> <20><>ų <20><><EFBFBD><EFBFBD> <20>Ұ<EFBFBD> <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ϳ<EFBFBD><CDBF>Դ<EFBFBD> attack state <20>ִ<EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> <20><><EFBFBD><EFBFBD>ġ <20><><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD>. (#13032)
if( m_pStateBlow->IsApplied( STATE_BLOW::BLOW_078 ) )
{
if( IsAttack( szActionName ) )
return;
}
if( SetActionQueue( szActionName, nLoopCount, fBlendFrame, 0.f, bCheckOverlapAction ) == false )
return;
int nActionIndex = GetElementIndex( szActionName );
bool bAILook = bIsAILook();
BYTE pBuffer[128];
CPacketCompressStream Stream( pBuffer, 128 );
Stream.Write( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT );
Stream.Write( &nLoopCount, sizeof(int), CPacketCompressStream::INTEGER_CHAR );
Stream.Write( &fBlendFrame, sizeof(float), CPacketCompressStream::FLOAT_SHORT, 1.f );
Stream.Write( &bAILook, sizeof(bool) );
if( bAILook )
Stream.Write( m_pAi->GetAILook(), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
else
Stream.Write( &EtVec3toVec2( *GetLookDir() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Write( &bFromStateBlow, sizeof(bool) );
#if defined( PRE_FIX_MOVEBACK )
bool bNearMoveBack = IsPrevMoveBack();
Stream.Write( &bNearMoveBack, sizeof(bool));
#endif
Send( eActor::SC_CMDACTION, &Stream );
ResetPositionRevision();
}
void CDnMonsterActor::CmdLook( EtVector2 &vVec, bool bForce )
{
Look( vVec, bForce );
BYTE pBuffer[128];
CPacketCompressStream Stream( pBuffer, 128 );
Stream.Write( &vVec, sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Write( &bForce, sizeof(bool) );
Send( eActor::SC_CMDLOOK, &Stream );
}
void CDnMonsterActor::CmdLook( DnActorHandle hActor, bool bLock )
{
if( bLock ) LookTarget( hActor );
else {
if( !hActor ) ResetLook();
else {
EtVector2 vVec;
vVec.x = hActor->GetPosition()->x - GetPosition()->x;
vVec.y = hActor->GetPosition()->z - GetPosition()->z;
EtVec2Normalize( &vVec, &vVec );
Look( vVec );
}
}
BYTE pBuffer[128];
CMemoryStream Stream( pBuffer, 128 );
DWORD dwUniqueID = ( hActor ) ? hActor->GetUniqueID() : -1;
Stream.Write( &dwUniqueID, sizeof(DWORD) );
Stream.Write( &bLock, sizeof(bool) );
Send( eActor::SC_CMDLOOKTARGET, &Stream );
}
int CDnMonsterActor::CmdAddStateEffect( const CDnSkill::SkillInfo* pParentSkill, STATE_BLOW::emBLOW_INDEX emBlowIndex, int nDurationTime,
const char *szParam, bool bOnPlayerInit/* = false*/, bool bCheckCanBegin/* = true*/ , bool bEternity /* = false */ )
{
int iID = CDnActor::CmdAddStateEffect( pParentSkill, emBlowIndex, nDurationTime, szParam, bOnPlayerInit, bCheckCanBegin , bEternity );
if( -1 == iID )
return -1;
DnBlowHandle hAddedBlow = m_pStateBlow->GetStateBlowFromID( iID );
const CPacketCompressStream* pPacketStream = hAddedBlow->GetPacketStream( szParam, false );
Send( eActor::SC_CMDADDSTATEEFFECT, const_cast<CPacketCompressStream*>(pPacketStream) );
return iID;
}
void CDnMonsterActor::CmdRemoveStateEffect( STATE_BLOW::emBLOW_INDEX emBlowIndex, bool bRemoveFromServerToo/* = true*/ )
{
if( m_pStateBlow->IsApplied( emBlowIndex ) )
{
if( bRemoveFromServerToo )
CDnActor::CmdRemoveStateEffect( emBlowIndex );
SendRemoveStateEffect( emBlowIndex );
}
}
void CDnMonsterActor::SendRemoveStateEffect( STATE_BLOW::emBLOW_INDEX emBlowIndex )
{
BYTE pBuffer[32];
CPacketCompressStream Stream( pBuffer, 32 );
Stream.Write( &emBlowIndex, sizeof(STATE_BLOW::emBLOW_INDEX) );
Send( eActor::SC_CMDREMOVESTATEEFFECT, &Stream );
}
void CDnMonsterActor::CmdSuicide( bool bDropItem, bool bDropExp )
{
if( IsDie() ) return;
SetDestroy();
if( m_hSummonerPlayerActor )
{
_ASSERT( m_hSummonerPlayerActor->IsPlayerActor() );
if( m_hSummonerPlayerActor->IsPlayerActor() )
{
CDnPlayerActor* pPlayerActor = static_cast<CDnPlayerActor*>(m_hSummonerPlayerActor.GetPointer());
pPlayerActor->OnDieSummonedMonster( GetMySmartPtr() );
}
}
if( bDropExp ) {
EnableDropItem( bDropItem );
OnDie( DnActorHandle() );
}
else {
if( bDropItem ) DropItems();
}
BYTE pBuffer[32];
CPacketCompressStream Stream( pBuffer, 32 );
Stream.Write( &bDropItem, sizeof(bool) );
Stream.Write( &bDropExp, sizeof(bool) );
Send( eActor::SC_CMDSUICIDE, &Stream );
}
void CDnMonsterActor::CmdMixedAction( const char *szActionBone, const char *szMaintenanceBone, const char *szActionName, float fFrame, float fBlendFrame )
{
int nActionIndex = GetElementIndex( szActionName );
int nMaintenanceBoneIndex = GetBoneIndex( szMaintenanceBone );
int nActionBoneIndex = GetBoneIndex( szActionBone );
int nBlendAniIndex = m_nAniIndex;
if( nActionIndex == -1 ) {
assert(0);
}
if( nActionBoneIndex == -1 || nMaintenanceBoneIndex == -1 )
return;
BYTE pBuffer[128] = {0,};
CPacketCompressStream Stream( pBuffer, 128 );
Stream.Write( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT );
Stream.Write( &nActionBoneIndex, sizeof(int), CPacketCompressStream::INTEGER_CHAR );
Stream.Write( &nMaintenanceBoneIndex, sizeof(int), CPacketCompressStream::INTEGER_CHAR );
Stream.Write( &fFrame, sizeof(float), CPacketCompressStream::FLOAT_SHORT, 10.f );
Stream.Write( &fBlendFrame, sizeof(float), CPacketCompressStream::FLOAT_SHORT, 10.f );
Send( eActor::SC_CMDMIXEDACTION, &Stream );
}
void CDnMonsterActor::CmdWarp( EtVector3 &vPos, EtVector2 &vLook, CDNUserSession* pGameSession, bool bCheckPlayerFollowSummonedMonster/*=false*/ )
{
CDnActor::CmdWarp( vPos, vLook, pGameSession, bCheckPlayerFollowSummonedMonster );
MAWalkMovementNav *pMovement = dynamic_cast<MAWalkMovementNav *>(GetMovement());
if( pMovement ) pMovement->ValidateCurCell();
}
void CDnMonsterActor::GenerationDropItem()
{
m_VecDropItemList.clear();
if( m_nItemDropGroupTableID < 1 ) return;
int nExtendDropRate = 0;
GetGameRoom()->GetExtendDropRateIgnoreTime(nExtendDropRate);
#if defined(PRE_ADD_WORLD_EVENT)
#else
#if defined(PRE_ADD_WEEKLYEVENT)
if (CDnWorld::GetInstance(GetRoom()).GetMapSubType() != EWorldEnum::MapSubTypeNest){
int nThreadID = GetGameRoom()->GetServerID();
int nEventValue = g_pDataManager->GetWeeklyEventValue(0, 0, WeeklyEvent::Event_10, nThreadID);
if (nEventValue != 0)
nExtendDropRate += nEventValue;
}
#endif // #if defined(PRE_ADD_WEEKLYEVENT)
#endif //#if defined(PRE_ADD_WORLD_EVENT)
#if defined( PRE_ADD_NEWCOMEBACK )
if( GetGameRoom() )
{
if( GetGameRoom()->GetTaskMng() )
{
CDnPartyTask* pPartyTask = (CDnPartyTask*)(GetGameRoom()->GetTaskMng()->GetTask("PartyTask"));
if( pPartyTask )
{
float fBlowValue = pPartyTask->GetPlayerDropUpBlowValue();
if( fBlowValue > 0 )
{
fBlowValue = fBlowValue * 100;
nExtendDropRate += (int)fBlowValue;
}
}
}
}
#endif
#if defined( PRE_ADD_STAGE_WEIGHT )
if( GetGameRoom() && GetGameRoom()->GetTaskMng() )
{
CDnGameTask* pGameTask = static_cast<CDnGameTask*>(GetGameRoom()->GetTaskMng()->GetTask("GameTask"));
if( pGameTask )
{
const TStageWeightData * pStageWeightData = pGameTask->GetStageWeightData();
if( pStageWeightData )
{
float fStageWeightBonus = pStageWeightData->fItemDropRate;
fStageWeightBonus = fStageWeightBonus * 100;
nExtendDropRate += (int)fStageWeightBonus;
}
}
}
#endif // #if defined( PRE_ADD_STAGE_WEIGHT )
float fCalcDropCount = ((float)((float)nExtendDropRate/100) + 1.0f);
for (int h = 0; 0 < fCalcDropCount; h++)
{
CDnDropItem::CalcDropItemList( GetRoom(), m_AIDifficult, m_nItemDropGroupTableID, m_VecDropItemList );
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--;
}
}
fCalcDropCount -= 1.0f;
if (h >= 4 || (fCalcDropCount < 1.0f && ((float)(_rand(GetRoom())%100)/100) > fCalcDropCount))
break; //4<><34><EFBFBD>̻<EFBFBD>(<28>̺<EFBFBD>Ʈ3<C6AE><33>)<29><> <20>Ұ<EFBFBD><D2B0>ϰ<EFBFBD> <20><><EFBFBD><EFBFBD>, 1<><31><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ȯ<><C8AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD> <20>Ѵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ǵ<EFBFBD>
}
}
void CDnMonsterActor::SetGenerationArea( SOBB &Box )
{
m_GenerationArea = Box;
}
SOBB *CDnMonsterActor::GetGenerationArea()
{
return &m_GenerationArea;
}
void CDnMonsterActor::SyncClassTime( LOCAL_TIME LocalTime )
{
MAActorRenderBase::m_LocalTime = LocalTime;
CDnActor::SyncClassTime( LocalTime );
}
void CDnMonsterActor::OnChangeAction( const char *szPrevAction )
{
if( m_pAi )
m_pAi->OnChangeAction( szPrevAction );
#ifdef PRE_ADD_AURA_FOR_MONSTER
_CheckActionWithProcessPassiveActionSkill(szPrevAction);
#endif
}
void CDnMonsterActor::_CheckActionWithProcessPassiveActionSkill( const char* szPrevAction )
{
// <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD> <20>ݺ<EFBFBD><DDBA><EFBFBD><EFBFBD≯<EFBFBD> <20>н<EFBFBD>
if( szPrevAction && m_nPrevActionIndex == m_nActionIndex )
return;
// if instantly passive skill, then cancel skill. ( ex) archer's spinkick)
// because state effect must deactivate when change to another attack action.
if( m_hProcessSkill )
{
m_setUseActionName.clear();
m_setUseActionName.insert( szPrevAction );
// <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> prev <20>׼<EFBFBD><D7BC><EFBFBD> next <20>׼<EFBFBD><D7BC>̶<EFBFBD><CCB6><EFBFBD> <20><>ų<EFBFBD><C5B3> <20>̾<EFBFBD><CCBE><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
// <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ų<EFBFBD><C5B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>׼<EFBFBD><D7BC>̾<EFBFBD><CCBE><EFBFBD> <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> next <20>׼<EFBFBD><D7BC><EFBFBD> <20>ƴ϶<C6B4><CFB6><EFBFBD>
// <20>нú<D0BD> <20><>ų<EFBFBD><C5B3> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ǵ<EFBFBD><C7B4>Ѵ<EFBFBD>.
ActionElementStruct* pElement = GetElement( szPrevAction );
bool bIsNextAction = false;
if( pElement )
{
// #25154 <20><20><><EFBFBD>ĵ<EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> <20><>ų<EFBFBD><C5B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> next <20>׼<EFBFBD><D7BC><EFBFBD> <20>̾<EFBFBD><CCBE><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
// <20><><EFBFBD><EFBFBD> <20><>ų <20>׼<EFBFBD><D7BC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20>Լ<EFBFBD><D4BC><EFBFBD> ȣ<><C8A3><EFBFBD>Ǿ<EFBFBD><C7BE><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> Stand <20><> <20>Ǿ<EFBFBD><C7BE>ִµ<D6B4> <20>ش<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// m_hProcessSkill <20><> <20><>ų<EFBFBD><C5B3> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ǴܵǾ NULL <20><> <20>Ǿ<EFBFBD><C7BE><EFBFBD> <20>Ѵ<EFBFBD>.
// m_hProcessSkill <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٸ<EFBFBD> <20><>ų <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> onend <20><> <20><> <20>ֱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ȵ<EFBFBD>.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> bIsNextAction <20><> false <20><> <20>ǰ<EFBFBD> m_hProcessSkill->IsUseSkillActionNames() <20>Լ<EFBFBD> <20><><EFBFBD>ο<EFBFBD><CEBF><EFBFBD>
// <20><>ų <20>׼<EFBFBD><D7BC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ǴܵǾ<DCB5><C7BE><EFBFBD> <20>Ѵ<EFBFBD>.
bIsNextAction = ((pElement->szNextActionName != "Stand") && (pElement->szNextActionName == GetCurrentAction()));
}
if( false == bIsNextAction &&
m_hProcessSkill->IsUseActionNames( m_setUseActionName ) )
{
if( (m_hProcessSkill->GetSkillType() == CDnSkill::Passive || m_hProcessSkill->GetSkillType() == CDnSkill::AutoPassive) &&
m_hProcessSkill->GetDurationType() == CDnSkill::Instantly )
{
// <20>нú<D0BD> <20><>ų<EFBFBD><C5B3> ü<><C3BC> <20>Է<EFBFBD><D4B7><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> üũ<C3BC>Ѵ<EFBFBD>. <20>ѹ<EFBFBD> üũ<C3BC>Ǵ<EFBFBD> <20><><EFBFBD><EFBFBD> ü<><C3BC> <20>Է<EFBFBD> <20>÷<EFBFBD><C3B7>״<EFBFBD> <20>ʱ<EFBFBD>ȭ<EFBFBD>ȴ<EFBFBD>.
// ü<><C3BC><EFBFBD>ԷµǴ<C2B5> <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> <20><><EFBFBD≯<EFBFBD>ŭ <20>нú<D0BD> <20><>ų <20><><EFBFBD><EFBFBD> <20><><EFBFBD>̰<EFBFBD> <20>þ<C3BE><EEB3AD>.
// <20>̷<EFBFBD><CCB7><EFBFBD> <20>÷<EFBFBD><C3B7>׿<EFBFBD> <20>ð<EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD> <20>нú<D0BD> <20><>ų<EFBFBD><C5B3> <20><><EFBFBD><EFBFBD> ü<><C3BC><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
if( false == m_hProcessSkill->CheckChainingPassiveSkill() )
{
m_hProcessSkill->OnEnd( MAActorRenderBase::m_LocalTime, 0.0f );
m_hProcessSkill.Identity();
}
}
else
// Note <20>ѱ<EFBFBD>: m_hProcessSkill <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ų <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȿ<EFBFBD>ؾ<EFBFBD>
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CDnPlayerActor::CmdStop() <20>ʿ<EFBFBD><CABF><EFBFBD> <20>ɷ<EFBFBD><C9B7><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ش<EFBFBD> <20>׼<EFBFBD> <20>ñ׳<C3B1><D7B3><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// ó<><C3B3><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CDnActor::OnChangeAction <20>ʿ<EFBFBD><CABF><EFBFBD> ProcessAction <20><> Identity <20><>Ŵ.
if( IsEnabledAuraSkill() && m_hProcessSkill->IsAuraOn() )
{
m_hProcessSkill.Identity();
ClearSelfStateSignalBlowQueue(); // <20><><EFBFBD><EFBFBD> <20><>ų<EFBFBD><C5B3> <20>ڱ<EFBFBD> <20>ڽſ<DABD><C5BF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF> Ÿ<>̹<EFBFBD> <20>ñ׳ο<D7B3> <20><><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD> ť <20>ʱ<EFBFBD>ȭ <20><>Ŵ. <20>ȱ׷<C8B1> <20>ٸ<EFBFBD> <20><>ų<EFBFBD><C5B3> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ش<EFBFBD>.
}
}
}
}
void CDnMonsterActor::OnFinishAction(const char* szPrevAction, LOCAL_TIME time)
{
if( m_bChangeAxisOnFinishAction )
{
EtVector2 vView = EtVec3toVec2( *GetLookDir() );
vView *= -1.f;
Look( vView, true );
m_bChangeAxisOnFinishAction = false;
}
if( m_pAi )
m_pAi->OnFinishAction(szPrevAction, time);
}
void CDnMonsterActor::ResetActor()
{
if( m_pAi )
m_pAi->ResetDelay();
}
void CDnMonsterActor::OnBeginStateBlow( DnBlowHandle hBlow )
{
CDnActor::OnBeginStateBlow( hBlow );
if( m_pAggroSystem )
m_pAggroSystem->OnStateBlowAggro( hBlow );
}
// MASkillUser
#ifdef PRE_FIX_GAMESERVER_OPTIMIZE
void CDnMonsterActor::OnAddSkill( DnSkillHandle hSkill, bool isInitialize/* = false*/ )
{
// <20>нú<D0BD> <20≯鼭 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF> Self <20><> <20>پ<EFBFBD><D9BE>ִ<EFBFBD> <20><>ų<EFBFBD><C5B3> <20><><EFBFBD>ٷ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>..
bool bPassiveBuff = false;
bPassiveBuff = ApplyPassiveSkill( hSkill, isInitialize );
if( bPassiveBuff )
m_vlhSelfPassiveBlowSkill.push_back( hSkill );
}
bool CDnMonsterActor::AddSkill( int nSkillTableID, int nLevel/* = 1*/, int iSkillLevelApplyType/* = CDnSkill::PVE*/ )
{
if( IsExistSkill( nSkillTableID, nLevel ) ) return false;
if( !MASkillUser::IsValidActor() ) return false;
if( GetRoom() == NULL ) return false;
DnSkillHandle hSkill = CDnSkill::CreateMonsterSkill( GetMySmartPtr(), nSkillTableID, nLevel );
if( !hSkill ) return false;
#ifdef PRE_ADD_AURA_FOR_MONSTER
CDnSkill::DurationTypeEnum eDurationType = hSkill->GetDurationType();
switch(eDurationType)
{
case CDnSkill::Aura:
m_vlhAuraSkills.push_back(hSkill);
}
#endif
#ifndef PRE_FIX_SKILLLIST
m_vlhSkillList.push_back( hSkill );
m_vbSelfAllocList.push_back( true );
#else
AddSkillObject( S_SKILL_OBJECT(hSkill, true) );
#endif // #ifndef PRE_FIX_SKILLLIST
if( hSkill->GetActor() )
hSkill->SetHasActor( GetMySmartPtr() );
OnAddSkill( hSkill );
return true;
}
#endif // #ifdef PRE_FIX_GAMESERVER_OPTIMIZE
bool CDnMonsterActor::ExecuteSkill( DnSkillHandle hSkill, LOCAL_TIME LocalTime, float fDelta )
{
if ( CDnActor::ExecuteSkill(hSkill, LocalTime, fDelta) == false )
return false;
BYTE pBuffer[128] = {0,};
CPacketCompressStream Stream( pBuffer, 128 );
int nSkillID = hSkill->GetClassID();
char cLevel = hSkill->GetLevel();
Stream.Write( &nSkillID, sizeof(int) );
Stream.Write( &cLevel, sizeof(char) );
Stream.Write( &EtVec3toVec2( *GetLookDir() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
#if defined( PRE_ADD_ACADEMIC )
int iSummonerSkillID = 0;
DnSkillHandle hSummonerSkill = FindSkill( nSkillID );
if( hSummonerSkill )
iSummonerSkillID = hSummonerSkill->GetSummonerDecreaseSPSkillID();
Stream.Write( &iSummonerSkillID, sizeof(int) );
#endif // #if defined( PRE_ADD_ACADEMIC )
Send( eActor::SC_USESKILL, &Stream );
ResetPositionRevision();
return true;
}
CDnSkill::UsingResult CDnMonsterActor::UseSkill( int nSkillTableID, bool bCheckValid/* = true*/, bool bAutoUseFromServer/* = false*/, int nLuaSkillIndex/*=-1*/ )
{
CDnSkill::UsingResult Result = MASkillUser::UseSkill( nSkillTableID, bCheckValid, bAutoUseFromServer );
if( Result == CDnSkill::UsingResult::Success && nLuaSkillIndex >= 0 )
{
std::map<int,int>::iterator itor = m_mUseSkillCount.find( nLuaSkillIndex );
if( itor == m_mUseSkillCount.end() )
{
m_mUseSkillCount.insert( std::make_pair(nLuaSkillIndex,1) );
}
else
{
++(*itor).second;
}
}
return Result;
}
int CDnMonsterActor::GetUseSkillCount( int iLuaSkillIndex )
{
std::map<int,int>::iterator itor = m_mUseSkillCount.find( iLuaSkillIndex );
if( itor != m_mUseSkillCount.end() )
return (*itor).second;
return 0;
}
void CDnMonsterActor::SetScale( float fValue )
{
m_fScale = fValue;
if( m_hObject ) {
m_hObject->SetCollisionScale( m_fScale );
}
MAActorRenderBase::SetScale( EtVector3( m_fScale, m_fScale, m_fScale ) );
if( m_fWeight == 0.f ) m_fRevisionWeight = 0.f;
else m_fRevisionWeight = m_fWeight + ( ( m_fScale - 1.f ) * CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::ScaleWeightValue ) );
}
float CDnMonsterActor::GetWeight()
{
return m_fRevisionWeight;
}
float CDnMonsterActor::GetThreatRange()
{
_ASSERT( dynamic_cast<CDNMonsterAggroSystem*>(m_pAggroSystem) );
return m_pAggroSystem ? static_cast<CDNMonsterAggroSystem*>(m_pAggroSystem)->GetThreatRange() : 0.f;
}
float CDnMonsterActor::GetCognizanceThreatRange()
{
_ASSERT( dynamic_cast<CDNMonsterAggroSystem*>(m_pAggroSystem) );
return m_pAggroSystem ? static_cast<CDNMonsterAggroSystem*>(m_pAggroSystem)->GetCognizanceThreatRange() : 0.f;
}
float CDnMonsterActor::GetCognizanceThreatRangeSq()
{
_ASSERT( dynamic_cast<CDNMonsterAggroSystem*>(m_pAggroSystem) );
return m_pAggroSystem ? static_cast<CDNMonsterAggroSystem*>(m_pAggroSystem)->GetCognizanceThreatRangeSq() : 0.f;
}
std::string CDnMonsterActor::GetAIFileName()
{
DNTableFileFormat* pSox = NULL;
int nItemID = 0;
if( m_nMonsterWeightTableID == -1 )
{
pSox = GetDNTable( CDnTableDB::TMONSTER );
nItemID = m_nMonsterClassID;
}
else
{
pSox = GetDNTable( CDnTableDB::TMONSTERWEIGHT );
nItemID = m_nMonsterWeightTableID;
}
if( !pSox || !pSox->IsExistItem( nItemID ) )
return std::string("");
std::string szName = pSox->GetFieldFromLablePtr( nItemID, "_CustomAI" )->GetString();
return szName;
}
void CDnMonsterActor::CalcMonsterWeightIndex()
{
if( m_nMonsterClassID == 0 ) return;
DNTableFileFormat* pSox = GetDNTable( CDnTableDB::TMONSTERWEIGHT );
if( !pSox )
{
g_Log.Log( LogType::_FILELOG, L"MonsterWeightTable.ext failed\r\n");
return;
}
std::vector<int> nVecList;
pSox->GetItemIDListFromField( "_MonsterTableIndex", m_nMonsterClassID, nVecList );
int nDifficulty;
for( DWORD i=0; i<nVecList.size(); i++ ) {
nDifficulty = pSox->GetFieldFromLablePtr( nVecList[i], "_Difficulty" )->GetInteger();
if( nDifficulty == m_AIDifficult ) {
m_nMonsterWeightTableID = nVecList[i];
break;
}
}
}
void CDnMonsterActor::SetNaviDestination( SOBB* pOBB, UINT uiMoveFrontRate )
{
if( m_pAi )
m_pAi->OnInitNaviDestination( pOBB, uiMoveFrontRate );
else
_DANGER_POINT();
}
int CDnMonsterActor::GetWaitOrderCount( int iSkillID )
{
std::map<int,int>::iterator itor = m_mOrderCount.find( iSkillID );
if( itor == m_mOrderCount.end() )
return 0;
return (*itor).second;
}
void CDnMonsterActor::AddWaitOrderCount( int iSkillID )
{
std::map<int,int>::iterator itor = m_mOrderCount.find( iSkillID );
if( itor == m_mOrderCount.end() )
{
m_mOrderCount.insert( std::make_pair(iSkillID,1) );
return;
}
++(*itor).second;
}
void CDnMonsterActor::DelWaitOrderCount( int iSkillID )
{
std::map<int,int>::iterator itor = m_mOrderCount.find( iSkillID );
if( itor == m_mOrderCount.end() )
return;
if( (*itor).second > 0 )
--(*itor).second;
}
bool CDnMonsterActor::OnAINonTarget()
{
// Walk_Font <20>׼<EFBFBD> <20>˻<EFBFBD>
if( !IsExistAction( "Walk_Front") )
return true;
if ( !IsHit() && IsMove() )
CmdStop( "Stand", 0, g_fBendFrame );
if ( !IsMovable() )
return false;
// <20><EFBFBD><EEBDBD> <20>Ÿ<EFBFBD><C5B8><EFBFBD>.
EtVector3 *pvPos = m_hActor->GetPosition();
EtVector3 vTemp;
vTemp = *pvPos;
vTemp.y = 0.f;
vTemp.x += cos( EtToRadian( _rand(m_hActor->GetRoom())%360 ) ) * ( 300 + _rand(m_hActor->GetRoom())%200 );
vTemp.z += sin( EtToRadian( _rand(m_hActor->GetRoom())%360 ) ) * ( 300 + _rand(m_hActor->GetRoom())%200 );
SOBB Box = *GetGenerationArea();
Box.Extent[1] = 1000000.f;
if( !Box.IsInside( vTemp ) )
{
vTemp = Box.Center;
vTemp -= Box.Axis[0] * Box.Extent[0];
vTemp -= Box.Axis[2] * Box.Extent[2];
int iModValue = static_cast<int>(Box.Extent[0] * 2.f);
if( iModValue > 0 ) vTemp += Box.Axis[0] * (float)( _rand(m_hActor->GetRoom())%iModValue );
else vTemp += Box.Axis[0];
iModValue = static_cast<int>(Box.Extent[2] * 2.f);
if( iModValue ) vTemp += Box.Axis[2] * (float)( _rand(m_hActor->GetRoom())%iModValue );
else vTemp += Box.Axis[2];
vTemp.y = CDnWorld::GetInstance(m_hActor->GetRoom()).GetHeight( vTemp );
vTemp += Box.Axis[1] * Box.Extent[1];
}
CmdMove( vTemp, "Walk_Front", -1, g_fBendFrame );
return true;
}
void CDnMonsterActor::OnBumpWall()
{
if( !m_pszCanBumpActionName )
return;
CmdAction( m_pszCanBumpActionName, 0, g_fBendFrame );
}
// <20><>Ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><> <20>κ<EFBFBD><CEBA><EFBFBD> CDnProjectile::GetPacketStream() <20><> <20><><EFBFBD><EFBFBD> <20>ʰ<EFBFBD> <20>׼<EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20>ñ׳<C3B1> <20>ε<EFBFBD><CEB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>Ŷ<EFBFBD><C5B6> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> <20>߻<EFBFBD>ü <20>ñ׳<C3B1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ã<><C3A3> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20>Ǿ<EFBFBD><C7BE>ִµ<D6B4> <20>ϴ<EFBFBD> <20>״<EFBFBD><D7B4><EFBFBD> <20>Ӵϴ<D3B4>.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>Ŀ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ٵ<EFBFBD><D9B5><EFBFBD> <20>Ҷ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD> <20>մϴ<D5B4>. - <20>ѱ<EFBFBD>.
void CDnMonsterActor::SendProjectile( CDnProjectile *pProjectile, ProjectileStruct* pStruct, MatrixEx& LocalCross, int iSignalIndex )
{
BYTE pBuffer[128];
CPacketCompressStream Stream( pBuffer, 128 );
DWORD dwVal = pProjectile->GetUniqueID();
Stream.Write( &dwVal, sizeof(DWORD) );
Stream.Write( &LocalCross.m_vPosition, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Write( &LocalCross.m_vXAxis, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT );
Stream.Write( &LocalCross.m_vYAxis, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT );
Stream.Write( &LocalCross.m_vZAxis, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT );
#if defined(PRE_FIX_55378)
int nActionIndex = m_nActionIndex;
std::string szChargerAction = GetChargerAction();
if (szChargerAction.empty() == false)
nActionIndex = GetElementIndex(szChargerAction.c_str());
Stream.Write( &nActionIndex, sizeof(int) );
#else
Stream.Write( &m_nActionIndex, sizeof(int) );
#endif // PRE_FIX_55378
Stream.Write( &iSignalIndex, sizeof(int) );
bool bUsedForceDir = pProjectile->IsUsedForceDir();
Stream.Write( &bUsedForceDir, sizeof(bool) );
if( bUsedForceDir )
{
const EtVector3& vForceDir = pProjectile->GetForceDir();
Stream.Write( &vForceDir, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT );
}
switch( pStruct->nTargetType )
{
case 2: // TargetPosition
{
Stream.Write( pProjectile->GetTargetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
break;
}
case 3: // Target
{
DnActorHandle hTarget = pProjectile->GetTargetActor();
if( !hTarget )
hTarget = GetActorHandle();
dwVal = hTarget->GetUniqueID();
Stream.Write( &dwVal, sizeof(DWORD) );
break;
}
}
Send( eActor::SC_PROJECTILE, &Stream );
}
// #15557 <20>̽<EFBFBD> <20><><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20>߻<EFBFBD>ü<EFBFBD><C3BC><EFBFBD><EFBFBD> <20>߻<EFBFBD>ü<EFBFBD><C3BC> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
// <20><EFBFBD><E2BABB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> LocalPlayerActor <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
// Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>Ƽ<EFBFBD><C6BC><EFBFBD><EFBFBD> <20><> <20>߻<EFBFBD>ü<EFBFBD><C3BC> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20><>Ŷ<EFBFBD><C5B6> ó<><C3B3><EFBFBD>Ѵ<EFBFBD>.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ݵ<EFBFBD><DDB5><EFBFBD> CDnLocalPlayerActor::OnProjectile() <20>ʵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD> <20><>.
void CDnMonsterActor::SendProjectileFromProjectile( CDnProjectile* pProjectile, int nSignalIndex )
{
CPacketCompressStream* pPacketStream = pProjectile->GetPacketStream();
_ASSERT( pPacketStream );
if( pPacketStream )
Send( eActor::SC_MONSTER_PROJECTILE_FROM_PROJECTILE, pPacketStream );
}
void CDnMonsterActor::OnSignal( SignalTypeEnum Type, void *pPtr, LOCAL_TIME LocalTime, LOCAL_TIME SignalStartTime, LOCAL_TIME SignalEndTime, int nSignalIndex )
{
switch( Type ) {
case STE_LockTargetLook:
{
#if defined( PRE_MOD_LOCK_TARGET_LOOK )
LockTargetLookStruct * pStruct = static_cast<LockTargetLookStruct*>(pPtr);
m_nLockLookEventArea = pStruct->LookEeventAreaID;
#endif // PRE_MOD_LOCK_TARGET_LOOK
#if defined( PRE_FIX_MOVEBACK )
if( !IsNearMoveBack() )
m_bLockLookTarget = true;
#else
m_bLockLookTarget = true;
#endif
break;
}
case STE_CanBumpWall:
{
CanBumpWallStruct* pStruct = static_cast<CanBumpWallStruct*>(pPtr);
m_pszCanBumpActionName = pStruct->szActionName;
break;
}
case STE_Projectile:
{
ProjectileStruct* pStruct = (ProjectileStruct *)pPtr;
// MultipleŸ<65><C5B8><EFBFBD≯<EFBFBD> <20>߰<EFBFBD><DFB0><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Projectile <20><><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD> <20>߻<EFBFBD>
#if defined (PRE_MOD_AIMULTITARGET)
if( static_cast<MAAiScript*>(GetAIBase())->m_cMultipleTarget.GetMultipleTarget() > 0 )
#else
if( static_cast<MAAiScript*>(GetAIBase())->m_cMultipleTarget.bIsMultipleTarget() )
#endif
{
static_cast<MAAiScript*>(GetAIBase())->m_cMultipleTarget.CreateProjectile( this, static_cast<ProjectileStruct*>(pPtr), nSignalIndex );
}
else
{
DNVector(DnActorHandle) StigmaActorList;
if (pStruct->nTargetStateIndex != 0)
{
ScanActorByStateIndex(StigmaActorList, STATE_BLOW::BLOW_246);
}
//<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD>츸 ó<><C3B3>
if (StigmaActorList.empty() == false)
{
int nStigmaActorCount = (int)StigmaActorList.size();
for (int i = 0; i < nStigmaActorCount; ++i)
{
//Ÿ<><C5B8> <20><><EFBFBD><EFBFBD>..
DnActorHandle hTargetActor = StigmaActorList[i];
CDnProjectile* pProjectile = CDnProjectile::CreateProjectile( GetRoom(), GetMySmartPtr(), m_Cross, pStruct, NULL, hTargetActor );
if( pProjectile == NULL )
return;
pProjectile->SetShooterType( GetMySmartPtr(), m_nActionIndex, nSignalIndex );
SendProjectile( pProjectile, pStruct, m_Cross, nSignalIndex );
OnProjectile( pProjectile, pStruct, m_Cross, nSignalIndex );
OnSkillProjectile( pProjectile );
}
}
else
{
//#52808 - <20>߰<EFBFBD> <20><>û (<28><><EFBFBD>ο<EFBFBD> <20>߻<EFBFBD>ü <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 2<><32> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߻<EFBFBD>ü <20><><EFBFBD><EFBFBD> <20>ȵ<EFBFBD>.
if (pStruct->nTargetStateIndex == 2)
return;
CDnProjectile* pProjectile = CDnProjectile::CreateProjectile( GetRoom(), GetMySmartPtr(), m_Cross, pStruct );
if( pProjectile == NULL )
return;
pProjectile->SetShooterType( GetMySmartPtr(), m_nActionIndex, nSignalIndex );
SendProjectile( pProjectile, pStruct, m_Cross, nSignalIndex );
OnProjectile( pProjectile, pStruct, m_Cross, nSignalIndex );
OnSkillProjectile( pProjectile );
}
}
return;
}
case STE_ProjectileTargetPosition:
{
if( m_pAi )
m_pAi->SetProjectileTarget();
break;
}
case STE_ReserveProjectileTarget:
{
if( m_pAi )
m_pAi->ReservedProjectileTarget();
break;
}
case STE_RotateResistance:
{
RotateResistanceStruct *pStruct = (RotateResistanceStruct *)pPtr;
m_fRotateResistance = pStruct->fResistanceRatio;
break;
}
case STE_PositionRevision:
{
PositionRevisionStruct* pStruct = reinterpret_cast<PositionRevisionStruct*>(pPtr);
m_uiForcePositionRevisionTick = pStruct->nRevisionTick;
return;
}
case STE_SuicideMonster:
{
SuicideMonsterStruct* pStruct = (SuicideMonsterStruct*)pPtr;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ°<CFB4>. <20><><EFBFBD>⼭ Ŭ<><C5AC><EFBFBD><EFBFBD> <20><>Ŷ<EFBFBD><C5B6> <20><><EFBFBD><EFBFBD>.
CmdSuicide( pStruct->bDropItem ? true : false, pStruct->bGetExp ? true : false );
}
break;
case STE_TriggerEvent:
{
TriggerEventStruct *pStruct = (TriggerEventStruct *)pPtr;
CDnWorld::GetInstance(GetRoom()).InsertTriggerEventStore( "EventArea", GetBirthAreaHandle() );
CDnWorld::GetInstance(GetRoom()).InsertTriggerEventStore( "ActorHandle", GetUniqueID() );
CDnWorld::GetInstance(GetRoom()).InsertTriggerEventStore( "EventID", pStruct->nEventID );
CDnWorld::GetInstance(GetRoom()).OnTriggerEventCallback( "CDnActor::TriggerEvent", LocalTime, 0.f );
}
break;
case STE_Announce:
{
AnnounceStruct* pStruct = reinterpret_cast<AnnounceStruct*>(pPtr);
DNVector(DnActorHandle) hScanList;
GetMAScanner().Scan( MAScanner::eType::MonsterSkillSameTeamExpectMe, m_hActor, 0.f, static_cast<float>(pStruct->nRange), hScanList );
for( UINT i=0 ; i<hScanList.size() ; ++i )
{
DnActorHandle hActor = hScanList[i];
if( hActor && hActor->IsMonsterActor() )
{
CDnMonsterActor* pMonster = static_cast<CDnMonsterActor*>(hActor.GetPointer());
if( pMonster->GetMonsterClassID() == pStruct->nTargetMonsterID )
{
pMonster->GetAIBase()->NotifyDieAnnounce();
}
}
}
break;
}
case STE_NextCustomAction:
{
if( !GetAIBase() )
return;
int state = 0;
float fLength = 0.0f;
EtVector3* pvPos = GetPosition();
MAAiScript* pScript = static_cast<MAAiScript*>(GetAIBase());
if( pScript->GetTarget() )
{
state = pScript->GetTargetDistanceState( pScript->GetTarget() );
fLength = EtVec3Length( &( *pvPos - *pScript->GetTarget()->GetPosition() ) );
}
if( static_cast<MAAiScript*>(GetAIBase())->GetAIState() == MAAiScript::AT_CustomAction )
static_cast<MAAiScript*>(GetAIBase())->OnCustomAction( state, fLength, 0 );
if( static_cast<MAAiScript*>(GetAIBase())->GetAIState() == MAAiScript::AT_UseSkill )
{
CancelUsingSkill();
static_cast<MAAiScript*>(GetAIBase())->OnUseSkill( state, fLength, 0 );
}
return;
}
#ifdef PRE_ADD_MONSTER_CATCH
case STE_CatchActor:
{
CatchActor( reinterpret_cast<CatchActorStruct*>(pPtr), nSignalIndex );
}
break;
case STE_ReleaseActor:
{
ReleaseAllActor( /*reinterpret_cast<ReleaseActorStruct*>(pPtr)*/ );
}
break;
#endif // #ifdef PRE_ADD_MONSTER_CATCH
case STE_ChangeAxis:
{
m_bChangeAxisOnFinishAction = true;
}
break;
}
CDnActor::OnSignal( Type, pPtr, LocalTime, SignalStartTime, SignalEndTime, nSignalIndex );
}
bool CDnMonsterActor::IsHittable( DnActorHandle hHitter, LOCAL_TIME LocalTime, HitStruct *pHitSignal, int iHitUniqueID )
{
#if defined(PRE_FIX_61382)
#else
//#59347
//<2F><><EFBFBD>ΰ<EFBFBD><CEB0><EFBFBD> <20><>ȯ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΰ<EFBFBD><CEB0><EFBFBD> <20><>Ʈ <20><><EFBFBD><EFBFBD> <20><><EFBFBD>θ<EFBFBD> <20><><EFBFBD>ΰ<EFBFBD><CEB0>ø<EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Hittable<6C><65><EFBFBD>θ<EFBFBD> üũ <20>ϵ<EFBFBD><CFB5><EFBFBD> <20>Ѵ<EFBFBD>.
if ( IsPuppetSummonMonster() && m_hSummonerPlayerActor )
{
bool bSummonerPlayerActorHittable = m_hSummonerPlayerActor->IsHittable(hHitter, LocalTime, pHitSignal, iHitUniqueID);
if (bSummonerPlayerActorHittable == false)
return false;
}
#endif // PRE_FIX_61382
if( m_bNoDamage ) return false;
return CDnActor::IsHittable( hHitter, LocalTime, pHitSignal, iHitUniqueID );
}
void CDnMonsterActor::ProcessPositionRevision( float fDelta )
{
if( CheckSignalPositionRevision( fDelta ) || CheckPositionRevision() )
{
BYTE pBuffer[128] = { 0, };
CPacketCompressStream Stream( pBuffer, 128 );
Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Write( &EtVec3toVec2( *GetMoveVectorZ() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Send( eActor::SC_POSREV, &Stream );
ResetPositionRevision();
}
}
bool CDnMonsterActor::CheckPositionRevision()
{
if( m_LastSendMoveMsg == 0 )
return false;
if( !IsMove() )
{
m_LastSendMoveMsg = CDnActionBase::m_LocalTime;
return false;
}
if( CDnActionBase::m_LocalTime - m_LastSendMoveMsg > s_nPositionRevisionTime )
return true;
return false;
}
bool CDnMonsterActor::CheckSignalPositionRevision( float fDelta )
{
if( m_uiForcePositionRevisionTick == 0 )
return false;
if( m_uiPrevForcePositionRevisionTick == 0 )
{
//std::cout << GetTickCount() << ":ù<><C3B9>° <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ <20><><EFBFBD><EFBFBD>" << std::endl;
m_fForcePositionRevisionDelta = m_uiForcePositionRevisionTick/1000.f;
return true;
}
m_fForcePositionRevisionDelta -= fDelta;
if( m_fForcePositionRevisionDelta <= 0.f )
{
m_fForcePositionRevisionDelta = m_uiForcePositionRevisionTick/1000.f;
//std::cout << GetTickCount() << ":<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ <20><><EFBFBD><EFBFBD>" << std::endl;
return true;
}
return false;
}
void CDnMonsterActor::ResetPositionRevision()
{
m_LastSendMoveMsg = CDnActionBase::m_LocalTime;
}
float CDnMonsterActor::GetRotateAngleSpeed()
{
return CDnMonsterState::GetRotateAngleSpeed() * m_fRotateResistance;
}
void CDnMonsterActor::AttachWeapon( DnWeaponHandle hWeapon, int nEquipIndex, bool bDelete )
{
CDnActor::AttachWeapon( hWeapon, nEquipIndex, bDelete );
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if( m_nMonsterWeightTableID == -1 ) return;
if( hWeapon->IsInfinityDurability() || hWeapon->GetDurability() <= 0 ) return;
DNTableFileFormat* pWeight = GetDNTable( CDnTableDB::TMONSTERWEIGHT );
int nDurability = (int)( hWeapon->GetDurability() * pWeight->GetFieldFromLablePtr( m_nMonsterWeightTableID, "_DurabilityWeight" )->GetFloat() );
hWeapon->SetDurability( nDurability );
}
void CDnMonsterActor::SetTeam( int nValue )
{
if( GetTeam() != nValue ) {
if( m_pAi ) m_pAi->ResetAggro();
}
CDnActor::SetTeam( nValue );
}
void CDnMonsterActor::ProcessPartyCombo( LOCAL_TIME LocalTime, float fDelta )
{
if( m_nPartyComboDelay > 0 ) m_nPartyComboDelay -= (int)( fDelta * 1000 );
if( m_nPartyComboDelay < 0 ) {
m_nPartyComboCount = 0;
m_nPartyComboDelay = 0;
m_hPartyHitActor.Identity();
}
}
void CDnMonsterActor::OnPartyCombo( DnActorHandle hHitter, int nComboDelay )
{
// #12170 <20>޺<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> 0<><30> hit <20><> <20>޺<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ƹ<EFBFBD><C6B9><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʵ<EFBFBD><CAB5><EFBFBD> ó<><C3B3>.
if( 0 == nComboDelay )
return;
if( m_hPartyHitActor == hHitter ) {
m_nPartyComboDelay = nComboDelay;
return;
}
m_hPartyHitActor = hHitter;
if( m_nPartyComboDelay > 0 ) {
m_nPartyComboCount++;
if( hHitter && hHitter->IsPlayerActor() ) {
CDnPlayerActor *pPlayer = static_cast<CDnPlayerActor *>(hHitter.GetPointer());
pPlayer->UpdatePartyCombo( m_nPartyComboCount );
}
}
else {
m_nPartyComboCount = 0;
}
m_nPartyComboDelay = nComboDelay;
}
void CDnMonsterActor::Process_AutoRecallRange()
{
if( NULL == m_hSummonerPlayerActor )
return;
if( 0 == m_nAutoRecallRange )
return;
//#55707 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ <20>ȵ<EFBFBD>
bool isAttackState = IsAttack();
if (isAttackState == true)
return;
EtVector2 vVec;
vVec.x = m_hSummonerPlayerActor->GetPosition()->x - m_Cross.m_vPosition.x;
vVec.y = m_hSummonerPlayerActor->GetPosition()->z - m_Cross.m_vPosition.z;
float fLength = EtVec2Length(&vVec);
if( m_nAutoRecallRange < fLength )
{
//#55707 <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD>׷<EFBFBD> <20><><EFBFBD><EFBFBD> <20><>Ŵ.
ResetAggro();
CmdWarp( *m_hSummonerPlayerActor->GetPosition(), EtVec3toVec2( *m_hSummonerPlayerActor->GetLookDir() ) );
}
}
void CDnMonsterActor::ReTransmitSlaveMsg(CDNUserSession* pBreakIntoSession) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><DFB1><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD> <20><><EFBFBD><EFBFBD>.
{
BYTE pBuffer[32];
CPacketCompressStream Stream( pBuffer, 32 );
Stream.Write( &m_dwSummonerActorID, sizeof(DWORD) );
Stream.Write( &m_bSummoned , sizeof(bool) );
Stream.Write( &m_nMaxHP, sizeof(INT64) );
Stream.Write( &m_nHP, sizeof(INT64) );
Stream.Write( &m_bFollowSummonerStage, sizeof(bool) );
Stream.Write( &m_bReCreatedFollowStageMonster, sizeof(bool) );
#if defined(PRE_FIX_55618)
//BaseState<74><65> MaxHP/HP/<2F>̵<EFBFBD> <20>ӵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD>ְ<EFBFBD>, <20><> <20><>Ŷ<EFBFBD><C5B6> <20><><EFBFBD><EFBFBD> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>س<EFBFBD><D8B3><EFBFBD>
//<2F><><EFBFBD>̻<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʵ<EFBFBD><CAB5><EFBFBD> m_bCopiedFromSummoner <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ش<EFBFBD>..
INT64 nBaseMaxHP = m_BaseState.GetMaxHP();
float nBaseMaxHPRate = m_BaseState.GetMaxHPRatio();
Stream.Write( &nBaseMaxHP, sizeof(INT64) );
Stream.Write( &nBaseMaxHPRate, sizeof(float) );
Stream.Write( &m_nMoveSpeed, sizeof(int) );
#endif // PRE_FIX_55618
Send( pBreakIntoSession , eActor::SC_SLAVE_OF, GetUniqueID() , &Stream );
}
void CDnMonsterActor::SlaveOf( DWORD dwSummonerActorUniqueID, bool bSummoned/* = false*/, bool bSuicideWhenSummonerDie/* = false*/, bool bFollowSummonerStage/* = false*/, bool bReCreateFollowStageMonster/* = false*/ )
{
BYTE pBuffer[32];
CPacketCompressStream Stream( pBuffer, 32 );
Stream.Write( &dwSummonerActorUniqueID, sizeof(DWORD) );
Stream.Write( &bSummoned, sizeof(bool) );
if( bSummoned )
{
Stream.Write( &m_nMaxHP, sizeof(INT64) );
Stream.Write( &m_nHP, sizeof(INT64) );
Stream.Write( &bFollowSummonerStage, sizeof(bool) );
Stream.Write( &bReCreateFollowStageMonster, sizeof(bool) );
#if defined(PRE_FIX_55618)
//BaseState<74><65> MaxHP/HP/<2F>̵<EFBFBD> <20>ӵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD>ְ<EFBFBD>, <20><> <20><>Ŷ<EFBFBD><C5B6> <20><><EFBFBD><EFBFBD> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>س<EFBFBD><D8B3><EFBFBD>
//<2F><><EFBFBD>̻<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʵ<EFBFBD><CAB5><EFBFBD> m_bCopiedFromSummoner <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ش<EFBFBD>..
INT64 nBaseMaxHP = m_BaseState.GetMaxHP();
float nBaseMaxHPRate = m_BaseState.GetMaxHPRatio();
Stream.Write( &nBaseMaxHP, sizeof(INT64) );
Stream.Write( &nBaseMaxHPRate, sizeof(float) );
Stream.Write( &m_nMoveSpeed, sizeof(int) );
#endif // PRE_FIX_55618
#if defined(PRE_FIX_61382)
Stream.Write(&m_isPuppetSummonMonster, sizeof(bool));
#endif // PRE_FIX_61382
}
Send( eActor::SC_SLAVE_OF, &Stream );
m_dwSummonerActorID = dwSummonerActorUniqueID;
if( bSummoned )
{
DnActorHandle hActor = CDnActor::FindActorFromUniqueID( GetRoom(), dwSummonerActorUniqueID );
//#53454 <20><><EFBFBD>ΰ<EFBFBD><CEB0><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ <20><>ü<EFBFBD><C3BC> PlayerActor<6F><72> <20>ƴ<EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD>.
if( hActor/* && hActor->IsPlayerActor()*/ )
{
m_hSummonerPlayerActor = hActor;
m_bSuicideWhenSummonerDie = bSuicideWhenSummonerDie;
m_bFollowSummonerStage = bFollowSummonerStage;
// <20>÷<EFBFBD><C3B7>̾ <20><>ȯ<EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ʹ<EFBFBD> pvp/pve <20><>ų<EFBFBD><C5B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̺<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
SelectSkillLevelDataType( hActor->GetSelectedSkillLevelDataType(), true );
}
}
m_bSummoned = bSummoned;
m_bReCreatedFollowStageMonster = bReCreateFollowStageMonster;
}
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
void CDnMonsterActor::SlaveRelease( void )
{
if( 0 == m_dwSummonerActorID )
return;
BYTE pBuffer[32];
CPacketCompressStream Stream( pBuffer, 32 );
Stream.Write( &m_dwSummonerActorID, sizeof(DWORD) );
Send( eActor::SC_SLAVE_RELEASE, &Stream );
if( m_hSummonerPlayerActor )
{
m_hSummonerPlayerActor.Identity();
}
}
void CDnMonsterActor::OnHitSuccess( LOCAL_TIME LocalTime, DnActorHandle hActor, HitStruct *pStruct )
{
// <20>Ϲ<EFBFBD><CFB9><EFBFBD><EFBFBD><EFBFBD> <20><>Ȳ<EFBFBD><C8B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20>÷<EFBFBD><C3B7>̾<EFBFBD><CCBE><EFBFBD> <20>޺<EFBFBD> ī<><C4AB>Ʈ<EFBFBD><C6AE> ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>.
if( m_hSummonerPlayerActor && m_hSummonerPlayerActor->IsPlayerActor() )
m_hSummonerPlayerActor->OnHitSuccess( LocalTime, hActor, pStruct );
}
void CDnMonsterActor::OnHitFinish( LOCAL_TIME LocalTime, HitStruct *pStruct )
{
CDnActor::OnHitFinish( LocalTime, pStruct );
if (IsSummonedMonster())
{
DnActorHandle hMasterActor = GetSummonerPlayerActor();
if (hMasterActor)
{
int nDieCount = 0;
for( DWORD i=0; i<m_hVecLastHitList.size(); i++ ) {
if( m_hVecLastHitList[i] && m_hVecLastHitList[i]->IsDie() ) nDieCount++;
}
hMasterActor->UpdateMissionByMonsterKillCount(nDieCount);
}
}
if( GetAIBase() )
GetAIBase()->OnHitFinish( LocalTime, pStruct );
}
void CDnMonsterActor::ResetAggro( void )
{
if( m_pAggroSystem )
m_pAggroSystem->ResetAggro();
}
void CDnMonsterActor::ResetAggro( DnActorHandle hActor )
{
if( m_pAggroSystem )
m_pAggroSystem->ResetAggro( hActor );
}
void CDnMonsterActor::RequestDamageFromStateBlow( DnBlowHandle hFromBlow, int iDamage )
{
if( m_bNoDamage ) return;
CDnActor::RequestDamageFromStateBlow( hFromBlow, iDamage );
}
#ifdef PRE_ADD_MONSTER_CATCH
void CDnMonsterActor::_CatchThisActor( DnActorHandle hResultActor, int nSignalIndex )
{
S_CATCH_ACTOR_INFO CatchActorInfo;
CatchActorInfo.hCatchedActor = hResultActor;
CatchActorInfo.hCatchedActor->SetActionQueue( m_strCatchedActorAction.c_str() );
m_iCatchedActorActionIndex = CatchActorInfo.hCatchedActor->GetElementIndex( m_strCatchedActorAction.c_str() );
// <20>̵<EFBFBD>/<2F>ൿ<EFBFBD>Ұ<EFBFBD> <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF> <20>߰<EFBFBD>.
CatchActorInfo.iCatchCantMoveBlowID = CatchActorInfo.hCatchedActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_070, -1, "", false, false );
CatchActorInfo.iCatchCantActionBlowID = CatchActorInfo.hCatchedActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_071, -1, "", false, false );
if( CatchActorInfo.hCatchedActor->IsPlayerActor() )
{
static_cast<CDnPlayerActor*>(CatchActorInfo.hCatchedActor.GetPointer())->SetCatcherMonsterActor( GetMySmartPtr() );
}
m_vlCatchedActors.push_back( CatchActorInfo );
// Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD>Ҵٰ<D2B4> <20><>Ŷ <20><><EFBFBD><EFBFBD>.
BYTE pBuffer[ 128 ] = { 0 };
CPacketCompressStream Stream( pBuffer, 128 );
DWORD dwCatchedActorID = CatchActorInfo.hCatchedActor->GetUniqueID();
int nCatchActionIndex = GetCurrentActionIndex();
int nCatchSignalArrayIndex = nSignalIndex;
Stream.Write( &dwCatchedActorID, sizeof(DWORD) );
Stream.Write( &nCatchActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT );
Stream.Write( &nCatchSignalArrayIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT );
Send( eActor::SC_CATCH_ACTOR, &Stream );
}
void CDnMonsterActor::CatchActor( CatchActorStruct* pCatchActor, int nSignalIndex )
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʴٸ<CAB4> <20>ѳ<EFBFBD><D1B3><EFBFBD> <20><><EFBFBD><EFBFBD> <20>־ ó<><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʰ<EFBFBD> <20>ѱ<EFBFBD><D1B1><EFBFBD>.
if( FALSE == pCatchActor->bMultiCatch )
if( false == m_vlCatchedActors.empty() )
return;
m_strCatchBoneName = pCatchActor->szCatchBoneName;
m_strTargetActorCatchBoneName = pCatchActor->szTargetActorCatchBoneName;
if( pCatchActor->szCatchedActorAction != NULL &&
0 < strlen(pCatchActor->szCatchedActorAction) )
{
m_strCatchedActorAction.assign( pCatchActor->szCatchedActorAction );
}
else
m_strCatchedActorAction.assign( "Hold" );
EtVector3 vCatchBonePos( 0.0f, 0.0f, 0.0f );
GetObjectHandle()->SetCalcAni( true );
EtMatrix matBoneWorld = GetBoneMatrix( m_strCatchBoneName.c_str() );
GetObjectHandle()->SetCalcAni( false );
memcpy_s( &vCatchBonePos, sizeof(EtVector3), &matBoneWorld._41, sizeof(EtVector3) );
// <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><> <20≯<EFBFBD><CCB8><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><>ġ <20><>ó<EFBFBD><C3B3><EFBFBD><EFBFBD> <20>ñ׳ο<D7B3><CEBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20>Ÿ<EFBFBD><C5B8><EFBFBD> ª<><C2AA> <20>ְ<EFBFBD> <20>ִ<EFBFBD><D6B4><EFBFBD> Ȯ<><C8AE>.
DNVector( DnActorHandle ) vlhActors;
ScanActor( GetGameRoom(), vCatchBonePos, pCatchActor->fCatchDistance, vlhActors );
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>̰<EFBFBD><CCB0><EFBFBD> <20><><EFBFBD><EFBFBD> üũ.
float fMinDistanceSQ = FLT_MAX;
DnActorHandle hResultActor;
for( int i = 0; i < (int)vlhActors.size(); ++i )
{
DnActorHandle hActor = vlhActors.at( i );
// <20><><EFBFBD><EFBFBD> <20>ñ׳ο<D7B3><CEBF><EFBFBD> <20>ѹ<EFBFBD> üũ<C3BC><C5A9> <20><> <20><><EFBFBD>ʹ<EFBFBD> <20><><EFBFBD><EFBFBD>.
if( m_setCatchCheckedActorIDs.end() != m_setCatchCheckedActorIDs.find( hActor->GetUniqueID() ) )
continue;
// <20>ڱ<EFBFBD> <20>ڽ<EFBFBD><DABD><EFBFBD> <20>н<EFBFBD>
if( GetMySmartPtr() == hActor )
continue;
// üũ<C3BC><C5A9> <20><> <20>ֵ<EFBFBD><D6B5><EFBFBD> set <20><> <20><><EFBFBD>ٷ<EFBFBD> <20>־<EFBFBD><D6BE><EFBFBD>.
m_setCatchCheckedActorIDs.insert( hActor->GetUniqueID() );
// <20>÷<EFBFBD><C3B7>̾<EFBFBD> <20><><EFBFBD>͸<EFBFBD>.
if( false == hActor->IsPlayerActor() )
continue;
// <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>.
if( GetTeam() == hActor->GetTeam() )
continue;
// CanHit <20><><EFBFBD><EFBFBD> Ȯ<><C8AE>.
if( FALSE == pCatchActor->bIgnoreCanHit )
{
if( false == hActor->CDnActorState::IsHittable() )
continue;
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ִٸ<D6B4> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
if( hActor->IsAppliedThisStateBlow( STATE_BLOW::BLOW_099 ) )
continue;
}
// bMultiCatch <20>÷<EFBFBD><C3B7>װ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ִٸ<D6B4> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><E0BCAE> <20><><EFBFBD><EFBFBD> ó<><C3B3>./
// <20><><EFBFBD><EFBFBD> <20>ִٸ<D6B4> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3>.
EtVector3 vTargetActorPos = *hActor->GetPosition();
EtVector3 vDist = vCatchBonePos - vTargetActorPos;
float fDistanceSQ = EtVec3LengthSq( &vDist );
if( TRUE == pCatchActor->bMultiCatch ||
fDistanceSQ < fMinDistanceSQ )
{
// <20><><EFBFBD>̵<EFBFBD> <20>´<EFBFBD><C2B4><EFBFBD> Ȯ<><C8AE>.
bool bHeightMax = vTargetActorPos.y < (pCatchActor->fHeightMax + vCatchBonePos.y);
bool bHeightMin = (vCatchBonePos.y + pCatchActor->fHeightMin) < vTargetActorPos.y; // HeightMin <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
if( bHeightMax && bHeightMin )
{
bool bCatchFailed = true;
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Ŭ<><C5AC><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, 0: <20>и<EFBFBD>, 1: <20><><EFBFBD><EFBFBD>, 2: <20><><EFBFBD>۾Ƹӷ<C6B8> <20>ߵ<EFBFBD>.
int iFailedType = -1;
int iBlowID = 0;
string strBlockOrParringAction;
//////////////////////////////////////////////////////////////////////////
// <20>и<EFBFBD> <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><><EFBFBD><20><>Ʈ<EFBFBD><C6AE> <20>ƴϹǷ<CFB9> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ȯ<><C8AE> üũ.
bool bPassParring = true;
if( FALSE == pCatchActor->bIgnoreParring )
{
bool bAppliedBlockBlow = hActor->IsAppliedThisStateBlow( STATE_BLOW::BLOW_030 );
bool bAppliedParringBlow = hActor->IsAppliedThisStateBlow( STATE_BLOW::BLOW_031 );
if( bAppliedBlockBlow || bAppliedParringBlow )
{
// <20>и<EFBFBD><D0B8><EFBFBD> <20><> <20><><EFBFBD><20>и<EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>..
// <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF><EFBFBD>ʿ<EFBFBD><CABF><EFBFBD> HitParam <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><20>Ѱ<EFBFBD><D1B0>ش<EFBFBD>.
SHitParam HitParam;
HitParam.szActionName = m_strCatchedActorAction;
HitParam.fDamage = 1.0f;// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ƴϹǷ<CFB9> <20>ƹ<EFBFBD><C6B9><EFBFBD><EFBFBD>̳<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>. 0 <20≯<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF>üũ<C3BC><C5A9><EFBFBD><EFBFBD> <20>н<EFBFBD><D0BD><EFBFBD>.
HitParam.bIgnoreParring = false;
CDnActorState* pState = static_cast<CDnActorState*>(this);
bool bSuccess = false;
if( bAppliedParringBlow )
{
DNVector(DnBlowHandle) vlhBlows;
hActor->GatherAppliedStateBlowByBlowIndex( STATE_BLOW::BLOW_031, vlhBlows );
if( false == vlhBlows.empty() )
{
DnBlowHandle hParringBlow = vlhBlows.front();
bSuccess = hParringBlow->OnDefenseAttack( GetMySmartPtr(), pState, HitParam, true );
if( bSuccess )
{
iFailedType = 0;
iBlowID = hParringBlow->GetBlowID();
}
}
}
if( (false == bSuccess) && bAppliedBlockBlow )
{
DNVector(DnBlowHandle) vlhBlows;
hActor->GatherAppliedStateBlowByBlowIndex( STATE_BLOW::BLOW_030, vlhBlows );
if( false == vlhBlows.empty() )
{
DnBlowHandle hBlockBlow = vlhBlows.front();
bSuccess = hBlockBlow->OnDefenseAttack( GetMySmartPtr(), pState, HitParam, true );
if( bSuccess )
{
iFailedType = 1;
iBlowID = hBlockBlow->GetBlowID();
}
}
}
if( bSuccess )
{
bPassParring = false;
// <20>и<EFBFBD> <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ǰ<EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20>ѱ<EFBFBD><D1B1><EFBFBD>.
if( HitParam.szActionName != m_strCatchedActorAction )
{
m_hActor->SetActionQueue( HitParam.szActionName.c_str() );
strBlockOrParringAction = HitParam.szActionName;
}
}
}
}
// <20>и<EFBFBD><D0B8><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>۾Ƹӷ<C6B8> <20>ߵ<EFBFBD><DFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> üũ.
if( bPassParring )
{
if( hActor->CatchCalcSuperArmor( GetMySmartPtr(), pCatchActor->nApplySuperArmorDamage ) )
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>۾Ƹ<DBBE> <20>ٵǾ<D9B5> <20><><EFBFBD><EFBFBD> <20><>.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>÷<EFBFBD><C3B7>װ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ο<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3>.
if( TRUE == pCatchActor->bMultiCatch )
{
_CatchThisActor( hActor, nSignalIndex );
}
else
{
hResultActor = hActor;
fMinDistanceSQ = fDistanceSQ;
}
bCatchFailed = false;
}
else
{
iFailedType = 2;
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ȿ<EFBFBD> <20>ִµ<D6B4><C2B5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> ij<><C4B3><EFBFBD><EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> <20>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
// <20>и<EFBFBD><D0B8>̳<EFBFBD> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD>۾ƸӰ<C6B8> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD>.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><ECBFA1> Ŭ<>󿡼<EFBFBD> Ƚ<><C8BD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ְ<EFBFBD>, <20>и<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD> <20><><EFBFBD><EFBFBD>Ű<EFBFBD><C5B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>.
if( bCatchFailed )
{
BYTE pBuffer[ 128 ] = { 0 };
CPacketCompressStream Stream( pBuffer, 128 );
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, 0: <20>и<EFBFBD>, 1: <20><><EFBFBD><EFBFBD>, 2: <20><><EFBFBD>۾Ƹӷ<C6B8> <20>ߵ<EFBFBD>.
int iFailedType = 0;
DWORD dwCatchFailedActorID = hActor->GetUniqueID();
int iParringOrBlockActionIndex = hActor->GetElementIndex( strBlockOrParringAction.c_str() );
Stream.Write( &iFailedType, sizeof(int), CPacketCompressStream::INTEGER_CHAR );
Stream.Write( &iBlowID, sizeof(int), CPacketCompressStream::INTEGER_SHORT );
Stream.Write( &dwCatchFailedActorID, sizeof(DWORD) );
Stream.Write( &iParringOrBlockActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT );
Send( eActor::SC_CATCH_ACTOR_FAILED, &Stream );
}
}
}
}
if( hResultActor )
{
_CatchThisActor( hResultActor, nSignalIndex );
}
}
void CDnMonsterActor::ReleaseThisActor( DnActorHandle hActor )
{
vector<S_CATCH_ACTOR_INFO>::iterator iter = m_vlCatchedActors.begin();
for( iter; iter != m_vlCatchedActors.end(); ++iter )
{
S_CATCH_ACTOR_INFO& CatchActorInfo = *iter;
if( CatchActorInfo.hCatchedActor == hActor )
{
ReleaseThisActor( CatchActorInfo );
m_vlCatchedActors.erase( iter );
break;
}
}
}
void CDnMonsterActor::ReleaseThisActor( S_CATCH_ACTOR_INFO &CatchActorInfo )
{
if( CatchActorInfo.hCatchedActor )
{
m_setCatchCheckedActorIDs.erase( CatchActorInfo.hCatchedActor->GetUniqueID() );
CatchActorInfo.hCatchedActor->CmdRemoveStateEffectFromID( CatchActorInfo.iCatchCantMoveBlowID );
CatchActorInfo.hCatchedActor->CmdRemoveStateEffectFromID( CatchActorInfo.iCatchCantActionBlowID );
// Ŭ<><C5AC><EFBFBD><EFBFBD> <20><><EFBFBD>´ٰ<C2B4> <20><>Ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
BYTE pBuffer[ 128 ] = { 0 };
CPacketCompressStream Stream( pBuffer, 128 );
DWORD dwCatchActorID = CatchActorInfo.hCatchedActor->GetUniqueID();
Stream.Write( &dwCatchActorID, sizeof(DWORD) );
Send( eActor::SC_RELEASE_ACTOR, &Stream );
// TODO: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>˸<EFBFBD> <20>ʿ䰡 <20>ִٸ<D6B4>.. <20><><EFBFBD><EFBFBD> <20><> ó<><C3B3><EFBFBD>ϰ<EFBFBD>.
if( CatchActorInfo.hCatchedActor->IsPlayerActor() )
{
static_cast<CDnPlayerActor*>( CatchActorInfo.hCatchedActor.GetPointer() )->ReleaseCatcherMonsterActor();
}
}
}
void CDnMonsterActor::ReleaseAllActor( void )
{
// üũ <20><> <20><><EFBFBD><EFBFBD>.
m_setCatchCheckedActorIDs.clear();
// <20>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF> <20><><EFBFBD><EFBFBD>
for( int i = 0; i < (int)m_vlCatchedActors.size(); ++i )
{
S_CATCH_ACTOR_INFO& CatchActorInfo = m_vlCatchedActors.at( i );
if( CatchActorInfo.hCatchedActor )
{
ReleaseThisActor( CatchActorInfo );
}
}
m_vlCatchedActors.clear();
}
void CDnMonsterActor::ProcessCatchActor( LOCAL_TIME LocalTime, float fDelta )
{
vector<S_CATCH_ACTOR_INFO>::iterator iter = m_vlCatchedActors.begin();
for( iter; iter != m_vlCatchedActors.end(); )
{
S_CATCH_ACTOR_INFO& CatchActorInfo = *iter;
// <20><><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20>÷<EFBFBD><C3B7>̾ <20>׾<EFBFBD><D7BE><EFBFBD> <20><>. <20><><EFBFBD>ش<EFBFBD>.
// TODO: <20><><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20>׾<EFBFBD><D7BE><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
if( CatchActorInfo.hCatchedActor &&
false == CatchActorInfo.hCatchedActor->IsDie() &&
false == IsDie() )
{
EtVector3 vCatchBonePos( 0.0f, 0.0f, 0.0f );
EtMatrix matBoneWorld = GetBoneMatrix( m_strCatchBoneName.c_str() );
memcpy_s( &vCatchBonePos, sizeof(EtVector3), &matBoneWorld._41, sizeof(EtVector3) );
// vCatchBonePos <20><> ij<><C4B3><EFBFBD><EFBFBD> Bip01 <20><> <20><>ġ<EFBFBD><C4A1><EFBFBD>Ѿ<EFBFBD> <20>Ѵ<EFBFBD>.
// <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> vCatchBonePos <20><> <20><><EFBFBD><EFBFBD> ij<><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Bip01 <20><> <20>Ÿ<EFBFBD><C5B8><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD>
// <20>׸<EFBFBD>ŭ <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
EtVector3 vPlayerCatchedPointPos( 0.0f, 0.0f, 0.0f );
CatchActorInfo.hCatchedActor->GetObjectHandle()->SetCalcAni( true );
matBoneWorld = CatchActorInfo.hCatchedActor->GetBoneMatrix( m_strTargetActorCatchBoneName.c_str() );
CatchActorInfo.hCatchedActor->GetObjectHandle()->SetCalcAni( false );
memcpy_s( &vPlayerCatchedPointPos, sizeof(EtVector3), &matBoneWorld._41, sizeof(EtVector3) );
EtVector3 vDelta = vCatchBonePos - vPlayerCatchedPointPos;
EtVector3 vNowCatchedActorPos = *CatchActorInfo.hCatchedActor->GetPosition();
EtVector3 vCatchedActorPos = vNowCatchedActorPos + vDelta;
CatchActorInfo.hCatchedActor->SetPosition( vCatchedActorPos );
//CatchActorInfo.hCatchedActor->SetActionQueue( m_strCatchedActorAction.c_str() );
// <20>ٸ<EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> <20><><EFBFBD>ϰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
int iCurrentActionIndex = CatchActorInfo.hCatchedActor->GetCurrentActionIndex();
if( iCurrentActionIndex != m_iCatchedActorActionIndex )
CatchActorInfo.hCatchedActor->SetActionQueue( m_strCatchedActorAction.c_str() );
++iter;
}
else
{
ReleaseThisActor( CatchActorInfo );
iter = m_vlCatchedActors.erase( iter );
}
}
if( false == IsSignalRange( STE_CatchActor ) )
{
if( false == m_setCatchCheckedActorIDs.empty() )
m_setCatchCheckedActorIDs.clear();
}
}
#endif // #ifdef PRE_ADD_MONSTER_CATCH
#if defined(PRE_FIX_51048)
void CDnMonsterActor::AddPassiveStateEffectInfo(PassiveStateEffectInfo& stateEffectInfo)
{
m_PassiveStateEffectInfoList.push_back(stateEffectInfo);
}
void CDnMonsterActor::InitPassiveStateEffectInfo()
{
m_PassiveStateEffectInfoList.clear();
}
void CDnMonsterActor::ApplyPassiveStateEffect()
{
if (m_PassiveStateEffectInfoList.empty())
return;
std::list<PassiveStateEffectInfo>::iterator iter = m_PassiveStateEffectInfoList.begin();
std::list<PassiveStateEffectInfo>::iterator endIter = m_PassiveStateEffectInfoList.end();
for (; iter != endIter; ++iter)
{
PassiveStateEffectInfo& passiveStateEffect = (*iter);
DnSkillHandle hSkill = FindSkill(passiveStateEffect.pParentSkill->iSkillID);
if (hSkill)
{
// <20><><EFBFBD><EFBFBD> -> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> <20><>Ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int iBlowID = CmdAddStateEffect( passiveStateEffect.pParentSkill, passiveStateEffect.emBlowIndex, -1, passiveStateEffect.szParam.c_str(), true ); // Duration Time<6D><65> -1 <20≯<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
OnApplyPassiveSkillBlow( iBlowID );
hSkill->SetAppliedPassiveBlows( true );
}
}
}
bool CDnMonsterActor::ApplyPassiveSkill( DnSkillHandle hSkill, bool isInitialize/* = false*/ )
{
bool bPassiveBuf = false;
if( CDnSkill::Passive == hSkill->GetSkillType() )
{
int iNumStateEffect = hSkill->GetStateEffectCount();
for( int i = 0; i < iNumStateEffect; ++i )
{
CDnSkill::StateEffectStruct* pSE = hSkill->GetStateEffectFromIndex( i );
if( CDnSkill::StateEffectApplyType::ApplySelf == pSE->ApplyType )
{
if( CDnSkill::DurationTypeEnum::Buff == hSkill->GetDurationType() )
{
bPassiveBuf = true;
if( hSkill->IsSatisfyWeapon() )
{
//<2F><>Ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
if (GetEnablePassiveStateEffectList() == true)
{
PassiveStateEffectInfo passiveStateEffectInfo;
passiveStateEffectInfo.pParentSkill = hSkill->GetInfo();
passiveStateEffectInfo.emBlowIndex = (STATE_BLOW::emBLOW_INDEX)pSE->nID;
passiveStateEffectInfo.nDurationTime = -1;
passiveStateEffectInfo.szParam = pSE->szValue;
AddPassiveStateEffectInfo(passiveStateEffectInfo);
}
else
{
// <20><><EFBFBD><EFBFBD> -> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> <20><>Ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int iBlowID = CmdAddStateEffect( hSkill->GetInfo(), (STATE_BLOW::emBLOW_INDEX)pSE->nID, -1, pSE->szValue.c_str(), true ); // Duration Time<6D><65> -1 <20≯<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
OnApplyPassiveSkillBlow( iBlowID );
hSkill->SetAppliedPassiveBlows( true );
}
#ifndef _FINAL_BUILD
char szTemp[256] = { 0, };
WideCharToMultiByte( CP_ACP, 0, hSkill->GetName(), -1, szTemp, _countof(szTemp), NULL, NULL );
OutputDebug( "[<5B>нú<D0BD> <20><><EFBFBD><EFBFBD> <20><>ų <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %d] \"%s\" <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF>Index: %d, Value:%s\n", hSkill->GetClassID(), szTemp, pSE->nID, pSE->szValue.c_str() );
#endif // #ifndef _FINAL_BUILD
}
#ifndef _FINAL_BUILD
else
{
char szTemp[256] = { 0, };
WideCharToMultiByte( CP_ACP, 0, hSkill->GetName(), -1, szTemp, _countof(szTemp), NULL, NULL );
OutputDebug( "[<5B>нú<D0BD> <20><><EFBFBD><EFBFBD> <20><>ų <20><><EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD>: %d] \"%s\" <20><>ų<EFBFBD><C5B3> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʿ<EFBFBD> <20><><EFBFBD><EFBFBD> Ÿ<><C5B8><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʽ<EFBFBD><CABD>ϴ<EFBFBD>.\n", hSkill->GetClassID(), szTemp );
}
#endif // #ifndef _FINAL_BUILD
}
#ifndef _FINAL_BUILD
else
{
char szTemp[256] = { 0, };
WideCharToMultiByte( CP_ACP, 0, hSkill->GetName(), -1, szTemp, _countof(szTemp), NULL, NULL );
OutputDebug( "[<5B><>ų <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ȯ<><C8AE> <20><><EFBFBD><EFBFBD>: %d] \"%s\" <20>нú<D0BD> <20><><EFBFBD><EFBFBD> <20><>ų<EFBFBD><C5B3> <20><><EFBFBD><EFBFBD><EFBFBD>dz<EFBFBD> Buff <20><> <20><><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD><EFBFBD> <20>ʾƼ<CABE> <20><><EFBFBD><EFBFBD> <20>ȵ<EFBFBD>\n", hSkill->GetClassID(), szTemp );
}
#endif // #ifndef _FINAL_BUILD
}
}
}
return bPassiveBuf;
}
#endif // PRE_FIX_51048
#if defined(PRE_FIX_61382)
void CDnMonsterActor::RequestDamageFromStateBlow( DnBlowHandle hFromBlow, int iDamage, CDnDamageBase::SHitParam* pHitParam/* = NULL*/ )
{
if (IsPuppetSummonMonster() == true)
{
DnActorHandle hOwnerActor = GetSummonerPlayerActor();
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD>츸? <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
if (IsAppliedThisStateBlow(STATE_BLOW::BLOW_051) && hOwnerActor)
{
#if defined(PRE_FIX_59347) && !defined(PRE_FIX_67656)
hOwnerActor->SetApplyPartsDamage(true);
#endif // PRE_FIX_59347
hOwnerActor->RequestDamageFromStateBlow(hFromBlow, iDamage, pHitParam);
#if defined(PRE_FIX_59347) && !defined(PRE_FIX_67656)
hOwnerActor->SetApplyPartsDamage(false);
#endif // PRE_FIX_59347
}
}
else
{
CDnActor::RequestDamageFromStateBlow(hFromBlow, iDamage, pHitParam);
}
}
#endif // PRE_FIX_61382
#if defined(PRE_FIX_64312)
void CDnMonsterActor::SendApplySummonMonsterExSkill(int nBaseSkillID, int nLevel, int nSelectedType, DWORD dwMasterUniqueID, int nMasterExSkillID)
{
BYTE pBuffer[128];
CPacketCompressStream Stream( pBuffer, 128 );
Stream.Write(&nBaseSkillID, sizeof(int));
Stream.Write(&nLevel, sizeof(int));
Stream.Write(&nSelectedType, sizeof(int));
Stream.Write(&dwMasterUniqueID, sizeof(DWORD));
Stream.Write(&nMasterExSkillID, sizeof(int));
Send( eActor::SC_APPLY_SUMMON_MONSTER_EX_SKILL, &Stream );
}
#endif // PRE_FIX_64312