#include "StdAfx.h" #include "DnProjectile.h" #include "DnWeapon.h" #include "MAActorRenderBase.h" #include "VelocityFunc.h" #include "EtActionSignal.h" #include "DnWorld.h" #include "DnMonsterActor.h" #include "MAAiBase.h" #include "DnWorldBrokenProp.h" #include "DNGameServerManager.h" #include "DnChainAttackBlow.h" #include "DnPingpongBlow.h" #include "MAWalkMovement.h" #include "DnPlayerActor.h" #include "TaskManager.h" #include "DnGameTask.h" #include "IDnOrbitProcessor.h" #include "DNMissionSystem.h" #include "DnPartsMonsterActor.h" #include "DnComboDamageLimitBlow.h" #include "DnStateBlow.h" #include "DnCurseBlow.h" #include "DnChangeStandActionBlow.h" int CDnProjectile::s_iHitUniqueID = 0; #define SHOOT_ACTION_NAME "Shoot" #define HIT_ACTION_NAME "Hit" #define DESTROY_ACTION_NAME "Destroy" // ¼­¹ö¿¡¼­´Â ÀÌ ¾×¼ÇÀ» ½ÇÇà½ÃŰÁö ¾Ê´Â´Ù. // °ÔÀÓ¼­¹ö¿Í Ŭ¶óÀ̾ðÆ®ÀÇ DnProjectile Ŭ·¡½º ÆÄÀÏÀÌ µû·Î ÀÖÀ¸¹Ç·Î ¼öÁ¤ÇÒ °æ¿ì °¢°¢ ¼öÁ¤ÇØÁÖ¾î¾ß ÇÔ. const int PROJECTILE_PACKET_BUFFER_SIZE = 128; CDnProjectile::CDnProjectile( CMultiRoom *pRoom, DnActorHandle hActor, bool bProcess, bool bIncreaseUniqueID ) : CDnWeapon( pRoom, bProcess, bIncreaseUniqueID ) , m_vPrevPos( 0.f, 0.f, 0.f ) , m_vStartPos( 0.f, 0.f, 0.f ) , m_vTargetPosition( 0.f, 0.f, 0.f ) , m_vHitPos( 0.f, 0.f, 0.f ) , m_bOnCollisionCalled( false ) , m_bPierce( false ) , m_LastHitSignalEndTime( 0 ) , m_iHitUniqueID( -1 ) , m_bHasHitAction( false ) , m_bHasHitSignalInHitAction( false ) , m_bHasHitSignalInShootAction( false ) , m_nLastHitSignalIndex( 0 ) , m_fElapsedTime( 0.0f ) , m_iShooterShootActionIndex( -1 ) , m_iSignalArrayIndex( -1 ) , m_fHitApplyPercent( -1.0f ) , m_pOrbitProcessor( NULL ) , m_pPacketBuffer( NULL ) , m_pPacketStream( NULL ) , m_vForceDir( 0.0f, 0.0f, 0.0f ) , m_bUseForceDir( false ) { SetWeaponType( WeaponTypeEnum::Projectile ); m_hShooter = hActor; m_InvalidLocalTime = 0; m_CreateLocalTime = 0; m_bValidDamage = true; m_bFallGravity = false; m_fSpeed = 3000.f; m_fResistance = 0.f; m_nDestroyOrbitTimeGap = 3000; m_bStick = false; m_fGravity = 0.f; m_bFirstProcess = true; m_DestroyOrbitType = FallGravity; m_ValidType = ValidTypeEnum( WeaponLength | Stick ); memset( &m_HitStruct, 0, sizeof(m_HitStruct) ); m_iHitUniqueID = ++s_iHitUniqueID; m_bHitSignalProcessed = false; m_bBombHitSignalStarted = false; // 2009.7.29 Çѱâ - Æø¹ß½Ã È÷Æ® ½Ã±×³ÎÀÌ µÚ¿¡ ÀÖ´Â °æ¿ì°¡ ÀÖÀ¸¹Ç·Î µÚ¿¡ ÀÖ´Â ÄÉÀ̽º°¡ À־ È÷Æ® ½Ã±×³Î ½ÃÀÛ ½Ã¿¡ Ç÷¡±× ÄÑÁÜ. m_VelocityType = Accell; m_ParentSkillInfo.hSkillUser = hActor; m_nMaxHitCount = 0; m_bHitActionStarted = false; m_bProcessingBombHitSignal = false; m_bFromCharger = false; m_fProjectileOrbitRotateZDegree = 0.0f; m_iShootActionIndex = -1; m_iHitActionIndex = -1; m_iDestroyActionIndex = -1; m_bHasDestroyAction = false; // ¹ß»çü·Î ½ð °ÍÀº µ¥¹ÌÁö °è»êÇÒ ¶§ ½î¾ÒÀ» ´ç½Ã¿¡ ¹Þ¾Æ³ù´ø state ¸¦ ±â¹ÝÀ¸·Î ó¸®.z m_HitParam.bFromProjectile = true; m_bTraceHitTarget = false; m_bTraceHitActorHittable = false; m_cShooterType = 0; m_dwShooterUniqueID = -1; m_nShooterSerialID = -1; m_nShooterActionIndex = -1; m_nShooterSignalIndex = -1; m_eForceHitElement = ElementEnum::ElementEnum_Amount; m_iSummonMonsterForceSkillLevel = 0; m_OrbitType = OrbitTypeCount; m_TargetType = TargetTypeCount; m_nTargetPartsBoneIndex = 0; m_nTargetPartsIndex = 0; m_nValidTime = 0; #if defined(PRE_FIX_52329) m_nIgnoreHitType = 0; #endif // PRE_FIX_52329 #if defined(PRE_ADD_55295) m_bHitActionVectorInit = false; #endif // PRE_ADD_55295 m_SkillStartTime = 0; #if defined(PRE_FIX_65287) m_fShooterFinalDamageRate = 0.0f; #endif // PRE_FIX_65287 } CDnProjectile::~CDnProjectile() { if (m_ParentSkillInfo.hSkillUser) { DnSkillHandle hSkill = m_ParentSkillInfo.hSkillUser->FindSkill(m_ParentSkillInfo.iSkillID); if (hSkill) hSkill->RemoveProjectile(this); } SAFE_DELETE( m_pOrbitProcessor ); SAFE_DELETE( m_pPacketBuffer ); SAFE_DELETE( m_pPacketStream ); FreeAction(); } bool CDnProjectile::Initialize( MatrixEx &Offset, OrbitTypeEnum OrbitType, DestroyOrbitTypeEnum DestroyType, TargetTypeEnum TargetType ) { m_OrbitType = OrbitType; m_DestroyOrbitType = DestroyType; m_TargetType = TargetType; m_Cross = Offset; m_OffsetCross = Offset; m_vStartPos = m_vPrevPos = m_Cross.m_vPosition; SetActionQueue( SHOOT_ACTION_NAME, 0, 0.f ); m_iShootActionIndex = GetElementIndex( SHOOT_ACTION_NAME ); m_nValidTime = 0; m_bFirstProcess = true; if( m_OrbitType == Homing || m_OrbitType == TerrainHoming ) { m_ValidType = (ValidTypeEnum)( m_ValidType | Time ); m_ValidType = (ValidTypeEnum)( m_ValidType & ~WeaponLength ); } if( IsExistAction( SHOOT_ACTION_NAME ) ) { // È÷Æ® ½Ã±×³ÎÀÌ ÀÖ´ÂÁö È®ÀÎÇÑ´Ù. // ÇöÀç È£¹Ö °¡¼ÓµµÀÎ °æ¿ì¿£ ½Ã°£ÀÌ ´ÙµÇ¸é µ¥¹ÌÁö¸¦ Àû¿ëÇϵµ·Ï µÇ¾îÀֱ⠶§¹®¿¡ Shoot ¾×¼Ç¿¡ Hit ½Ã±×³ÎÀÌ ¾ø´Â °æ¿ì // µ¥¹ÌÁö 󸮸¦ ÇÏÁö ¾Êµµ·Ï ±¸ºÐÇϱâ À§Çؼ­ ¿©±â¼­ ¹Ì¸® ±¸ºÐÇØµÎµµ·Ï ÇÑ´Ù. CEtActionBase::ActionElementStruct* pShootActionElement = this->GetElement( SHOOT_ACTION_NAME ); int iNumSignals = static_cast(pShootActionElement->pVecSignalList.size()); for( int iSignal = 0; iSignal < iNumSignals; ++iSignal ) { SignalTypeEnum eSignalType = (SignalTypeEnum)pShootActionElement->pVecSignalList.at( iSignal )->GetSignalIndex(); if( STE_Hit == eSignalType ) { m_bHasHitSignalInShootAction = true; break; } } } if( IsExistAction( HIT_ACTION_NAME ) ) { m_bHasHitAction = true; // È÷Æ® ½Ã±×³ÎÀÌ ÀÖ¾î¾ß ½ÇÁ¦·Î È÷Æ® ¾×¼ÇÀÌ À¯È¿ÇÏ´Ù°í ÆÇ´ÜÇÑ´Ù. CEtActionBase::ActionElementStruct* pHitActionElement = this->GetElement( HIT_ACTION_NAME ); m_iHitActionIndex = GetElementIndex( HIT_ACTION_NAME ); int iNumSignals = static_cast(pHitActionElement->pVecSignalList.size()); for( int iSignal = 0; iSignal < iNumSignals; ++iSignal ) { SignalTypeEnum eSignalType = (SignalTypeEnum)pHitActionElement->pVecSignalList.at( iSignal )->GetSignalIndex(); if( STE_Hit == eSignalType || STE_Projectile == eSignalType ) // µð½ºÅä¼Ç ¿¡·Î¿ì µîÀº ¹ß»çüÀÇ hit ¾×¼Ç¿¡¼­ ¹ß»çü¸¦ ´Ù½Ã ½ð´Ù.. { m_bHasHitSignalInHitAction = true; break; } } } if( IsExistAction( DESTROY_ACTION_NAME ) ) { m_iDestroyActionIndex = GetElementIndex( DESTROY_ACTION_NAME ); m_bHasDestroyAction = true; } return true; } bool CDnProjectile::PostInitialize( void ) { bool bResult = false; _ASSERT( NULL == m_pOrbitProcessor ); S_PROJECTILE_PROPERTY OrbitProperty; OrbitProperty.eOrbitType = m_OrbitType; OrbitProperty.eTargetType = m_TargetType; OrbitProperty.eVelocityType = m_VelocityType; OrbitProperty.fSpeed = m_fSpeed; OrbitProperty.fResistance = m_fResistance; OrbitProperty.fProjectileOrbitRotateZ = m_fProjectileOrbitRotateZDegree; m_pOrbitProcessor = IDnOrbitProcessor::Create( m_Cross, m_OffsetCross, &OrbitProperty ); // ÃʱâÀ§Ä¡´Â ¿ÀÇÁ¼Â°ú °°Áö¸¸.. Àǹ̻ó ÀÌ·¸°Ô µû·Î ³Ö¾îÁØ´Ù. _ASSERT( m_pOrbitProcessor ); if( NULL != m_pOrbitProcessor ) { m_pOrbitProcessor->SetRoom( GetRoom() ); m_pOrbitProcessor->SetTargetActor( m_hTargetActor ); m_pOrbitProcessor->SetTargetPosition( m_vTargetPosition ); m_pOrbitProcessor->SetValidTimePointer( &m_nValidTime ); m_pOrbitProcessor->SetTargetPartsIndex(m_nTargetPartsIndex, m_nTargetPartsBoneIndex); bResult = true; } return bResult; } void CDnProjectile::ProcessOrbit( LOCAL_TIME LocalTime, float fDelta ) { if( m_bTraceHitTarget ) { if( m_hTraceActor ) { EtVector3 vPos = *m_hTraceActor->GetPosition(); m_Cross.SetPosition( vPos ); return; } } if( m_bStick ) return; // »ý¼ºµÇ´Ù ¸¸ ¹ß»çü´Â PostInitialize °¡ È£ÃâÀÌ ¾ÈµÇ¾î ÀÖ´Â °æ¿ìµµ ÀÖ´Ù. // ´ëÇ¥ÀûÀÎ ¿¹°¡ È­»ìÅë º¸Á¶¹«±â ¾øÀÌ ¿¡¾î¸®¾ó üÀμ¦ÀÌ ³ª°¡´Â °æ¿ì. if( m_pOrbitProcessor ) m_pOrbitProcessor->ProcessOrbit( m_Cross, m_vPrevPos, LocalTime, fDelta ); } void CDnProjectile::ProcessValid( LOCAL_TIME LocalTime, float fDelta ) { // ÇÑ ¹ø invalid üũµÈ °ÍÀº ´Ù½Ã üũÇÏÁö ¾Ê´Â´Ù. // hit µÇ¾î Æø¹ßÇÏ´Â ¹ß»çü °°Àº °æ¿ì m_bValidDamage Ç÷¡±×°¡ Æø¹ß½Ã¿¡ ÄÑÁ³´Ù°¡ // ´Ù½Ã ProcessValid ³»¿¡¼­ »ç°Å¸®°¡ ´Ù µÇ¾î ValidDamage°¡ false·Î µÇ´Â °æ¿ì°¡ ÀÖ´Ù. if( 0 == m_InvalidLocalTime ) { if( m_bValidDamage && ( m_ValidType & ValidTypeEnum::WeaponLength ) ) { if( GetWeaponLength() != -1 ) { bool bRangeOut = false; if( RangeFallGravity == m_DestroyOrbitType ) { float fAdditionalRange = CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::RangeFallGravityAdditionalProjectileRange ); float fRangeFallGravityLength = float(GetWeaponLength()) * fAdditionalRange; bRangeOut = (fRangeFallGravityLength < EtVec3Length( &( m_Cross.m_vPosition - m_vStartPos ) )); } else { bRangeOut = ( EtVec3Length( &( m_Cross.m_vPosition - m_vStartPos ) ) > GetWeaponLength() ); } if( bRangeOut ) { m_bValidDamage = false; m_InvalidLocalTime = LocalTime; // #43085 Ŭ¶ó¿¡¼­´Â Destroy ¾×¼ÇÀ» ½ÇÇà½ÃŰ´Â ½ÃÁ¡.. ¼­¹ö¿¡¼­´Â °ð¹Ù·Î ¹ß»çü Á¦°Å. if( m_bHasDestroyAction ) { // FallGravity ´Â ÆÛ´Ï½Ì ½ºÀ®À̳ª ÆÄÀ̾ ó·³ °í°¢À¸·Î ½÷¼­ ¶³¾î¶ß¸®´Â °Ç ¸Â¾Æ¾ß ÇϹǷΠRangeFallGravity ¸¸ ó¸®. if( RangeFallGravity == m_DestroyOrbitType ) SetDestroy(); } } } } } // Çѹø invalid µÈ °ÍÀº ´Ù½Ã invalid ó¸® µÇÁö ¾Êµµ·Ï ÇÑ´Ù. // hit ¾×¼ÇÀÌ ÀÖ´Â °æ¿ì validdamage °¡ ´Ù½Ã ÄÑÁö¹Ç·Î m_bOnCollisionCalled ·Î ±¸ºÐÇÑ´Ù. if( m_bValidDamage && ( m_ValidType & ValidTypeEnum::Time ) && false == m_bOnCollisionCalled ) { if( (int)( LocalTime - m_CreateLocalTime ) > m_nValidTime ) { m_bValidDamage = false; m_InvalidLocalTime = LocalTime; if( m_hTargetActor && m_hShooter && OrbitTypeEnum::Homing == m_OrbitType && VelocityTypeEnum::Accell == m_VelocityType ) { if( m_HitParam.szActionName.empty() ) m_HitParam.szActionName.assign( "Hit_Front" ); // hit ¾×¼Ç¿¡ hit ½Ã±×³ÎÀÌ ÀÖ´Ù¸é valid damage go on Ç÷¡±×¸¦ true ·Î È£ÃâÇÑ´Ù. // È£¹Ö °¡¼Óµµ¶óµµ ProcessDamage ¿¡¼­ hit 󸮰¡ ¸ÕÀúµÉ ¶§µµ ÀÖ°í ¿©±â¼­ µÉ ¶§µµ ÀÖ´Ù. // ¹ß»çüÀÇ À§Ä¡·Î Ãæµ¹ 󸮰¡ µÈ´Ù¸é ProcessDamage ÂÊ¿¡¼­ 󸮰¡ µÇ°í ±×·¸Áö ¾Ê´Ù¸é ¿©±â¼­ 󸮰¡ µÈ´Ù. // È£¹Ö °¡¼Óµµ ¹ß»çü¿¡ Shoot ¾×¼Ç¿¡ Hit ½Ã±×³ÎÀÌ ¾ø´Ù¸é Hit 󸮴 ´ç¿¬È÷ ¾ÈµÇ´Â °Å°í, // CheckAndApplyDamage() ÇÔ¼ö ³»ºÎ¿¡¼­ Ãß°¡µÇµµ·Ï 󸮵Ǵ »óÅÂÈ¿°ú°¡ Ãß°¡µÇ¸é ¾ÈµÇ¹Ç·Î OnCollisionWithActor() ¸¸ È£ÃâÇØÁØ´Ù. // ÀÌÂÊ¿¡´Â óÀ½ hit µÉ ¶§ À̹ǷΠShoot ¾×¼ÇÀÏ ¶§ µé¾î¿È. if( m_bHasHitSignalInShootAction ) { if( m_bTraceHitTarget || m_hTargetActor->IsHittable( m_hShooter, LocalTime, &m_HitStruct ) ) { #if defined(PRE_FIX_59238) //²ÀµÎ°¢½Ã¿Í ²ÀµÎ°¢½Ã¸¦ ¼ÒȯÇÑ ÁÖÀÎ ¾×ÅÍ´Â µ¿½Ã È÷Æ® µÇÁö ¾Ê¾Æ¾ß ÇÑ´Ù. if (IsHittable(m_hTargetActor)) { CheckAndApplyDamage( m_hTargetActor, m_bHasHitSignalInHitAction ); } #else CheckAndApplyDamage( m_hTargetActor, m_bHasHitSignalInHitAction ); #endif // PRE_FIX_59238 } } else { OnCollisionWithActor(); } } else { // #38437 Ŭ¶ó¿¡¼­´Â Destroy ¾×¼ÇÀ» ½ÇÇà½ÃŰ¹Ç·Î ¼­¹ö¿¡¼­´Â ÀÖ´ÂÁö ¾ø´ÂÁö¸¸ Ã¼Å©ÇØ¼­ ÀÖÀ¸¸é // Destroy ¾×¼Ç ½ÇÇàÀÌ ¾Æ´Ñ ¹Ù·Î ¾ø¾Öµµ·Ï ó¸®. if( m_bHasDestroyAction ) SetDestroy(); } } } #if defined(PRE_FIX_52329) //IgnoreHitType ¼³Á¤ÀÌ 0ÀÌ ¾Æ´Ñ °æ¿ì Validüũ´Â ÇÏÁö ¾Êµµ·Ï ÇÑ´Ù.. if (m_nIgnoreHitType == 0) { #endif // PRE_FIX_52329 // terrain linear ¶ó¸é ÇöÀç À§Ä¡°¡ °¥ ¼ö ¾ø´Â Áö¿ª¿¡¼± ÇÁ·ÎÁ§Å¸ÀÏ »ç¶óÁöµµ·Ï ó¸®. // ·Ñ¸µ ¶ó¹Ù °°Àº °æ¿ì terraing linear À̸鼭 ¸ø°¡´Â °÷¿¡ ºÎµúÇûÀ» ¶§µµ hit ÀÇ hit ½Ã±×³ÎÀÌ // ó¸® µÇ¾î¾ß ÇϹǷΠhit ¾×¼ÇÀ» °®°í ÀÖ´Â ¹ß»çüÀÎ °æ¿ì µ¥¹ÌÁö ó¸®Çϵµ·Ï º¯°æ. if( OrbitTypeEnum::TerrainLinear == m_OrbitType || OrbitTypeEnum::TerrainHoming == m_OrbitType) { if( false == MAWalkMovement::IsMovableBlock( &INSTANCE(CDnWorld), m_Cross.GetPosition() ) ) { if( m_bValidDamage ) { m_bValidDamage = false; m_InvalidLocalTime = LocalTime; } m_bStick = true; OnCollisionWithGround(); } } if( !m_bStick && ( m_ValidType & ValidTypeEnum::Stick ) ) { #if defined(PRE_FIX_55855) float fHeight = CDnWorld::GetInstance( GetRoom() ).GetMaxHeightWithProp( m_Cross.m_vPosition ); #else float fHeight = CDnWorld::GetInstance(GetRoom()).GetHeight( m_Cross.m_vPosition ); #endif // PRE_FIX_55855 if( m_Cross.m_vPosition.y < fHeight ) { // ¹ß»çüÀÇ Àý´ëÀûÀÎ À§Ä¡ °ª ±âÁØÀ¸·Î ¹æÇâÀ» ±¸ÇÑ´Ù. // ZVector ´Â OrbitProcessor ¿¡¼­ ÄÁÆ®·ÑÇϰí, ½ÇÁ¦ ¹æÇâ°ú ´Ù¸¦ ¼ö ÀÖ´Ù. EtVector3 vDir = m_Cross.m_vPosition - m_vPrevPos; EtVec3Normalize( &vDir, &vDir ); EtVector3 vPickPos; if( CDnWorld::GetInstance(GetRoom()).Pick( m_vPrevPos, vDir, vPickPos ) == true ) { m_Cross.m_vPosition = vPickPos; #if defined(PRE_FIX_55855) m_Cross.m_vPosition.y = CDnWorld::GetInstance( GetRoom() ).GetMaxHeightWithProp( vPickPos ); #endif // PRE_FIX_55855 } else m_Cross.m_vPosition.y = fHeight; //m_Cross.m_vPosition += m_Cross.m_vZAxis * -10.f; if( m_bValidDamage ) { m_bValidDamage = false; m_InvalidLocalTime = LocalTime; } m_bStick = true; OnCollisionWithGround(); } } // °¡¼Óµµ È£¹ÖÀÎ °æ¿ì¿£ ÇÁ¶ø°ú Ãæµ¹Çß´ÂÁö È®ÀÎ. if( m_hTargetActor && OrbitTypeEnum::Homing == m_OrbitType && VelocityTypeEnum::Accell == m_VelocityType ) { float fLength = EtVec3Length( &( m_Cross.m_vPosition - m_vPrevPos ) ); EtVector3 vCenter = m_vPrevPos + ( m_Cross.m_vZAxis * ( fLength * 0.5f ) ); float fPropContactDistance = FLT_MAX; float fPropContactTime = FLT_MAX; DnPropHandle hResultProp = _CheckPropCollision( vCenter, fLength, fPropContactTime, fPropContactDistance ); if( hResultProp ) { OnCollisionWithProp(); m_bValidDamage = false; m_InvalidLocalTime = LocalTime; m_bStick = true; } } #if defined(PRE_FIX_52329) } #endif // PRE_FIX_52329 // ÀÌ¹Ì hit ¾×¼ÇÀ» ½ÇÇàÇϰí ÀÖ´Ù¸é ¾×¼ÇÀ» ´Ù½Ã ½ÇÇà½ÃŰÁö ¾Ê´Â´Ù. (#21384) // µû·Î OnCollision~ ÇÔ¼ö°¡ È£ÃâµÇÁö ¾Ê¾Ò´Âµ¥ hit ¾×¼ÇÀ¸·Î ¹Ù²î¾îÀÖ´Ù¸é shoot ¾×¼Ç¿¡¼­ // Á÷Á¢ ¹Ù²Û °æ¿ìÀ̹ǷΠOnCollisionWithGround() ¸¦ È£ÃâÇØÁØ´Ù. if( false == m_bOnCollisionCalled && m_iHitActionIndex == GetCurrentActionIndex() && m_iHitActionIndex != -1 ) { if( m_bValidDamage ) { m_bValidDamage = false; m_InvalidLocalTime = LocalTime; } m_bStick = true; OnChangedNextActionToHit(); } } void CDnProjectile::ProcessDestroyOrbit( LOCAL_TIME LocalTime, float fDelta ) { if( LocalTime - m_InvalidLocalTime > m_nDestroyOrbitTimeGap ) { SetDestroy(); } switch( m_DestroyOrbitType ) { case Instantly: if( false == m_bHasHitAction ) // hit ¾×¼Ç °®°í ÀÖ´Â ¹ß»çü´Â hit ¾×¼Ç ³¡³ª°Å³ª valid time ´Ù µÇ¸é ¾Ë¾Æ¼­ destroy µÊ. SetDestroy(); break; case FallGravity: case RangeFallGravity: { if( !m_bStick ) { m_Cross.m_vPosition.y += CalcMovement( m_fGravity, fDelta, FLT_MAX, FLT_MIN, -15.f ); // summon comet ó·³ »ç°Å¸® ´Ù µÇ¾î fall gravity ·Î ¶³¾îÁöµµ·Ï ¿¬ÃâÇÏ´Â °æ¿ì°¡ ÀÖÀ¸¹Ç·Î // fall gravity ·Î ¶³¾îÁö´Â µ¿¾È¿¡µµ µ¥¹ÌÁö¸¦ ¸Ôµµ·Ï ó¸®. m_bValidDamage = true; m_bFallGravity = true; } } break; } } DnPropHandle CDnProjectile::_CheckPropCollision( EtVector3& vCenter, float fLength, float& fPropContactDistance, float& fPropContactTime ) { DnPropHandle hResult; DNVector(DnPropHandle) hVecProp; int nCount = CDnWorld::GetInstance(GetRoom()).ScanProp( vCenter, fLength * 0.5f, hVecProp, FilterProjectileHitSignal() ); if( nCount > 0 ) { float fMinContactTime = FLT_MAX; float fNowContactTime = 0.f; SCollisionResponse Response; SSegment Segment; Segment.vOrigin = m_vPrevPos; Segment.vDirection = m_Cross.m_vZAxis * fLength; for( int i=0; iIsProjectileSkip() ) continue; if( hVecProp[i] == m_hShooterProp ) continue; if( hVecProp[i]->GetObjectHandle() && hVecProp[i]->GetObjectHandle()->FindSegmentCollision( Segment, Response ) ) { // ¼­¹ö¿¡¼­´Â ÇÁ·¹ÀÓÀÌ ´ÊÀ» ¼ö Àֱ⠶§¹®¿¡ ¹ß»çüÀÇ ÇöÀç À§Ä¡·Î ºñ±³ÇÏ¸é ¾ÈµÊ. // ¿£Áø¿¡¼­ ´øÁ®ÁÖ´Â µµ´Þ½Ã°£ ±âÁØÀ¸·Î °ñ¶ó³»µµ·ÏÇÑ´Ù. //fNowContactTime = EtVec3LengthSq( &( hVecProp[i]->GetMatEx()->m_vPosition - m_Cross.m_vPosition ) ); fNowContactTime = Response.fContactTime; if( fNowContactTime < fMinContactTime ) { fMinContactTime = fNowContactTime; hResult = hVecProp[i]; // EtVector3 vVec = m_Cross.m_vPosition - m_vPrevPos; // EtVec3Normalize( &vVec, &vVec ); m_vHitPos = m_vPrevPos + ( Segment.vDirection * Response.fContactTime ); fPropContactDistance = EtVec3LengthSq( &( Segment.vDirection * Response.fContactTime ) ); fPropContactTime = Response.fContactTime; } } } } return hResult; } bool CDnProjectile::ProcessDamage( LOCAL_TIME LocalTime, float fDelta, LOCAL_TIME SignalStartTime, LOCAL_TIME SignalEndTime, int nSignalIndex, BOOL bUseHitSignalArea ) { bool bHitResult = false; // Çѹø hit µÈ ³à¼®¿¡°Õ ´Ù½Ã µ¥¹ÌÁö ÁÖÁö ¾Ê´Â´Ù. // #40133 ¹Ì¼Ç¿¡ ¾Ë·ÁÁÖ±â À§ÇØ Á×ÀÎ ¾Öµé Ä«¿îÆ®. int iKillCount = 0; if( !m_hShooter ) return false; if( (m_hShooter->GetActorType() != CDnActorState::PropActor) && m_hShooter->IsDie() ) return false; float fLength = EtVec3Length( &( m_Cross.m_vPosition - m_vPrevPos ) ); //if( /*fLength > 0.f ||*/ m_bOnCollisionCalled ) { EtVector3 vCenter = m_vPrevPos + ( m_Cross.m_vZAxis * ( fLength * 0.5f ) ); // Prop Check float fPropContactDistance = FLT_MAX; float fPropContactTime = FLT_MAX; DnPropHandle hResultProp = _CheckPropCollision( vCenter, fLength, fPropContactDistance, fPropContactTime ); // ¾×ÅÍ Ã¼Å© float fNowFrameActorContactDistanceSQ = FLT_MAX; DNVector(DnActorHandle) hVecList; float fMinDistance = FLT_MAX; float fDist = 0.f; // È÷Æ® ½Ã±×³Î µé°í°¡´Â ÇÁ·ÎÁ§Å¸Àϰú Æø¹ß È÷Æ®½Ã±×³Î¿¡¼­ °°ÀÌ »ç¿ëÇÔ. if( TRUE == bUseHitSignalArea || m_bOnCollisionCalled ) { m_bProcessingBombHitSignal = true; MatrixEx CrossTemp = m_Cross; CrossTemp.MoveLocalZAxis( m_HitStruct.vOffset->z ); CrossTemp.MoveLocalXAxis( m_HitStruct.vOffset->x ); CrossTemp.MoveLocalYAxis( m_HitStruct.vOffset->y ); EtVector3 vPos = CrossTemp.m_vPosition; float fDistance = max( m_HitStruct.fDistanceMax, (m_HitStruct.fHeightMax - m_HitStruct.fHeightMin) ); float fXZDistanceSQ = m_HitStruct.fDistanceMax; float fXZDistanceMinSQ = m_HitStruct.fDistanceMin; fXZDistanceSQ *= fXZDistanceSQ; fXZDistanceMinSQ *= fXZDistanceMinSQ; CDnActor::ScanActor( GetRoom(), vPos, fDistance, hVecList ); //#53454 ²ÀµÎ°¢½Ã ¼Òȯ¾×ÅÍÀÎ °æ¿ì, ²ÀµÎ°¢½Ã ÁÖÀÎ?Àº HitList¿¡¼­ Á¦¿Ü ½ÃŲ´Ù. #if defined(PRE_FIX_61382) DNVector(DnActorHandle) hVecActorToApplyStateEffect; CDnActor::ExceptionHitList2(hVecList, m_Cross, GetShooterActor(), &m_HitStruct, hVecActorToApplyStateEffect, 1, fDistance, m_vPrevPos); #else CDnActor::ExceptionHitList(hVecList, m_Cross, GetShooterActor(), &m_HitStruct); #endif // PRE_FIX_61382 EtVector3 vDir; EtVector3 vZVec = m_Cross.m_vZAxis; if( m_HitStruct.fCenterAngle != 0.f ) { EtMatrix matRotate; EtMatrixRotationY( &matRotate, EtToRadian( m_HitStruct.fCenterAngle ) ); EtVec3TransformNormal( &vZVec, &vZVec, &matRotate ); #if defined(PRE_FIX_63356) CrossTemp.m_vZAxis = vZVec; #endif // PRE_FIX_63356 } SAABox Box; float fDot = 0.0f; bool bFirstHit = true; bool bCheckEndTime = false; #ifdef PRE_FIX_PIERCE_WITH_HIT_AREA if( m_LastHitSignalEndTime > LocalTime ) { if( m_bPierce ) { bCheckEndTime = true; } else { return false; } } #else if( m_LastHitSignalEndTime > LocalTime ) return false; #endif if( m_nLastHitSignalIndex != nSignalIndex ) { bFirstHit = true; m_nLastHitSignalIndex = nSignalIndex; } bool isFirstHitActor = true; int nHitCount = 0; bool isHitLimited = false; // Actor üũ for( DWORD i=0; i::iterator iter = find( m_VecHittedActor.begin(), m_VecHittedActor.end(), hVecList[i] ); if( iter != m_VecHittedActor.end() ) { bFindHittedActor = true; if( bCheckEndTime ) continue; } } } #endif ////////////////////////////////////////////////////////////////////////// // Hit¼ö Á¦ÇÑ //ÃÖ´ë Hit¼ö°¡ ¼³Á¤µÇ¾î ÀÖ°í, Hit¼ö°¡ ÃÖ´ë Hit¼ö¸¦ ³Ñ¾î °¡¸é ¸ØÃá´Ù. isHitLimited = (m_HitParam.nHitLimitCount != 0 && nHitCount >= m_HitParam.nHitLimitCount); if (isHitLimited) break; ////////////////////////////////////////////////////////////////////////// if (false == m_HitStruct.isSelfCheck) { // ÀÚ±â ÀÚ½ÅÀº üũÇÏÁö ¾ÊÀ½. if( m_hShooter == hVecList[i] ) continue; } #if defined(PRE_FIX_59238) //²ÀµÎ°¢½Ã¿Í ²ÀµÎ°¢½Ã¸¦ ¼ÒȯÇÑ ÁÖÀÎ ¾×ÅÍ´Â µ¿½Ã È÷Æ® µÇÁö ¾Ê¾Æ¾ß ÇÑ´Ù. if (IsHittable(hVecList[i]) == false) continue; #endif // PRE_FIX_59238 bool bSendRegist = false; if( !hVecList[i]->IsHittableSkill( m_ParentSkillInfo.iSkillID , bSendRegist ) ) { if( bSendRegist ) { hVecList[i]->SendAddSEFail( CDnStateBlow::ADD_FAIL_BY_IMMUNE , STATE_BLOW::BLOW_154 ); } continue; } if( !hVecList[i]->IsHittable( m_hShooter, LocalTime, &m_HitStruct, m_HitParam.iUniqueID ) ) continue; switch( hVecList[i]->GetHitCheckType() ) { case CDnActor::BoundingBox: { m_HitParam.vPosition = vPos; vDir = *hVecList[i]->GetPosition() - vPos; vDir.y = 0.f; hVecList[i]->GetBoundingBox( Box ); if( CDnActor::SquaredDistance( vPos, Box ) > fXZDistanceSQ ) continue; if( CDnActor::SquaredDistance( vPos, Box, false ) < fXZDistanceMinSQ ) continue; EtVec3Normalize( &vDir, &vDir ); fDot = EtVec3Dot( &vZVec, &vDir ); if( EtToDegree( acos( fDot ) ) > m_HitStruct.fAngle ) continue; if( Box.Min.y < vPos.y + m_HitStruct.fHeightMin && Box.Max.y < vPos.y + m_HitStruct.fHeightMin ) continue; if( Box.Min.y > vPos.y + m_HitStruct.fHeightMax && Box.Max.y > vPos.y + m_HitStruct.fHeightMax ) continue; fNowFrameActorContactDistanceSQ = EtVec3LengthSq( &EtVector3( vPos - m_vPrevPos ) ); if( fNowFrameActorContactDistanceSQ > fPropContactDistance ) continue; m_HitParam.vViewVec = -vDir; } break; case CDnActor::Collision: { SCollisionCapsule Capsule; SCollisionResponse CollisionResult; DNVector(SCollisionResponse) vCollisionResult; // Capsule.Segment.vOrigin = vPos; float fHeight = m_HitStruct.fHeightMax - m_HitStruct.fHeightMin; Capsule.Segment.vOrigin.y = Capsule.Segment.vOrigin.y - ( m_HitStruct.fHeightMin + ( fHeight / 2.f ) ); Capsule.Segment.vDirection = EtVector3( 0.f, fHeight / 2.f, 0.f ); Capsule.fRadius = m_HitStruct.fDistanceMax; EtVector3 vDestPos; if( hVecList[i]->GetObjectHandle()->CEtCollisionEntity::FindCapsuleCollision( Capsule, CollisionResult, &vCollisionResult ) == false ) continue; if( CollisionResult.pCollisionPrimitive ) { for( UINT k=0 ; kGetBoundingBox( Box ); if( Box.Min.y < vPos.y + m_HitStruct.fHeightMin && Box.Max.y < vPos.y + m_HitStruct.fHeightMin ) { vCollisionResult.erase( vCollisionResult.begin() + k ); k--; continue; } if( Box.Min.y > vPos.y + m_HitStruct.fHeightMax && Box.Max.y > vPos.y + m_HitStruct.fHeightMax ) { vCollisionResult.erase( vCollisionResult.begin() + k ); k--; continue; } DNVector(EtVector3) vPointList; vPointList.push_back( Box.GetCenter() ); #ifdef PRE_FIX_COLMESH_RECTANGLE_HITSIGNAL if( vCollisionResult[k].pCollisionPrimitive->Type == CT_BOX || vCollisionResult[k].pCollisionPrimitive->Type == CT_CAPSULE ) { #else if( vCollisionResult[k].pCollisionPrimitive->Type == CT_BOX ) { #endif // #ifdef PRE_FIX_COLMESH_RECTANGLE_HITSIGNAL Box.GetVertices( vPointList ); } bool bCheck = false; for( DWORD m=0; mCheckCollisionHitCondition(vPos, CrossTemp, vPointList[m], m_HitStruct.fAngle) == true ) { #else if( hVecList[i]->CheckCollisionHitCondition(vPos, m_Cross, vPointList[m], m_HitStruct.fAngle) == true ) { #endif // PRE_FIX_63356 bCheck = true; break; } } if( bCheck == false ) { vCollisionResult.erase( vCollisionResult.begin() + k ); k--; continue; } m_HitParam.vBoneIndex.push_back( hVecList[i]->GetObjectHandle()->GetParentBoneIndex( vCollisionResult[k].pCollisionPrimitive ) ); } } if( vCollisionResult.empty() ) continue; GetCenterPos( *CollisionResult.pCollisionPrimitive, vDestPos ); m_HitParam.vPosition = vDestPos; } else { ASSERT( 0 ); } if( m_HitStruct.fDistanceMin > 100.f ) { vCollisionResult.clear(); Capsule.fRadius = m_HitStruct.fDistanceMin; if( hVecList[i]->GetObjectHandle()->CEtCollisionEntity::FindCapsuleCollision( Capsule, CollisionResult, &vCollisionResult ) == true ) { if( CollisionResult.pCollisionPrimitive ) { for( UINT k=0 ; kGetBoundingBox( Box ); if( Box.Min.y < vPos.y + m_HitStruct.fHeightMin && Box.Max.y < vPos.y + m_HitStruct.fHeightMin ) { vCollisionResult.erase( vCollisionResult.begin() + k ); k--; continue; } if( Box.Min.y > vPos.y + m_HitStruct.fHeightMax && Box.Max.y > vPos.y + m_HitStruct.fHeightMax ) { vCollisionResult.erase( vCollisionResult.begin() + k ); k--; continue; } DNVector(EtVector3) vPointList; vPointList.push_back( Box.GetCenter() ); #ifdef PRE_FIX_COLMESH_RECTANGLE_HITSIGNAL if( vCollisionResult[k].pCollisionPrimitive->Type == CT_BOX || vCollisionResult[k].pCollisionPrimitive->Type == CT_CAPSULE ) { #else if( vCollisionResult[k].pCollisionPrimitive->Type == CT_BOX ) { #endif // #ifdef PRE_FIX_COLMESH_RECTANGLE_HITSIGNAL Box.GetVertices( vPointList ); } bool bCheck = false; for( DWORD m=0; mCheckCollisionHitCondition(vPos, CrossTemp, vPointList[m], m_HitStruct.fAngle) == false ) { #else if( hVecList[i]->CheckCollisionHitCondition(vPos, m_Cross, vPointList[m], m_HitStruct.fAngle) == false ) { #endif // PRE_FIX_63356 #else #if defined(PRE_FIX_63356) if( hVecList[i]->CheckCollisionHitCondition(vPos, CrossTemp, vPointList[m], m_HitStruct.fAngle) == true ) { #else if( hVecList[i]->CheckCollisionHitCondition(vPos, m_Cross, vPointList[m], m_HitStruct.fAngle) == true ) { #endif // PRE_FIX_63356 #endif // #ifdef PRE_FIX_COLMESH_RECTANGLE_HITSIGNAL bCheck = true; break; } } #ifdef PRE_FIX_COLMESH_RECTANGLE_HITSIGNAL if( bCheck == true ) { #else if( bCheck == false ) { #endif // #ifdef PRE_FIX_COLMESH_RECTANGLE_HITSIGNAL vCollisionResult.erase( vCollisionResult.begin() + k ); k--; continue; } int nBoneIndex = hVecList[i]->GetObjectHandle()->GetParentBoneIndex( vCollisionResult[k].pCollisionPrimitive ); std::vector::iterator it = std::find( m_HitParam.vBoneIndex.begin(), m_HitParam.vBoneIndex.end(), nBoneIndex ); if( it != m_HitParam.vBoneIndex.end() ) { m_HitParam.vBoneIndex.erase( it ); } } } } } if( m_HitParam.vBoneIndex.empty() ) continue; } m_HitParam.vViewVec = vPos - vDestPos; fNowFrameActorContactDistanceSQ = EtVec3LengthSq( &m_HitParam.vViewVec ); if( fNowFrameActorContactDistanceSQ > fPropContactDistance ) continue; EtVec3Normalize( &m_HitParam.vViewVec, &m_HitParam.vViewVec ); } break; } m_HitParam.bFirstHit = bFirstHit; bFirstHit = false; bHitResult = true; bool bExistActionName = !m_HitParam.szActionName.empty(); if( bExistActionName ) { m_vHitPos = vPos; hResultProp.Identity(); } #if !defined( PRE_FIX_PROJECTILE_PREFIX_APPLY_POINT ) #if defined(PRE_ADD_PREFIX_SYSTE_RENEW) // HitSignal¿¡¼­ ½ºÅ³ ¿©ºÎ »ó°ü¾øÀÌ Á¢µÎ»ç ½ºÅ³ ¹ßµ¿ // Á¢µÎ¾î »óÅÂÈ¿°ú ¹«½ÃÇÏ´Â »óÅÂÈ¿°ú°¡ ÀÖÀ¸¸é Àû¿ë ¾ÈµÊ // #40186 Á¢¹Ì»ç? ¹ßµ¿ Á¶°Ç º¯°æ (µ¥¹ÌÁö ºñÀ²ÀÌ 0ÀÎ °æ¿ì ¹ßµ¿ µÇÁö ¾Êµµ·ÏÇÔ.) if (m_HitParam.bFirstHit && m_HitStruct.fDamageProb != 0.0f && !m_hShooter->IsAppliedThisStateBlow(STATE_BLOW::BLOW_183) && isFirstHitActor) { m_hShooter->ProcessPrefixOffenceSkill_New(); isFirstHitActor = false; } #else ////////////////////////////////////////////////////////////////////////// // Á¢µÎ¾î °ø°Ý¿ë ½ºÅ³ ¹ßµ¿ Áغñ ÀÛ¾÷.. // ¹ß»çü´Â bFromProjectileSkillÀÏ °æ¿ì´Â ½ºÅ³¿¡ ÀÇÇÑ ¹ß»çü... // Á¢µÎ¾î »óÅÂÈ¿°ú ¹«½ÃÇÏ´Â »óÅÂÈ¿°ú°¡ ÀÖÀ¸¸é Àû¿ë ¾ÈµÊ [2011/03/23 semozz] if( (!m_HitParam.bFromProjectileSkill && !m_hShooter->IsAppliedThisStateBlow(STATE_BLOW::BLOW_183)) && m_HitParam.bFirstHit && isFirstHitActor) { OutputDebug("CDnProjectile::ProcessDamage 1 -> STE_Hit start %d current %d end %d\n", SignalStartTime, LocalTime, SignalEndTime); //¿©±â¼­´Â Àڽſ¡°Ô Àû¿ë ÇÏ´Â »óÅ ȿ°ú¸¸ Àû¿ë½Ã۰í, //¸Â´Â ³à¼®¿¡°Ô Àû¿ëÇØ¾ßÇÒ »óÅ ȿ°ú´Â Target->OnDamage¿¡¼­ ó¸® µÇµµ·ÏÇÑ´Ù.?? m_hShooter->ProcessPrefixOffenceSkill(1.0f); isFirstHitActor = false; } #endif // PRE_ADD_PREFIX_SYSTE_RENEW #endif // PRE_FIX_PROJECTILE_PREFIX_APPLY_POINT #ifdef PRE_FIX_PIERCE_WITH_HIT_AREA if( m_bPierce == true && bFindHittedActor == false ) m_VecHittedActor.push_back( hVecList[i] ); #endif // CheckAndApplyDamage ¿¡¼­ ¾×¼Ç À̸§ÀÌ ÀÖ°í ¾ø°í¸¦ ±¸ºÐÇØ¼­ ó¸®Çϰí ÀÖÀ¸¹Ç·Î ¾×¼Ç À̸§ Á¸Àç ¿©ºÎ Á¶°Ç¹® ¹Ù±ù¿¡¼­ È£ÃâÇØµµ µÈ´Ù. // #23510, #23591 À̽´ ¶§¹®¿¡, µ¥¹ÌÁö´Â µé¾î°¡Áö ¾Ê´õ¶óµµ »óÅÂÈ¿°ú´Â ºÎ¿©µÇµµ·Ï ¼öÁ¤ÇÕ´Ï´Ù. CheckAndApplyDamage( hVecList[i], true, &nHitCount ); if( bHitResult ) { // [2010/12/02 semozz] // Hit ½Ã±×³Î ¸¶Áö¸· ½Ã°£À» ³Ö¾î ³õÀ¸¸é ¸¶Áö¸· ÇÁ·¹ÀÓ¿¡ °É·Á¼­ Çѹø ´õ ¸ÂÀ» ¼ö ÀÖ´Ù. // ±×·¡¼­ Hit 󸮰¡ µÇ°í ³ª¼­ m_LastHitSignalEndTime¿¡ SignalEndTime + 1À» ´õ ÀÌ»ó Hit ó¸® ¾ÈµÇµµ·Ï ÇÑ´Ù. m_LastHitSignalEndTime = SignalEndTime + 1; if( hVecList[ i ]->IsDie() ) iKillCount++; } } #if defined(PRE_FIX_61382) //È÷Æ® ¿µ¿ª¿¡¼­ ¼Òȯ ¾×ÅÍ¿Í ÁÖÀÎ ¾×ÅͰ¡ µ¿½Ã¿¡ Á¸Àç ÇÒ¶§ ÁÖÀÎ ¾×ÅÍ´Â È÷Æ® ¸®½ºÆ®¿¡¼­ Á¦¿Ü µÈ´Ù. //»óÅÂÈ¿°ú´Â Àû¿ëµÇ¾î¾ß Çϴµ¥, ÀÌ ½ÃÁ¡¿¡¼­ »óÅÂÈ¿°ú¸¦ Àû¿ëÇÑ´Ù. int nApplyStateEffectActorListSize = (int)hVecActorToApplyStateEffect.size(); for (int iIndex = 0; iIndex < nApplyStateEffectActorListSize; ++iIndex) { DnActorHandle hActor = hVecActorToApplyStateEffect[iIndex]; ApplySkillStateEffect(hActor); } #endif // PRE_FIX_61382 #if defined(PRE_ADD_50903) //µ¥¹ÌÁö ºÐ»ê »óÅÂÈ¿°ú¸¦ À§ÇÑ ÃÖÁ¾ HitCount ¼³Á¤. DnSkillHandle hParentSkill = GetParentSkill(); if (hParentSkill) hParentSkill->SetHitCountForVarianceDamage(nHitCount); #endif // PRE_ADD_50903 // È÷Æ®½Ã±×³Î µé°í°¡´Â ¹ß»çüÀÇ °æ¿ì ÇÁ¶øµµ üũ // Note: ÇÁ¶øÃ¼Å©´Â »óÅÂÈ¿°ú¸¸ ÀÖ´Â Heal °°Àº °ÍÀº üũÇÏÁö ¾Êµµ·Ï ÇÕ´Ï´Ù. HitAction ÀÌ ¾ø´Â °ÍÀ¸·Î ±¸ºÐ. if( false == m_HitParam.szActionName.empty() ) { DNVector(CEtWorldProp*) pVecProp; CDnWorld* pWorld = CDnWorld::GetInstancePtr(GetRoom()); pWorld->ScanProp( vPos, fDistance, pVecProp ); for( DWORD i=0; iIsBrokenType() ) continue; if( !((CDnWorldBrokenProp*)pVecProp[i])->IsHittable( m_hShooter, LocalTime ) ) continue; pVecProp[i]->GetBoundingBox( Box ); if( CDnActor::SquaredDistance( vPos, Box ) > fXZDistanceSQ ) continue; if( CDnActor::SquaredDistance( vPos, Box, false ) < fXZDistanceMinSQ ) continue; vDir = ((CDnWorldProp*)pVecProp[i])->GetMatEx()->m_vPosition - vPos; EtVec3Normalize( &vDir, &vDir ); fDot = EtVec3Dot( &vZVec, &vDir ); if( EtToDegree( acos( fDot ) ) > m_HitStruct.fAngle ) continue; if( Box.Min.y < vPos.y + m_HitStruct.fHeightMin && Box.Max.y < vPos.y + m_HitStruct.fHeightMin ) continue; if( Box.Min.y > vPos.y + m_HitStruct.fHeightMax && Box.Max.y > vPos.y + m_HitStruct.fHeightMax ) continue; m_HitParam.vViewVec = -vDir; ((CDnWorldProp*)pVecProp[i])->OnDamage( m_hShooter, m_HitParam ); } } } else { size_t nCount = 0; nCount = CDnActor::ScanActor( GetRoom(), vCenter, fLength, hVecList ); //#53454 ²ÀµÎ°¢½Ã ¼Òȯ¾×ÅÍÀÎ °æ¿ì, ²ÀµÎ°¢½Ã ÁÖÀÎ?Àº HitList¿¡¼­ Á¦¿Ü ½ÃŲ´Ù. #if defined(PRE_FIX_61382) DNVector(DnActorHandle) hVecActorToApplyStateEffect; nCount = CDnActor::ExceptionHitList2(hVecList, m_Cross, GetShooterActor(), &m_HitStruct, hVecActorToApplyStateEffect, 2, fLength, m_vPrevPos); #else nCount = CDnActor::ExceptionHitList(hVecList, m_Cross, GetShooterActor(), &m_HitStruct); #endif // PRE_FIX_61382 if( nCount > 0 ) { m_LastHitSignalEndTime = SignalEndTime; float fThickness = max( fabs( m_HitStruct.fHeightMin ), fabs( m_HitStruct.fHeightMax ) ); SSegment Segment; Segment.vOrigin = m_vPrevPos; Segment.vDirection = m_Cross.m_vZAxis * fLength; SCollisionCapsule Capsule; Capsule.Segment = Segment; Capsule.fRadius = fThickness; bool isFirstHitActor = true; int nHitCount = 0; bool isHitLimited = false; for( size_t i=0; i= m_HitParam.nHitLimitCount); if (isHitLimited) break; // Note: ´À¸®°Ô °¡´Â ÇÁ·ÎÁ§Å¸ÀÏÀº ¿©·¯¹ø ¸ÂÀ» ¼ö ÀÖ¾î¾ß Çϱ⠶§¹®¿¡ ÀÌ ºÎºÐÀº »®´Ï´Ù.. vector::iterator iter = find( m_VecHittedActor.begin(), m_VecHittedActor.end(), hVecList[i] ); if( !m_VecHittedActor.empty() ) { if( iter != m_VecHittedActor.end() ) continue; } #if defined(PRE_FIX_59238) //²ÀµÎ°¢½Ã¿Í ²ÀµÎ°¢½Ã¸¦ ¼ÒȯÇÑ ÁÖÀÎ ¾×ÅÍ´Â µ¿½Ã È÷Æ® µÇÁö ¾Ê¾Æ¾ß ÇÑ´Ù. if (IsHittable(hVecList[i]) == false) continue; #endif // PRE_FIX_59238 if( !hVecList[i]->IsHittable( m_hShooter, LocalTime, &m_HitStruct, m_HitParam.iUniqueID ) ) continue; if( !hVecList[i]->GetObjectHandle() ) continue; // üÀÎ ¶óÀÌÆ®´× ¹ß»çüÀÎ °æ¿ì¿£ üÀÎ ¹ß»çü¸¦ ½ð ¾×ÅͰ¡ ´Ù½Ã hit µÇÁö ¾Êµµ·Ï ÇÑ´Ù. // üÀÎ ¶óÀÌÆ®´×À» »ç¿ëÇßÀ» ¶§¸¸ hPrevAttacker °¡ ¼ÂÆÃµÈ´Ù. if( m_ParentSkillInfo.hPrevAttacker == hVecList[i] ) continue; bool bResult = false; SCollisionResponse Response; DNVector(SCollisionResponse) vResponse; CDnActor::HitCheckTypeEnum eHitCheckType = hVecList[i]->GetHitCheckType(); switch( eHitCheckType ) { case CDnActor::BoundingBox: if( fThickness == 0.f ) bResult = hVecList[i]->GetObjectHandle()->FindSegmentCollision( Segment, Response ); else bResult = hVecList[i]->GetObjectHandle()->FindCapsuleCollision( Capsule, Response ); fNowFrameActorContactDistanceSQ = EtVec3LengthSq( &EtVector3( *hVecList[i]->GetPosition() - m_vPrevPos ) ); if( fNowFrameActorContactDistanceSQ > fPropContactDistance ) continue; break; case CDnActor::Collision: { int nParentBoneIndex = -1; EtVector3 vDestPos; if( fThickness == 0.f ) { bResult = hVecList[i]->GetObjectHandle()->FindSegmentCollision( Segment, Response, &vResponse ); } else { bResult = hVecList[i]->GetObjectHandle()->FindCapsuleCollision( Capsule, Response, &vResponse ); } if( bResult ) { fNowFrameActorContactDistanceSQ = EtVec3LengthSq( &EtVector3( Segment.vDirection * Response.fContactTime ) ); if( fNowFrameActorContactDistanceSQ > fPropContactDistance ) continue; for( UINT k=0 ; kGetObjectHandle()->GetParentBoneIndex( vResponse[k].pCollisionPrimitive ) ); } } } break; } if( bResult ) { EtVector3 vHitPos = Segment.vOrigin + (Segment.vDirection * Response.fContactTime); fDist = EtVec3Length( &( *hVecList[i]->GetPosition() - m_Cross.m_vPosition ) ); float fLength2 = EtVec3Length( &( *hVecList[i]->GetPosition() - m_vStartPos ) ); SSphere Sphere; hVecList[i]->GetBoundingSphere( Sphere ); // ÀÌ Å¸ÀÔÀº fallgravity »óŰ¡ µÈ ¼ø°£ºÎÅÍ Ãß°¡ »ç°Å¸® ´Ù µÇ¸é ¹Ù·Î »èÁ¦. if( RangeFallGravity == m_DestroyOrbitType ) { float fAdditionalRange = CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::RangeFallGravityAdditionalProjectileRange ); float fRangeFallGravityLength = float(GetWeaponLength()) * fAdditionalRange; if( CDnActor::Collision == eHitCheckType ) { // ĸ½¶ÀÎ °æ¿ì ĸ½¶ÀÇ radius µµ °¨¾ÈÇØ ÁØ´Ù. if( 0.0f < fThickness ) { fRangeFallGravityLength += Capsule.fRadius; if( CollisionType::CT_CAPSULE == Response.pCollisionPrimitive->Type ) { fRangeFallGravityLength += static_cast(Response.pCollisionPrimitive)->fRadius; } } float fWeaponLengthSQ = fRangeFallGravityLength*fRangeFallGravityLength; EtVector3 vShootToHitPosDist = vHitPos - m_vStartPos; float fShootToHitPosDistSQ = EtVec3LengthSq( &vShootToHitPosDist ); if( fWeaponLengthSQ < fShootToHitPosDistSQ ) continue; } else if( fLength2 > fRangeFallGravityLength + ( Sphere.fRadius / 2.f ) ) { continue; } } else { float fWeaponLength = float(GetWeaponLength()); if( CDnActor::Collision == eHitCheckType ) { // ĸ½¶ÀÎ °æ¿ì ĸ½¶ÀÇ radius µµ °¨¾ÈÇØ ÁØ´Ù. if( 0.0f < fThickness ) { fWeaponLength += Capsule.fRadius; if( CollisionType::CT_CAPSULE == Response.pCollisionPrimitive->Type ) { fWeaponLength += static_cast(Response.pCollisionPrimitive)->fRadius; } } EtVector3 vShootToHitPosDist = vHitPos - m_vStartPos; float fShootToHitPosDistSQ = EtVec3LengthSq( &vShootToHitPosDist ); if( fWeaponLength*fWeaponLength < fShootToHitPosDistSQ ) continue; } else if( fLength2 > fWeaponLength + ( Sphere.fRadius / 2.f ) ) { continue; } } if( fDist < fMinDistance ) { fMinDistance = fDist; // ÀÏÁ÷¼± »óÀ¸·Î ¸ÕÀú µµ´ÞÇÏ´Â °Í¿¡ ¸ÕÀú ¸ÂÀ½. ÇÁ¶øÀÌ ¸ÕÀú ¸Â´Â´Ù¸é ¾×ÅÍ´Â hit ó¸®ÇÏÁö ¾Ê´Â´Ù. m_vHitPos = vHitPos; fNowFrameActorContactDistanceSQ = EtVec3LengthSq( &(Segment.vDirection * Response.fContactTime) ); if( Response.fContactTime > fPropContactTime ) continue; // ÇÇ°ÝµÈ À§Ä¡·Î ¹ß»çüÀÇ À§Ä¡¸¦ ¼ÂÆÃÇØÁØ´Ù. // ÀÌ·¸°Ô ÇØ¾ß Æø¹ß ¾×¼ÇÀÇ hit ½Ã±×³Î ¿¬»êÀ» ÇÒ ¶§ Á¤È®ÇÏ°Ô Ã¼Å©°¡ µÈ´Ù. if( false == m_bPierce ) m_Cross.m_vPosition = m_vHitPos; } #if !defined( PRE_FIX_PROJECTILE_PREFIX_APPLY_POINT ) #if defined(PRE_ADD_PREFIX_SYSTE_RENEW) // HitSignal¿¡¼­ ½ºÅ³ ¿©ºÎ »ó°ü¾øÀÌ Á¢µÎ»ç ½ºÅ³ ¹ßµ¿ // Á¢µÎ¾î »óÅÂÈ¿°ú ¹«½ÃÇÏ´Â »óÅÂÈ¿°ú°¡ ÀÖÀ¸¸é Àû¿ë ¾ÈµÊ // #40186 Á¢¹Ì»ç? ¹ßµ¿ Á¶°Ç º¯°æ (µ¥¹ÌÁö ºñÀ²ÀÌ 0ÀÎ °æ¿ì ¹ßµ¿ µÇÁö ¾Êµµ·ÏÇÔ.) if (m_HitParam.bFirstHit && m_HitStruct.fDamageProb != 0.0f && !m_hShooter->IsAppliedThisStateBlow(STATE_BLOW::BLOW_183) && isFirstHitActor) { m_hShooter->ProcessPrefixOffenceSkill_New(); isFirstHitActor = false; } #else ////////////////////////////////////////////////////////////////////////// // Á¢µÎ¾î °ø°Ý¿ë ½ºÅ³ ¹ßµ¿ Áغñ ÀÛ¾÷.. // ÆòŸÀ϶§¸¸ Á¢µÎ¾î ½Ã½ºÅÛ °ø°Ý½ºÅ³ ¹ßµ¿ // ¹ß»çü´Â bFromProjectileSkillÀÏ °æ¿ì´Â ½ºÅ³¿¡ ÀÇÇÑ ¹ß»çü... // Á¢µÎ¾î »óÅÂÈ¿°ú ¹«½ÃÇÏ´Â »óÅÂÈ¿°ú°¡ ÀÖÀ¸¸é Àû¿ë ¾ÈµÊ [2011/03/23 semozz] if( (!m_HitParam.bFromProjectileSkill && !m_hShooter->IsAppliedThisStateBlow(STATE_BLOW::BLOW_183)) && m_HitParam.bFirstHit && isFirstHitActor) { OutputDebug("CDnProjectile::ProcessDamage 2 -> STE_Hit start %d current %d end %d\n", SignalStartTime, LocalTime, SignalEndTime); //¿©±â¼­´Â Àڽſ¡°Ô Àû¿ë ÇÏ´Â »óÅ ȿ°ú¸¸ Àû¿ë½Ã۰í, //¸Â´Â ³à¼®¿¡°Ô Àû¿ëÇØ¾ßÇÒ »óÅ ȿ°ú´Â Target->OnDamage¿¡¼­ ó¸® µÇµµ·ÏÇÑ´Ù.?? m_hShooter->ProcessPrefixOffenceSkill(1.0f); isFirstHitActor = false; } ////////////////////////////////////////////////////////////////////////// #endif // PRE_ADD_PREFIX_SYSTE_RENEW #endif m_VecHittedActor.push_back( hVecList[i] ); CheckAndApplyDamage( hVecList[i], true, &nHitCount ); bHitResult = true; if( hVecList[ i ]->IsDie() ) iKillCount++; if(false == m_bPierce) return bHitResult; } } #if defined(PRE_FIX_61382) //È÷Æ® ¿µ¿ª¿¡¼­ ¼Òȯ ¾×ÅÍ¿Í ÁÖÀÎ ¾×ÅͰ¡ µ¿½Ã¿¡ Á¸Àç ÇÒ¶§ ÁÖÀÎ ¾×ÅÍ´Â È÷Æ® ¸®½ºÆ®¿¡¼­ Á¦¿Ü µÈ´Ù. //»óÅÂÈ¿°ú´Â Àû¿ëµÇ¾î¾ß Çϴµ¥, ÀÌ ½ÃÁ¡¿¡¼­ »óÅÂÈ¿°ú¸¦ Àû¿ëÇÑ´Ù. int nApplyStateEffectActorListSize = (int)hVecActorToApplyStateEffect.size(); for (int iIndex = 0; iIndex < nApplyStateEffectActorListSize; ++iIndex) { DnActorHandle hActor = hVecActorToApplyStateEffect[iIndex]; ApplySkillStateEffect(hActor); } #endif // PRE_FIX_61382 #if defined(PRE_ADD_50903) //µ¥¹ÌÁö ºÐ»ê »óÅÂÈ¿°ú¸¦ À§ÇÑ ÃÖÁ¾ HitCount ¼³Á¤. DnSkillHandle hParentSkill = GetParentSkill(); if (hParentSkill) hParentSkill->SetHitCountForVarianceDamage(nHitCount); #endif // PRE_ADD_50903 } } // MakeHitParam ¿¡¼­ ¾²´Â m_vHitPos°¡ ¾×ÅÍ Ã¼Å©ÇÒ¶§ ¾÷µ¥ÀÌÆ® µÇ¹Ç·Î ÇÁ¶ø 󸮴 ¾×ÅÍ Ã³¸® ³¡³­ ÈÄ ¿©±â¼­. if( hResultProp ) { switch( hResultProp->GetPropType() ) { case PTE_Static: { #if defined(PRE_FIX_52329) //IgnoreHitType ¼³Á¤ÀÌ 0ÀÌ ¾Æ´Ñ °æ¿ì Validüũ´Â ÇÏÁö ¾Êµµ·Ï ÇÑ´Ù.. if (m_nIgnoreHitType == 0) { if( m_bValidDamage ) { m_bValidDamage = false; m_InvalidLocalTime = LocalTime; } m_bStick = true; } #endif } break; case PTE_Action: case PTE_Trap: if( m_bValidDamage ) { m_bValidDamage = false; m_InvalidLocalTime = LocalTime; } m_bStick = true; break; case PTE_Broken: case PTE_BrokenDamage: case PTE_HitMoveDamageBroken: case PTE_ShooterBroken: case PTE_BuffBroken: { if( !m_bValidDamage ) break; // ÇÁ¶ø±îÁö °Å¸®°¡ »ç°Å¸®º¸´Ù ±æ¸é ¸ÂÀ¸¸é ¾ÈµÊ. #23322 float fLengthToPropSQ = EtVec3LengthSq(&EtVector3(m_vStartPos - hResultProp->GetMatEx()->m_vPosition)); // ÀÌ Å¸ÀÔÀº fallgravity »óŰ¡ µÈ ¼ø°£ºÎÅÍ Ãß°¡ »ç°Å¸® ´Ù µÇ¸é ¹Ù·Î »èÁ¦. float fWeaponLength = 0.0f; if( RangeFallGravity == m_DestroyOrbitType ) { float fAdditionalRange = CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::RangeFallGravityAdditionalProjectileRange ); fWeaponLength = float(GetWeaponLength()) * fAdditionalRange; } else { fWeaponLength = (float)GetWeaponLength(); } float fWeaponLengthSQ = fWeaponLength * fWeaponLength; if( fWeaponLengthSQ < fLengthToPropSQ ) // Á¦°ö±âÁØÀ¸·Î fPropDistance °ª µé¾îÀÖÀ½. break; if( ((CDnWorldBrokenProp*)hResultProp.GetPointer())->IsHittable( m_hShooter, LocalTime ) ) { CDnDamageBase::SHitParam HitParam; MakeHitParam( HitParam ); hResultProp->OnDamage( m_hShooter, HitParam ); } else { m_bValidDamage = false; m_InvalidLocalTime = LocalTime; m_bStick = true; } } break; } #if defined(PRE_FIX_52329) //IgnoreHitType ¼³Á¤ÀÌ 0ÀÌ ¾Æ´Ñ °æ¿ì Validüũ´Â ÇÏÁö ¾Êµµ·Ï ÇÑ´Ù.. if (m_nIgnoreHitType == 0) { OnCollisionWithProp(); } #endif } } if( 2 <= iKillCount && m_hShooter->IsPlayerActor() ) { CDnPlayerActor* pPlayerActor = static_cast(m_hShooter.GetPointer()); CDNUserSession* pSession = pPlayerActor->GetUserSession(); pSession->GetEventSystem()->OnEvent( EventSystem::OnKillMonster, 1, EventSystem::GenocideCount, iKillCount ); } return bHitResult; } void CDnProjectile::CheckAndApplyDamage( DnActorHandle hActor, bool bValidDamageGoOn/* = true*/, int *pHitCount /*= NULL*/ ) { if( !m_hShooter || !hActor ) return; // ¿É¼Ç¿¡ µû¶ó ÃßÀûÁßÀÎ ¾×ÅÍ¿¡°Ô´Â hit µÇÁö ¾Êµµ·Ï ÇÑ´Ù. µðÆúÆ®´Â ¾È¸Â´Â °ÅÀÓ. if( false == m_bTraceHitActorHittable ) { if( m_hTraceActor == hActor ) return; } if( !m_HitParam.szActionName.empty() && !hActor->IsDie() ) { CDnDamageBase::SHitParam HitParam; MakeHitParam( HitParam ); // Â÷Á® »óÅÂÈ¿°ú·Î ¹ß»çµÈ ¹ß»çü¶ó¸é ¾×ÅÍ¿¡ ¼ÂÆÃÇϰí OnDamage È£ÃâÇÏ°í ¹Ù·Î Ç®¾îÁÜ. // Â÷Á® »óÅÂÈ¿°ú¿¡¼­ ³ª°£ ¹ß»çü´Â ÄÞº¸ °è»ê¿¡¼­ »«´Ù. if( m_bFromCharger && m_hShooter ) m_hShooter->SetAllowCombo( false ); hActor->OnDamage( m_hShooter, HitParam, &m_HitStruct ); #if defined(PRE_FIX_59238) AddHittedActor(hActor); #endif // PRE_FIX_59238 if (pHitCount) (*pHitCount)++; if( m_bFromCharger && m_hShooter ) m_hShooter->SetAllowCombo( true ); bValidDamageGoOn = SetTraceActor( hActor, bValidDamageGoOn ); OnCollisionWithActor(); // Note: OnCollision() ¿¡¼­ Æø¹ß µ¥¹ÌÁö¸¦ ó¸®Çϱâ À§Çؼ­ ValidDamage ¸¦ ´Ù½Ã true·Î ÄÑÁÖÁö¸¸ // ÀÌ ÇÔ¼ö È£Ã⠽ÿ¡ bValidDamageGoOn À» ²ô°í È£ÃâÇÑ °æ¿ì¿£ Æø¹ß µ¥¹ÌÁö¸¦ °¨¾ÆÇÏÁö ¾ÊÀ¸¹Ç·Î ValidDamage ¸¦ ²¨ÁØ´Ù. if( false == bValidDamageGoOn ) m_bValidDamage = false; } //¹ß»çü ½ºÅ³ »óÅÂÈ¿°ú Àû¿ë.. ApplySkillStateEffect(hActor); // °üÅëÇüÀ϶§¸¸,, ÃÖ´ë È÷Æ®¼ö°¡ 0ÀÎ °æ¿ì¿£ ¿ø·¡ 󸮵Ǵø´ë·Î ³¡±îÁö °è¼Ó ¸Â°Ô µÈ´Ù. if( m_bPierce && m_nMaxHitCount != 0 ) { //m_nMaxHitCount--; map::iterator iter = m_mapMaxHitCount.find(hActor.GetPointer() ); if( m_mapMaxHitCount.end() == iter ) m_mapMaxHitCount[ hActor.GetPointer() ] = 0; else { ++(iter->second); if( m_nMaxHitCount-1 == iter->second ) { m_bValidDamage = false; m_InvalidLocalTime = m_LocalTime; // Ŭ¶ó´Â ¾Ë ¼ö°¡ ¾ø±â ¶§¹®¿¡ ¼­¹ö¿¡¼­ ÆÐŶÀ» º¸³»ÁØ´Ù. BYTE pBuffer[ 32 ]; CPacketCompressStream Stream( pBuffer, 32 ); Stream.Write( &m_dwUniqueID, sizeof(DWORD) ); m_hShooter->Send( eActor::SC_INVALID_PROJECTILE, &Stream ); } } } } void CDnProjectile::Process( LOCAL_TIME LocalTime, float fDelta ) { if( m_CreateLocalTime == 0 ) m_CreateLocalTime = LocalTime; // Çѱâ 2009.7.22 // ÇÁ·ÎÁ§Å¸ÀÏ »ý¼ºµÈ ÈÄÀÇ Áö³ª°£ ½Ã°£ // ÇÁ·ÎÁ§Å¸ÀÏ ±ËÀû °ü·Ã.. (#4851) m_fElapsedTime = float(LocalTime - m_CreateLocalTime) * 0.001f; m_bHitSignalProcessed = false; ProcessOrbit( LocalTime, fDelta ); CDnWeapon::Update( m_Cross ); CDnWeapon::Process( LocalTime, fDelta ); if( 0 != m_InvalidLocalTime ) ProcessDestroyOrbit( LocalTime, fDelta ); ProcessValid( LocalTime, fDelta ); m_vPrevPos = m_Cross.m_vPosition; m_bFirstProcess = false; // 301¹ø ¿Üµý¼¶¿¡¼­ Ç÷¹À̾îÀÇ À§Ä¡°¡ Ʋ¾îÁ³À» ¶§ Ĭơ²É ¹ß»çüÀÇ ¹æÇâ º¤ÅͰ¡ 0, 0, 0 À¸·Î ¼ÂÆÃµÇ¾î »ç¶óÁöÁö ¾Ê´Â °æ¿ì ¹æ¾îÄÚµå ³ÖÀ½. if( EtVec3LengthSq( &m_Cross.m_vZAxis ) < 0.001f ) { // Projectile ŸÀÔÀÇ ¹ß»çü´Â ¼Óµµ°¡ 0 À¸·Î ¼ÂÆÃµÇ¾îÀÖÀ» ¼ö ÀÖ´Ù. ½Ç½Ã°£À¸·Î ¼Óµµ¸¦ °è»êÇϱ⠶§¹®¿¡~ if( Projectile != m_OrbitType ) SetDestroy(); } } void CDnProjectile::MakeHitParam( CDnDamageBase::SHitParam &HitParam ) { HitParam = m_HitParam; HitParam.RemainTime = m_LastHitSignalEndTime; HitParam.hHitter = m_hShooter; HitParam.hWeapon = GetMySmartPtr(); HitParam.bFirstHit = true; HitParam.vPosition = m_vHitPos; // ¿µ¿ªÀÌ ÀÖ´Â È÷Æ® ½Ã±×³ÎÀ» »ç¿ëÇÏ´Â Æø¹ßÇÏ´Â ¹ß»çü´Â ÀÌ¹Ì hit ½Ã±×³Î Áß½ÉÁ¡À» ±âÁØÀ¸·Î Á¦´ë·ÎµÈ ºä º¤ÅͰ¡ µé¾î°¡ ÀÖÀ½. if( !m_bProcessingBombHitSignal ) HitParam.vViewVec = -m_Cross.m_vZAxis; HitParam.iUniqueID = m_iHitUniqueID; if( -1.0f != m_fHitApplyPercent ) HitParam.fDamage = m_fHitApplyPercent; } void CDnProjectile::OnSignal( SignalTypeEnum Type, void *pPtr, LOCAL_TIME LocalTime, LOCAL_TIME SignalStartTime, LOCAL_TIME SignalEndTime, int nSignalIndex ) { switch( Type ) { case STE_Hit: { //OutputDebug( "STE_Hit\n" ); if (m_hShooter && m_hShooter->ProcessIgnoreHitSignal() == true) break; HitStruct *pStruct = (HitStruct *)pPtr; #ifdef PRE_FIX_MEMOPT_SIGNALH CopyShallow_HitStruct(m_HitStruct, pStruct); #else m_HitStruct = *pStruct; #endif m_HitParam.szActionName = pStruct->szTargetHitAction; m_HitParam.fDamage = pStruct->fDamageProb * 0.01f; m_HitParam.fDurability = pStruct->fDurabilityDamageProb * 0.01f; m_HitParam.vVelocity = *pStruct->vVelocity; m_HitParam.vResistance = *pStruct->vResistance; m_HitParam.fStiffProb = pStruct->fStiffProb * 0.01f; m_HitParam.nSkillSuperAmmorIndex = pStruct->nApplySuperAmmorIndex - 1; m_HitParam.nSkillSuperAmmorDamage = pStruct->nApplySuperAmmorDamage; m_HitParam.nDamageType = pStruct->nDamageType; m_HitParam.DistanceType = (pStruct->nDistanceType == 0) ? CDnDamageBase::DistanceTypeEnum::Melee : CDnDamageBase::DistanceTypeEnum::Range; m_HitParam.cAttackType = (char)pStruct->nAttackType; if( ElementEnum_Amount != m_eForceHitElement ) { m_HitParam.HasElement = m_eForceHitElement; } else { m_HitParam.HasElement = ( m_hShooter ) ? m_hShooter->CalcHitElementType( ( pStruct->bUseSkillApplyWeaponElement == TRUE ) ? true : false, m_ParentSkillInfo.eSkillElement, true ) : CDnActorState::ElementEnum_Amount; } m_HitParam.bIgnoreCanHit = ( pStruct->bIgnoreCanHit == TRUE ); m_HitParam.bIgnoreParring = ( pStruct->bIgnoreParring == TRUE ); m_HitParam.nHitLimitCount = pStruct->nHitLimitCount; if( m_bValidDamage ) { bool bHitResult = ProcessDamage( LocalTime, 0.0f, SignalStartTime, SignalEndTime, nSignalIndex, pStruct->bUseHitAreaOnProjectile ); if( bHitResult ) { // #59118 ¹ß»çüµµ g_Lua_BeHitSkill Àû¿ëÇÑ´Ù. if( m_hShooter && m_hShooter->IsMonsterActor() ) { CDnMonsterActor* pMonster = static_cast(m_hShooter.GetPointer()); #ifdef PRE_FIX_PROPMON_PROJ // ÇÁ¶ø ¸ó½ºÅÍÀÇ °æ¿ì MonsterActorÀ̸鼭µµ AI¸¦ °¡ÁöÁö ¾Ê´Â °æ¿ì°¡ ÀÖÀ½. (#59952) if (pMonster) { MAAiBase* pCurBase = pMonster->GetAIBase(); if (pCurBase) pCurBase->OnHitFinish( LocalTime, &m_HitStruct ); } #else pMonster->GetAIBase()->OnHitFinish( LocalTime, &m_HitStruct ); #endif } } } m_bHitSignalProcessed = true; // Æø¹ß½Ã È÷Æ® ½Ã±×³ÎÀÌ µÚ¿¡ ÀÖ´Â °æ¿ì°¡ ÀÖÀ¸¹Ç·Î µÚ¿¡ ÀÖ´Â ÄÉÀ̽º°¡ À־ È÷Æ® ½Ã±×³Î ½ÃÀÛ ½Ã¿¡ Ç÷¡±× ÄÑÁÜ. // ¾È±×·¯¸é m_bValidDamage°¡ false °¡ µÇ¾î Æø¹ß 󸮰¡ ¾ÈµÊ. if( m_bOnCollisionCalled && m_bHitActionStarted ) m_bBombHitSignalStarted = true; } break; case STE_SummonMonster: { SummonMonsterStruct* pStruct = (SummonMonsterStruct *)pPtr; CDnGameTask* pGameTask = static_cast(CTaskManager::GetInstancePtr(GetRoom())->GetTask( "GameTask" )); if( pGameTask ) { if( m_hShooter ) { // ³»ºÎÀûÀ¸·Î °ªÀ» ¹Ù²ã¼­ »ç¿ëÇϱ⠶§¹®¿¡ ¹Ýµå½Ã º¹»çÇØ¼­ »ç¿ëÇÑ´Ù. #ifdef PRE_FIX_MEMOPT_SIGNALH SummonMonsterStruct Struct; CopyShallow_SummonMonsterStruct(Struct, pStruct); #else SummonMonsterStruct Struct = *pStruct; #endif // 167¹ø ¼Òȯ ¸ó½ºÅÍ ½ºÅ³·¹º§ °­Á¦ ¼ÂÆÃ »óÅÂÈ¿°ú ó¸®. /////////////////// if( m_hShooter->IsPlayerActor() ) { if( 0 < m_iSummonMonsterForceSkillLevel ) Struct.nForceSkillLevel = m_iSummonMonsterForceSkillLevel; } ////////////////////////////////////////////////////////////////////////// // ¹ß»çü¿¡¼­ ¸ó½ºÅÍ ¼Òȯ½Ã ¹ß»çüÀÇ À§Ä¡·Î ´ëü½ÃÄÑ »ý¼º½ÃÄÑ ÁØ´Ù. #18315 // #36873 ³×ºñ°ÔÀÌ¼Ç ¸Þ½Ã³ª attribute °¡ ¹«½ÃµÇ¹Ç·Î º¸Á¤µÈ À§Ä¡·Î.. // #37991 ÀÌÀü À§Ä¡ ±âÁØÀ¸·Î ³×ºñ ¸Þ½Ã°¡ ¸Â´ÂÁö È®ÀÎÇØº¸°í ¾Æ´Ï¶ó¸é ÇöÀç ij¸¯ÅͰ¡ ¼­ ÀÖ´Â °÷À¸·Î ¼Òȯ½ÃÄÑÁØ´Ù. MatrixEx CrossRevisionedPos; if( true == INSTANCE(CDnWorld).IsOnNavigationMesh( m_vPrevPos ) ) { CrossRevisionedPos = m_Cross; INSTANCE(CDnWorld).RevisionPosByNaviMesh( CrossRevisionedPos, m_vPrevPos ); } else { CrossRevisionedPos.m_vPosition = m_hShooter->GetMatEx()->m_vPosition; if( Struct.PositionCheck == TRUE ) break; } EtVector3 vTemp = *(m_hShooter->GetPosition());; m_hShooter->SetPosition( CrossRevisionedPos.m_vPosition ); pGameTask->RequestSummonMonster( m_hShooter, &Struct, false, m_ParentSkillInfo.iSkillID ); m_hShooter->SetPosition( vTemp ); } } break; } case STE_Gravity: { if( !m_hShooter ) break; GravityStruct *pStruct = (GravityStruct *)pPtr; EtVector3 vPos = m_Cross.m_vPosition + *pStruct->vOffset; DNVector(DnActorHandle) hVecList; CDnActor::ScanActor( GetRoom(), vPos, pStruct->fDistanceMax, hVecList ); for( DWORD i=0; iIsDie() ) continue; if( hVecList[i]->GetWeight() == 0.f ) continue; if( hVecList[i]->IsNpcActor() ) continue; if( hVecList[i]->ProcessIgnoreGravitySignal() ) continue; bool bHittable = false; switch( pStruct->nTargetType ) { case 0: // Enemy if( hVecList[i]->GetTeam() == m_hShooter->GetTeam() ) break; bHittable = true; break; case 1: // Friend if( hVecList[i]->GetTeam() != m_hShooter->GetTeam() ) break; bHittable = true; break; case 2: // All bHittable = true; break; } if( !bHittable ) continue; MAMovementBase *pMovement = hVecList[i]->GetMovement(); if( !pMovement ) continue; EtVector3 vDir = *hVecList[i]->GetPosition() - vPos; float fDistance = EtVec3Length( &vDir ); float fDistance2 = EtVec3Length( &EtVector3( vDir.x, 0.f, vDir.z ) ); EtVec3Normalize( &vDir, &vDir ); float fTemp = pStruct->fMinVelocity + ( ( (pStruct->fMaxVelocity - pStruct->fMinVelocity) / pStruct->fDistanceMax ) * ( pStruct->fDistanceMax - fDistance ) ); EtVector3 vVel; if( pMovement ) { pMovement->Look( EtVec3toVec2(vDir) ); pMovement->SetVelocityZ( -fTemp ); pMovement->SetResistanceZ( fTemp * 2.f ); } } } break; } CDnWeapon::OnSignal( Type, pPtr, LocalTime, SignalStartTime, SignalEndTime, nSignalIndex ); } void CDnProjectile::OnDamageSuccess( DnActorHandle hDamagedActor, CDnDamageBase::SHitParam &HitParam ) { // ¿©±â¼­ ÇǾî½ÌÀ̳ª ±âŸ µîµîÀÇ Å¸ÀÔ¿¡ µû¶ó¼­ ¾ø¿¤°ÇÁö µûÀ§¸¦ ¼ÂÆÃÇØÁÖ°Ô ÇÏÀÚ. // Æø¹ßÇÏ´Â °Å ¸Â¾ÒÀ» ¶© Destroy ó¸® ÇØÁÖÁö ¾Ê´Â´Ù. if( false == m_bPierce && /*m_bHasHitAction &&*/ !m_bOnCollisionCalled ) { ShowWeapon( false ); m_bValidDamage = false; m_InvalidLocalTime = m_LocalTime; m_DestroyOrbitType = FallGravity; m_nDestroyOrbitTimeGap = 1000; m_bStick = true; } // ¹ß»çü¸¦ ½ð ¾×ÅÍ¿¡°Ô ¹ß»çü°¡ ¸íÁßÇßÀ½À» ¾Ë¸°´Ù. if( m_hShooter ) { m_hShooter->OnHitProjectile( m_LocalTime, hDamagedActor, HitParam ); } } void CDnProjectile::AddStateEffect( CDnSkill::StateEffectStruct &Struct ) { #if defined(PRE_FIX_59336) //242¹ø »óÅÂÈ¿°ú¸¸ µû·Î ¸®½ºÆ®·Î °ü¸® Çϵµ·Ï ÇÑ´Ù. if (Struct.nID == STATE_BLOW::BLOW_242) { m_ComboLimitStateEffectList.push_back(Struct); } else { m_VecStateEffectList.push_back( Struct ); } #else m_VecStateEffectList.push_back( Struct ); #endif // PRE_FIX_59336 } void CDnProjectile::OnCollisionWithActor( void ) { if( false == m_bPierce && false == m_bOnCollisionCalled ) { if( m_bHasHitAction ) { #if defined(PRE_ADD_55295) //#55295 //È÷Æ® ¾×¼ÇÀ¸·Î º¯°æµÉ¶§ ÀÌ Ç÷¡±×°¡ ¼³Á¤ µÇ¾î ÀÖÀ¸¸é ¹æÇ⺤Å͸¦ Æò¸é°ú ÆòÇà? Çϵµ·Ï º¯°æÇÑ´Ù. if (m_bHitActionVectorInit) ChangeProjectileRotation(); #endif // PRE_ADD_55295 SetActionQueue( HIT_ACTION_NAME, 0, 0.0f ); m_bOnCollisionCalled = true; if( false == m_bValidDamage ) m_bValidDamage = true; // hit ¾×¼Ç ±æÀ̸¸Å­ ½Ã°£ »Ì¾ÆµÒ CEtActionBase::ActionElementStruct* pActionElement = GetElement( HIT_ACTION_NAME ); m_nDestroyOrbitTimeGap = int(((float)pActionElement->dwLength / CDnActionBase::m_fFPS) * 1000.0f); // »õ·Î¿î Æø¹ß hit ½Ã±×³ÎÀÌ µ¹¾Æ°¥ °ÍÀ̹ǷΠ¹ß»çü ¸ÂÀº ù ¾×ÅÍ ±âÁØ end signal ½Ã°£Àº ÃʱâÈ­ ½ÃŲ´Ù. ¾È±×·¯¸é Æø¹ß µ¥¹ÌÁö ¾Èµé¾î°¨. m_LastHitSignalEndTime = 0; } } } void CDnProjectile::OnCollisionWithGround( void ) { if( false == m_bOnCollisionCalled ) { if( m_bHasHitAction ) { #if defined(PRE_ADD_55295) //#55295 //È÷Æ® ¾×¼ÇÀ¸·Î º¯°æµÉ¶§ ÀÌ Ç÷¡±×°¡ ¼³Á¤ µÇ¾î ÀÖÀ¸¸é ¹æÇ⺤Å͸¦ Æò¸é°ú ÆòÇà? Çϵµ·Ï º¯°æÇÑ´Ù. if (m_bHitActionVectorInit) ChangeProjectileRotation(); #endif // PRE_ADD_55295 SetActionQueue( HIT_ACTION_NAME, 0, 0.0f ); m_bOnCollisionCalled = true; if( false == m_bValidDamage ) m_bValidDamage = true; // hit ¾×¼Ç ±æÀ̸¸Å­ ½Ã°£ »Ì¾ÆµÒ CEtActionBase::ActionElementStruct* pActionElement = GetElement( HIT_ACTION_NAME ); m_nDestroyOrbitTimeGap = int(((float)pActionElement->dwLength / CDnActionBase::m_fFPS) * 1000.0f); // TargetPositionType ÀÌ¸é ¸ñÀû À§Ä¡ °ð¹Ù·Î ¼ÂÆÃ if( 2 == m_TargetType ) m_Cross.SetPosition( m_vTargetPosition ); // »õ·Î¿î Æø¹ß hit ½Ã±×³ÎÀÌ µ¹¾Æ°¥ °ÍÀ̹ǷΠ¹ß»çü ¸ÂÀº ù ¾×ÅÍ ±âÁØ end signal ½Ã°£Àº ÃʱâÈ­ ½ÃŲ´Ù. ¾È±×·¯¸é Æø¹ß µ¥¹ÌÁö ¾Èµé¾î°¨. m_LastHitSignalEndTime = 0; } } } void CDnProjectile::OnCollisionWithProp( void ) { if( false == m_bOnCollisionCalled ) { if( m_bHasHitAction ) { #if defined(PRE_ADD_55295) //#55295 //È÷Æ® ¾×¼ÇÀ¸·Î º¯°æµÉ¶§ ÀÌ Ç÷¡±×°¡ ¼³Á¤ µÇ¾î ÀÖÀ¸¸é ¹æÇ⺤Å͸¦ Æò¸é°ú ÆòÇà? Çϵµ·Ï º¯°æÇÑ´Ù. if (m_bHitActionVectorInit) ChangeProjectileRotation(); #endif // PRE_ADD_55295 // ÀÌ¹Ì hit ¾×¼ÇÀ» ½ÇÇàÇϰí ÀÖ´Ù¸é ¾×¼ÇÀ» ´Ù½Ã ½ÇÇà½ÃŰÁö ¾Ê´Â´Ù. (#21384) SetActionQueue( HIT_ACTION_NAME, 0, 0.0f ); m_bOnCollisionCalled = true; if( false == m_bValidDamage ) m_bValidDamage = true; // hit ¾×¼Ç ±æÀ̸¸Å­ ½Ã°£ »Ì¾ÆµÒ CEtActionBase::ActionElementStruct* pActionElement = GetElement( HIT_ACTION_NAME ); m_nDestroyOrbitTimeGap = int(((float)pActionElement->dwLength / CDnActionBase::m_fFPS) * 1000.0f); // »õ·Î¿î Æø¹ß hit ½Ã±×³ÎÀÌ µ¹¾Æ°¥ °ÍÀ̹ǷΠ¹ß»çü ¸ÂÀº ù ¾×ÅÍ ±âÁØ end signal ½Ã°£Àº ÃʱâÈ­ ½ÃŲ´Ù. ¾È±×·¯¸é Æø¹ß µ¥¹ÌÁö ¾Èµé¾î°¨. m_LastHitSignalEndTime = 0; } else { // ÇÁ¶ø¿¡ ºÎµúÇû´Ù¸é hit ¾×¼ÇÀÌ ¾ø°Å³ª hit ¾×¼ÇÀº ÀÖµÇ hit signal ÀÌ ¾ø´Â ¹ß»çü´Â °ð¹Ù·Î »èÁ¦µÇµµ·Ï ó¸®. SetDestroy(); } } } void CDnProjectile::OnChangedNextActionToHit( void ) { if( false == m_bOnCollisionCalled ) { if( m_bHasHitAction ) { m_bOnCollisionCalled = true; if( false == m_bValidDamage ) m_bValidDamage = true; // hit ¾×¼Ç ±æÀ̸¸Å­ ½Ã°£ »Ì¾ÆµÒ CEtActionBase::ActionElementStruct* pActionElement = GetElement( HIT_ACTION_NAME ); m_nDestroyOrbitTimeGap = int(((float)pActionElement->dwLength / CDnActionBase::m_fFPS) * 1000.0f); // TargetPositionType ÀÌ¸é ¸ñÀû À§Ä¡ °ð¹Ù·Î ¼ÂÆÃ if( 2 == m_TargetType ) m_Cross.SetPosition( m_vTargetPosition ); } } } void CDnProjectile::OnChangeAction( const char *szPrevAction ) { if( m_bHasHitAction ) { if( NULL != szPrevAction && strcmp( SHOOT_ACTION_NAME, szPrevAction ) ) { m_bHitActionStarted = true; } } // È÷Æ®µÈ ´ë»óÀÌ ¶Ç È÷Æ®µÇ´Â°ÍÀ» ¹æÁöÇϱâÀ§Çؼ­ m_LastHitSignalEndTimeÀÌ Á¸ÀçÇϴµ¥ , ¹ß»çüÀÇ ¾×¼ÇÀÚü°¡ º¯ÇÒ°æ¿ì ÀÌÀü ½Ã±×³Î ±âÁØÀÇ EndTime ÀÌ ¼³Á¤µÇ±â¶§¹®¿¡ // ¾×¼ÇÀÌ º¯ÇÏ°í »õ·Î¿î Hit°¡ µé¾î¿Íµµ ÀÌÀü°ªÀ» »ç¿ëÇØ¼­ ¿ÀÀÛµ¿ÀÌ ÀϾ°ÔµÈ´Ù // ±×·¡¼­ ¾×¼ÇÀÌ ¹Ù²î¸é m_LastHitSignalEndTimeÀ» ÃʱâÈ­ ÇØÁÖµµ·Ï ÇÏÀÚ , ¸íÈ®ÇÏ°Ô ÇÏ·Á¸é ¹ß»çü ¾×¼Ç¸¶´Ù HitµÈ ´ë»óÀÇ ÀÌÀüÁ¤º¸¸¦ ±â¾ïÇØ¼­ ¸ÂÀº ´ë»óÀÌ ¶Ç ¸ÂÁö¾Êµµ·Ï // ¼³Á¤À» ÇØ¾ßÇÏÁö¸¸ ÀÏ´ÜÀº Â¥¿©Áø ´ë·Î ¼³Á¤Çϵµ·Ï ÇÕ´Ï´Ù. m_LastHitSignalEndTime = 0; } void CDnProjectile::OnFinishAction( const char* szPrevAction, LOCAL_TIME time ) { // Æø¹ß ¾×¼Ç Á¾·á½Ã¿£ °ð¹Ù·Î »èÁ¦. if( m_bHasHitAction ) if( 0 == strcmp( HIT_ACTION_NAME, szPrevAction ) ) SetDestroy(); } // NOTE: CrossHair ÇÁ·ÎÁ§Å¸ÀÏÀÎ °æ¿ì ¼­¹ö ÂÊ¿¡¼­´Â ÇÁ·ÎÁ§Å¸ÀÏ °ü·Ã Á¤º¸¸¦ Ŭ¶ó¿¡¼­ »ý¼ºµÈ °ÍÀ» ±×´ë·Î ¹Þ±â ¶§¹®¿¡ (CS_PROJECTILE) // ¿©±â¼­ »ý¼ºµÇÁö ¾Ê½À´Ï´Ù. // ¹ß»çü ½Ã±×³ÎÀ» Á÷Á¢ ¹Þ¾Æ¼­ »ý¼º. CDnProjectile *CDnProjectile::CreateProjectile( CMultiRoom *pRoom, DnActorHandle hShooter, MatrixEx &LocalCross, ProjectileStruct *pStruct, EtVector3* pForceTargetPos/*=NULL*/, DnActorHandle hForceTarget/*=CDnActor::Identity()*/, EtVector3* pForceDir/* = NULL*/ ) { MatrixEx CrossResult = LocalCross; CrossResult.m_vPosition += CrossResult.m_vXAxis * ( pStruct->vOffset->x * hShooter->GetScale()->x ); CrossResult.m_vPosition += CrossResult.m_vYAxis * ( pStruct->vOffset->y * hShooter->GetScale()->y ); CrossResult.m_vPosition += CrossResult.m_vZAxis * ( pStruct->vOffset->z * hShooter->GetScale()->z ); CDnProjectile *pProjectile = NULL; float fVelocityMultiply = 1.0f; // ½Ã±×³Î ±¸Á¶Ã¼¿¡ ÀÖ´Â ¹æÇâ°ªÀº ±æÀÌ¿Í °ü°è ¾øÀÌ ¹æÇ⸸ Àǹ̰¡ ÀÖ°í, // CrossResult.m_vZAxis ¸¦ Á¤±ÔÈ­½ÃŰ°í ¼Óµµ´Â ¿À·ÎÁö ½Ã±×³Î ±¸Á¶Ã¼¿¡¼­ Á¤ÇØÁø fSpeed ·Î °áÁ¤µÈ´Ù. switch( pStruct->nTargetType ) { case TargetTypeEnum::CrossHair: { SAFE_DELETE( pProjectile ); return NULL; } break; case TargetTypeEnum::Direction: { pProjectile = new CDnProjectile( pRoom, hShooter ); EtVector3 vDirection = *pStruct->vDirection; bool bAILook = false; // MonsterActor if( hShooter && hShooter->IsMonsterActor() ) { CDnMonsterActor *pMonster = static_cast(hShooter.GetPointer()); if( pMonster && pMonster->bIsAILook() ) { // STE_ProjectileTargetPosition Àº TargetPosition ÀÎ °æ¿ì¿¡¸¸ »ç¿ëÇÏ´Â ½Ã±×³ÎÀÌ´Ù. if( !pMonster->bIsProjectileTargetSignal() ) { vDirection = EtVec2toVec3( *pMonster->GetAIBase()->GetAILook() ); bAILook = true; } } } EtVector3 vTemp; if( bAILook ) vTemp = vDirection; else EtVec3TransformNormal( &vTemp, &vDirection, LocalCross ); if( FALSE == pStruct->bNormalizeDirectionVector ) { fVelocityMultiply = EtVec3Length( &vTemp ); CrossResult.m_vZAxis = vTemp / fVelocityMultiply; } else { fVelocityMultiply = 1.0f; EtVec3Normalize( &vTemp, &vTemp ); CrossResult.m_vZAxis = vTemp; } CrossResult.MakeUpCartesianByZAxis(); } break; case TargetTypeEnum::TargetPosition: case TargetTypeEnum::Target: case TargetTypeEnum::Shooter: { if( hShooter->IsPlayerActor() ) { SAFE_DELETE( pProjectile ); return NULL; } else if( hShooter->IsMonsterActor() ) { pProjectile = new CDnProjectile( pRoom, hShooter ); CDnMonsterActor *pMonster = static_cast(hShooter.GetPointer()); // ¹ß»ç ´ë»óÀÌ Shooter ÀÚ±â ÀÚ½ÅÀÎ °æ¿ì DnActorHandle hTarget; // ReserveProjectileTarget ½Ã±×³Î·Î ¹Ì¸® Á¤Çصξú´ø Ÿ°ÙÀÌ ÀÖ´Ù¸é ¹Þ¾Æ¿Â´Ù. // ¾øÀ¸¸é ¿ø·¡ ¾ò¾î¿À´Â AI ¿¡°Ô¼­ ¾ò¾î¿È. hTarget = pMonster->GetReservedProjectileTarget(); if( !hTarget ) hTarget = pMonster->GetAggroTarget(); EtVector3 vTargetPos; bool bTarget = true; // °­Á¦Å¸°Ù¼³Á¤ if( pForceTargetPos ) vTargetPos = *pForceTargetPos; else if( pStruct->nTargetType == TargetTypeEnum::TargetPosition && pMonster->bIsProjectileTargetSignal() ) vTargetPos = *pMonster->GetAIBase()->GetProjectileTarget(); else if( hTarget ) vTargetPos = *hTarget->GetPosition(); else bTarget = false; if( bTarget ) { // TargetPosRandomValue if( pStruct->nTargetPosRandomValue > 0 ) { _srand( pRoom, pProjectile->GetUniqueID() ); vTargetPos.x += cos( EtToRadian( _rand(pRoom)%360 ) ) * pStruct->nTargetPosRandomValue; vTargetPos.z += sin( EtToRadian( _rand(pRoom)%360 ) ) * pStruct->nTargetPosRandomValue; } float fHeight = CDnWorld::GetInstance(pRoom).GetHeight( vTargetPos ); // #28665 ´ëÆ÷ ¸÷ÀÌ ¾Æ´Ñ °æ¿ì¿¡¸¸. °è»êµÈ ´ëÆ÷ÀÇ ¸ñÀûÁö´Â °Çµå¸®Áö ¾Ê´Â´Ù. #ifdef PRE_FIX_PARTSMONSTER_AI_TARGETTING if( hTarget && fHeight < vTargetPos.y && (pMonster->GetActorType() != CDnActorState::Cannon) && hTarget->IsPartsMonsterActor() == false ) vTargetPos -= hTarget->GetMatEx()->m_vZAxis * ( vTargetPos.y - fHeight ); #else if( hTarget && fHeight < vTargetPos.y && (pMonster->GetActorType() != CDnActorState::Cannon) ) vTargetPos -= hTarget->GetMatEx()->m_vZAxis * ( vTargetPos.y - fHeight ); #endif } else { vTargetPos = *hShooter->GetPosition() + ( hShooter->GetMatEx()->m_vZAxis * pMonster->GetThreatRange() ); } // TargetPosition if( pStruct->nTargetType == TargetTypeEnum::TargetPosition ) { pProjectile->SetTargetPosition( vTargetPos ); CrossResult.m_vZAxis = vTargetPos - CrossResult.GetPosition(); EtVec3Normalize( &CrossResult.m_vZAxis, &CrossResult.m_vZAxis ); } // Target if( pStruct->nTargetType == TargetTypeEnum::Target ) { // °­Á¦Å¸°Ù¼³Á¤ if( hForceTarget ) hTarget = hForceTarget; if( !hTarget ) hTarget = hShooter; if (pStruct->nTargetStateIndex != 0) { vTargetPos = *hTarget->GetPosition(); pProjectile->SetTargetPosition(vTargetPos); } pProjectile->SetTargetActor( hTarget ); } else if( pStruct->nTargetType == TargetTypeEnum::Shooter ) { hTarget = hShooter; vTargetPos = *hTarget->GetPosition(); pProjectile->SetTargetActor( hTarget ); pProjectile->SetTargetPosition( vTargetPos ); } //¸ñÇ¥ ÁöÁ¡À¸·Î ³¯¾Æ °¡´Â ¹ß»çüÀÎ °æ¿ì ÇöÀç ¹ß»çü À§Ä¡¿¡¼­ ¸ñÇ¥ ÁöÁ¡À¸·ÎÀÇ ¹æÇâ º¤ÅÍ º¯°æ ÇØ¾ß ÇÑ´Ù. //ÀÏ´Ü ³«ÀÎ¿ë ¹ß»çü¿¡¼­¸¸ µ¿ÀÛ Çϵµ·Ï ¼öÁ¤ÇÑ´Ù. if (pStruct->nTargetStateIndex != 0) { CrossResult.m_vZAxis = vTargetPos - CrossResult.GetPosition(); EtVec3Normalize( &CrossResult.m_vZAxis, &CrossResult.m_vZAxis ); } else if( EtVec3LengthSq( pStruct->vDirection ) == 0.f ) { _ASSERT( !(pStruct->nOrbitType == Projectile && pStruct->VelocityType == Accell && pStruct->nTargetType == 2) && "Áß·Â °¡¼Óµµ°¡ Àû¿ëµÇ´Â Projectile/TargetPosition ŸÀÔÀÇ ¹ß»çü´Â ¹Ýµå½Ã ¹æÇâÀ» Á¤ÇØÁà¾ß ÇÕ´Ï´Ù." ); CrossResult.m_vZAxis = vTargetPos - CrossResult.GetPosition(); EtVec3Normalize( &CrossResult.m_vZAxis, &CrossResult.m_vZAxis ); } else if( !( (pStruct->nOrbitType == OrbitTypeEnum::Linear) && (pStruct->nTargetType == TargetTypeEnum::TargetPosition) ) ) { // ´ëÆ÷¿¡¼­ À¯Àú°¡ Á¤ÇÑ ¹æÇâÀ¸·Î ½î¾Æ¾ßÇÒ °æ¿ì ÇØ´ç ¹æÇâÀ¸·Î ¼ÂÆÃÇØÁØ´Ù. if( NULL == pForceDir ) { EtVector3 vTemp; EtVec3TransformNormal( &vTemp, pStruct->vDirection, LocalCross ); if( pStruct->bUseTargetPositionDir ) { EtVector3 vTargetPosDir = vTargetPos - CrossResult.m_vPosition; EtVec3Normalize( &vTargetPosDir, &vTargetPosDir ); MatrixEx CrossTargetPosDir; CrossTargetPosDir.m_vZAxis = vTargetPosDir; CrossTargetPosDir.MakeUpCartesianByZAxis(); EtVector3 vToolDefinedDir = *pStruct->vDirection; EtVector3 vDirZ( vToolDefinedDir.x, 0.0f, vToolDefinedDir.z ); EtVec3Normalize( &vDirZ, &vDirZ ); EtVec3Normalize( &vToolDefinedDir, &vToolDefinedDir ); float fDot = EtVec3Dot( &vToolDefinedDir, &vDirZ ); float fRotX = EtAcos( fDot ); CrossTargetPosDir.RotatePitch( EtToDegree( -fRotX ) ); vTemp = CrossTargetPosDir.m_vZAxis; } if( FALSE == pStruct->bNormalizeDirectionVector ) { fVelocityMultiply = EtVec3Length( &vTemp ); CrossResult.m_vZAxis = vTemp / fVelocityMultiply; } else { fVelocityMultiply = 1.0f; EtVec3Normalize( &vTemp, &vTemp ); CrossResult.m_vZAxis = vTemp; } } else { EtVector3 vTemp; EtVec3TransformNormal( &vTemp, pForceDir, LocalCross ); EtVec3Normalize( &CrossResult.m_vZAxis, &vTemp ); pProjectile->SetForceDir( *pForceDir ); } } CrossResult.MakeUpCartesianByZAxis(); } } break; case TargetTypeEnum::DestPosition: { pProjectile = new CDnProjectile( pRoom, hShooter ); EtVector3 vDestOffset = *(pStruct->vDestPosition); if( pStruct->nTargetPosRandomValue > 0 ) { _srand( pRoom, pProjectile->GetUniqueID() ); vDestOffset.x += cos( EtToRadian( _rand(pRoom)%360 ) ) * pStruct->nTargetPosRandomValue; vDestOffset.z += sin( EtToRadian( _rand(pRoom)%360 ) ) * pStruct->nTargetPosRandomValue; } // ¹æÇ⺤ÅͰ¡ Åø¿¡¼­ ¼³Á¤µÇ¾îÀÖ´Ù¸é dest position ÀÌÁö¸¸ ±×ÂÊ ¹æÇâÀ¸·Î µ¹·ÁÁÜ.. EtVector3 vDirection; if( EtVec3LengthSq( pStruct->vDirection ) != 0.f ) { vDirection = vDestOffset; EtVec3Normalize( &vDirection, &vDirection ); MatrixEx CrossDestDir; CrossDestDir.m_vZAxis = vDirection; CrossDestDir.MakeUpCartesianByZAxis(); EtVector3 vToolDefinedDir = *pStruct->vDirection; EtVector3 vDirZ( vToolDefinedDir.x, 0.0f, vToolDefinedDir.z ); EtVec3Normalize( &vDirZ, &vDirZ ); EtVec3Normalize( &vToolDefinedDir, &vToolDefinedDir ); float fDot = EtVec3Dot( &vToolDefinedDir, &vDirZ ); float fRotX = EtAcos( fDot ); CrossDestDir.RotatePitch( EtToDegree( -fRotX ) ); vDirection = CrossDestDir.m_vZAxis; } else { // ¹æÇâ º¤ÅͰ¡ ¼³Á¤µÇ¾îÀÖÁö ¾Ê´Ù¸é dest position ÂÊÀ¸·Î ¹æÇâÀ» Àâ¾ÆÁØ´Ù. vDirection = vDestOffset - (*pStruct->vOffset); EtVec3Normalize( &vDirection, &vDirection ); } EtVector3 vWorldDirection; EtVec3TransformNormal( &vWorldDirection, &vDirection, LocalCross ); CrossResult.m_vZAxis = vWorldDirection; EtVec3Normalize( &CrossResult.m_vZAxis, &CrossResult.m_vZAxis ); CrossResult.MakeUpCartesianByZAxis(); // ÀÌ¹Ì DestPosition À» ÇâÇØ ¹æÇâÀÌ Á¤ÇØÁø »óÅÂÀ̹ǷΠ¸ñÀûÁö´Â ·ÎÄà ZÃàÀ¸·Î °Å¸®°ª¸¸Å­ À̵¿½Ã۸éµÈ´Ù. float fDestLength = EtVec3Length( &vDestOffset ); MatrixEx crossDestPosition = CrossResult; crossDestPosition.m_vPosition += CrossResult.m_vZAxis * fDestLength; crossDestPosition.m_vPosition.y = CDnWorld::GetInstance( hShooter->GetRoom() ).GetHeightWithProp( crossDestPosition.m_vPosition ); pProjectile->SetTargetPosition( crossDestPosition.m_vPosition ); } break; } if( pStruct->nWeaponTableID > 0 ) { if( pStruct->nProjectileIndex != -1 ) { DnWeaponHandle hWeapon = CDnWeapon::GetSmartPtr( (CMultiRoom*)g_pGameServerManager->GetRootRoom(), pStruct->nProjectileIndex ); if( hWeapon ) *(CDnWeapon*)pProjectile = *hWeapon.GetPointer(); } else { if (pProjectile == NULL) { _DANGER_POINT(); return NULL; } pProjectile->CDnWeapon::Initialize( pStruct->nWeaponTableID, 0 ); pProjectile->CreateObject(); } } else if( hShooter->GetWeapon(1) ) { *(CDnWeapon*)pProjectile = *hShooter->GetWeapon(1); } else { SAFE_DELETE( pProjectile ); return NULL; } pProjectile->SetWeaponType( (WeaponTypeEnum)( pProjectile->GetWeaponType() | WeaponTypeEnum::Projectile ) ); pProjectile->Initialize( CrossResult, (CDnProjectile::OrbitTypeEnum)pStruct->nOrbitType, (CDnProjectile::DestroyOrbitTypeEnum)pStruct->nDestroyOrbitType, (CDnProjectile::TargetTypeEnum)pStruct->nTargetType); pProjectile->SetSpeed( pStruct->fSpeed * fVelocityMultiply ); pProjectile->SetResistance( pStruct->fResistance ); pProjectile->SetValidTime( pStruct->nValidTime ); if( pProjectile->GetOrbitType() == OrbitTypeEnum::Homing || pProjectile->GetOrbitType() == OrbitTypeEnum::TerrainHoming || pProjectile->GetOrbitType() == OrbitTypeEnum::Projectile ) { pProjectile->SetVelocityType( (VelocityTypeEnum)pStruct->VelocityType ); } int nLength = pProjectile->GetWeaponLength(); if( pStruct->bIncludeMainWeaponLength ) { DnWeaponHandle hWeapon = hShooter->GetWeapon(0); if ( hWeapon ) nLength += hWeapon->GetWeaponLength(); } if( hShooter->IsProcessSkill() ) { nLength += hShooter->GetProcessSkill()->GetIncreaseRange(); } if( hShooter->IsEnabledToggleSkill() ) { nLength += hShooter->GetEnabledToggleSkill()->GetIncreaseRange(); } pProjectile->SetWeaponLength( nLength ); pProjectile->SetPierce( ( pStruct->bPierce == TRUE ) ? true : false ); pProjectile->SetMaxHitCount( pStruct->nMaxHitCount ); pProjectile->SetProjectileOrbitRotateZ( pStruct->fProjectileOrbitRotateZ ); pProjectile->SetTraceHitTarget( (pStruct->bTraceHitTarget == TRUE) ? true : false, (pStruct->bTraceHitActorHittable == TRUE) ? true : false ); #if defined(PRE_FIX_52329) pProjectile->SetIgnoreHitType(pStruct->nIgnoreHitType); #endif // PRE_FIX_52329 #if defined(PRE_ADD_55295) pProjectile->SetHitActionVectorInit(pStruct->bHitActionVectorInit == TRUE ? true : false); #endif // PRE_ADD_55295 pProjectile->PostInitialize(); return pProjectile; } // Ŭ¶ó·ÎºÎÅÍ ÆÐŶÀ» ¹Þ¾Æ¼­ »ý¼ºÇÏ´Â ¹ß»çü °´Ã¼. // °¢ Ŭ¶óÀÇ LocalPlayer µé·ÎºÎÅÍ ÆÐŶµéÀÌ ¿Ã¶ó¿È. CDnProjectile* CDnProjectile::CreatePlayerProjectileFromClientPacket( DnActorHandle hShooter, const BYTE* pPacket ) { if( false == hShooter->IsPlayerActor() ) return NULL; CPacketCompressStream Stream( const_cast(pPacket), 128 ); CDnPlayerActor* pPlayerActor = static_cast(hShooter.GetPointer()); if( pPlayerActor->IsInvalidPlayerChecker() ) return NULL; bool bActorAttachWeapon; int nWeaponTableID, nWeaponLength = 0; DWORD dwUniqueID,dwGap; float fSpeed = 0.f; float fResistance = 0.f; int nValidTime = 0; int VelocityType = 0; EtVector3 vTargetPos; DWORD dwTargetUniqueID; CDnProjectile::OrbitTypeEnum OrbitType; CDnProjectile::DestroyOrbitTypeEnum DestroyType; CDnProjectile::TargetTypeEnum TargetType; MatrixEx Cross; EtVector3 vDirection( 0.0f, 0.0f, 0.0f ); int nActionIndex; int nMaxHitCount = 0; int nSignalIndex = -1; float fProjectileOrbitRotateZ = 0.0f; ProjectileStruct* pProjectileStruct = NULL; Stream.Read( &dwGap, sizeof(DWORD) ); Stream.Read( &bActorAttachWeapon, sizeof(bool) ); Stream.Read( &dwUniqueID, sizeof(DWORD) ); if( !bActorAttachWeapon ) { Stream.Read( &nWeaponTableID, sizeof(int) ); } Stream.Read( &Cross.m_vPosition, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); Stream.Read( &Cross.m_vXAxis, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT ); Stream.Read( &Cross.m_vYAxis, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT ); Stream.Read( &Cross.m_vZAxis, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT ); #ifdef PRE_MOD_PROJECTILE_HACK char cShooterType; DWORD dwParentShooterUniqueID = -1; DWORD dwShooterUniqueID = -1; INT64 nShooterSerialID = -1; int nShooterActionIndex; int nShooterSignalIndex; bool bSendSerialID; DnWeaponHandle hParentProjectileWeapon; Stream.Read( &cShooterType, sizeof(char) ); Stream.Read( &dwParentShooterUniqueID, sizeof(DWORD) ); switch( cShooterType ) { case 0: dwShooterUniqueID = dwParentShooterUniqueID; break; case 1: { Stream.Read( &bSendSerialID, sizeof(bool) ); if( bSendSerialID ) Stream.Read( &nShooterSerialID, sizeof(INT64) ); else Stream.Read( &dwShooterUniqueID, sizeof(DWORD) ); } break; } Stream.Read( &nShooterActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); Stream.Read( &nShooterSignalIndex, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); ProjectileStruct *pShooterStruct = NULL; nWeaponLength = 0; switch( cShooterType ) { case 0: { DnActorHandle hHandle = CDnActor::FindActorFromUniqueID( pPlayerActor->GetRoom(), dwShooterUniqueID ); if( hHandle ) { if( hHandle->GetCurrentActionIndex() == nShooterActionIndex ) { bool bCheckStandAction = CDnChangeStandActionBlow::CheckUsableAction( pPlayerActor->GetActorHandle(), true, pPlayerActor->GetCurrentAction() ); if( bCheckStandAction == false ) { pPlayerActor->ReportInvalidAction(); return NULL; } CEtActionSignal *pSignal = hHandle->GetSignal( nShooterActionIndex, nShooterSignalIndex ); if( pSignal && pSignal->GetSignalIndex() == STE_Projectile ) { pShooterStruct = static_cast( pSignal->GetData() ); } else if( hHandle->GetCustomActionIndex() > 0 ) { CEtActionSignal *pCustomActionSignal = hHandle->GetSignal( hHandle->GetCustomActionIndex(), nShooterSignalIndex ); if( pCustomActionSignal && pCustomActionSignal->GetSignalIndex() == STE_Projectile ) { pShooterStruct = static_cast( pCustomActionSignal->GetData() ); } } } else { // Ŭ¶ó¿Í ¼­¹ö°¡ ¾×¼Ç À妽º°¡ ´Ù¸§. ÇÙÀ¸·Î ó¸®. return NULL; } } } break; case 1: { DnWeaponHandle hHandle; if( bSendSerialID ) { for( DWORD i=0; i<2; i++ ) { // FindItemFromSerialID ¸¦ ¸¸µé¾î¾ß ÇÏÁö¸¸ ÀÏ´ÜÀº ÇÊ¿ä¾ø¾î¼­ EquipWeapon ¿¡¼­¸¸ ã½À´Ï´Ù. DnWeaponHandle hWeapon = pPlayerActor->GetWeapon(i); if( hWeapon && hWeapon->GetSerialID() == nShooterSerialID ) { hHandle = hWeapon; break; } hWeapon = pPlayerActor->GetCashWeapon(i); if( hWeapon && hWeapon->GetSerialID() == nShooterSerialID ) { hHandle = hWeapon; break; } } } else { hHandle = CDnWeapon::FindWeaponFromUniqueIDAndShooterUniqueID( pPlayerActor->GetRoom(), dwShooterUniqueID, dwParentShooterUniqueID ); if( hHandle ) { hParentProjectileWeapon = hHandle; // nWeaponLength += hHandle->GetWeaponLength(); } } if( hHandle ) { CEtActionSignal *pSignal = hHandle->GetSignal( nShooterActionIndex, nShooterSignalIndex ); if( pSignal && pSignal->GetSignalIndex() == STE_Projectile ) { pShooterStruct = static_cast( pSignal->GetData() ); } } } break; } if( !pShooterStruct ) return NULL; pProjectileStruct = pShooterStruct; OrbitType = (CDnProjectile::OrbitTypeEnum)pShooterStruct->nOrbitType; DestroyType = (CDnProjectile::DestroyOrbitTypeEnum)pShooterStruct->nDestroyOrbitType; TargetType = (CDnProjectile::TargetTypeEnum)pShooterStruct->nTargetType; nValidTime = pShooterStruct->nValidTime; fProjectileOrbitRotateZ = pShooterStruct->fProjectileOrbitRotateZ; #ifdef PRE_ADD_PROJECTILE_RANDOM_WEAPON // ·£´ý ¹ß»çü °ü·Ã üũ if( pShooterStruct->RandomWeaponParam && strlen( pShooterStruct->RandomWeaponParam ) > 0 ) { std::vector vecWeaponID; vecWeaponID.push_back( pShooterStruct->nWeaponTableID ); std::vector tokens; TokenizeA( pShooterStruct->RandomWeaponParam, tokens, "/" ); if( tokens.size() > 1 ) { for( int i=1; i( tokens.size() ); i++ ) { std::vector tokensparam; TokenizeA( tokens[i].c_str(), tokensparam, ";" ); if( tokensparam.size() > 0 ) { vecWeaponID.push_back( atoi( tokensparam[0].c_str() ) ); } tokensparam.clear(); } } bool bUsableWeaponTableID = false; for( int i=0; i( vecWeaponID.size() ); i++ ) { if( vecWeaponID[i] == nWeaponTableID ) { bUsableWeaponTableID = true; break; } } tokens.clear(); vecWeaponID.clear(); if( !bUsableWeaponTableID ) // »ç¿ëÇÒ ¼ö ¾ø´Â WeaponID ÀÓ! return NULL; } #endif // PRE_ADD_PROJECTILE_RANDOM_WEAPON #else Stream.Read( &OrbitType, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); Stream.Read( &DestroyType, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); Stream.Read( &TargetType, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); Stream.Read( &nValidTime, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); Stream.Read( &nWeaponLength, sizeof(int) ); Stream.Read( &fProjectileOrbitRotateZ, sizeof(float) ); #endif int nTargetPartsIndex = -1; int nTargetBoneIndex = -1; Stream.Read(&nTargetPartsIndex, sizeof(int)); Stream.Read(&nTargetBoneIndex, sizeof(int)); switch( TargetType ) { case CDnProjectile::CrossHair: case CDnProjectile::Direction: break; case CDnProjectile::TargetPosition: case CDnProjectile::Target: case CDnProjectile::DestPosition: case CDnProjectile::Shooter: Stream.Read( &vTargetPos, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); Stream.Read( &dwTargetUniqueID, sizeof(DWORD), CPacketCompressStream::NOCOMPRESS ); break; } Stream.Read( &fSpeed, sizeof(float) ); #ifdef PRE_MOD_PROJECTILE_HACK bool bPierce = ( pShooterStruct->bPierce == TRUE ); nMaxHitCount = pShooterStruct->nMaxHitCount; bool bTraceHitTarget = ( pShooterStruct->bTraceHitTarget == TRUE ); bool bTraceHitActorHittable = (pShooterStruct->bTraceHitActorHittable == TRUE); switch( OrbitType ) { case CDnProjectile::Linear: case CDnProjectile::TerrainLinear: break; case CDnProjectile::Projectile: VelocityType = pShooterStruct->VelocityType; break; case CDnProjectile::Homing: case CDnProjectile::TerrainHoming: VelocityType = pShooterStruct->VelocityType; break; case CDnProjectile::Acceleration: fResistance = pShooterStruct->fResistance; break; } Stream.Read( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); if( false == pPlayerActor->IsIgnoreSkillCoolTime() ) { if( nActionIndex != -1 && nActionIndex != pPlayerActor->GetCurrentActionIndex() ) { // ÇÙ¾´°ÍÀÔ´Ï´Ù. //break; return NULL; } } nSignalIndex = nShooterSignalIndex; #else bool bPierce = false; Stream.Read( &bPierce, sizeof(bool) ); if( bPierce ) Stream.Read( &nMaxHitCount, sizeof(int) ); bool bTraceHitTarget = false; bool bTraceHitActorHittable = false; Stream.Read( &bTraceHitTarget, sizeof(bool) ); Stream.Read( &bTraceHitActorHittable, sizeof(bool) ); switch( OrbitType ) { case CDnProjectile::Linear: case CDnProjectile::TerrainLinear: break; case CDnProjectile::Projectile: Stream.Read( &VelocityType, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); break; case CDnProjectile::Homing: case CDnProjectile::TerrainHoming: Stream.Read( &VelocityType, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); break; case CDnProjectile::Acceleration: Stream.Read( &fResistance, sizeof(float), CPacketCompressStream::FLOAT_SHORT, 1.f ); break; } Stream.Read( &nActionIndex, sizeof(int) ); if( false == pPlayerActor->IsIgnoreSkillCoolTime() ) { if( nActionIndex != -1 && nActionIndex != pPlayerActor->GetCurrentActionIndex() ) { return NULL; } } // Note Çѱâ: üÀÎ °ø°Ý »óÅÂÈ¿°ú¸¦ À§ÇØ ½Ã±×³Î struct ¸¦ ãÀ» ¼ö ÀÖ´Â index °¡ ÇÊ¿äÇÔ. Stream.Read( &nSignalIndex, sizeof(int) ); // Note Çѱâ: projectile ½Ã±×³Î struct ¸¦ ã´Â´Ù. // ½ºÅ³ÀÏ ¶§¸¸ ActionIndex°¡ À¯È¿ÇÔ. if( -1 != nSignalIndex && -1 != nActionIndex ) { CEtActionSignal *pSignal = pPlayerActor->GetSignal( nActionIndex, nSignalIndex ); if( pSignal && pSignal->GetSignalIndex() == STE_Projectile ) { pProjectileStruct = static_cast( pSignal->GetData() ); } } #endif #ifdef PRE_MOD_PROJECTILE_HACK #else // º¸¿ì ¸¶½ºÅÍÀÇ ·¹º¼·ç¼Å³Ê¸® ¹ß¸®½ºÅ¸ °°Àº ¹ß»çü¾î¼­ ¹ß»çü ½î´Â ½ºÅ³¿¡¼­ ÃÖÃÊ·Î ³ª°£ ¹ß»çü¿¡¼­ // ´É·ÂÄ¡¸¦ ÀÌÀüÇϱâ À§ÇÑ Á¤º¸... DWORD dwParentID = 0; Stream.Read( &dwParentID, sizeof(DWORD) ); DWORD dwParentShooterUniqueID = 0; Stream.Read( &dwParentShooterUniqueID, sizeof(DWORD) ); #endif #if defined(PRE_FIX_52329) int nIgnoreHitType = 0; Stream.Read(&nIgnoreHitType, sizeof(nIgnoreHitType)); #endif // PRE_FIX_52329 #if defined(PRE_ADD_55295) bool bHitActionVectorInit = false; Stream.Read(&bHitActionVectorInit, sizeof(bHitActionVectorInit)); #endif // PRE_ADD_55295 pPlayerActor->GetPlayerSpeedHackChecker()->OnSyncDatumGap( dwGap ); CDnProjectile* pParentProjectile = NULL; DnSkillHandle hParentSkill; bool bFromParentProjectile = false; #ifndef PRE_MOD_PROJECTILE_HACK DnWeaponHandle hParentProjectileWeapon = CDnWeapon::FindWeaponFromUniqueIDAndShooterUniqueID( pPlayerActor->GetRoom(), dwParentID, dwParentShooterUniqueID ); #endif if( hParentProjectileWeapon ) { // ¹ß»çü¿¡¼­ ¹ß»çü¸¦ ½î´Â °æ¿ì Ŭ¶óÀÌ¾ðÆ®¿¡¼­ ÆÐŶÀÌ ÀÌ·¸°Ô ¿Â´Ù. if( hParentProjectileWeapon->GetWeaponType() == CDnWeapon::Projectile ) { pParentProjectile = static_cast(hParentProjectileWeapon.GetPointer()); hParentSkill = pParentProjectile->GetParentSkill(); if( hParentSkill ) // ¹ß»çü¿¡¼­ ¹ß»çü¸¦ ½î´Â °æ¿ìÀÇ ½ºÅ³¸¸ °ñ¶ó¼­.. { pPlayerActor->AddReservedProjectileCount(); bFromParentProjectile = true; } } } // ¹ß»çü¿¡¼­ ¹ß»çü¸¦ ½î´Â °æ¿ì´Â üũ¿¡¼­ Á¦¿ÜÇÑ´Ù. // ÀÌÀ¯´Â, ¹ß»çü ½î´Â À§Ä¡¸¦ ÇÙ¿¡¼­ ¼­¹ö·Î º¸³»´õ¶óµµ ½Ç½Ã°£À¸·Î »ý¼ºµÇ´Â ºÎ¸ð ¹ß»çüÀÇ id ¸¦ °°ÀÌ // º¸³»ÁÖÁö ¾ÊÀ¸¸é ¹Ù·Î À§ÀÇ ·çƾ¿¡¼­ °É¸®±â ¶§¹®¿¡ ¹ß»çü¿¡¼­ ¹ß»çü¸¦ ½î´Â °ÍÀ¸·Î ÀÎÁ¤µÇÁö ¾Ê±â ¶§¹®ÀÌ´Ù. // ¿ì¼± ÀÏ¹Ý °ø°ÝÀÎ °æ¿ì¿¡¸¸ ¸·ÀÚ. if( (false == bFromParentProjectile) && (-1 == nSignalIndex || -1 == nActionIndex) ) { // X, Z Æò¸é ±âÁØÀ¸·Î¸¸ üũÇÑ´Ù. ³ôÀ̱îÁö üũÇÏ´Â °ÍÀº ÃßÈÄ¿¡ ÇÊ¿äÇϸé Ãß°¡. EtVector2 vShooterXZPos( hShooter->GetPosition()->x, hShooter->GetPosition()->z ); EtVector2 vProjectileShootPosXZ( Cross.m_vPosition.x, Cross.m_vPosition.z ); EtVector2 vDist = vProjectileShootPosXZ - vShooterXZPos; float fDistanceSQ = EtVec2LengthSq( &vDist ); //#37327 µ¥¸ô¸®¼Ç ¹ß»çü °æ¿ì 100À» ³Ñ°Ô Offset°ªÀÌ ¼³Á¤µÈ °æ¿ì°¡ ÀÖÀ½. //ÀÏ´Ü ³Ë³ËÇÏ°Ô ÃÖ´ë °ª 200À¸·Î üũ Çϵµ·Ï ¼öÁ¤(200*200 = 40000) if( 40000.0f < fDistanceSQ ) { // ¹ß»çü ½ÃÀÛ À§Ä¡¸¦ ÀÓÀÇ´ë·Î Á¶ÀÛÇØ¼­ º¸³½ ÇÙÀ¸·Î ÆÇ´Ü. #ifndef _FINAL_BUILD OutputDebug( "¹ß»çü ¹ß»ç À§Ä¡ °Å¸® üũ¿¡ °É·Á ÇÙÀ¸·Î ÆÇ´Ü.\n" ); #endif // #ifndef _FINAL_BUILD return NULL; } } bool bValidProjectile = true; //³«ÀÎÀ» À§ÇÑ ¹ß»çüÀÎ °æ¿ì ¹ß»çü ½Ã±×³Î ¼ö º¸´Ù ¸¹Àº ¹ß»çü°¡ ¹ß»çµÈ´Ù. //³«ÀÎ¿ë ¹ß»çü°¡ ¾Æ´Ñ°æ¿ì¸¸ ¹ß»çü üũ Çϵµ·Ï ¼öÁ¤ÇÔ. if (pShooterStruct->nTargetStateIndex == 0) bValidProjectile = pPlayerActor->UseAndCheckAvailProjectileCount(); if( false == bValidProjectile ) return NULL; // ÇöÀç ŸÀֿ̹¡ ¸Â´Â ¹ß»çüÀÎÁö üũ // ¹ß»çü¿¡¼­ ¹ß»çü¸¦ ½î´Â Ư¼öÇÑ °æ¿ì´Â Á¦¿Ü. if( false == bFromParentProjectile ) { bValidProjectile = true; //³«ÀÎÀ» À§ÇÑ ¹ß»çüÀÎ °æ¿ì ¹ß»çü ½Ã±×³Î ¼ö º¸´Ù ¸¹Àº ¹ß»çü°¡ ¹ß»çµÈ´Ù. //³«ÀÎ¿ë ¹ß»çü°¡ ¾Æ´Ñ°æ¿ì¸¸ ¹ß»çü üũ Çϵµ·Ï ¼öÁ¤ÇÔ. if (pShooterStruct->nTargetStateIndex == 0) bValidProjectile = pPlayerActor->CheckProjectileSignalFrameTerm(); if( false == bValidProjectile ) { #ifndef _FINAL_BUILD OutputDebug( "CDnPlayerActor::CheckProjectileSignalFrameTerm(): ÇöÀç ŸÀֿ̹¡ ¿Ã ¼ö ¾ø´Â ¹ß»çü ¿äû ½Ã±×³Î. ÇÙÀ¸·Î ÆÇ´Ü.\n" ); #endif // #ifndef _FINAL_BUILD return NULL; } } CDnProjectile *pProjectile = new CDnProjectile( pPlayerActor->GetRoom(), hShooter ); pProjectile->SetUniqueID( dwUniqueID ); pProjectile->SetPierce( bPierce ); pProjectile->SetMaxHitCount( nMaxHitCount ); pProjectile->SetTargetPartsIndex(nTargetPartsIndex, nTargetBoneIndex); if( bActorAttachWeapon ) { CDnWeapon *pWeapon = pPlayerActor->GetWeapon(1); if( pWeapon ) { *(CDnWeapon*)pProjectile = *pWeapon; } } else { if( pProjectileStruct && pProjectileStruct->nProjectileIndex != -1 ) { DnWeaponHandle hLocalParentProjectileWeapon = CDnWeapon::GetSmartPtr( (CMultiRoom*)g_pGameServerManager->GetRootRoom(), pProjectileStruct->nProjectileIndex ); if( hLocalParentProjectileWeapon ) *(CDnWeapon*)pProjectile = *hLocalParentProjectileWeapon.GetPointer(); } else { // ¯±ú¿¡¼­ ÀÏ¹Ý °ø°ÝÀ¸·Î ¹«±â ID ¹Ù²ã¼­ º¸³»´Â °æ¿ì üũ. // ¹ß»çü¿¡¼­ ¹ß»çü ½î´Â Ư¼öÇÑ °æ¿ì´Â Á¦¿Ü. if( false == bFromParentProjectile ) { if( false == pPlayerActor->CheckAndEraseWeaponIDUsingProjectileSignal( nWeaponTableID ) ) { // TODO: ÇÙÀÌ´Ù! Á¢¼Ó ²÷¾î¹ö·ÈÀ¸¸é ÁÁ°Ú´Âµ¥.. #ifndef _FINAL_BUILD OutputDebug( "CDnProjectile::CreatePlayerProjectileFromClientPacket(): ÇöÀç ¾×¼Ç¿¡ ÀÖ´Â ¹ß»çü ½Ã±×³Î¿¡¼­ »ç¿ëÇÏÁö ¾Ê´Â ¹«±â Å×À̺í À妽º. ÇÙÀÔ´Ï´Ù.\n" ); #endif // #ifndef _FINAL_BUILD return NULL; } } pProjectile->CDnWeapon::Initialize( nWeaponTableID, 0 ); pProjectile->CDnWeapon::CreateObject(); } } #ifdef PRE_MOD_PROJECTILE_HACK nWeaponLength = pProjectile->GetWeaponLength(); if( pShooterStruct->bIncludeMainWeaponLength && hShooter->GetWeapon(0) ) nWeaponLength += hShooter->GetWeapon(0)->GetWeaponLength(); if( hShooter->IsProcessSkill() ) nWeaponLength += hShooter->GetProcessSkill()->GetIncreaseRange(); if( hShooter->IsEnabledToggleSkill() ) nWeaponLength += hShooter->GetEnabledToggleSkill()->GetIncreaseRange(); #endif pProjectile->SetWeaponLength( nWeaponLength ); pProjectile->SetWeaponType( (CDnWeapon::WeaponTypeEnum)( pProjectile->GetWeaponType() | CDnWeapon::Projectile ) ); pProjectile->SetSpeed( fSpeed ); switch( OrbitType ) { case CDnProjectile::Acceleration: pProjectile->SetResistance( fResistance ); break; } switch( TargetType ) { case CDnProjectile::TargetPosition: case CDnProjectile::Target: case CDnProjectile::DestPosition: pProjectile->SetTargetPosition( vTargetPos ); pProjectile->SetTargetActor( CDnActor::FindActorFromUniqueID( pPlayerActor->GetRoom(), dwTargetUniqueID ), false ); ////////////////////////////////////////////////////////////////////////// //¸ñÇ¥ ÁöÁ¡À¸·Î ³¯¾Æ °¡´Â ¹ß»çüÀÎ °æ¿ì ÇöÀç ¹ß»çü À§Ä¡¿¡¼­ ¸ñÇ¥ ÁöÁ¡À¸·ÎÀÇ ¹æÇâ º¤ÅÍ º¯°æ ÇØ¾ß ÇÑ´Ù. //ÀÏ´Ü ³«ÀÎ¿ë ¹ß»çü¿¡¼­¸¸ µ¿ÀÛ Çϵµ·Ï ¼öÁ¤ÇÑ´Ù. if (pShooterStruct->nTargetStateIndex != 0) { Cross.m_vZAxis = vTargetPos - Cross.GetPosition(); EtVec3Normalize( &Cross.m_vZAxis, &Cross.m_vZAxis ); } ////////////////////////////////////////////////////////////////////////// break; } pProjectile->Initialize( Cross, OrbitType, DestroyType, TargetType ); pProjectile->SetValidTime( nValidTime ); pProjectile->SetVelocityType( (CDnProjectile::VelocityTypeEnum)VelocityType ); pProjectile->SetProjectileOrbitRotateZ( fProjectileOrbitRotateZ ); pProjectile->SetTraceHitTarget( bTraceHitTarget, bTraceHitActorHittable ); // Note: Ŭ¶óÀÌ¾ðÆ®¿¡¼­ ½ºÅ³À» ½èÀ» ¶§¸¸ nActionIndex °¡ ¼ÂÆÃµÇ¾î ÆÐŶÀ¸·Î ³¯¶ó¿È. // pProjectileStruct °¡ NULL ÀÎ °æ¿ì¿£ Ŭ¶ó¿Í ¼­¹öÀÇ nSignalIndex °¡ ÀÏÄ¡ÇÏÁö ¾Ê¾Æ¼­ÀÓ. // Áï, ¼­¹ö/Ŭ¶ó°£ÀÇ action ÆÄÀÏ ¸®¼Ò½º°¡ ´Ù¸£´Ù´Â ÀǹÌ. if( pProjectileStruct && -1 != nSignalIndex && -1 != nActionIndex ) pPlayerActor->OnProjectile( pProjectile, pProjectileStruct, Cross, nSignalIndex ); if( bFromParentProjectile ) { pProjectile->SetShooterStateSnapshot( pParentProjectile->GetShooterStateSnapshot() ); pProjectile->SetParentSkill( hParentSkill ); #ifdef PRE_ADD_PROJECTILE_SE_INFO pProjectile->SetShooterStateBlow( pParentProjectile->GetShooterStateBlow() ); #endif //¹ß»çü¿¡¼­ ¹ß»çü¸¦ ½î´Â °æ¿ì ºÎ¸ð ¹ß»çü¿¡ ÀÖ´ø »óÅÂÈ¿°úµéÀ» µî·ÏÇÑ´Ù.. pProjectile->ApplyParentProjectile(pParentProjectile); //¹ß»çü -> ¹ß»çü ¹ß»ç ÇÒ¶§ ½ºÅ³¿¡ ÀÇÇÑ ¹ß»çüÀÎÁö ºÎ¸ð ¹ß»çü¿¡¼­ Á¤º¸¸¦ ¹Þ¾Æ¼­ ¼³Á¤ ÇØÁà¾ß ÇÔ. pProjectile->FromSkill(pParentProjectile->IsFromSkill()); #if defined(PRE_FIX_65287) pProjectile->SetShooterFinalDamageRate(pParentProjectile->GetShooterFinalDamageRate()); #endif // PRE_FIX_65287 } else { bool bApplyStateBlowInfo = pProjectileStruct->bApplyStateBlowInfo == TRUE; #if defined( PRE_FIX_PROJECTILE_PREFIX_APPLY_POINT ) if( hShooter && hShooter->IsPlayerActor() ) { if( hShooter->IsAppliedThisStateBlow(STATE_BLOW::BLOW_183) == false ) { hShooter->ProcessPrefixOffenceSkill_New(); if( hShooter->IsApplyPrefixOffenceSkill() ) bApplyStateBlowInfo = true; } } #endif // ½ºÅ³ÀÌ´ø ÀÏ¹Ý ÆòŸÀÌ´ø Ç÷¹À̾î´Â ´É·ÂÄ¡ ¼ÂÆÃ ÇÊ¿äÇÔ. (#17829) boost::shared_ptr pActorStateSnapshot( new CDnState ); *pActorStateSnapshot = *static_cast( pPlayerActor ); pProjectile->SetShooterStateSnapshot( pActorStateSnapshot ); #ifdef PRE_ADD_PROJECTILE_SE_INFO if( bApplyStateBlowInfo == true ) { boost::shared_ptr pActorStateBlow = boost::shared_ptr(new CDnStateBlow(pPlayerActor->GetMySmartPtr())); pActorStateBlow->MakeCloneStateBlowList( pPlayerActor->GetStateBlow()->GetStateBlowList() ); pProjectile->SetShooterStateBlow( pActorStateBlow ); } #endif #if defined(PRE_FIX_65287) float fFinalDamageRate = 0.0f; if (pPlayerActor && pPlayerActor->IsAppliedThisStateBlow(STATE_BLOW::BLOW_050)) { DNVector(DnBlowHandle) vlhBlows; pPlayerActor->GatherAppliedStateBlowByBlowIndex( STATE_BLOW::BLOW_050, vlhBlows ); int iNumBlow = (int)vlhBlows.size(); for( int i = 0; i < iNumBlow; ++i ) { fFinalDamageRate += vlhBlows[i]->GetFloatValue(); } } pProjectile->SetShooterFinalDamageRate(fFinalDamageRate); #endif // PRE_FIX_65287 // #30571 ÇöÀç Çϰí ÀÖ´Â ½ºÅ³ ¾×¼Ç¿¡¼­ ¹ß»çµÈ ¹ß»çü¿¡¼­¸¸ È£ÃâÇØÁØ´Ù. // else À§ ±¸¹®ÀÇ ¹ß»çü¿¡¼­ ¹ß»çü¸¦ ½î´Â °æ¿ì¿£ ÃßÈÄ¿¡ ¹ß»çü¿¡¼­ ¹ß»çü°¡ // ¹ß»çµÉ ¶§ Ŭ¶ó¿¡¼­ ÆÐŶÀÌ ¶Ç ¿À¹Ç·Î ¿©±â¼­ ±¸ºÐÇØÁ־ È£ÃâÇØÁà¾ß ÇÑ´Ù. hShooter->OnSkillProjectile( pProjectile ); } #if defined(PRE_FIX_52329) pProjectile->SetIgnoreHitType(nIgnoreHitType); #endif // PRE_FIX_52329 #if defined(PRE_ADD_55295) pProjectile->SetHitActionVectorInit(bHitActionVectorInit); #endif // PRE_FIX_52329 pProjectile->PostInitialize(); return pProjectile; } // »ý¼ºµÈ ¹ß»çü °´Ã¼¿¡¼­ ÆÐŶÀ» ¸¸µç´Ù. // Ŭ¶óÀÌ¾ðÆ®¿Í ¿ÏÀüÈ÷ µ¿ÀÏÇÑ ·çƾÀ̾î¾ß ÇÔ. (ÀÌ ÆÄÀÏ ÀÚü´Â Ŭ¶ó/¼­¹ö ºÐ¸® µÇ¾îÀÖÀ¸¹Ç·Î ÁÖÀÇ) CPacketCompressStream* CDnProjectile::GetPacketStream( void ) { if( !m_hShooter ) return NULL; // óÀ½ ¿äû µé¾î¿Â °ÍÀÌ¶ó °´Ã¼¶ó ¾ø´Ù¸é ÆÐŶ ½ºÆ®¸² ¸¸µé¾î ÁÜ. // Çѹø ¸¸µç ÀÌÈÄ¿£ ¹ß»çü °´Ã¼ÀÇ ³»¿ëÀÌ ¹Ù²î¾îµµ ¹Ý¿µµÇÁö ¾ÊÀ¸¹Ç·Î ÁÖÀÇ. // ÇöÀç Create µÈ ÈÄ »ý¼ºµÈ ¹ß»çüÀÇ ³»¿ëÀ» ¹Ù²Ù´Â °æ¿ì´Â ¾ø´Ù. if( NULL == m_pPacketStream ) { m_pPacketBuffer = new char[ PROJECTILE_PACKET_BUFFER_SIZE ]; m_pPacketStream = new CPacketCompressStream( m_pPacketBuffer, PROJECTILE_PACKET_BUFFER_SIZE*sizeof(char) ); bool bActorAttachWeapon = false; int VelocityType = 0; int nValidTime = 0; float fValue; if( m_hShooter->GetWeapon(1) && this->GetClassID() == m_hShooter->GetWeapon(1)->GetClassID() ) bActorAttachWeapon = true; DWORD dwGap = 0; m_pPacketStream->Write( &dwGap, sizeof(DWORD) ); // ¼­¹ö¿¡¼­ º¸³»´Â °ÍÀ̹ǷΠó¸®ÇÒ ÇÊ¿ä ¾øÀ½. m_pPacketStream->Write( &bActorAttachWeapon, sizeof(bool) ); int nValue = 0; DWORD dwValue = this->GetUniqueID(); m_pPacketStream->Write( &dwValue, sizeof(DWORD) ); if( bActorAttachWeapon == false ) { nValue = this->GetClassID(); m_pPacketStream->Write( &nValue, sizeof(int) ); } m_pPacketStream->Write( &this->GetMatEx()->m_vPosition, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); m_pPacketStream->Write( &this->GetMatEx()->m_vXAxis, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT ); m_pPacketStream->Write( &this->GetMatEx()->m_vYAxis, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT ); m_pPacketStream->Write( &this->GetMatEx()->m_vZAxis, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT ); #ifdef PRE_MOD_PROJECTILE_HACK DWORD dwShooterUniqueID = m_hShooter->GetUniqueID(); m_pPacketStream->Write( &m_cShooterType, sizeof(char) ); m_pPacketStream->Write( &dwShooterUniqueID, sizeof(DWORD) ); switch( m_cShooterType ) { case 0: break; case 1: { bool bSendSerialID = ( m_nShooterSerialID == -1 ) ? false : true; m_pPacketStream->Write( &bSendSerialID, sizeof(bool) ); if( bSendSerialID ) m_pPacketStream->Write( &m_nShooterSerialID, sizeof(INT64) ); else m_pPacketStream->Write( &m_dwShooterUniqueID, sizeof(DWORD) ); } break; } m_pPacketStream->Write( &m_nShooterActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); m_pPacketStream->Write( &m_nShooterSignalIndex, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); #else nValue = (int)this->GetOrbitType(); m_pPacketStream->Write( &nValue, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); nValue = (int)this->GetDestroyOrbitType(); m_pPacketStream->Write( &nValue, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); nValue = (int)this->GetTargetType(); m_pPacketStream->Write( &nValue, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); nValidTime = this->GetValidTime(); m_pPacketStream->Write( &nValidTime, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); nValue = this->GetWeaponLength(); m_pPacketStream->Write( &nValue, sizeof(int) ); fValue = this->GetProjectileOrbitRotateZ(); m_pPacketStream->Write( &fValue, sizeof(float) ); #endif m_pPacketStream->Write(&m_nTargetPartsIndex, sizeof(int)); m_pPacketStream->Write(&m_nTargetPartsBoneIndex, sizeof(int)); switch( this->GetTargetType() ) { case CDnProjectile::CrossHair: case CDnProjectile::Direction: break; case CDnProjectile::TargetPosition: case CDnProjectile::Target: case CDnProjectile::DestPosition: case CDnProjectile::Shooter: { m_pPacketStream->Write( this->GetTargetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); DWORD dwUniqueID = ( this->GetTargetActor() ) ? this->GetTargetActor()->GetUniqueID() : -1; m_pPacketStream->Write( &dwUniqueID, sizeof(DWORD) ); } break; } fValue = this->GetSpeed(); m_pPacketStream->Write( &fValue, sizeof(float) ); #ifdef PRE_MOD_PROJECTILE_HACK int nActionIndex = -1; if( m_hShooter->GetProcessSkill() ) nActionIndex = m_hShooter->GetCurrentActionIndex(); m_pPacketStream->Write( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); #else bool bPierce = this->GetPierce(); m_pPacketStream->Write( &bPierce, sizeof(bool) ); if( bPierce ) { int nMaxHitCount = this->GetMaxHitCount(); m_pPacketStream->Write( &nMaxHitCount, sizeof(int) ); } bool bTraceHitTarget = this->IsTraceHitTarget(); bool bTraceHitActorHittable = this->IsTraceHitActorHittable(); m_pPacketStream->Write( &bTraceHitTarget, sizeof(bool) ); m_pPacketStream->Write( &bTraceHitActorHittable, sizeof(bool) ); VelocityType = (int)this->GetVelocityType(); switch( this->GetOrbitType() ) { case CDnProjectile::Linear: case CDnProjectile::TerrainLinear: break; case CDnProjectile::Projectile: m_pPacketStream->Write( &VelocityType, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); break; case CDnProjectile::Homing: case CDnProjectile::TerrainHoming: m_pPacketStream->Write( &VelocityType, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); break; case CDnProjectile::Acceleration: fValue = this->GetResistance(); m_pPacketStream->Write( &fValue, sizeof(float), CPacketCompressStream::FLOAT_SHORT, 1.f ); break; } // ¾Æ·¡ ÀÌÇÏ´Â ¸ó½ºÅÍ¿¡¼­ »ç¿ëÇÏÁö ¾Ê´Â´Ù. int nActionIndex = -1; if( m_hShooter->GetProcessSkill() ) nActionIndex = m_hShooter->GetCurrentActionIndex(); m_pPacketStream->Write( &nActionIndex, sizeof(int) ); // Note : üÀÎ °ø°Ý »óÅÂÈ¿°ú¸¦ À§ÇØ ½Ã±×³Î struct ¸¦ ãÀ» ¼ö ÀÖ´Â index °¡ ÇÊ¿äÇÔ. m_pPacketStream->Write( &m_iSignalArrayIndex, sizeof(int) ); // º¸¿ì ¸¶½ºÅÍÀÇ ·¹º¼·ç¼Å³Ê¸® ¹ß¸®½ºÅ¸ °°Àº ¹ß»çü¾î¼­ ¹ß»çü ½î´Â ½ºÅ³¿¡¼­ ÃÖÃÊ·Î ³ª°£ ¹ß»çü¿¡¼­ // ´É·ÂÄ¡¸¦ ÀÌÀüÇϱâ À§ÇÑ Á¤º¸... // Ŭ¶ó¿¡¼­ ¼­¹ö·Î º¸³»´Â °ÍÀ¸·Î ¼­¹ö¿¡¼­ Ŭ¶ó·Î º¸³¾ ÀÏÀº ¾ø´Ù. // Çü½ÄÀ» ¸ÂÃß±â À§ÇØ ½áÁØ´Ù. DWORD dwParentID = UINT_MAX;//this->GetParentProjectileID(); DWORD dwParentShooterUniqueID = m_hShooter->GetUniqueID(); m_pPacketStream->Write( &dwParentID, sizeof(DWORD) ); m_pPacketStream->Write( &dwParentShooterUniqueID, sizeof(DWORD) ); #endif #if defined(PRE_FIX_52329) m_pPacketStream->Write( &m_nIgnoreHitType, sizeof(m_nIgnoreHitType)); #endif // PRE_FIX_52329 } return m_pPacketStream; } void CDnProjectile::SetShooterType( DnActorHandle hActor, int nActionIndex, int nSignalIndex ) { m_cShooterType = 0; m_dwShooterUniqueID = hActor->GetUniqueID(); m_nShooterActionIndex = nActionIndex; m_nShooterSignalIndex = nSignalIndex; } void CDnProjectile::SetShooterType( DnWeaponHandle hWeapon, int nActionIndex, int nSignalIndex ) { m_cShooterType = 1; m_dwShooterUniqueID = -1; m_nShooterSerialID = -1; if( hWeapon->GetSerialID() == -1 ) m_dwShooterUniqueID = hWeapon->GetUniqueID(); else m_nShooterSerialID = hWeapon->GetSerialID(); m_nShooterActionIndex = nActionIndex; m_nShooterSignalIndex = nSignalIndex; } void CDnProjectile::ApplyParentProjectile(CDnProjectile* pParentProjectile) { if (pParentProjectile == NULL) return; const std::vector& stateEffectList = pParentProjectile->GetStateEffectList(); if (stateEffectList.empty()) return; int nStateEffectCount = (int)stateEffectList.size(); for (int i = 0; i < nStateEffectCount; ++i) { CDnSkill::StateEffectStruct& stateEffect = const_cast(stateEffectList.at(i)); if( stateEffect.ApplyType == CDnSkill::ApplySelf ) continue; this->AddStateEffect( stateEffect ); } } void CDnProjectile::SetTargetActor( DnActorHandle hActor, bool bUpdateTargetPartsIndex/* = true*/ ) { m_hTargetActor = hActor; if (bUpdateTargetPartsIndex) UpdateTargetPartsIndex(); } void CDnProjectile::UpdateTargetPartsIndex() { int nSelectPartsIndex = -1; int nSelectBoneIndex = -1; //ÆÄÃ÷ ¸ó½ºÅÍ ÀÏ °æ¿ì ÇØ´ç ÆÄÃ÷¸¦ ¼±ÅÃ ÇØ¾ß ÇÑ´Ù.. if (m_hTargetActor && m_hTargetActor->IsMonsterActor()) { if( m_hTargetActor->IsPartsMonsterActor() ) { CDnPartsMonsterActor* pPartsMonsterActor = static_cast(m_hTargetActor.GetPointer()); int nCount = pPartsMonsterActor->GetPartsSize(); //¼±Åð¡´ÉÇÑ Parts Index¸¦ ÀúÀå ÇØ³õ´Â´Ù.. struct SelectPartsInfo { int PartsIndex; int BoneCount; }; std::vector indexList; for (int i = 0; i < nCount; ++i) { MonsterParts* pMonsterParts = pPartsMonsterActor->GetPartsByIndex(i); if (pMonsterParts == NULL) continue; const MonsterParts::_Info& boneInfo = pMonsterParts->GetPartsInfo(); if (boneInfo.PartsState != MonsterParts::ePartsState::eNormal) continue; //°¡´ÉÇÑ parts À妽º¿Í ÀÌ PartsÀÇ bone °¹¼ö¸¦ ´ã¾Æ ³õ´Â´Ù. SelectPartsInfo _tempInfo; _tempInfo.PartsIndex = i; _tempInfo.BoneCount = (int)boneInfo.vParts.size(); indexList.push_back(_tempInfo); } int nListCount = (int)indexList.size(); if (nListCount > 0) { //´ã±ä ÆÄÃ÷µé Áß¿¡¼­ Çϳª¸¦ ¼±ÅÃÇÑ´Ù.. int nIndex = rand() % nListCount; SelectPartsInfo &tempPartsInfo = indexList[nIndex]; nSelectPartsIndex = tempPartsInfo.PartsIndex; //¼±ÅÃµÈ ÆÄÃ÷Áß º» Çϳª¸¦ ¼±Åà ÇÑ´Ù. nSelectBoneIndex = rand() % tempPartsInfo.BoneCount; } } } SetTargetPartsIndex(nSelectPartsIndex, nSelectBoneIndex); } bool CDnProjectile::SetTraceActor( DnActorHandle hActor, bool bValidDamageGoOn ) { bool bValidDamageGoOnResult = bValidDamageGoOn; // µû¶ó°¡´Â ¹ß»çüÀÇ °æ¿ì damage ¸¦ hit »óÅ¿¡¼­ °è¼Ó ÁÙ ¼ö Àֱ⠶§¹®¿¡ valid damage ¸¦ ÄÑÁØ´Ù. #22666 // shoot ¾×¼ÇÀÏ ¶§ Çѹø¸¸ ¼ÂÆÃµÇ¸é µÊ. if( m_nActionIndex == m_iShootActionIndex && m_bTraceHitTarget && hActor && !m_hTraceActor ) { bValidDamageGoOn = true; m_hTraceActor = hActor; // ÃßÀû ¹ß»çü°¡ µÇ¸é hit ¾×¼Ç ³¡³¯ ¶§ ±îÁö ½Ã°£°ú ¹«°üÇÏ°Ô »ç¶óÁöÁö ¾Ê´Â´Ù. m_ValidType = (ValidTypeEnum)( m_ValidType & ~Time ); } return bValidDamageGoOnResult; } void CDnProjectile::GetChainAttackInfo(const CDnSkill::StateEffectStruct& stateEffectStruct, float& fRange, int& nMaxCount) { switch(stateEffectStruct.nID) { case STATE_BLOW::BLOW_060: { std::string str = stateEffectStruct.szValue; std::vector tokens; std::string delimiters = ";"; //1. ±¸ºÐ TokenizeA(str, tokens, delimiters); if (tokens.size() != 3) fRange = 1000.0f; else { fRange = (float)atoi(tokens[0].c_str()); nMaxCount = atoi(tokens[1].c_str()); } } break; case STATE_BLOW::BLOW_208: { std::string str = stateEffectStruct.szValue;//"ÃÖ´ëÈ÷Æ®¼ö;¹üÀ§(cm);ºñÀ²"; std::vector tokens; std::string delimiters = ";"; //1. ±¸ºÐ TokenizeA(str, tokens, delimiters); if (tokens.size() != 3) fRange = 1000.0f; else { nMaxCount = atoi(tokens[0].c_str()); fRange = (float)atoi(tokens[1].c_str()); } } break; } } DnActorHandle CDnProjectile::FindNextChainActor(int iRootAttackerTeam, DnActorHandle hActor, DnActorHandle hPrevActor, float fRange) { DNVector(DnActorHandle) vlActorsInRange; CDnActor::ScanActor( hActor->GetRoom(), *hActor->GetPosition(), fRange, vlActorsInRange ); float fShortestDistanceSQ = FLT_MAX; DnActorHandle hActorToAttack; DWORD dwNumActors = (DWORD)vlActorsInRange.size(); for( DWORD dwActor = 0; dwActor < dwNumActors; ++dwActor ) { DnActorHandle hTargetActor = vlActorsInRange.at( dwActor ); if (!hTargetActor) continue; if( false == (hTargetActor->IsShow() && hTargetActor->IsProcess()) ) continue; //Á×Àº ³à¼®Àº ½ºÅµ... if (hTargetActor->IsDie()) continue; // Á÷Àü¿¡ ³ª¿¡°Ô »óÅÂÈ¿°ú ³Ñ°ÜÁá´ø ¾×ÅÍÇÑÅ×´Â ´Ù½Ã ÁÖÁö ¾Ê´Â´Ù. if( hPrevActor != hTargetActor ) { // #30643 ³ª À̿ܿ£ ´Ù ÀûÀÌ´Ù~~~ if( iRootAttackerTeam != hTargetActor->GetTeam() && hTargetActor != hActor ) { EtVector3 vDistance = (*hActor->GetPosition()) - (*hTargetActor->GetPosition()); float fLengthSQ = EtVec3LengthSq( &vDistance ); if( fLengthSQ < fShortestDistanceSQ ) { fShortestDistanceSQ = fLengthSQ; hActorToAttack = hTargetActor; } } } } return hActorToAttack; } void CDnProjectile::CreateChainAttackProjectile(DnActorHandle hRootAttacker, DnActorHandle hActor, DnActorHandle hActorToAttack, ProjectileStruct* pProjectileSignalInfo, CDnSkill::SkillInfo& parentSkillInfo) { // ÇÁ·ÎÁ§Å¸ÀÏ ¹ß»ç °ü·Ã ±âŸ ¼³Á¤µé. DnSkillHandle hSkill = hRootAttacker->FindSkill( parentSkillInfo.iSkillID ); // È£¹ÖÀ¸·Î Ÿ°ÙÀ» ¼³Á¤Åä·Ï Á¤ÇØÁØ´Ù. pProjectileSignalInfo->nOrbitType = CDnProjectile::Homing; pProjectileSignalInfo->nTargetType = CDnProjectile::Target; pProjectileSignalInfo->VelocityType = CDnProjectile::Accell; pProjectileSignalInfo->fSpeed = 1000.0f;//CHAINATTACK_PROJECTILE_SPEED; pProjectileSignalInfo->nValidTime = 5000; MatrixEx Cross = *hActor->GetMatEx(); Cross.m_vPosition.y += hActor->GetHeight() / 2.0f; CDnProjectile *pProjectile = new CDnProjectile( GetRoom(), hRootAttacker ); pProjectile->SetPierce( pProjectileSignalInfo->bPierce == TRUE ? true : false ); pProjectile->SetMaxHitCount( pProjectileSignalInfo->nMaxHitCount ); if( pProjectileSignalInfo->nWeaponTableID > 0 ) { if( pProjectileSignalInfo->nProjectileIndex != -1 ) { DnWeaponHandle hWeapon = CDnWeapon::GetSmartPtr( (CMultiRoom*)g_pGameServerManager->GetRootRoom(), pProjectileSignalInfo->nProjectileIndex ); if( hWeapon ) *(CDnWeapon*)pProjectile = *hWeapon.GetPointer(); } } int nLength = pProjectile->GetWeaponLength(); if( pProjectileSignalInfo->bIncludeMainWeaponLength ) { DnWeaponHandle hWeapon = hActor->GetWeapon(0); if ( hWeapon ) nLength += hWeapon->GetWeaponLength(); } pProjectile->SetWeaponLength( nLength ); pProjectile->SetWeaponType( (CDnWeapon::WeaponTypeEnum)( pProjectile->GetWeaponType() | CDnWeapon::Projectile ) ); pProjectile->SetSpeed( pProjectileSignalInfo->fSpeed ); pProjectile->SetTargetPosition( *hActorToAttack->GetPosition() ); pProjectile->SetTargetActor( hActorToAttack ); pProjectile->Initialize( Cross, static_cast(pProjectileSignalInfo->nOrbitType), static_cast(pProjectileSignalInfo->nDestroyOrbitType), static_cast(pProjectileSignalInfo->nTargetType) ); pProjectile->SetValidTime( pProjectileSignalInfo->nValidTime ); pProjectile->SetVelocityType( static_cast(pProjectileSignalInfo->VelocityType) ); pProjectile->SetParentSkill( hSkill ); parentSkillInfo.hPrevAttacker = hActor; parentSkillInfo.iLeaveCount -= 1; // ¼³Á¤µÇ¾îÀÖ´Â Ä«¿îÆ® Çϳª¾¿ ÁÙÀδÙ. pProjectile->SetParentSkillInfo( parentSkillInfo ); pProjectile->FromSkill( true ); CDnState rootAttackerState; int iNumSE = hSkill->GetStateEffectCount(); for( int i = 0; i < iNumSE; ++i ) { const CDnSkill::StateEffectStruct* pStateEffect = hSkill->GetStateEffectFromIndex( i ); if( pStateEffect->ApplyType == CDnSkill::ApplySelf ) continue; CDnSkill::StateEffectStruct SE = *pStateEffect; pProjectile->AddStateEffect( SE ); } //#45331 //¹ß»çü°¡ »ý¼ºµÉ ½ÃÁ¡¿¡ ÀúÀåµÇ¾î ÀÖ´ø ¾×ÅÍÀÇ »óŰªÀ» ±×´ë·Î Àü´Þ ÇØÁØ´Ù. pProjectile->SetShooterStateSnapshot( m_pShooterState ); #if defined(PRE_FIX_65287) pProjectile->SetShooterFinalDamageRate(m_fShooterFinalDamageRate); #endif // PRE_FIX_65287 pProjectile->PostInitialize(); } #if defined(PRE_ADD_55295) void CDnProjectile::ChangeProjectileRotation() { //¹æÇâÀº ±×´ë·Î µÎ°í, YÃุ ´Ù½Ã ¼³Á¤À» À§ÇØ, YÃàÀº ÃʱâÈ­ ÇØ¼­ //X, Z¹æÇâ º¤ÅÍ ´Ù½Ã °è»ê m_Cross.m_vYAxis = EtVector3(0.0f, 1.0f, 0.0f); m_Cross.MakeUpCartesianByYAxis(); } #endif // PRE_ADD_55295 #if defined(PRE_FIX_59238) void CDnProjectile::AddHittedActor(DnActorHandle hHittedActor) { if (hHittedActor) m_HittedActorList.insert(std::make_pair(hHittedActor->GetUniqueID(), hHittedActor)); } bool CDnProjectile::IsHittable(DnActorHandle hActor) { //¸ÕÀú ¾×ÅÍ À¯È¿¼º È®ÀÎ.. if (!hActor) return false; bool isSummonMonster = false; bool isOwnerActor = false; //²ÀµÎ°¢½Ã »óÅÂÈ¿°ú°¡ ÀÖ´Â ÁÖÀξ×ÅÍ ÀÎÁö.. if (hActor->IsAppliedThisStateBlow(STATE_BLOW::BLOW_247)) { isOwnerActor = true; } //¼Òȯ ¸ó½ºÅÍÀÎÁö... else if (hActor->IsMonsterActor()) { CDnMonsterActor* pMonsterActor = static_cast(hActor.GetPointer()); if (pMonsterActor && pMonsterActor->IsSummonedMonster() && pMonsterActor->IsPuppetSummonMonster()) isSummonMonster = true; } //¼Òȯ ¸ó½ºÅ͵µ ¾Æ´Ï°í, ²ÀµÎ°¢½Ã »óÅÂÈ¿°ú¸¦ °¡Áø ¾×Å͵µ ¾Æ´Ï¶ó¸é È÷Æ® °¡´É.. //¼Òȯ ¸ó½ºÅÍÀ̰í, ²ÀµÎ°¢½Ã »óÅÂÈ¿°ú¸¦ °¡Áø ¾×ÅͶó¸é ¹º°¡ ¹®Á¦ ÀÖÀ½..(±×³É È÷Æ® °¡´É Çϵµ·Ï...) if ((isSummonMonster == false && isOwnerActor == false) || (isSummonMonster == true && isOwnerActor == true)) return true; //²ÀµÎ°¢½Ã »óÅÂÈ¿°ú¸¦ °¡Áø ¾×ÅͶó¸é ÀÌ¹Ì È÷Æ®µÈ ¾×ÅÍ ¸®½ºÆ®¿¡¼­ ÀÚ½ÅÀÌ ¼ÒȯÇÑ ¼Òȯ ¸ó½ºÅÍ ¾×ÅͰ¡ //Æ÷ÇԵǾî ÀÖ´Ù¸é ÀÚ½ÅÀº È÷Æ® µÇÁö ¾Ê¾Æ¾ß ÇÑ´Ù. if (isOwnerActor == true) { //ÀÚ½ÅÀÇ ¼Òȯ ¸ó½ºÅÍ ¸®½ºÆ® const std::list & listSummonMonster = hActor->GetSummonedMonsterList(); std::list::const_iterator iter = listSummonMonster.begin(); for( iter; iter != listSummonMonster.end(); ++iter ) { DnMonsterActorHandle hMonster = (*iter); if (!hMonster) continue; //¼Òȯ ¸ó½ºÅͰ¡ ¾Æ´Ï°í, PuppetSummon¸ó½ºÅͰ¡ ¾Æ´Ï¸é ½ºÅµ if (hMonster->IsSummonedMonster() == false || hMonster->IsPuppetSummonMonster() == false) continue; //¼ÒȯÇÑ ¸ó½ºÅͰ¡ ÀÌ¹Ì È÷Æ® ¸®½ºÆ®¿¡ ÀÖ´Ù¸é ÀÚ½ÅÀº È÷Æ® µÇÁö ¾Ê¾Æ¾ß ÇÑ´Ù. std::map::iterator iter = m_HittedActorList.find(hMonster->GetUniqueID()); if (iter != m_HittedActorList.end()) return false; } //ÀÚ½ÅÀÇ ¼Òȯ ±×·ì ¸ó½ºÅÍ ¸®½ºÆ® const std::map >& groupSummonMonster = hActor->GetGroupingSummonedMonsterList(); std::map >::const_iterator mapIter; for (mapIter = groupSummonMonster.begin(); mapIter != groupSummonMonster.end(); ++mapIter) { const std::list & listSummonMonster = mapIter->second; std::list::const_iterator iter = listSummonMonster.begin(); for (; iter != listSummonMonster.end(); ++iter) { DnMonsterActorHandle hMonster = (*iter); if (!hMonster) continue; //¼Òȯ ¸ó½ºÅͰ¡ ¾Æ´Ï°í, PuppetSummon¸ó½ºÅͰ¡ ¾Æ´Ï¸é ½ºÅµ if (hMonster->IsSummonedMonster() == false || hMonster->IsPuppetSummonMonster() == false) continue; //¼ÒȯÇÑ ¸ó½ºÅͰ¡ ÀÌ¹Ì È÷Æ® ¸®½ºÆ®¿¡ ÀÖ´Ù¸é ÀÚ½ÅÀº È÷Æ® µÇÁö ¾Ê¾Æ¾ß ÇÑ´Ù. std::map::iterator iter = m_HittedActorList.find(hMonster->GetUniqueID()); if (iter != m_HittedActorList.end()) return false; } } return true; } //¼Òȯ ¸ó½ºÅͶó¸é, ÀÌ¹Ì È÷Æ®µÈ ¾×ÅÍ ¸®½ºÆ®¿¡¼­ ÀÚ½ÅÀÇ ÁÖÀÎ ¾×ÅͰ¡ ÀÖ´Ù¸é È÷Æ® µÇÁö ¾Ê¾Æ¾ß ÇÑ´Ù. else if (isSummonMonster == true) { DnActorHandle hOwnerActor; CDnMonsterActor* pMonsterActor = static_cast(hActor.GetPointer()); if (pMonsterActor) hOwnerActor = pMonsterActor->GetSummonerPlayerActor(); //¼Òȯ ÁÖÀÎ ¾×ÅͰ¡ ²ÀµÎ°¢½Ã »óÅÂÈ¿°ú¸¦ °¡Áö°í ÀÖÁö ¾ÊÀ¸¸é È÷Æ®µÇ¾îµµ µÈ´Ù.. if (!hOwnerActor || hOwnerActor->IsAppliedThisStateBlow(STATE_BLOW::BLOW_247) == false) return true; //¼Òȯ ¸ó½ºÅÍÀÇ ÁÖÀÎ ¾×ÅͰ¡ ÀÌ¹Ì È÷Æ® ¸®½ºÆ®¿¡ Á¸Àç Çϸé ÀÌ ¾×ÅÍ´Â È÷Æ® µÇ¸é ¾ÈµÇ°í, //ÁÖÀÎ ¾×ÅͰ¡ È÷Æ® ¸®½ºÆ®¿¡ ¾øÀ¸¸é È÷Æ® µÇ¾î¾ßÇÔ. std::map::iterator iter = m_HittedActorList.find(hOwnerActor->GetUniqueID()); if (iter != m_HittedActorList.end()) return false; else return true; } return true; } #endif // PRE_FIX_59238 #if defined(PRE_FIX_59336) void CDnProjectile::ApplyComboLimitStateEffect( DnActorHandle hActor ) { for( DWORD i= 0 ; i < m_ComboLimitStateEffectList.size(); i++ ) { const CDnSkill::StateEffectStruct& SE = m_ComboLimitStateEffectList.at(i); if (m_HitStruct.szSkipStateBlows && CDnSkill::IsSkipStateBlow(m_HitStruct.szSkipStateBlows, (STATE_BLOW::emBLOW_INDEX)SE.nID)) continue; // ¾Æ±º±îÁö Èú ½ÃÄÑÁÖ´Â ½ºÅ³ÀÇ °æ¿ì¿£ Self Èú°ú Target Èú µÎ °³ÀÇ »óÅÂÈ¿°ú°¡ ¼±¾ðµÇ¾îÀÖµû. // Self »óÅÂÈ¿°ú´Â Àڽſ¡°Ô ÀÌ¹Ì Àû¿ëµÇ¾ú°í ¿©±ä Hit ½Ã±×³Î ÆÇÁ¤µÇ´Â °÷ÀÌ±â ‹š¹®¿¡ Target ¸¸ Àû¿ëµÈ´Ù. switch( SE.ApplyType ) { case CDnSkill::ApplySelf: continue; break; case CDnSkill::ApplyTarget: break; case CDnSkill::ApplyEnemy: if( m_hShooter->GetTeam() == hActor->GetTeam() ) continue; break; case CDnSkill::ApplyFriend: if( m_hShooter->GetTeam() != hActor->GetTeam() ) continue; break; } m_ParentSkillInfo.iProjectileShootActionIndex = m_iShooterShootActionIndex; m_ParentSkillInfo.iProjectileSignalArrayIndex = m_iSignalArrayIndex; //°°Àº ½ºÅ³ÀÇ °°Àº ½ÃÀÛ ½Ã°£ÀÌ ÀÖÀ¸¸é Ãß°¡ ¾ÈµÇµµ·Ï.. bool isExistSameSkillTimeBlow = false; DNVector(DnBlowHandle) vlAppliedBlows; hActor->GatherAppliedStateBlowByBlowIndex( (STATE_BLOW::emBLOW_INDEX)m_ComboLimitStateEffectList[i].nID, vlAppliedBlows ); int iNumAppliedBlow = (int)vlAppliedBlows.size(); for( int iAppliedBlow = 0; iAppliedBlow < iNumAppliedBlow; ++iAppliedBlow ) { DnBlowHandle hBlow = vlAppliedBlows.at( iAppliedBlow ); if (!hBlow) continue; CDnSkill::SkillInfo* pExistSkillInfo = const_cast(hBlow->GetParentSkillInfo()); ////////////////////////////////////////////////////////////////////////// // #56880 // ½ºÅ³ ½ÃÀÛ ½Ã°£ÀÌ °°ÀºÁöµµ È®ÀÎ ÇØ¾ß ÇÑ´Ù.. LOCAL_TIME parentSkillStartTime = 0; LOCAL_TIME nowBlowSkillStartTime = 0; parentSkillStartTime = GetSkillStartTime(); CDnComboDamageLimitBlow* pNowBlow = static_cast(hBlow.GetPointer()); if (pNowBlow) nowBlowSkillStartTime = pNowBlow->GetSkillStartTime(); ////////////////////////////////////////////////////////////////////////// if (pExistSkillInfo) { if (m_ParentSkillInfo.hSkillUser && m_ParentSkillInfo.hSkillUser == pExistSkillInfo->hSkillUser && //½ºÅ³ »ç¿ëÀÚ°¡ °°°í m_ParentSkillInfo.iSkillID == pExistSkillInfo->iSkillID && //½ºÅ³ÀÌ °°Àº°æ¿ì nowBlowSkillStartTime == parentSkillStartTime //½ºÅ³ ½ÃÀÛ ½Ã°£ÀÌ °°Àº °æ¿ì ) { isExistSameSkillTimeBlow = true; break; } } } int iID = -1; bool bCheckCanBegin = true; if (isExistSameSkillTimeBlow == false) { //¹ß»çü¿¡¼­ »óÅÂÈ¿°ú Ãß°¡ÇÒ¶§ ¹ß»çü ½ºÅ³ ½ÃÀÛ ½Ã°£À» ´ã¾Æ¼­ Àü´ÞÇÑ´Ù.. m_ParentSkillInfo.projectileSkillStartTime = GetSkillStartTime(); #ifdef PRE_FIX_REMOVE_STATE_EFFECT_PACKET // ¼­¹ö¿¡¼­¸¸ »ç¿ëÇÏ´Â ÇüÅÂÀ̱⶧¹®¿¡ ÆÐŶ½îÁö¾Ê½À´Ï´Ù. iID = hActor->CDnActor::CmdAddStateEffect( &m_ParentSkillInfo, (STATE_BLOW::emBLOW_INDEX)m_ComboLimitStateEffectList[i].nID, m_ComboLimitStateEffectList[i].nDurationTime, m_ComboLimitStateEffectList[i].szValue.c_str(), false, bCheckCanBegin ); #else iID = hActor->CmdAddStateEffect( &m_ParentSkillInfo, (STATE_BLOW::emBLOW_INDEX)m_ComboLimitStateEffectList[i].nID, m_ComboLimitStateEffectList[i].nDurationTime, m_ComboLimitStateEffectList[i].szValue.c_str(), false, bCheckCanBegin ); #endif //¹ß»çü ½Ã°£ ¸®¼Â.. m_ParentSkillInfo.projectileSkillStartTime = 0; } // Ãß°¡ÇÑ »óÅÂÈ¿°ú Áß¿¡ chain attack »óÅÂÈ¿°ú°¡ ÀÖ´Ù¸é ¹ß»çü °ü·Ã Á¤º¸µé ¼ÂÆÃÇØÁà¾ß ÇÑ´Ù. // ÇÎÆþ¹ã »óÅÂÈ¿°úµµ ¸¶Âù°¡Áö·Î Ãß°¡ÇØÁà¾ß ÇÔ. if( iID != -1 ) { DnBlowHandle hBlow = hActor->GetStateBlowFromID( iID ); //#56880 ¹ß»çü·Î »óÅÂÈ¿°ú Ãß°¡ µÉ¶§ 242»óÅÂÈ¿°ú Àΰæ¿ì ¹ß»çü ½ºÅ³ÀÇ ½ÃÀÛ ½Ã°£À» ¼³Á¤ÇÑ´Ù..?? if (m_ComboLimitStateEffectList[i].nID == STATE_BLOW::BLOW_242) { LOCAL_TIME skillStartTime = GetSkillStartTime(); DnBlowHandle hBlow = hActor->GetStateBlowFromID( iID ); if( hBlow ) { CDnComboDamageLimitBlow* pComboLimitBlow = static_cast( hBlow.GetPointer() ); if (pComboLimitBlow) pComboLimitBlow->SetSkillStartTime(skillStartTime); } } } } } #endif // PRE_FIX_59336 void CDnProjectile::ApplySkillStateEffect(DnActorHandle hActor) { if (!hActor) return; // ´ë»óÀÌ ¾óÀ½°¨¿Á »óÅÂÀ϶§´Â »óÅÂÈ¿°ú Àû¿ë ¹«½Ã if (hActor->IsAppliedThisStateBlow(STATE_BLOW::BLOW_149)) return; // ½ºÅ³ ´ë»ó ¼³Á¤ÀÌ ¾Æ±ºÀΰ¡ Ÿ°ÙÀΰ¡¿¡ µû¶ó »óÅÂÈ¿°ú Àû¿ëÀ» ±¸ºÐÇÑ´Ù. switch( m_ParentSkillInfo.eTargetType ) { case CDnSkill::Enemy: case CDnSkill::Self: if( m_hShooter->GetTeam() == hActor->GetTeam() ) return; break; case CDnSkill::Friend: case CDnSkill::Party: if( m_hShooter->GetTeam() != hActor->GetTeam() ) return; break; // ½ºÅ³ Àû¿ë ´ë»óÀÌ ¾Æ±º/Àû±º ÀüºÎ ´Ù ¶ó¸é »óÅÂÈ¿°ú Àû¿ë ÂÊ¿¡¼­ Àû¿ë ¿©ºÎ¸¦ ±¸ºÐÇØ¾ß ÇÑ´Ù. case CDnSkill::All: break; } // »óÅÂÀÌ»ó Add // ¾î¶² ½ºÅ³·Î ÀÎÇØ »ý¼ºµÈ Projectile À̶ó¸é, CDnSkill::CanApply eResult = CDnSkill::CanApply::Apply; map mapDuplicateResult; //½ºÅ³ ·¹º§¾÷¿¡ ÀÇÇØ ¹ß»çü ½ºÅ³ Á¤º¸°¡ InvalidµÉ ¼ö ÀÖ´Ù. //¹ß»çü ¾×ÅͰ¡ ÀÖ°í, ½ºÅ³ ID°¡ ¼³Á¤µÇ¾î Àִµ¥ ½ºÅ³ÀÌ InvalidÇÏ¸é ½ºÅ³ ´Ù½Ã ¼³Á¤ÇÑ´Ù. if (m_hShooter && m_ParentSkillInfo.iSkillID != 0 && !m_hParentSkill) { DnSkillHandle hSkill = m_hShooter->FindSkill(m_ParentSkillInfo.iSkillID); if (hSkill) SetParentSkill(hSkill); } if( m_hParentSkill ) { // ÇØ´ç ActorÀÇ Áö¼ÓÈ¿°ú ±¸ºÐ À妽º¸¦ ±¸ºÐÇÏ¿© ¼º°øÇÑ °æ¿ì¿¡ »óÅÂÀÌ»ó Ãß°¡ ½ÃÅ´. eResult = CDnSkill::CanApplySkillStateEffect( hActor, m_hParentSkill, mapDuplicateResult, true ); } if( CDnSkill::CanApply::Fail != eResult ) { for( DWORD i= 0 ; i < m_VecStateEffectList.size(); i++ ) { const CDnSkill::StateEffectStruct& SE = m_VecStateEffectList.at(i); if (m_HitStruct.szSkipStateBlows && CDnSkill::IsSkipStateBlow(m_HitStruct.szSkipStateBlows, (STATE_BLOW::emBLOW_INDEX)SE.nID)) continue; // ¾Æ±º±îÁö Èú ½ÃÄÑÁÖ´Â ½ºÅ³ÀÇ °æ¿ì¿£ Self Èú°ú Target Èú µÎ °³ÀÇ »óÅÂÈ¿°ú°¡ ¼±¾ðµÇ¾îÀÖµû. // Self »óÅÂÈ¿°ú´Â Àڽſ¡°Ô ÀÌ¹Ì Àû¿ëµÇ¾ú°í ¿©±ä Hit ½Ã±×³Î ÆÇÁ¤µÇ´Â °÷ÀÌ±â ‹š¹®¿¡ Target ¸¸ Àû¿ëµÈ´Ù. switch( SE.ApplyType ) { case CDnSkill::ApplySelf: continue; break; case CDnSkill::ApplyTarget: break; case CDnSkill::ApplyEnemy: if( m_hShooter->GetTeam() == hActor->GetTeam() ) continue; break; case CDnSkill::ApplyFriend: if( m_hShooter->GetTeam() != hActor->GetTeam() ) continue; break; } // °°Àº ½ºÅ³ ÁßøÀÏ °æ¿ì¿£ ½ºÅ³ È¿°ú Áß¿¡ È®·ü üũÇÏ´Â °ÍµéÀº ÀÌ¹Ì CanApplySkillStateEffect ¿¡¼­ È®·üüũµÇ°í // Åë°úµÈ »óÅÂÀÌ´Ù. µû¶ó¼­ ¿©±â¼± È®·ü üũ µÈ°ÇÁö È®ÀÎÇÏ°í µÈ°Å¶ó¸é ´Ù½Ã È®·ü üũ ¾ÈÇϵµ·Ï ÇÔ¼ö È£Ãâ ÇØÁØ´Ù. bool bAllowAddThisSE = true; bool bCheckCanBegin = true; if( CDnSkill::ApplyDuplicateSameSkill == eResult ) { map::iterator iter = mapDuplicateResult.find( m_VecStateEffectList[i].nID ); // ¸Ê¿¡ ¾ø´Â °æ¿ì ÇöÀç ¾×ÅͰ¡ »óÅÂÈ¿°ú¿¡ °É·ÁÀÖÁö ¾ÊÀ¸¹Ç·Î ±×³É Á¤»óÀûÀ¸·Î »óÅÂÈ¿°ú Ãß°¡ ·çƾ ½ÇÇà. if( mapDuplicateResult.end() != iter ) { // °°Àº ½ºÅ³ÀÇ È®·üÀÖ´Â »óÅÂÈ¿°ú°¡ ÇöÀç °É·ÁÀ־ CanAdd ¸¦ È£ÃâÇØº¸¾ÒÀ¸³ª ½ÇÆÐÇßÀ½. // ÀÌ·± °æ¿ì¿£ »óÅÂÈ¿°ú Ãß°¡ÇÏÁö ¾Ê´Â´Ù. if( false == (iter->second) ) bAllowAddThisSE = false; else // ÀÌ¹Ì CanAdd ¸¦ Åë°úÇÑ »óÅÂÀ̹ǷΠCmdAddStateEffect È£Ã⠽à µû·Î üũÇÏÁö ¾Êµµ·Ï ÇØÁØ´Ù. bCheckCanBegin = false; } } m_ParentSkillInfo.iProjectileShootActionIndex = m_iShooterShootActionIndex; m_ParentSkillInfo.iProjectileSignalArrayIndex = m_iSignalArrayIndex; if( bAllowAddThisSE ) { // #72931 ½ºÅ©¸®¸Ó ÀúÁÖ ÄðŸÀÓ °øÀ¯ ó¸® -> ³ªÁß¿¡ ÀÌ·±½ÄÀ¸·Î ¾²´Â°Å ¸¹¾ÆÁö¸é ÀϹÝÈ­ÇØ¾ßÇÔ bool bShareCurseCoolTime = false; if( m_VecStateEffectList[i].nID == STATE_BLOW::BLOW_244 ) { DNVector(DnBlowHandle) vlhBlows; hActor->GatherAppliedStateBlowByBlowIndex( STATE_BLOW::BLOW_244, vlhBlows ); if( static_cast( vlhBlows.size() ) > 0 ) { CDnCurseBlow* pDnCurseBlow = static_cast( vlhBlows[0].GetPointer() ); if( pDnCurseBlow ) { m_VecStateEffectList[i].szValue += ";"; m_VecStateEffectList[i].szValue += FormatA( "%f", pDnCurseBlow->GetCoolTime() ); bShareCurseCoolTime = true; } } } // ¿©±â¼­ µî·ÏµÇ¾î ÀÖ´Â Á¦°Å µÇ¾î¾ßÇÒ »óÅÂÈ¿°úµé ¾ø¾Ø´Ù. [2010/12/08 semozz] hActor->RemoveResetStateBlow(); //¹ß»çü¿¡¼­ »óÅÂÈ¿°ú Ãß°¡ÇÒ¶§ ¹ß»çü ½ºÅ³ ½ÃÀÛ ½Ã°£À» ´ã¾Æ¼­ Àü´ÞÇÑ´Ù.. m_ParentSkillInfo.projectileSkillStartTime = GetSkillStartTime(); int iID = hActor->CmdAddStateEffect( &m_ParentSkillInfo, (STATE_BLOW::emBLOW_INDEX)m_VecStateEffectList[i].nID, m_VecStateEffectList[i].nDurationTime, m_VecStateEffectList[i].szValue.c_str(), false, bCheckCanBegin ); if( bShareCurseCoolTime ) // #72931 ÄðŸÀÓ ºÙ¿´´ø°Å ´Ù½Ã Á¦°Å { std::string::size_type delimiterindex = m_VecStateEffectList[i].szValue.rfind( ";" ); if( delimiterindex != std::string::npos ) { m_VecStateEffectList[i].szValue.erase( delimiterindex, m_VecStateEffectList[i].szValue.length() - delimiterindex ); } } //¹ß»çü ½Ã°£ ¸®¼Â.. m_ParentSkillInfo.projectileSkillStartTime = 0; // Ãß°¡ÇÑ »óÅÂÈ¿°ú Áß¿¡ chain attack »óÅÂÈ¿°ú°¡ ÀÖ´Ù¸é ¹ß»çü °ü·Ã Á¤º¸µé ¼ÂÆÃÇØÁà¾ß ÇÑ´Ù. // ÇÎÆþ¹ã »óÅÂÈ¿°úµµ ¸¶Âù°¡Áö·Î Ãß°¡ÇØÁà¾ß ÇÔ. if( iID != -1 ) { DnBlowHandle hBlow = hActor->GetStateBlowFromID( iID ); if( hBlow ) { if( STATE_BLOW::BLOW_060 == m_VecStateEffectList.at( i ).nID ) { CDnChainAttackBlow* pChainAttackBlow = static_cast( hBlow.GetPointer() ); pChainAttackBlow->SetProjectileSignal( m_pProjectileSignal.get() ); pChainAttackBlow->SetRootAttackerState( m_pShooterState.get() ); } else if( STATE_BLOW::BLOW_208 == m_VecStateEffectList.at( i ).nID ) { CDnPingpongBlow* pPingPongBlow = static_cast( hBlow.GetPointer() ); pPingPongBlow->SetProjectileSignal( m_pProjectileSignal.get() ); pPingPongBlow->SetRootAttackerState( m_pShooterState.get() ); } } //#56880 ¹ß»çü·Î »óÅÂÈ¿°ú Ãß°¡ µÉ¶§ 242»óÅÂÈ¿°ú Àΰæ¿ì ¹ß»çü ½ºÅ³ÀÇ ½ÃÀÛ ½Ã°£À» ¼³Á¤ÇÑ´Ù..?? if (m_VecStateEffectList[i].nID == STATE_BLOW::BLOW_242) { LOCAL_TIME skillStartTime = GetSkillStartTime(); DnBlowHandle hBlow = hActor->GetStateBlowFromID( iID ); if( hBlow ) { CDnComboDamageLimitBlow* pComboLimitBlow = static_cast( hBlow.GetPointer() ); if (pComboLimitBlow) pComboLimitBlow->SetSkillStartTime(skillStartTime); } } } else { //ChainAttackÀÌ ¾Æ´Ñ °æ¿ì´Â ¾Æ·¡ ·çƾ ½ºÅµÇÔ. STATE_BLOW::emBLOW_INDEX eBlowIndex = (STATE_BLOW::emBLOW_INDEX)m_VecStateEffectList[i].nID; if (eBlowIndex != STATE_BLOW::BLOW_060 && eBlowIndex != STATE_BLOW::BLOW_208) continue; //0. »óÅÂÈ¿°ú ¼³Á¤°ª È®ÀÎ... float fRange = 1000.0f; int nMaxCount = -1; GetChainAttackInfo(m_VecStateEffectList[i], fRange, nMaxCount); //¹ß»çü ÀüÀÌ È½¼ö ¼³Á¤. if (m_ParentSkillInfo.iLeaveCount == -1) m_ParentSkillInfo.iLeaveCount = nMaxCount; ////////////////////////////////////////////////////////////////////////// //2. ´ÙÀ½ Ÿ°Ù ij¸¯ÅÍ ¼±Åà ////////////////////////////////////////////////////////////////////////// DnActorHandle hRootAttacker = m_ParentSkillInfo.hSkillUser; int iRootAttackerTeam = hRootAttacker->GetTeam(); DnActorHandle hActorToAttack = FindNextChainActor(iRootAttackerTeam, hActor, m_ParentSkillInfo.hPrevAttacker, fRange); //¹ß»çü ÀÌÀü Ƚ¼ö°¡ ¾ø°Å³ª, ÀÌÀüµÉ ¾×Å͸¦ ¸ø ãÀ¸¸é ½ºÅµ.. if (m_ParentSkillInfo.iLeaveCount <= 0 || !hActorToAttack) continue; ////////////////////////////////////////////////////////////////////////// //1. ¹ß»çü ½Ã±×³Î Á¤º¸ ¼³Á¤. ////////////////////////////////////////////////////////////////////////// // °¡Àå óÀ½ °ø°ÝÇÑ °ø°ÝÀÚ ¾×ÅÍÀÇ unique id DWORD dwRootAttackerActorUniqueID = hRootAttacker->GetUniqueID(); DWORD dwPrevAttackerActorUniqueID = m_ParentSkillInfo.hPrevAttacker ? m_ParentSkillInfo.hPrevAttacker->GetUniqueID() : UINT_MAX; // ÇÁ·ÎÁ§Å¸ÀÏ ½Ã±×³ÎÀ» Ŭ¶óÀÌ¾ðÆ®¿¡¼­ ã´Âµ¥ ÇÊ¿äÇÑ °íÀ¯ Á¤º¸µé. int iActionIndex = m_ParentSkillInfo.iProjectileShootActionIndex; int iProjectileSignalArrayIndex = m_ParentSkillInfo.iProjectileSignalArrayIndex; ProjectileStruct projectileSignalInfo; bool bFound = false; CEtActionSignal *pSignal = hRootAttacker->GetSignal( iActionIndex, iProjectileSignalArrayIndex ); if( pSignal && pSignal->GetSignalIndex() == STE_Projectile ) { #ifdef PRE_FIX_MEMOPT_SIGNALH CopyShallow_ProjectileStruct(projectileSignalInfo, static_cast(pSignal->GetData())); #else projectileSignalInfo = *(static_cast(pSignal->GetData())); #endif bFound = true; } ////////////////////////////////////////////////////////////////////////// //ÆÐŶ Ŭ¶óÀÌ¾ðÆ®·Î Àü¼Û.. hActor->SendChainAttackProjectile(hRootAttacker, dwPrevAttackerActorUniqueID, iActionIndex, iProjectileSignalArrayIndex, hActorToAttack, m_ParentSkillInfo.iSkillID); //3. ¹ß»çü Á¤º¸ ¼³Á¤ ÇÏ°í »ý¼º ////////////////////////////////////////////////////////////////////////// CreateChainAttackProjectile(hRootAttacker, hActor, hActorToAttack, &projectileSignalInfo, m_ParentSkillInfo); ////////////////////////////////////////////////////////////////////////// } } } } #if defined(PRE_FIX_59336) //242¹ø »óÅÂÈ¿°ú Ãß°¡.. ApplyComboLimitStateEffect(hActor); #endif // PRE_FIX_59336 }