コード例 #1
0
ファイル: CommonCtrl.cpp プロジェクト: careysky/FlyFF
	FOR_LINKMAP( GetWorld(), vPos, pObj, nRange, CObj::linkPlayer, GetLayer() )
	{
		if( pObj->GetType() == OT_MOVER )				// 대상이 무버일때만.
		{
			CMover *pTarget = (CMover *)pObj;
			if( pTarget->IsLive() && pAttacker != pTarget )
			{
				if( pObj->IsRangeObj( vPos, 1.0f ) )
				{
#if __VER >= 9	// __SKILL_0706
					int n = 0;
					if( bPVP && pAttacker->IsPVPTarget( pTarget ) )
						n	= pTarget->m_pActMover->SendDamage( AF_FORCE, pAttacker->GetId(), nDamagePVP, FALSE );	
					else if( bPVP && (m_bControl || pAttacker->IsGuildCombatTarget( pTarget )
								/*아레나 추가*/	|| pAttacker->IsArenaTarget( pTarget ) 
						) )
						n	= pTarget->m_pActMover->SendDamage( AF_FORCE, pAttacker->GetId(), nDamage, FALSE );	
#else	// __SKILL_0706
					int n	= pTarget->m_pActMover->SendDamage( AF_FORCE, pAttacker->GetId(), nDamage, FALSE );	
#endif	// __SKILL_0706
					if( n > 0 )
					{
						m_nLife ++;		// 부딪힐때마다 카운트 올라감
						if( m_nLife >= (int)( m_pAddSkillProp->dwSkillLvl / 2 ) )
							DestroyWall();

						// 뒤로 밀리기 처리.
						FLOAT fPushAngle = pTarget->GetAngle() + 180.0f;
						FLOAT fPower = 0.825f;
						AngleToVectorXZ( &pTarget->m_pActMover->m_vDeltaE, fPushAngle, fPower );
						g_UserMng.AddPushPower( pTarget, pTarget->GetPos(), pTarget->GetAngle(), fPushAngle, fPower );
					}
				}
			}
		}
	}
コード例 #2
0
int		CWndWorld::ControlFlying( DWORD dwMessage, CPoint point )
{
	static	float	fTurnAngle	= 0.0f;
	static BOOL	s_bTraceKeyed = 0, s_bSelectKeyed = 0, s_bTurbo2 = 0;
//	static	BOOL	s_bFastTurn;
	int		nMsg = 0;
//	BOOL	bFlyKey;
 	BOOL	bUp, bDown, bLeft, bRight;
	BOOL	bAcc = FALSE;
	BOOL	bTurbo;
//	BOOL	bFastTurn = FALSE;
	BYTE nFrame		= MAX_CORR_SIZE_150;
	CMover* pMover = CMover::GetActiveMover();

	bUp	  = g_bKeyTable[g_Neuz.Key.chUp];
	bDown = g_bKeyTable['S'];

	// 좌/우 회전
	bLeft  = g_bKeyTable[g_Neuz.Key.chLeft];
	bRight = g_bKeyTable['D'];
	
	// 급선회.
//	bFastTurn = g_bKeyTable[ VK_SHIFT ];
	
//	CMover* pMoverTarget = (CMover*)g_WorldMng.Get()->GetObjFocus() ;

	// 가속 상태면 전진 명령 계속 보냄
	bool fMoved	= false;
	bool fBehavior	= false;
	
	if( pMover->m_pActMover->IsStateFlag( OBJSTAF_ACC ) ) {
		if( pMover->SendActMsg( OBJMSG_FORWARD ) == 1 ) {
			fMoved	= true;
		}
	}
	else {
		if( pMover->SendActMsg( OBJMSG_STAND ) == 1 ) {
			fMoved	= true;
		}
	}
	//
	bAcc	= g_bKeyTable[VK_SPACE];
	if( bAcc && !s_bAccKeyed ) 		// 키 누른순간에만 토글시킴.
	{
		if( pMover->m_pActMover->IsStateFlag( OBJSTAF_ACC ) ) 		// 가속중이었다면 
		{
			pMover->SendActMsg( OBJMSG_ACC_STOP );		// 가속 멈춤
			if( pMover->m_pActMover->IsActTurn() )
			{
				fMoved	= true;
			}
		}
		else 
		{
			// 가속중이 아니었다면 가속 시킴.
			if( pMover->SendActMsg( OBJMSG_ACC_START ) == 0 )		
				g_WndMng.PutString( prj.GetText( TID_GAME_AIRFUELEMPTY ) );
			else
			{
				if( pMover->SendActMsg( OBJMSG_FORWARD ) == 1 ) 
					fMoved	= true;
			}
		}
	}
	s_bAccKeyed = bAcc;

	bTurbo = g_bKeyTable[g_Neuz.Key.chWalk];
	if( bTurbo && !s_bTurbo2 )		// 토글 방식.
	{
		if( pMover->m_pActMover->IsStateFlag( OBJSTAF_TURBO ) )
		{
			if( pMover->SendActMsg( OBJMSG_MODE_TURBO_OFF ) == 1 )
				fMoved = true;
		} else
		{
			if( pMover->SendActMsg( OBJMSG_MODE_TURBO_ON ) == 1 )
				fMoved = true;
		}
	}
	s_bTurbo2 = bTurbo;
	
	if( pMover->m_pActMover->IsFly() )
	{
		if( g_bKeyTable[g_Neuz.Key.chTrace] && !s_bTraceKeyed )
		{
			CCtrl* pFocusObj = (CCtrl*)(pMover->GetWorld()->GetObjFocus());
			if( pFocusObj && pFocusObj->GetType() == OT_MOVER )
			{
				CMover* pFocusMover = (CMover*)pFocusObj;
				if( pMover->m_dwFlag & MVRF_TRACKING )	// 이미 실행중이면 해제.
				{
					pMover->m_dwFlag &= (~MVRF_TRACKING);		// 추적모드해제.
					pMover->m_idTracking = NULL_ID;
				} else
				{
					// 비행중 추적모드.
					pMover->m_dwFlag |= MVRF_TRACKING;		// 추적모드.
					pMover->m_idTracking = pFocusMover->GetId();
				}
			} else
			{	// 타겟이 없을때 Z키를 누르면 자동추적이 풀린다.
				pMover->m_dwFlag &= (~MVRF_TRACKING);		// 추적모드해제.
				pMover->m_idTracking = NULL_ID;
			}
		}
		s_bTraceKeyed = g_bKeyTable[g_Neuz.Key.chTrace];

		// 타겟선택 키
		if( g_bKeyTable[VK_TAB] && !s_bSelectKeyed )
		{
			if( m_aFlyTarget.GetSize() > 0 )		// 선택된 타겟있을때.
			{
				if( m_nSelect >= m_aFlyTarget.GetSize() )
					m_nSelect = 0;
				OBJID idSelect = m_aFlyTarget.GetAt( m_nSelect++ );
				CMover *pSelectMover = prj.GetMover( idSelect );
				if( IsValidObj(pSelectMover) )
				{
					CWorld *pWorld = pMover->GetWorld();
					if( pWorld )
					{
						pWorld->SetObjFocus( pSelectMover );			// 이놈을 타겟으로 설정함.
						pMover->m_idTracking = pSelectMover->GetId();	// 탭으로 타겟을 바꾸면 자동추적타겟도 그놈으로 바뀐다.
					}
				}
			}
		}
		s_bSelectKeyed = g_bKeyTable[VK_TAB];
	}



	if( /*m_bFlyMove &&*/ m_bLButtonDown || g_bKeyTable[VK_INSERT] )	// 192 = `
	{
		CObj *pObj = pMover->GetWorld()->GetObjFocus();		// 타겟잡힌놈이 있을때만 휘두를수 있다.
		if( pObj && pObj->GetType() == OT_MOVER )
		{
			if( pMover->IsAttackAble( pObj ) )	// 공격 가능한지 검사.
			{
				OBJID	idTarget = ((CMover *)pObj)->GetId();
				ItemProp *pWeapon = pMover->GetActiveHandItemProp();
				if( pWeapon )
				{
					g_pPlayer->PlayCombatMusic();

					if( pWeapon->dwItemKind3 == IK3_WAND )
					{
						D3DXVECTOR3 vFront, vTarget;
						AngleToVector( &vFront, g_pPlayer->GetAngle(), -g_pPlayer->GetAngleX(), 1.0f );
						vTarget = pObj->GetPos() - g_pPlayer->GetPos();
						D3DXVec3Normalize( &vTarget, &vTarget );		// 타겟쪽으로의 벡터의 유닛벡터.
						FLOAT fDot = D3DXVec3Dot( &vFront, &vTarget );
						if( fDot >= cosf(D3DXToRadian(60.0f)) )	// 타겟이 내가 보는 방향의 +-30도 안에 있으면 발사할수 있다.
						{
							if( pMover->IsRangeObj( pObj, 64.0f ) )		// 사정거리에 들어오면 발사.
							{
								pMover->DoAttackMagic( pObj, 0 );
							}
						}
					}
					else
					{
						pMover->SendActMsg( OBJMSG_ATK1, idTarget );
					}
				}
			}
		}
	}

//	fTurnAngle	= 0.6f;
	ItemProp* pItemProp = prj.GetItemProp( g_pPlayer->GetRideItemIdx() );
	if( pItemProp )
	{
		fTurnAngle = pItemProp->fFlightLRAngle;
	}
	else
	{
		Error( "ControlFlying : 빗자루정보 읽기 실패 %d", g_pPlayer->GetRideItemIdx() );
		fTurnAngle = 0.6f;
	}

	if( bUp ) {
		if( g_WorldMng.Get()->GetFullHeight( pMover->GetPos() ) < pMover->GetPos().y ) {
			if( pMover->SendActMsg( OBJMSG_LOOKDOWN ) == 1 ) {
				fMoved	= true;
			}
		}
	}
	else if( bDown ) {
		if( pMover->SendActMsg( OBJMSG_LOOKUP ) == 1 ) {
			fMoved	= true;
		}
	}
	else {
		if( pMover->SendActMsg( OBJMSG_STOP_LOOK ) == 1 ) {
			fMoved	= true;
		}
	}

	if( bLeft ) {
		m_fRollAng -= 1.0f;
		if( m_fRollAng < -45.0f )	
			m_fRollAng = -45.0f;
		if( pMover->SendActMsg( OBJMSG_LTURN, (int)( fTurnAngle * 100.0f ) ) == 1 ) {
			fMoved	= true;
		}
	}
	else if( bRight ) {
		m_fRollAng += 1.0f;
		if( m_fRollAng > 45.0f )	
			m_fRollAng = 45.0f;
		if( pMover->SendActMsg( OBJMSG_RTURN, (int)( fTurnAngle * 100.0f ) ) == 1 ) {
			fMoved	= true;
		}
	}
	else {
		if( m_fRollAng < 0 )
		{
			m_fRollAng += 2.0f;
			if( m_fRollAng > 0 )	m_fRollAng = 0;
		} else
		if( m_fRollAng > 0 )
		{
			m_fRollAng -= 2.0f;
			if( m_fRollAng < 0 )	m_fRollAng = 0;
		}
		if( pMover->SendActMsg( OBJMSG_STOP_TURN ) == 1 ) {
			fMoved	= true;
//			fBehavior	= true;
		}
	}

	// 오른쪽 버튼 드래그는 빗자루 움직임
	if( dwMessage == WM_MOUSEMOVE /*&& m_bRButtonDown*/ )
	{
		float fAng = pMover->GetAngle();
		float fAdd = (point.x - m_ptMouseOld.x) / 2.0f;
		fAng -= fAdd;
		pMover->SetAngle( fAng );
		
		float fAngX = pMover->GetAngleX();
		float fAddX = (point.y - m_ptMouseOld.y) / 4.0f;
		fAngX += fAddX;
		if( fAddX > 0 && fAngX > 45.0f )
			fAngX = 45.0f;
		else
		if( fAddX < 0 && fAngX < -45.0f )
			fAngX = -45.0f;
			
		pMover->SetAngleX( fAngX );

		if( fAdd || fAddX )
			g_DPlay.PostPlayerAngle( TRUE );
	}
	


	BOOL bTempKey;
	if( bTempKey = g_bKeyTable[ '8' ] )
	{
		if( !m_bTemp3ed )
		{
			pMover->SendActMsg( OBJMSG_TEMP2 );
			//			__bTestLOD ^= 1;
		}
	}
	m_bTemp3ed	= bTempKey;
	


	if( fMoved )
	{
		g_DPlay.SendPlayerMoved2( nFrame );
	}
	if( fBehavior )
	{
		pMover->ClearDest();
		g_DPlay.SendPlayerBehavior2();
	}
	
	return nMsg;
}
コード例 #3
0
void	CActionMover::ProcessFlyMove( void )
{
#ifdef __CLIENT	
	g_nDrift = 0;									// 드리프트 플랙 클리어 
#endif
	float fLenSq = D3DXVec3LengthSq( &m_vDelta );
	if( fLenSq == 0.0f && (GetStateFlag() & OBJSTAF_ACC ) == 0 )	  
		return;										// 멈춤 상태면 리턴 

	CMover* pMover = m_pMover;
	FLOAT fAccPwr = m_fAccPower;

#ifdef __CLIENT
	ProcessFlyTracking();
#endif // client
	
	// 터보모드 처리 
	if( (GetStateFlag() & OBJSTAF_TURBO) && (GetStateFlag() & OBJSTAF_ACC) )		// 터보모드 & 전진중
	{
	#ifdef __WORLDSERVER
		pMover->m_tmAccFuel	=  (int)( pMover->m_tmAccFuel - (1000.0f / (float)FRAME_PER_SEC) );		// 1/60만큼 깎음
	#endif
		if( pMover->m_tmAccFuel <= 0 )				// 가속연료가 다 떨어지면
		{
			pMover->m_tmAccFuel = 0;
			SendActMsg( OBJMSG_MODE_TURBO_OFF );	// 터보모드 중지 
		#ifdef __WORLDSERVER
			g_UserMng.AddSendActMsg( pMover, OBJMSG_MODE_TURBO_OFF );
		#endif
		}
		else
			fAccPwr *= 1.2f;						// 가속연료가 남아있다면 터보모드
	}

#ifdef __CLIENT
	ProcessFlyParticle( fLenSq );
#endif

	// 관성처리 
	if( fAccPwr > 0.0f )
	{
		// 힘벡터 생성
		FLOAT fAngX  = D3DXToRadian( pMover->GetAngleX() );		
		FLOAT fAng   = D3DXToRadian( pMover->GetAngle() );
		FLOAT fDist  = cosf(fAngX) * fAccPwr;		

		D3DXVECTOR3	vAcc;
		vAcc.x = sinf( fAng ) * fDist;
		vAcc.z = -cosf( fAng ) * fDist;
		vAcc.y = -sinf( fAngX ) * fAccPwr;

		// 관성벡터와 추진력벡터가 각도가 50도 이하면 급추진
		if( fLenSq > 0.01f )
		{
			D3DXVECTOR3 vDeltaNorm, vAccNorm;
			D3DXVec3Normalize( &vDeltaNorm, &m_vDelta );
			D3DXVec3Normalize( &vAccNorm, &vAcc );
			float fDot = D3DXVec3Dot( &vDeltaNorm, &vAccNorm );	

			if( fDot < 0.633319f )					// 이전코드: cosf(70.0f)  값으로는 대략 50도 
			{
				vAcc *= 2.0f;						
				m_vDelta *= 0.985f;
			#ifdef __CLIENT
				g_nDrift = 1;
				
				if( ! ( pMover->IsMode( TRANSPARENT_MODE ) ) )		// 투명상태가 아닐때만 렌더.
				{	
					if( (g_nProcessCnt & 3) == 0 )
						CreateSfx( g_Neuz.m_pd3dDevice, XI_NAT_DUST_RUN, pMover->GetPos() );
				}
			#endif
			}
		}
			
		fLenSq = D3DXVec3LengthSq( &m_vDelta );		// 1/60 sec 속도
		float fMaxSpeed = 0.3f;
		if( GetStateFlag() & OBJSTAF_TURBO )		// 터보모드에선 MAX속도가 1.1배
			fMaxSpeed *= 1.1f;
			
		if( fLenSq < (fMaxSpeed * fMaxSpeed) )		// 일정이상 속도를 넘지 않게 하자.
			m_vDelta += vAcc;						// 관성벡터 += 추진력벡터
	}

	m_vDelta *= (1.0f - FRIC_AIR);					// 마찰력에 의한 감소  

	// raiders - 수치적 안정성을 위해서 적은 수치가 계산되는 것을 피한다.
	fLenSq = D3DXVec3LengthSq( &m_vDelta );
	if( m_fAccPower == 0.0f && fLenSq < 0.0002f * 0.0002f )		
	{
		fLenSq = 0;
		m_vDelta = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );		
		RemoveStateFlag( OBJSTAF_ACC );				// 가속상태 해제 
	}

#ifdef __CLIENT
	if( pMover->IsActiveMover() )
	{
		g_nFlySpeed = (int)( (sqrt(fLenSq) * 60.0f) * 60.0f * 60.0f );
		g_nFlySpeed	= (int)( g_nFlySpeed / 200.0f );
	}
#endif
}
コード例 #4
0
ファイル: CommonCtrl.cpp プロジェクト: careysky/FlyFF
// 싸이킥 월
void CCommonCtrl::_ProcessWall( void )
{
	if( m_nCount == 0 )
	{
	#ifdef __CLIENT		
		m_pSfxModel = new CSfxModel;
		m_pSfxModel2 = new CSfxModel;
		m_pSfxModel->SetSfx( "sfx_sklpsypsychicwall02" );
		m_pSfxModel2->SetSfx( "sfx_sklpsypsychicwall04" );
	#endif
	}

	D3DXVECTOR3	vPos = GetPos();

#ifndef __CLIENT
	CObj* pObj;
	BOOL bApply;
#endif //__CLIENT

	int nRange = 4;
	// 일반적으로 fDepth가 가장 길기때문에 검사 영역은 fDepth로 했다. 
	float fDepth = 3;
	
	if( fDepth <= 4.0f )		nRange = 4;
	else if( fDepth <= 8.0f )	nRange = 8;
	else if( fDepth <= 16.0f )	nRange = 16;
	else						nRange = 32;

#ifdef __WORLDSERVER
	CMover *pAttacker = prj.GetMover( m_idAttacker );
	
	if( IsInvalidObj( pAttacker ) )		// 일단 어태커가 사라지면 컨트롤도 사라지게 하자.
	{
		DestroyWall();
		return;
	}
	int nMin = m_pAddSkillProp->dwAbilityMin + (pAttacker->GetLevel() + (pAttacker->GetInt() / 10) * (int)m_pAddSkillProp->dwSkillLvl);
	int nMax = m_pAddSkillProp->dwAbilityMax + (pAttacker->GetLevel() + (pAttacker->GetInt() / 10) * (int)m_pAddSkillProp->dwSkillLvl);
	int nDamage = xRandom( nMin, nMax );
#if __VER >= 9	// __SKILL_0706
	int nMinPVP	= m_pAddSkillProp->dwAbilityMinPVP + ( pAttacker->GetLevel() + ( pAttacker->GetInt() / 10 ) * (int)m_pAddSkillProp->dwSkillLvl );
	int nMaxPVP		= m_pAddSkillProp->dwAbilityMaxPVP + ( pAttacker->GetLevel() + ( pAttacker->GetInt() / 10 ) * (int)m_pAddSkillProp->dwSkillLvl );
	int nDamagePVP	= xRandom( nMinPVP, nMaxPVP );
#endif	// __SKILL_0706

	int nHitPoint = 0;
	int nTargetHP = 0;
	
	FOR_LINKMAP( GetWorld(), vPos, pObj, nRange, CObj::linkDynamic, GetLayer() )
	{
		bApply = FALSE;
		if( pObj->GetType() == OT_MOVER )				// 대상이 무버일때만.
		{
			CMover *pTarget = (CMover *)pObj;
			if( pTarget->IsPeaceful() == FALSE )		// NPC가 아닌경우만 적용
				bApply = TRUE;
#if __VER >= 8 //	#ifdef	__JHMA_VER_8_5_1			 // 8.5차 경비병 범위스킬 공격효과 불가로 수정 World
			if( pAttacker->IsPlayer() && pAttacker->IsChaotic() == FALSE && pTarget->GetProp()->dwClass == RANK_GUARD )
				bApply = FALSE;
#endif //			#endif // __JHMA_VER_8_5_1			 // 8.5차 경비병 범위스킬 공격효과 불가로 수정 World	
			if( bApply )
			{
				if( IsValidObj( pTarget ) && pTarget->IsLive() )
				{
					if( pObj->IsRangeObj( vPos, 1.0f ) )
					{
						if( IsValidObj(pAttacker) )
						{
							nTargetHP = pTarget->GetHitPoint();
							nHitPoint = nTargetHP - nDamage;
							if( nHitPoint > 0 )
							{
								pTarget->m_nHitPoint = nHitPoint;
								g_UserMng.AddDamage( pTarget, pAttacker->GetId(), nDamage, AF_GENERIC );
							}
							else
							{
								pAttacker->SubExperience( pTarget );		// pTarget를 죽이고 난후의 m_pAttacker 경험치 처리.
								pTarget->DropItemByDied( pAttacker );				// 몬스터였다면 아이템 드랍.
								pAttacker->m_nAtkCnt = 0;					// 타겟을 죽였으면 공격자의 어택카운트 클리어
								pTarget->DoDie( pAttacker );				// pTarget 죽어라. 
								pTarget->m_nHitPoint = 0;
							}
						}
						m_nLife ++;		// 부딪힐때마다 카운트 올라감
						if( m_nLife >= (int)(m_pAddSkillProp->dwSkillLvl / 2) )
							DestroyWall();
						
						// 뒤로 밀리기 처리.
#if __VER >= 10	// __AI_0711
						if( pTarget->IsRank( RANK_MIDBOSS ) == FALSE )
#endif	// __AI_0711
						{
							FLOAT fPushAngle = pTarget->GetAngle() + 180.0f;
							FLOAT fPower = 0.825f;
							AngleToVectorXZ( &pTarget->m_pActMover->m_vDeltaE, fPushAngle, fPower );
							g_UserMng.AddPushPower( pTarget, pTarget->GetPos(), pTarget->GetAngle(), fPushAngle, fPower );
						}
					}
				}
			}
		}
	}
コード例 #5
0
void CActionMover::PresupposePos2( D3DXVECTOR3* pv, D3DXVECTOR3* pvd, float* pf, float* pfAngleX, float* pfAccPower, u_long uTickCount )
{
	CMover* pMover	= GetMover();
	D3DXVECTOR3 v	= pMover->GetPos();
	float fAngle	= pMover->GetAngle();
	D3DXVECTOR3 vDelta	= m_vDelta;
	
	if( prj.GetItemProp( pMover->m_dwRideItemIdx ) == NULL )
		return;

	float fAcc = prj.GetItemProp( pMover->m_dwRideItemIdx )->fFlightSpeed;	// 무버가 타고있는 아이템의 인덱스에서 추진력을 꺼내옴.

	fAcc	*= 0.75f;
	float fTheta, fThetaX, d;

	DWORD dwMoveState	= GetMoveState();
	DWORD dwTurnState	= GetTurnState();
	DWORD dwLookState	= GetLookState();

	float fX = pMover->GetAngleX();
	float fAccPower	= m_fAccPower;
	float fTurnAngle;
	
	D3DXVECTOR3	vAcc;
	for( u_long i = 0; i < uTickCount; i++ )
	{
		fTheta	= D3DXToRadian( fAngle );
		switch( dwMoveState )
		{
			case OBJSTA_STAND:
				fAccPower	= 0;
				break;
			case OBJSTA_FMOVE:
				fAccPower	= fAcc;
				break;
		}
		switch( dwTurnState )
		{
			case OBJSTA_LTURN:
				fTurnAngle	= m_fTurnAngle;
				if( ( GetStateFlag() & OBJSTAF_ACC ) == 0 )
					fTurnAngle *= 2.5f;
				fAngle	+= fTurnAngle;
				if( fAngle > 360.0f )
					fAngle -= 360.0f;
				break;
			case OBJSTA_RTURN:
				fTurnAngle	= m_fTurnAngle;
				if( ( GetStateFlag() & OBJSTAF_ACC ) == 0 )
					fTurnAngle *= 2.5f;
				fAngle	-= fTurnAngle;
				if( fAngle < 0.0f )
					fAngle	+= 360.0f;
				break;
		}
		switch( dwLookState )
		{
			case OBJSTA_LOOKUP:
				if( fX > -45.0f )	fX	-= 1.0f;
				break;
			case OBJSTA_LOOKDOWN:
				if( fX < 45.0f )	fX	+= 1.0f;
				break;
		}

		fThetaX	= D3DXToRadian( fX );
		if( GetStateFlag() & OBJSTAF_TURBO )
			fAccPower	*= 1.5f;
		d	= cosf( fThetaX ) * fAccPower;
		fTheta	= D3DXToRadian( fAngle );
		
		vAcc.x	= sinf( fTheta ) * d;
		vAcc.z	= -cosf( fTheta ) * d;
		vAcc.y	= -sinf( fThetaX ) * fAccPower;

		float fLenSq	= D3DXVec3LengthSq( &vDelta );
		D3DXVECTOR3 vDeltaNorm, vAccNorm;
		D3DXVec3Normalize( &vDeltaNorm, &vDelta );
		D3DXVec3Normalize( &vAccNorm, &vAcc );
		float fDot	= D3DXVec3Dot( &vDeltaNorm, &vAccNorm );
		if( fAccPower > 0.0f )
		{
			if( fLenSq > 0.01f )
			{
				if( fDot < cosf( 70.0f ) )
				{
					vAcc	*= 2.0f;
					vDelta	*= 0.985f;
				}
			}
		}
		fLenSq	= D3DXVec3Length( &vDelta );
		if( fLenSq < 0.3f )
		{
			vDelta	+= vAcc;
		}
		vDelta	*= ( 1.0f - FRIC_AIR );
		v	+= vDelta;
		if( v.y > MAX_MOVE_HEIGHT )
			v.y	= MAX_MOVE_HEIGHT;

		CWorld* pWorld = GetWorld();
		pWorld->ClipX( v.x );
		pWorld->ClipZ( v.z );
	}

	*pv	        = v;
	*pf	        = fAngle;
	*pvd	    = vDelta;
	*pfAngleX	= fX;
	*pfAccPower	= fAccPower;

	pMover->m_nCorr = (int)uTickCount;
}
コード例 #6
0
void CActionMover::ProcessFlyTracking()
{
	CMover* pMover = m_pMover;

	// 자동 추적 모드. g_pPlayer만 실행된다.
	if( pMover->IsActiveMover() && (pMover->m_dwFlag & MVRF_TRACKING) )
	{
		static float s_fTurnAcc = 0, s_fTurnAccH = 0;
		{
			CMover *pTarget = prj.GetMover( pMover->m_idTracking );		// 추적할 목표.
			if( pTarget )
			{
				D3DXVECTOR3	vDist = pTarget->GetPos() - pMover->GetPos();		// 나를 원점으로 타겟까지의 벡터.
				FLOAT fAngXZ, fAngH;
				
				xGetDegree( &fAngXZ, &fAngH, vDist );		// 타겟과의 각도 구함.
				// 남쪽이 0도 기준. 시계방향 -180까지 시계반대방향 +180
				// 3도 이하는 무시.
				FLOAT fMoverAng = pMover->GetAngle();
				if( fMoverAng > 180.0f )	// 계산하기 좋게 좌표계를 +,- 로 바꿈.
					fMoverAng -= 360.0f;
				FLOAT fSubAng = fAngXZ - fMoverAng;
				if( fSubAng > 180.0f )
					fSubAng -= 360.0f;
				else if( fSubAng < -180.0f )
					fSubAng += 360.0f;

			#ifdef _DEBUG 
			#ifdef __XUZHU				
				extern float _g_fReg[];
				_g_fReg[1] = fSubAng;
				_g_fReg[2] = fAngXZ;
			#endif
			#endif
				
				if( fSubAng < -3.0f )		// 오른쪽으로 돌아야 한다.
					s_fTurnAcc = -2.5f;
				else 
				if( fSubAng > 3.0f )	// 왼쪽으로 돌아야 한다.
					s_fTurnAcc = 2.5f;
				else
					s_fTurnAcc = 0;

				FLOAT fMoverAngX = pMover->GetAngleX();
				FLOAT fSubAngH = fAngH - fMoverAngX;
				if( fSubAngH > 180.0f )
					fSubAngH -= 360.0f;
				else if( fSubAngH < -180.0f )
					fSubAngH += 360.0f;

				if( fSubAngH < -3.0f )
					s_fTurnAccH = -1.5f;
				else
				if( fSubAngH > 3.0f )
					s_fTurnAccH = 1.5f;
				else
					s_fTurnAccH = 0;

				pMover->SetAngle( pMover->GetAngle() + s_fTurnAcc );
				pMover->SetAngleX( pMover->GetAngleX() + s_fTurnAccH );

				if( s_fTurnAcc || s_fTurnAccH )	// 값이 달라지면 전송함.
					g_DPlay.PostPlayerAngle( TRUE );
			}
		}
	}
}
コード例 #7
0
void CActionMover::ProcessFlyParticle( float fLenSq )
{
	CMover *pMover = m_pMover;

	// 운영자 투명모드때는 파티클 안나옴.
	if( (pMover->IsMode( TRANSPARENT_MODE ) ) == 0 )
	{
		ItemProp* pRideProp = prj.GetItemProp( m_pMover->m_dwRideItemIdx );		// 현재 타고있는 탈것의 프로퍼티.
		// 비행 파티클 처리.
		if( fLenSq > 0.01f )
		{
			if( (pMover->IsActiveMover() && g_Neuz.m_camera.m_fZoom > 2.0f) || pMover->IsActiveMover() == FALSE )		// 일정속도 이상이 되면 꼬리에 파티클이 나오기 시작.
			{
				int nType = 0;
				if( pRideProp && pRideProp->dwID == II_RID_RID_BOR_RIDINGCLOUD )
					nType = 1;
				CreateFlyParticle( pMover, pMover->GetAngleX(), nType );
			}
		}
		
		if( fLenSq > 0.001f  )
		{
			if( (pMover->IsActiveMover() && g_Neuz.m_camera.m_fZoom > 1.0f) || pMover->IsActiveMover() == FALSE )
			{
				if( pRideProp && pRideProp->dwItemKind3 == IK3_BOARD )		// 보드만 꼬리가 나온다.
				{
					if( m_pTail )
					{
						if( pRideProp->dwID == II_RID_RID_BOR_RIDINGCLOUD ) // 근두운일때
						{
							if( m_pTail->GetType() != 2 )	// 생성되었던 꼬리고 근두운용이 아니면
								m_pTail->ChangeTexture( D3DDEVICE, "etc_Tail2.bmp", 2 );
						} else
						{
							if( m_pTail->GetType() != 1 )	// 생성되었던 꼬리고 일반보드용이 아니면 
								m_pTail->ChangeTexture( D3DDEVICE, "etc_Tail1.bmp", 1 );	// 일반보드용으로 텍스쳐 교체.
						}

							
					}
					if( m_pTail == NULL )	// 아직 할당 안됐으면 할당하고.
					{
						if( pRideProp->dwID == II_RID_RID_BOR_RIDINGCLOUD ) // 근두운...
						{
							m_pTail = (CTailEffectBelt*)g_TailEffectMng.AddEffect( g_Neuz.m_pd3dDevice, "etc_Tail2.bmp", 2 );
						}
						else
						{
							m_pTail = (CTailEffectBelt*)g_TailEffectMng.AddEffect( g_Neuz.m_pd3dDevice, "etc_Tail1.bmp", 1 );
						}
					}
					D3DXVECTOR3	vPos1, vPos2;
					D3DXVECTOR3	vLocal;
					FLOAT		fAngXZ = pMover->GetAngle();
					FLOAT		fAngH  = pMover->GetAngleX();
					
					AngleToVectorXZ( &vLocal, fAngXZ, -1.0f );

					fAngXZ -= 90.0f;
					if( fAngXZ < 0 )
						fAngXZ += 360.0f;
					AngleToVector( &vPos1, fAngXZ, -fAngH, 0.5f );
					vPos1 += pMover->GetPos();

					vPos1 += vLocal;
				
					fAngXZ = pMover->GetAngle();
					fAngH  = pMover->GetAngleX();
					
					AngleToVectorXZ( &vLocal, fAngXZ, -1.0f );

					fAngXZ += 90.0f;
					if( fAngXZ > 360.0f )
						fAngXZ -= 360.0f;
					AngleToVector( &vPos2, fAngXZ, -fAngH, 0.5f );
					vPos2 += pMover->GetPos();
					vPos2 += vLocal;
						
					if( m_pTail )
						m_pTail->CreateTail( vPos1, vPos2 );
				}
			}
		}
	} // 투명모드가 아닐때
}		
コード例 #8
0
ファイル: Camera.cpp プロジェクト: iceberry/flyffsf
void CBackCamera::Process( LPDIRECT3DDEVICE9 pd3dDevice ,float fFactor )
{
#ifdef __CLIENT
	CMover *pMover = CMover::GetActiveMover();
	// 여기서 카메라 세팅!!!!!
	if( pMover == NULL )	return;

	CWorld* pWorld = pMover->GetWorld();
	if( pWorld == NULL )
		return;
	D3DXMATRIX matView, mat;

	FLOAT fAngle = 0, fAngleY = 0;

	D3DXVECTOR3 vPos = pMover->GetPos();
	
	vPos.y += 0.9f;
#if __VER >= 13 // __HOUSING
	if(m_nCamMode == CM_MYROOM)
	{
		if(m_fZoom <= 0.5f) m_fZoom = 0.5f;
	//	if(m_fZoom >= 3.0f) m_fZoom = 3.0f;
	}
#endif // __HOUSING
	CMover* pMoverTarget = (CMover*)g_WorldMng.Get()->GetObjFocus() ;
	D3DXVECTOR3 vTarget,vTemp;
	if( pMoverTarget && pMover->m_pActMover->IsFly() && (pMover->m_dwFlag & MVRF_TRACKING) ) 
	{	// 날고 있는 경우 타겟이 있다면
		// 타겟쪽으로 카메라 방향을 수정한다.
		vTemp = vPos - pMoverTarget->GetPos();
		if( vTemp.z > 0 ) 
		{
			fAngle =- (float)( atan( vTemp.x / vTemp.z ) * 180 / 3.1415926f );
		}
		else 
		{
			fAngle =- (float)( atan( vTemp.x / vTemp.z ) * 180 / 3.1415926f ) + 180;
		}
		D3DXVECTOR3	vDistXZ = vTemp;
		vDistXZ.y = 0;
		float fDistSq = D3DXVec3Length( &vDistXZ );		// XZ평면에서의 길이
		fAngleY = atan2( fDistSq, vTemp.y/* * vTemp.y*/ );
		fAngleY = D3DXToDegree( fAngleY );

		float fReg1 = vTemp.y / 40.0f;
		if( fReg1 > 0 )
		{
			if( fReg1 >= 2.0f )	fReg1 = 2.0f;
		} else
		if( fReg1 < 0 )
		{
			if( fReg1 <= -2.0f )	fReg1 = -2.0f;
		}

		m_fCurRoty = m_fRoty + m_fZoom * fReg1;
		if( m_bLock )
			fAngle = 0;

	}
	else 
	{
		fAngle = pMover->GetAngle();
		if( m_bLock )
			fAngle = 0;
		fAngleY = 90.0f;

		m_fCurRoty = m_fRoty + m_fZoom * 4;
	}
	m_vLookAt = vPos;

#ifdef __Y_CAMERA_SLOW_8
	if( !g_WndMng.m_pWndWorld->m_bRButtonDown && ( !g_bKeyTable[ VK_LEFT ] && !g_bKeyTable[ VK_RIGHT ] ) )
	{
		static FLOAT fSpeed = 2.0f;
		BOOL  bLeft = FALSE;
		BOOL  bRight = FALSE;
		FLOAT fTemp = 0.0f;

		fTemp = m_fRotx;

		if( (GetAnglePie(fTemp) == 1 && GetAnglePie(m_fCurRotx) == 4) )
			bRight = TRUE;

		if( (GetAnglePie(fTemp) == 4 && GetAnglePie(m_fCurRotx) == 1) )
			bLeft = TRUE;

		if( bRight )
		{
			m_fCurRotx += m_fRotx;

			if( m_fCurRotx < fTemp )
			{
				m_fCurRotx += fSpeed;
			}

			m_fCurRotx -= m_fRotx;

			if( m_fCurRotx >= 0.0f )
			{
				m_fCurRotx = -360.0f;
			}
		}

		if( bLeft )
		{
			fTemp += -360.0f;
			
			if( m_fCurRotx > fTemp )
			{
				m_fCurRotx += -fSpeed;

				if( m_fCurRotx < -360.0f )
					m_fCurRotx = 0.0f;
			}

			fTemp -= -360.0f;
		}

		if( !bLeft && !bRight )
		{
			FLOAT fGoal = fabs(m_fCurRotx - fTemp);
			if( m_fCurRotx < fTemp )
			{
				if( fGoal > fSpeed )
					m_fCurRotx += fSpeed;
			}
			else
			{
				if( fGoal > fSpeed )
					m_fCurRotx -= fSpeed;
			}
		}
	}
	else
	{
		m_fCurRotx = m_fRotx;
	}

#else //__Y_CAMERA_SLOW_8
	m_fCurRotx = m_fRotx;
#endif //__Y_CAMERA_SLOW_8

#ifdef __XUZHU
	_g_fReg[0] = fAngleY;
#endif
	
	float fAdjAng = (1.0f - fAngleY / 90.0f) * 45.0f;
	m_fCurRoty += fAdjAng;
	m_fCurRoty += pMover->GetAngleX();
	
	if( pMover->m_pActMover->IsFly() )	// 비행할땐 조금 들어주자
		m_fCurRoty += 0.0f;
	if( m_fCurRoty > 80.0f ) 
		m_fCurRoty = 80.0f;

#if __VER >= 13 // __HOUSING
	if(m_nCamMode == CM_MYROOM)
	{
		if(m_fCurRoty <= 10.0f) 
		{
			m_fCurRoty = 10.0f;
			if(m_fRoty > 0.0f) m_fRoty = 0.0f;
			if(m_fRoty < -30.0f) m_fRoty = -30.0f;
		}
	}
#endif // __HOUSING

	fAngle = m_fCurRotx - fAngle + 180.0f;

	D3DXMATRIX matTemp;
	// zoom 상태에 따라 카메라 위치를 조정
	extern float fDiv;
	
	if( fDiv == 2.0f )
		//vTemp = D3DXVECTOR3( 0.0f, 0.0f, -0.0f - (m_fZoom / 2.0f) * 2.0f );
		vTemp = D3DXVECTOR3( 0.0f, 0.0f, -0.0f - 2.0f );
	else
	{
		if( g_pShip )
			vTemp = D3DXVECTOR3( 0.0f, 0.0f, -4.0f - m_fZoom * 16.0f );
		else
			//vTemp = D3DXVECTOR3( 0.0f, 0.0f, -50.0f );
			vTemp = D3DXVECTOR3( 0.0f, 0.0f, -4.0f - m_fZoom * 2.0f );
	}
	
	D3DXVECTOR3 vecOut;
	D3DXMatrixRotationX( &matTemp, D3DXToRadian( m_fCurRoty / 1.0f ) );
	D3DXVec3TransformCoord( &vTemp, &vTemp, &matTemp );
	D3DXMatrixRotationY( &matTemp, D3DXToRadian( fAngle ) );
	D3DXVec3TransformCoord( &m_vOffsetDest, &vTemp, &matTemp );

	D3DXVECTOR3 vecOffsetDelta = ( ( m_vOffsetDest - m_vOffset ) + m_vPosVal ) / fFactor;

	m_vOffset += vecOffsetDelta;

	m_vPosVal /= 2;

	m_vPos = vPos + m_vOffset;

	BOOL  bCrash;
	FLOAT fLength;
	static D3DXVECTOR3 m_vLimitPos;
	D3DXVECTOR3 m_vOutPos = m_vPos;

	m_vLookAt.y += 0.4f;
#if __VER >= 11 // __GUILD_COMBAT_1TO1
	if( g_pPlayer && g_GuildCombat1to1Mng.IsPossibleMover( g_pPlayer ) )
		bCrash = FALSE;
	else
		bCrash = pWorld->CheckBound( &m_vPos, &m_vLookAt, &m_vOutPos, &fLength );
#else //__GUILD_COMBAT_1TO1
	bCrash = pWorld->CheckBound( &m_vPos, &m_vLookAt, &m_vOutPos, &fLength );
#endif //__GUILD_COMBAT_1TO1

	// 충돌이있다면 마지막으로 충돌했던 거리를 저장
	if( bCrash )
		m_fLength2 = fLength;

	// 전프레임에 충돌, 현재는 충돌이 아닐때...즉, 서서히 뒤로 가게하는 시점..
	if( m_bOld && bCrash == FALSE )
	{
		m_fLength1 = fLength;
		m_bStart = TRUE;
	}

	if( m_bStart )
	{
		D3DXVECTOR3 vCPos = vPos + m_vOffset;
		D3DXVECTOR3 vDir  = vCPos - m_vLookAt;
		D3DXVec3Normalize(&vDir, &vDir);
#if __VER >= 12 // __CAM_FAST_RECOVER
		m_fLength2 += 0.37f;
#else
		m_fLength2 += 0.07f;
#endif
		if( m_fLength2 > fLength )
			m_bStart = FALSE;

		m_vOutPos = m_vLookAt + (vDir * m_fLength2);
	}
	else
	if( bCrash )
	{/*
		if( fLength < 5.0f )
		{
			D3DXVECTOR3 vCPos = vPos + m_vOffset;
			D3DXVECTOR3 vDir  = vCPos  - m_vLookAt;
			D3DXVec3Normalize(&vDir, &vDir);
			
			FLOAT fff = m_vOutPos.y;
			m_vOutPos = m_vLookAt + (vDir * 5.0f);
			m_vOutPos.y = fff;
		}
	 */
	}

	m_bOld = bCrash;

	g_ModelGlobal.SetCamera( m_vOutPos, m_vLookAt );

	m_vPos = m_vOutPos;
#endif // CLIENT
}
コード例 #9
0
ファイル: ActionMoverMsg.cpp プロジェクト: iceberry/flyffsf
//
//	Action Message Process
//	액션 메시지를 받아 처리한다.
//	어떤 행위가 발생하는 시점에 대한 처리를 담당.
//	최적화를 위해서 이미 설정되어 있는 상태면 중복 처리 하지 않음
//
int		CActionMover::ProcessActMsg1( CMover* pMover,  OBJMSG dwMsg, int nParam1, int nParam2, int nParam3, int nParam4, int nParam5 )
{
	CModelObject* pModel = (CModelObject*)pMover->m_pModel;

	switch( dwMsg )
	{
	// 평화모드 제자리에 서있어라!
	case OBJMSG_STAND:
#ifdef __Y_INTERFACE_VER3
		if( (GetMoveState() == OBJSTA_FMOVE) || (GetMoveState() == OBJSTA_BMOVE) || (GetMoveState() == OBJSTA_LMOVE) || (GetMoveState() == OBJSTA_RMOVE) )	// 전/후진중일때 제자리에 세운다.
#else //__Y_INTERFACE_VER3
		if( (GetMoveState() == OBJSTA_FMOVE) || (GetMoveState() == OBJSTA_BMOVE) )	// 전/후진중일때 제자리에 세운다.
#endif //__Y_INTERFACE_VER3
		{
			ResetState( OBJSTA_MOVE_ALL );		
			m_vDelta.x = m_vDelta.z = 0;
			if( pMover->IsFlyingNPC() )
			{
				m_vDelta.y = 0;
				pMover->SetAngleX(0);
			}
		}

		if( GetMoveState() == OBJSTA_STAND )	return 0;
		if( GetMoveState() == OBJSTA_PICKUP )	return 0;
		if( IsActJump() )		return -1;
		if( IsActAttack() )		return -2;
		if( IsActDamage() )		return -3;
		if( IsDie() )			return -4;
		if( IsAction() )		return 0;
		SetMoveState( OBJSTA_STAND );
		pMover->SetMotion( MTI_STAND );
		RemoveStateFlag( OBJSTAF_ETC );
		break;
	case OBJMSG_STOP:		
	case OBJMSG_ASTOP:
	#ifdef __Y_INTERFACE_VER3
		if( (GetMoveState() == OBJSTA_FMOVE) || (GetMoveState() == OBJSTA_BMOVE) || (GetMoveState() == OBJSTA_LMOVE) || (GetMoveState() == OBJSTA_RMOVE) )	// 전/후진중일때 제자리에 세운다.
	#else //__Y_INTERFACE_VER3
		if( (GetMoveState() == OBJSTA_FMOVE) || (GetMoveState() == OBJSTA_BMOVE) )	// 전/후진중일때 제자리에 세운다.
	#endif //__Y_INTERFACE_VER3
		{
			ResetState( OBJSTA_MOVE_ALL );		
			m_vDelta.x = m_vDelta.z = 0;
			if( pMover->IsFlyingNPC() )
			{
				m_vDelta.y = 0;
				pMover->SetAngleX(0);
			}
		}
		pMover->ClearDest();
		return 0;	// ControlGround에서 키입력없을때 STOP을 부르는데 거기서 리턴값을 맞추기 위해 이렇게 했음. 
		break;
	case OBJMSG_SITDOWN:
		if( GetStateFlag() & OBJSTAF_SIT )	return 0;		// 이미 앉은모드면 리턴 - 플래그로 검사하지 말고 state로 직접검사하자.

		if( nParam3 == 0 )
		{
			if( IsActJump() )	return 0;
			if( IsActAttack() )	return 0;
			if( IsActDamage() )	return 0;
			if( IsAction() )	return 0;
		#ifdef __CLIENT
			if( pMover->IsActiveMover() && (pMover->m_dwReqFlag & REQ_USESKILL) )	return 0;		// 서버로부터 useskill응답이 오기전까진 액션해선 안됨.
		#endif	// __CLIENT
		}
		AddStateFlag( OBJSTAF_SIT );		
		SendActMsg( OBJMSG_STOP );
		pMover->SetMotion( MTI_SIT, ANILOOP_CONT );		// 앉기 모션시작
		SetMoveState( OBJSTA_SIT );
		break;
	case OBJMSG_STANDUP:
		if( (GetStateFlag() & OBJSTAF_SIT) == 0 )	return 0;	

		if( nParam3 == 0 )
		{
			if( IsActJump() )	return 0;
			if( IsActAttack() )	return 0;
			if( IsActDamage() )	return 0;
			if( IsAction() )	return 0;
#ifdef __CLIENT
			if( pMover->IsActiveMover() && (pMover->m_dwReqFlag & REQ_USESKILL) )	return 0;		// 서버로부터 useskill응답이 오기전까진 액션해선 안됨.
#endif	// __CLIENT
		}
		SetMoveState( OBJSTA_SIT );
		AddStateFlag( OBJSTAF_SIT );		 
		pMover->SetMotion( MTI_GETUP, ANILOOP_CONT );
		break;
	case OBJMSG_PICKUP:
		if( IsSit() )	return 0;
		if( IsAction() )	return 0;
		if( IsActJump() )	return 0;
		if( IsActAttack() )	return 0;
		if( IsActDamage() )	return 0;
#ifdef __CLIENT
		if( pMover->IsActiveMover() )
		{
			if( pMover->m_dwReqFlag & REQ_USESKILL )	return 0;		// 서버로부터 useskill응답이 오기전까진 액션해선 안됨.
			if( pMover->m_dwReqFlag & REQ_MOTION )		return 0;	// 서버로부터 모션 응답이 오기전까지 액션 금지.
		}
#endif	// __CLIENT
		if( GetMoveState() == OBJSTA_PICKUP )	return 0;	// 이미 집고 있으면 추가로 실행되지 않게 .
		SetMoveState( OBJSTA_PICKUP );
		pMover->SetMotion( MTI_PICKUP, ANILOOP_1PLAY, MOP_FIXED );
		break;

	case OBJMSG_COLLECT:
		
		//if( IsSit() )		return 0;
		//if( IsAction() )	return 0;
		//if( IsActJump() )	return 0;
		//if( IsActAttack() )	return 0;
		//if( IsActDamage() )	return 0;
		//SetState( OBJSTA_ACTION_ALL, OBJSTA_COLLECT );
		//pMover->SetMotion( MTI_COLLECT, ANILOOP_LOOP, MOP_FIXED );
		//pMover->RemoveInvisible();
		
		// 康	// 채집
		ClearState();
		ResetState( OBJSTA_ACTION_ALL );
		SetState( OBJSTA_ACTION_ALL, OBJSTA_COLLECT );
		//pMover->m_dwFlag |= MVRF_NOACTION;
		pMover->SetMotion( MTI_COLLECT, ANILOOP_LOOP, MOP_FIXED );
		pMover->RemoveInvisible();
		break;

	case OBJMSG_STUN:
		SetState( OBJSTA_ACTION_ALL, OBJSTA_STUN );		// 스턴은 어떤 상태에서도 걸릴 수 있으니 상태는 무조것 세팅하자.
		pMover->m_dwFlag |= MVRF_NOACTION;				// 액션 금지 상태로 전환.
		pMover->m_wStunCnt = (short)nParam1;			// 얼마동안이나 스턴상태가 되느냐.

		if( GetState() == OBJSTA_STAND )
			pMover->SetMotion( MTI_GROGGY, ANILOOP_LOOP, MOP_FIXED );		// 아무것도 안하는 스탠딩 상태면 스턴 모션 내자.
		break;
		
	case OBJMSG_FALL:
		if( IsActJump() )	return 0;

		// 무적이면 여기서 리턴.
		if( pMover->m_dwMode & MATCHLESS_MODE )		
			return 0;
		
		pMover->m_dwFlag |= MVRF_NOACTION;				// 액션 금지 상태로 전환.
		
		if( GetState() != OBJSTA_DMG_FLY )
		{
			SetState( OBJSTA_DMG_ALL, OBJSTA_DMG_FLY );	
			pMover->SetMotion( MTI_DMGFLY, ANILOOP_LOOP, MOP_FIXED );
		}
		break;
		
	// 전진해라!
	case OBJMSG_TURNMOVE:
		if( GetMoveState() == OBJSTA_FMOVE && (int)pMover->GetAngle() == nParam1 )	return 0;	// 전진 상태이며 각도가 같으면 메시지 무효 
		if( pMover->m_dwFlag & MVRF_NOMOVE )	
			return 0;		// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
		if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans
		
		if( GetState() & OBJSTA_DMG_FLY_ALL )	// 날라가는 동작중이면 취소
			return 0;
		
		if( IsActAttack() )		return -2;
		if( GetDmgState() == OBJSTA_DMG )	// 피격 중 명령이면 피격 상태를 클리어 시킨다.
			ResetState( OBJSTA_DMG_ALL );
		else if( GetState() & OBJSTA_DMG_ALL )	// 그외 피격동작은 다 취소
			return -3;
		pMover->SetAngle( (float)nParam1 );
		if( pMover->IsFlyingNPC() )
			pMover->SetAngleX( (float)nParam2 );
		SendActMsg( OBJMSG_STOP_TURN );
		SendActMsg( OBJMSG_FORWARD );
		break;
	case OBJMSG_TURNMOVE2:
		if( GetMoveState() == OBJSTA_FMOVE && (int)pMover->GetAngle() == nParam1 )	return 0;	// 전진 상태이며 각도가 같으면 메시지 무효 
		if( pMover->m_dwFlag & MVRF_NOMOVE )	return 0;		// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
		if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans

		if( IsAction() )	return 0;

		if( GetState() & OBJSTA_DMG_FLY_ALL )	// 날라가는 동작중이면 취소
			return 0;

		if( IsActJump() )	return -1;	// 점프거나 공격 상태면 메시지 무효 처리
		if( IsActAttack() )		return -2;
		if( GetDmgState() == OBJSTA_DMG )	// 피격 중 명령이면 피격 상태를 클리어 시킨다.
			ResetState( OBJSTA_DMG_ALL );
		else if( GetState() & OBJSTA_DMG_ALL )	// 그외 피격동작은 다 취소
			return -3;
		pMover->SetAngle( (float)nParam1 );
		if( pMover->IsFlyingNPC() )
			pMover->SetAngleX( (float)nParam2 );
		SendActMsg( OBJMSG_STOP_TURN );
		SendActMsg( OBJMSG_BACKWARD );
		break;

#ifdef __Y_INTERFACE_VER3
	case OBJMSG_LFORWARD:
		if( IsActJump() )	return -1;
		if( IsActAttack() )		return -2;
		if( GetDmgState() == OBJSTA_DMG )	// 피격 중 명령이면 피격 상태를 클리어 시킨다.
			ResetState( OBJSTA_DMG_ALL );
		else
			if( GetState() & OBJSTA_DMG_ALL )	// 그외 피격동작은 다 취소
				return -3;
		if( GetMoveState() == OBJSTA_LMOVE )	return 0;	// 이미 전진상태면 추가로 처리 하지 않음
		if( IsSit() )		return 0;		// 리턴 0으로 해도 되나?.
		if( pMover->m_dwFlag & MVRF_NOMOVE )	return 0;		// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
		if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans

		SetMoveState( OBJSTA_LMOVE );
		if( IsStateFlag( OBJSTAF_WALK ) )	// 걷는모드
		{
			pMover->SetMotion( MTI_WALK );		// 전투모드로 걷기
		} 
		else
		{
			if( pMover->SetMotion( MTI_RUN ) )
				pModel->SetMotionBlending( TRUE );
		}
		break;
	case OBJMSG_RFORWARD:
		if( IsActJump() )	return -1;
		if( IsActAttack() )		return -2;
		if( GetDmgState() == OBJSTA_DMG )	// 피격 중 명령이면 피격 상태를 클리어 시킨다.
			ResetState( OBJSTA_DMG_ALL );
		else
			if( GetState() & OBJSTA_DMG_ALL )	// 그외 피격동작은 다 취소
				return -3;
		if( GetMoveState() == OBJSTA_RMOVE )	return 0;	// 이미 전진상태면 추가로 처리 하지 않음
		if( IsSit() )		return 0;		// 리턴 0으로 해도 되나?.
		if( pMover->m_dwFlag & MVRF_NOMOVE )	return 0;		// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
		if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans

		SetMoveState( OBJSTA_RMOVE );
		if( IsStateFlag( OBJSTAF_WALK ) )	// 걷는모드
		{
			pMover->SetMotion( MTI_WALK );		// 전투모드로 걷기
		} 
		else
		{
			if( pMover->SetMotion( MTI_RUN ) )
				pModel->SetMotionBlending( TRUE );
		}
		break;
#endif //__Y_INTERFACE_VER3

	case OBJMSG_FORWARD:
		if( IsActJump() )	return -1;
		if( IsActAttack() )		return -2;
		if( GetDmgState() == OBJSTA_DMG )	// 피격 중 명령이면 피격 상태를 클리어 시킨다.
			ResetState( OBJSTA_DMG_ALL );
		else if( GetState() & OBJSTA_DMG_ALL )	// 그외 피격동작은 다 취소
				return -3;
		if( GetMoveState() == OBJSTA_FMOVE )	return 0;	// 이미 전진상태면 추가로 처리 하지 않음
		if( IsSit() )		return 0;		// 리턴 0으로 해도 되나?.
		if( pMover->m_dwFlag & MVRF_NOMOVE )	return 0;		// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
		if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans

		SetMoveState( OBJSTA_FMOVE );
		if( IsStateFlag( OBJSTAF_WALK ) )	// 걷는모드
		{
			pMover->SetMotion( MTI_WALK );	
		} 
		else
		{
			if( pMover->SetMotion( MTI_RUN ) )
				pModel->SetMotionBlending( TRUE );
		}
		pMover->OnActFMove();
		break;
		
	case OBJMSG_STOP_RUN:
	#ifdef __CLIENT
		if( IsActJump() )	return -1;
		if( IsActAttack() )		return -2;
		if( GetDmgState() == OBJSTA_DMG )	// 피격 중 명령이면 피격 상태를 클리어 시킨다.
			ResetState( OBJSTA_DMG_ALL );
		else if( GetState() & OBJSTA_DMG_ALL )	// 그외 피격동작은 다 취소
			return -3;
		if( GetMoveState() == OBJSTA_STOP_RUN )	return 0;	// 이미 전진상태면 추가로 처리 하지 않음
		if( IsSit() )		return 0;						// 리턴 0으로 해도 되나?.
		if( pMover->m_dwFlag & MVRF_NOMOVE )	return 0;	// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
		if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans

		SetMoveState( OBJSTA_STOP_RUN );
	#endif
		break;

	
	// 후진해라!
	case OBJMSG_BACKWARD:
		if( IsActJump() )	return -1;	// if jump, x
		if( IsActAttack() )		return -2;	// 공격동작중이면 취소됨.
		if( IsActDamage() )		return -3;
		if( GetMoveState() == OBJSTA_BMOVE )	return 0;
		if( IsSit() )		return 0;		// 리턴 0으로 해도 되나?.
		if( IsAction() )	return 0;
		if( pMover->m_dwFlag & MVRF_NOMOVE )	return 0;		// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
		if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans

		SetMoveState( OBJSTA_BMOVE );
		pMover->SetMotion( MTI_WALK );		
		break;
	// 좌/우 턴 해라!
	case OBJMSG_LTURN:
		if( IsActJump() )	return -1;
		if( IsActAttack() )		return -2;
		if( GetDmgState() == OBJSTA_DMG )	// 피격 중 명령이면 피격 상태를 클리어 시킨다.
			ResetState( OBJSTA_DMG_ALL );
		else if( GetState() & OBJSTA_DMG_ALL )	// 그외 피격동작은 다 취소
				return -3;
		if( GetTurnState() == OBJSTA_LTURN )	return 0;
		if( IsSit() )		return 0;		// 리턴 0으로 해도 되나?.
		if( IsAction() )	return 0;
		if( pMover->m_dwFlag & MVRF_NOMOVE )	return 0;		// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
		if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans

		SetTurnState( OBJSTA_LTURN );
		break;
	case OBJMSG_RTURN:
		if( IsActJump() )	return -1;
		if( IsActAttack() )		return -2;
		if( GetDmgState() == OBJSTA_DMG )	// 피격 중 명령이면 피격 상태를 클리어 시킨다.
			ResetState( OBJSTA_DMG_ALL );
		else if( GetState() & OBJSTA_DMG_ALL )	// 그외 피격동작은 다 취소
			return -3;
		if( GetTurnState() == OBJSTA_RTURN )	return 0;
		if( IsSit() )		return 0;		// 리턴 0으로 해도 되나?.
		if( IsAction() )	return 0;
		if( pMover->m_dwFlag & MVRF_NOMOVE )	return 0;		// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
		if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans

		SetTurnState( OBJSTA_RTURN );
		break;
	case OBJMSG_STOP_TURN:
		if( GetTurnState() == 0 )		return 0;		// 이미 턴 상태가 없다면 처리 안함
		SetTurnState( 0 );		// 턴을 중지
		break;

	// 피치를 들어올림. 비행몹의 경우만 사용.
	case OBJMSG_LOOKUP:
		if( IsActJump() )	return -1;
		if( IsActAttack() )		return -2;
		if( GetDmgState() == OBJSTA_DMG )	// 피격 중 명령이면 피격 상태를 클리어 시킨다.
			ResetState( OBJSTA_DMG_ALL );
		else if( GetState() & OBJSTA_DMG_ALL )	// 그외 피격동작은 다 취소
			return -3;
		if( GetTurnState() == OBJSTA_LOOKUP )	return 0;
		if( IsSit() )		return 0;		// 리턴 0으로 해도 되나?.
		if( IsAction() )	return 0;
		if( pMover->m_dwFlag & MVRF_NOMOVE )	return 0;		// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
		if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans

		SetLookState( OBJSTA_LOOKUP );
		break;
	case OBJMSG_LOOKDOWN:
		if( IsActJump() )	return -1;
		if( IsActAttack() )		return -2;
		if( GetDmgState() == OBJSTA_DMG )	// 피격 중 명령이면 피격 상태를 클리어 시킨다.
			ResetState( OBJSTA_DMG_ALL );
		else if( GetState() & OBJSTA_DMG_ALL )	// 그외 피격동작은 다 취소
			return -3;
		if( GetTurnState() == OBJSTA_LOOKDOWN )	return 0;
		if( IsSit() )		return 0;		// 리턴 0으로 해도 되나?.
		if( IsAction() )	return 0;
		if( pMover->m_dwFlag & MVRF_NOMOVE )	return 0;		// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
		if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans

		SetLookState( OBJSTA_LOOKDOWN );
		break;
	case OBJMSG_STOP_LOOK:
		if( GetLookState() == 0 )		return 0;
		SetLookState( 0 );		// 룩 중지
		break;
		// 점프
	case OBJMSG_JUMP:
		if( IsActJump() )		return 0;
		if( IsActAttack() )		return -2;
		if( IsActDamage() )		return -3;
		if( IsSit() )			return 0;		// 리턴 0으로 해도 되나?.
		if( IsAction() )		return 0;
		if( pMover->m_dwFlag & MVRF_NOMOVE )	return 0;		// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
		if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans

#ifdef __CLIENT
		if( pMover->IsActiveMover() )
		{
			if( pMover->m_dwReqFlag & REQ_USESKILL )	return 0;	// 서버로부터 useskill응답이 오기전까진 점프해선 안됨.
			if( pMover->m_dwReqFlag & REQ_MOTION )		return 0;	// 서버로부터 모션 응답이 오기전까지 점프 금지.
		}
#endif	// __CLIENT
		SendActMsg( OBJMSG_STOP_TURN );
		SetJumpState( OBJSTA_SJUMP1 );
		if( (GetState() & OBJSTA_COLLECT)== 0 ) pMover->SetMotion( MTI_JUMP1, ANILOOP_1PLAY );
		pModel->SetMotionBlending( FALSE );
		break;
	// 완드공격
	case OBJMSG_ATK_MAGIC1:	// 공격 1
		{
			if( IsAction() )	return 0;
			if( IsSit() )		// 앉아있는상태였으면 해제
				ResetState( OBJSTA_MOVE_ALL );
			if( GetState() & OBJSTA_ATK_ALL )	return 0;		// 이미 공격동작을 하고 있으면 취소.
			if( pMover->m_dwFlag & MVRF_NOATTACK )	return -1;		// 공격금지 상태면 걍 리턴.
			if( pMover->IsMode( NO_ATTACK_MODE ) ) return -1;
			CMover* pHitObj		= prj.GetMover( nParam1 );
			if( IsInvalidObj( pHitObj ) )	return -1;
			if( pHitObj->IsDie() )	return -1;
#ifdef __WORLDSERVER
			if( !g_eLocal.GetState( EVE_STEAL ) )
			{
				if( pMover->IsSteal( pHitObj ) )	// pHitObj를 스틸하려하면 이공격은 무시.
					return -1;
			}
#endif
			if( IsActDamage() )
				ResetState( OBJSTA_DMG_ALL );
			if( IsStateFlag( OBJSTAF_COMBAT ) == FALSE )
				SendActMsg( OBJMSG_MODE_COMBAT );
		
			SendActMsg( OBJMSG_STOP_TURN );
			SendActMsg( OBJMSG_STAND );
			SetState( OBJSTA_ATK_ALL, OBJSTA_ATK_MAGIC1 );
			pMover->SetMotion( MTI_ATK1, ANILOOP_1PLAY );		// 완드동작이 없으므로 공격동작으로 대신함.
			pHitObj->SetJJim( pMover );
			pMover->m_nAtkCnt = 1;		// 카운트 시작.
			pMover->OnAttackStart( pHitObj, dwMsg );			// 공격시작 핸들러.
		}
		break;
		// 레인지공격
	case OBJMSG_ATK_RANGE1:	// 공격 1
		{
			if( IsAction() )	return 0;
			if( pMover->m_dwFlag & MVRF_NOATTACK )	return -1;		// 공격금지 상태면 걍 리턴.
			if( pMover->IsMode( NO_ATTACK_MODE ) ) return -1;
			if( IsSit() )		// 앉아있는상태였으면 해제
				ResetState( OBJSTA_MOVE_ALL );
			if( GetState() & OBJSTA_ATK_ALL )	return 0;		// 이미 공격동작을 하고 있으면 취소.
			CMover* pHitObj		= prj.GetMover( nParam1 );
			if( IsValidObj( (CObj*)pHitObj ) == FALSE )	
				return -1;
			if( pHitObj->IsDie() )
				return -1;

			m_idTarget = (DWORD)nParam1;		// 공격 타겟.

#ifdef __WORLDSERVER
			if( !g_eLocal.GetState( EVE_STEAL ) )
			{
				if( pMover->IsSteal( pHitObj ) )	// pHitObj를 스틸하려하면 이공격은 무시.
					return -1;
			}
#endif
			if( GetDmgState() == OBJSTA_DMG )	// 피격 중 공격명령이면 피격 상태를 클리어 시킨다.
				ResetState( OBJSTA_DMG_ALL );
			else if( GetState() & OBJSTA_DMG_ALL )	// 그외 피격동작은 다 취소
				return -1;
			if( IsStateFlag( OBJSTAF_COMBAT ) == FALSE )
				SendActMsg( OBJMSG_MODE_COMBAT );
			
			int nUseMotion = nParam2;
//			SendActMsg( OBJMSG_STOP_TURN );
//			SendActMsg( OBJMSG_STAND );
			SetState( OBJSTA_ATK_ALL, OBJSTA_ATK_RANGE1 );
			pMover->SetMotion( nUseMotion, ANILOOP_1PLAY );		// 완드동작이 없으므로 공격동작으로 대신함.
			pHitObj->SetJJim( pMover );			// 공격이 시작되면 타겟에다가 내가 찜했다는걸 표시.
			pMover->OnAttackStart( pHitObj, dwMsg );			// 공격시작 핸들러.
			pMover->m_nAtkCnt = 1;		// 카운트 시작.
		}
		break;
		// 공격 - 리턴값 -2는 클라로 부터 받은 명령을 완전 무시한다.
	case OBJMSG_ATK1:	// 공격 1
	case OBJMSG_ATK2:	// 공격 2
	case OBJMSG_ATK3:	// 공격 3	
	case OBJMSG_ATK4:	// 공격 4
		{
			if( IsAction() )
				return 0;
			if( pMover->m_dwFlag & MVRF_NOATTACK )
				return -2;		// 공격금지 상태면 걍 리턴.
			if( pMover->IsMode( NO_ATTACK_MODE ) )
				return -2;

#ifdef __CLIENT
			if( pMover->IsActiveMover() )
#endif
			{
				// 기본은 오른손 검사( 완드용 )
				CItemElem* pItemElem = pMover->GetWeaponItem();
				if( pItemElem && (pItemElem->GetProp()->dwItemKind3 == IK3_WAND || pItemElem->GetProp()->dwItemKind3 == IK3_BOW ) )
					return -2;
			}
				
			CMover* pHitObj		= prj.GetMover( nParam1 );
			if( IsValidObj( (CObj*)pHitObj ) == FALSE )
				return( -1 );

#ifdef __XUZHU
			if( pMover->IsPlayer() )
			{
				int a = 0;
			}
#endif // xuzhu
			m_idTarget = (DWORD)nParam1;		// 공격 타겟.
#ifdef __WORLDSERVER
			if( !g_eLocal.GetState( EVE_STEAL ) )
			{
				if( pMover->IsSteal( pHitObj ) )	// pHitObj를 스틸하려하면 이공격은 무시.
					return -2;
			}
#endif
			if( pHitObj->m_pActMover->IsDie() )	return( -1 );
			if( GetState() & OBJSTA_ATK_ALL )	return( 0 );	// 이미 공격중이면 리턴
			if( IsSit() )		// 앉아있는상태였으면 해제
				ResetState( OBJSTA_MOVE_ALL );
			if( GetDmgState() == OBJSTA_DMG )	// 피격 중 공격명령이면 피격 상태를 클리어 시킨다.
				ResetState( OBJSTA_DMG_ALL );
			else
			if( GetState() & OBJSTA_DMG_ALL )	// 그외 피격동작은 다 취소
				return -3;
			if( IsStateFlag( OBJSTAF_COMBAT ) == FALSE )
				SendActMsg( OBJMSG_MODE_COMBAT );
			SendActMsg( OBJMSG_STOP_TURN );	// 공격할땐 턴을 정지시킴
			SendActMsg( OBJMSG_STAND );
			

			DWORD dwOption = MOP_SWDFORCE | MOP_NO_TRANS;
			
#ifdef __XSLOW1018
			int nMin, nTemp;
			pMover->GetHitMinMax( &nMin, &nTemp );
			if( dwMsg == OBJMSG_ATK3 || dwMsg == OBJMSG_ATK4 )
				if( pMover->GetLevel() >= 12 && pHitObj->GetHitPoint() < (int)(nMin * 1.5f) )
					dwOption |= MOP_HITSLOW;
#endif // xSlow1018
			if( pMover->IsPlayer() )
				pMover->m_fAniSpeed = pMover->GetAttackSpeed();
			
			switch( dwMsg )
			{
				case OBJMSG_ATK1:
					SetState( OBJSTA_ATK_ALL, OBJSTA_ATK1 );
					pMover->SetMotion( MTI_ATK1, ANILOOP_1PLAY, dwOption );		// 최초 메시지 입력시 동작 설정
					break;
				case OBJMSG_ATK2:	
					SetState( OBJSTA_ATK_ALL, OBJSTA_ATK2 );
					pMover->SetMotion( MTI_ATK2, ANILOOP_1PLAY, dwOption );		// 최초 메시지 입력시 동작 설정
					break;
				case OBJMSG_ATK3:	
					SetState( OBJSTA_ATK_ALL, OBJSTA_ATK3 );
					pMover->SetMotion( MTI_ATK3, ANILOOP_1PLAY, dwOption );		// 최초 메시지 입력시 동작 설정
					break;
				case OBJMSG_ATK4:	
					SetState( OBJSTA_ATK_ALL, OBJSTA_ATK4 );
					pMover->SetMotion( MTI_ATK4, ANILOOP_1PLAY, dwOption );		// 최초 메시지 입력시 동작 설정
					break;
			}
			pMover->SetAngle( GetDegree( pHitObj->GetPos(), m_pMover->GetPos() ) );
			pHitObj->SetJJim( pMover );

			pMover->m_nAtkCnt = 1;		// 카운트 시작.
			pMover->OnAttackStart( pHitObj, dwMsg );			// 공격시작 핸들러.
			m_objidHit	= (OBJID)nParam1;	// 타겟의 아이디.	

			m_dwAtkFlags	= (DWORD)LOWORD( (DWORD)nParam3 );
#ifdef __WORLDSERVER
			if( m_dwAtkFlags == 0 ) 
			{
				if( pMover->GetAttackResult( pHitObj, dwOption ) )		// 공격 성공률을 얻는다.
					m_dwAtkFlags = AF_GENERIC;
				else
					m_dwAtkFlags = AF_MISS;
			}
#else
			m_dwAtkFlags = AF_GENERIC;		// 구조가 좀 이상한데. 클라에서는 명중판정을 하지 않으므로 무조건 평타명중으로 인정.
#endif
			
			return( (int)m_dwAtkFlags );
			break;
		}	
	// 몬스터들의 특수공격.
	case OBJMSG_SP_ATK1:
	case OBJMSG_SP_ATK2:
		{
			CMover* pHitObj		= prj.GetMover( nParam1 );
			//nParam2;		// 특수공격에 사용할 무기. 보통은 몬스터이므로 가상아이템이 들어온다.
			int		nUseMotion	= nParam3;		// 사용할 모션.
			if( IsValidObj( (CObj*)pHitObj ) == FALSE )	return( -1 );
			if( pHitObj->m_pActMover->IsDie() )	return( -1 );
			if( GetState() & OBJSTA_ATK_ALL )	return( 0 );	// 이미 공격중이면 리턴
			if( pMover->m_dwFlag & MVRF_NOATTACK )	return 0;		// 공격금지 상태면 걍 리턴.
			if( GetDmgState() == OBJSTA_DMG )	// 피격 중 공격명령이면 피격 상태를 클리어 시킨다.
				ResetState( OBJSTA_DMG_ALL );
			else
			if( GetState() & OBJSTA_DMG_ALL )	// 그외 피격동작은 다 취소
				return -3;
			if( IsStateFlag( OBJSTAF_COMBAT ) == FALSE )
				SendActMsg( OBJMSG_MODE_COMBAT );
			SendActMsg( OBJMSG_STOP_TURN );	// 공격할땐 턴을 정지시킴
			SendActMsg( OBJMSG_STAND );

			DWORD dwOption = MOP_SWDFORCE /*| MOP_NO_TRANS*/;	// 몬스터니까 공격동작도 모션트랜지션 되게 해봤다.
			SetState( OBJSTA_ATK_ALL, OBJSTA_SP_ATK1 );
			pMover->SetMotion( nUseMotion, ANILOOP_1PLAY, dwOption );		// 최초 메시지 입력시 동작 설정
			pMover->SetAngle( GetDegree( pHitObj->GetPos(), m_pMover->GetPos() ) );
			pMover->OnAttackStart( pHitObj, dwMsg );			// 공격시작 핸들러.
			return 1;
		}
		break;

	// 전사들의 근접 전투스킬류
	case OBJMSG_MELEESKILL:
		{
			if( IsAction() )	return -2;	
			if( pMover->m_dwFlag & MVRF_NOATTACK )	return -2;		// 공격금지 상태면 걍 리턴.
			CMover* pHitObj		= prj.GetMover( nParam2 );
			if( IsValidObj( pHitObj ) == FALSE )	return -2;
#ifdef __WORLDSERVER
			if( GetState() & OBJSTA_ATK_RANGE1 )
				ResetState( OBJSTA_ATK_RANGE1 );
			if( GetState() & OBJSTA_ATK_ALL )	return -2;	// 이미 공격중이면 리턴. 서버에선 씹히지 않게 하자.
			pMover->m_dwMotion = -1;	// 나머지 경우는 간단하게 생각하기 위해 모두 클리어 시키고 스킬만 실행하자.
			ClearState();				// 상태 클리어하고 다시 맞춤,.
#else
			// 이리저리 해보니 액티브 무버건 아니건 서버에서 신호오면 바로 시작하는게 좋을거 같애서 이렇게 함.
			pMover->m_dwMotion = -1;	
			ClearState();				// 상태 클리어하고 다시 맞춤,.
#endif
			SetState( OBJSTA_ATK_ALL, OBJSTA_ATK_MELEESKILL );			// 근접전투스킬상태 설정.
			DWORD dwMotion = (DWORD)nParam1;
			int	nLoop = ANILOOP_1PLAY;

			int	nSkill = pMover->GetActParam( 0 );
			if( nSkill == SI_BLD_DOUBLESW_SILENTSTRIKE || nSkill == SI_ACR_YOYO_COUNTER )
				nLoop = ANILOOP_CONT;

#ifdef __CLIENT			
			if( pMover->HasBuffByIk3( IK3_TEXT_DISGUISE ) )
				dwMotion = MTI_ATK1;
#endif

			pMover->SetMotion( dwMotion, nLoop, MOP_SWDFORCE | MOP_NO_TRANS | MOP_FIXED );		// 해당 동작애니 시작.
			pMover->OnAttackStart( pHitObj, dwMsg );			// 공격시작 핸들러.
			
			m_nMotionHitCount = 0;
			
			break;
		}
	// 마법사들의 마법스킬류.
	case OBJMSG_MAGICSKILL:
	case OBJMSG_MAGICCASTING:
		{
			if( IsAction() )	return -2;
			if( pMover->m_dwFlag & MVRF_NOATTACK )	return -2;		// 공격금지 상태면 걍 리턴.
			CMover* pHitObj		= prj.GetMover( nParam2 );
			if( IsValidObj( pHitObj ) == FALSE )	return -2;
		#ifdef __WORLDSERVER
			if( GetState() & OBJSTA_ATK_ALL )	return -2;	// 이미 공격중이면 리턴
		#endif  

			pMover->m_dwMotion = -1;	
			ClearState();				// 상태 클리어하고 다시 맞춤.

			m_nCastingTime	= nParam3 * 4;	// ProcessAction은 서버/클라 호출 회수 동일하므로, SEC1 사용이 적당하지 않다.

#if __VER >= 10 // __LEGEND	//	9차 전승시스템	Neuz, World, Trans
			m_dwCastingEndTick = (DWORD)( GetTickCount() + nParam3 * 66.66F );
			m_nCastingTick	= (int)( nParam3 * 66.66F );
			m_nCastingSKillID = nParam4;
#endif	//__LEGEND	//	9차 전승시스템	Neuz, World, Trans
			if( m_nCastingTime > 0 )	// 캐스팅 타임이 있을때만...
			{
				m_nCount	= 0;	// 전체 캐스팅 타임은 동작1+동작2의 합이어야 하므로 여기서 카운터를 초기화 한다.
				SetState( OBJSTA_ATK_ALL, OBJSTA_ATK_CASTING1 );			// 캐스팅부터 시작 -> 발사모션.
			}
			else
				SetState( OBJSTA_ATK_ALL, OBJSTA_ATK_MAGICSKILL );			// 발사모션만.

		#ifdef __CLIENT
			if( dwMsg == OBJMSG_MAGICSKILL && pMover->HasBuffByIk3( IK3_TEXT_DISGUISE ) )
				nParam1 = MTI_ATK1;
		#endif

			pMover->SetMotion( nParam1, ANILOOP_1PLAY, MOP_SWDFORCE | MOP_NO_TRANS | MOP_FIXED );		// 해당 동작애니 시작.
			pMover->OnAttackStart( pHitObj, dwMsg );			// 공격시작 핸들러.
			m_nMotionHitCount = 0;
			break;
		}
			

	//-------------------- 맞았다.
	case OBJMSG_DAMAGE:
	case OBJMSG_DAMAGE_FORCE:	// 강공격에 맞았다. 날아감.
		{
			CMover* pAttacker = PreProcessDamage( pMover, (OBJID)nParam2, nParam4, nParam5 );
			if( pAttacker == NULL )
				return 0;

			if( dwMsg == OBJMSG_DAMAGE_FORCE )			// 강공격으로 들어왔을때
				if( pMover->CanFlyByAttack() == FALSE )	// 날아가지 못하는 상태면.
					dwMsg = OBJMSG_DAMAGE;				// 일반 데미지로 바꿈.

			// 실제 가격한 데미지를 리턴함.
			int nDamage = _ProcessMsgDmg( dwMsg, pAttacker, (DWORD)nParam1, nParam3, nParam4, nParam5 );	
#if __VER >= 10	// __METEONYKER_0608
#ifdef __WORLDSERVER
#if __VER >= 12 // __NEW_ITEMCREATEMON_SERVER
			if( pAttacker->IsPlayer() && CCreateMonster::GetInstance()->IsAttackAble( static_cast<CUser*>(pAttacker), pMover ) )
#endif // __NEW_ITEMCREATEMON_SERVER
#endif // __WORLDSERVER
				pMover->PostAIMsg( AIMSG_DAMAGE, pAttacker->GetId(), nDamage );
#endif	// __METEONYKER_0608
			return nDamage;
		}
		break;

	// HP가 0이 된 순간 호출
	case OBJMSG_DIE:
	{
		if( IsSit() )						// 앉아있는상태였으면 해제
			ResetState( OBJSTA_MOVE_ALL );
		
		ClearState();						// 죽을땐 다른 동작 하고 있던거 다 클리어 시켜버리자.
		m_vDelta.x = m_vDelta.z = 0;		// 죽었으면 델타값 클리어.

		pMover->RemoveInvisible();
#ifdef __WORLDSERVER
		pMover->PostAIMsg( AIMSG_DIE, nParam2 );
#endif
		CMover *pAttacker = (CMover *)nParam2;	
		if( pAttacker )
		{
			if( pMover->IsPlayer() && pAttacker->IsPlayer() )	// 죽은놈과 죽인놈이 플레이어고
			{
#ifdef __WORLDSERVER
				if( pMover->m_nDuel == 1 && pMover->m_idDuelOther == pAttacker->GetId() )	// 둘이 듀얼중이었으면
				{
					pMover->ClearDuel();
					pAttacker->ClearDuel();
					((CUser*)pMover)->AddSetDuel( pMover );
					((CUser*)pAttacker)->AddSetDuel( pAttacker );
				}
				else if( pMover->m_nDuel == 2 && pMover->m_idDuelParty == pAttacker->m_idparty )
				{
					pMover->m_nDuelState	= 300;		
					CMover *pMember;
					CParty* pParty	= g_PartyMng.GetParty( pMover->m_idparty );

					if( pParty )
					{
						int i; for( i = 0; i < pParty->m_nSizeofMember; i ++ )
						{
							pMember = (CMover *)g_UserMng.GetUserByPlayerID( pParty->m_aMember[i].m_uPlayerId );
							if( IsValidObj( pMember ) )
								((CUser*)pMember)->AddSetDuel( pMover );
						}
					}

					CParty* pParty2		= g_PartyMng.GetParty( pMover->m_idDuelParty );
					if( pParty2 )
					{
						int i; for( i = 0; i < pParty2->m_nSizeofMember; i ++ )
						{
							pMember = (CMover *)g_UserMng.GetUserByPlayerID( pParty2->m_aMember[i].m_uPlayerId );
							if( IsValidObj( pMember ) )
								((CUser*)pMember)->AddSetDuel( pMover );
						}
					}
				}
#endif	// __WORLDSERVER
			}

			if( pAttacker->IsNPC() )	// 공격자가 몹.
			{	// 날때린몹의 어태커가 나일경우는 죽기전에 클리어시켜준다.
				if( pAttacker->m_idAttacker == pMover->GetId() )	// 공격한몹을 친사람이 나일경우는 스틸체크 해제.
				{
					pAttacker->m_idAttacker = NULL_ID;
					pAttacker->m_idTargeter = NULL_ID;
				}
			}
		}
		
		switch( nParam1 )
		{
#ifdef __BS_DEATH_ACTION
		case OBJMSG_DAMAGE:
		case OBJMSG_DAMAGE_FORCE:
		{
			int rAngle = 0;
			int rPower = 0;
			int nCase = rand() % 6;
			if( nCase < 3 )
			{
				rAngle = -2;
				rPower = 10 + rand() % 50;
			}
			else if( nCase < 4 )
			{
				rAngle = 10;
				rPower = 10 + rand() % 50;
			}
			else if( nCase < 5 )
			{
				rAngle = 50;
				rPower = 10 + rand() % 50;
			}
			else
			{
				rAngle = rand() % 30;
				rPower = rand() % 200;
			}
			
			if( OBJMSG_DAMAGE_FORCE == nParam1 )
				rPower += 50;
		
			CMover *pAttacker = (CMover *)nParam2;
			SetState( OBJSTA_DMG_ALL, OBJSTA_DMG_FLY );
			pMover->SetMotion( MTI_DMGFLY, ANILOOP_CONT );
			if( pAttacker )
			{
				float faddPower = rPower * 0.01f;
				float faddAngle = (float)( rAngle );

				DoDamageFly( pAttacker->GetAngle(), 100.0f + faddAngle, 0.05f + faddPower );	// 어태커가 보는쪽으로 날려보냄.
			}
		}
		break;
#else
		case OBJMSG_DAMAGE_FORCE:	// 강 공격으로 죽었다면 날아가서 죽기
			{
			CMover *pAttacker = (CMover *)nParam2;
			SetState( OBJSTA_DMG_ALL, OBJSTA_DMG_FLY );
			pMover->SetMotion( MTI_DMGFLY, ANILOOP_CONT );
			if( pAttacker )
				DoDamageFly( pAttacker->GetAngle(), 145.0f, 0.25f );	// 어태커가 보는쪽으로 날려보냄.
			}
			break;
		case OBJMSG_DAMAGE:		// 걍 일반 데미지로 죽었다면 그냥 쓰러져 죽기
#endif
		default:	
			SetState( OBJSTA_DMG_ALL, OBJSTA_DEAD );
			pMover->SetMotion( MTI_DIE1, ANILOOP_CONT );
			break;

		}

		if( !pMover->IsPlayer() )	// 몬스터일 경우.
		{
		#ifdef __WORLDSERVER			
			m_nDeadCnt	= 60*3;	// 디폴트 - 3초 후에 없어짐.
			MoverProp *pProp = pMover->GetProp();
			if( pProp )
			{
				
				if( pProp->dwSourceMaterial != NULL_ID || pProp->dwClass == RANK_MATERIAL )	// 자원 몹이면..
				{
					if( pProp->dwHoldingTime == NULL_ID )
						Error( "%s 의 MoverProp::dwHoldingTime 값이 -1", pMover->GetName() );
					m_nDeadCnt = (int)(60.0f * (pProp->dwHoldingTime / 1000.0f));
					if( pProp->dwHoldingTime < 10000 )		// 10초 이하일때
						Error( "dwHoldingTime : %d %s", pProp->dwHoldingTime, pMover->GetName() );
					pMover->m_nCollectOwnCnt = PROCESS_COUNT * 40;
					CMover *pAttacker = (CMover *)nParam2;	
					if( pAttacker )
						pMover->m_idCollecter = pAttacker->GetId();		// 공격자가 소유자가 된다.
					
				}
				{
					if( pProp->dwSourceMaterial == NULL_ID && pProp->dwClass == RANK_MATERIAL )	// 자원몹인데 자원값이 없는경우
						Error( "OBJMSG_DIE : %s %d", pMover->GetName(), pProp->dwSourceMaterial );
					if( pProp->dwSourceMaterial != NULL_ID && pProp->dwClass != RANK_MATERIAL )	// 자원몹이 아닌데 자원값이 있는경우.
						Error( "OBJMSG_DIE 2 : %s %d", pMover->GetName(), pProp->dwSourceMaterial );
				}
				
			}
		#endif // WorldServer
		}
		break;
	}
		
	case OBJMSG_APPEAR:
		SetState( OBJSTA_ACTION_ALL, OBJSTA_APPEAR );
		pMover->SetMotion( MTI_APPEAR2, ANILOOP_1PLAY, MOP_FIXED | MOP_NO_TRANS );
		break;
	//---- 모드전환 ------------------------
	case OBJMSG_MODE_COMBAT:
		if( GetStateFlag() & OBJSTAF_COMBAT )	return 0;		// 이미 전투모드면 리턴
		if( IsActJump() )	return 0;
		if( IsActAttack() )	return 0;
		if( IsActDamage() )	return 0;
		if( IsSit() )		return 0;
		if( IsAction() )	return 0;
		AddStateFlag( OBJSTAF_COMBAT );	// 전투모드로 서라가 아니고 전투모드로 바꿔라기땜에 서다 명령은 발생시키지 않는다.
		pMover->m_dwMotion = -1;	// 같은 모션을 하라고 한거라 모션이 안바뀌므로 이렇게...
		pMover->SetMotion( MTI_STAND );
		break;
	case OBJMSG_MODE_PEACE:
		if( (GetStateFlag() & OBJSTAF_COMBAT) == 0 )	return 0;
		if( IsActJump() )	return 0;
		if( IsActAttack() )	return 0;
		if( IsActDamage() )	return 0;
		if( IsSit() )		return 0;
		if( IsAction() )	return 0;
		RemoveStateFlag( OBJSTAF_COMBAT );
		pMover->m_dwMotion = -1;
		pMover->SetMotion( MTI_STAND );
		break;
	case OBJMSG_MODE_WALK:
		if( IsSit() )		return 0;
		if( IsAction() )	return 0;
		if( GetStateFlag() & OBJSTAF_WALK )	return 0;		// 이미 걷기모드면 리턴
		AddStateFlag( OBJSTAF_WALK );
		break;
	case OBJMSG_MODE_RUN:
		if( IsSit() )		return 0;
		if( IsAction() )	return 0;
		if( (GetStateFlag() & OBJSTAF_WALK) == 0 )	return 0;		// 
		RemoveStateFlag( OBJSTAF_WALK );
		break;
	case OBJMSG_MODE_FLY:
	{
		if( nParam3 == 0 )
		{
			if( IsSit() )		return 0;
			if( IsAction() )	return 0;
			if( IsActAttack() )	return 0;
			if( pMover->m_dwFlag & MVRF_NOMOVE )	return 0;		// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
			if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans

			{
				CWorld* pWorld	= pMover->GetWorld();
				if( pWorld )
				{
					int nAttr = pMover->GetWorld()->GetHeightAttribute( pMover->GetPos().x, pMover->GetPos().z );		// 이동할 위치의 속성 읽음.
					if( nAttr == HATTR_NOFLY )		// 비행 금지 지역에서 타려고 하면 못탄다.
						return 0;
				}
			}
		}
		AddStateFlag( OBJSTAF_FLY );
		ItemProp *pItemProp = prj.GetItemProp( nParam1 );	// 빗자루 프로퍼티.
		if( pItemProp )
		{
			if( pMover->m_nFuel == -1 )		// 초기값이면
				pMover->m_nFuel = (int)pItemProp->dwFFuelReMax;	// 빗자루 최대 연료량을 세팅.
			// -1일때만 세팅해야지 연료를 반쯤 쓰다가 빗자루를 바꿔도 새로 세팅 되지 않는다.
		}
#ifndef __JEFF_9_20
#ifdef __WORLDSERVER
		if( pMover->IsPlayer() )
		{
			((CUser*)pMover)->SetFlyTimeOn();
		}
#endif // __WORLDSERVER
#endif	// __JEFF_9_20
		ClearState();
#ifdef __CLIENT
		if( m_pMover == CMover::GetActiveMover() )
		{
			m_pMover->GetWorld()->SetObjFocus( NULL );	// 비행직전에 기존타겟팅을 클리어해준다.
			g_Neuz.m_camera.Unlock();
			g_WndMng.m_pWndTaskBar->OnCancelSkill();	// 비행직전엔 스킬바 사용 취소.
		}
#endif

		CModel* pModel = prj.m_modelMng.LoadModel( D3DDEVICE, OT_ITEM, (DWORD) nParam1 );
#if __VER >= 14 // __WING_ITEM
		CModelObject* pModelObject = (CModelObject*)pModel;
		if( pModelObject->m_pBone )
		{
			CString strMotion = pModelObject->GetMotionFileName( _T("stand") );
			assert( strMotion != _T("") );
			pModelObject->LoadMotion( strMotion );
		}
#endif // __WING_ITEM
		m_pMover->SetRide( pModel, (DWORD) nParam1 );
		break;
	}
	case OBJMSG_MOTION:		// 단순 모션 플레이
		{
			if( IsSit() )		return 0;
			if( IsAction() )	return 0;
			if( IsActJump() )	return 0;
			if( IsActAttack() )	return 0;
			if( IsActDamage() )	return 0;
			if( pMover->m_dwFlag & MVRF_NOMOVE )	return 0;		// 이동금지 상태면 걍 리턴.
#if __VER >= 10 // __LEGEND	//	10차 전승시스템	Neuz, World, Trans
		if( pMover->GetAdjParam( DST_CHRSTATE ) & CHS_LOOT)			return 0;
#endif	//__LEGEND	//	10차 전승시스템	Neuz, World, Trans

			AddStateFlag( OBJSTAF_ETC );		// 단순 모션 플레이 상태
			m_nMotionEx = nParam1;				// 모션 인덱스
			int nPlayMode = nParam2;			// 루핑 모드.
			if( m_nMotionEx != -1 )
				pMover->SetMotion( m_nMotionEx, nPlayMode, MOP_FIXED/* | MOP_SWDFORCE*/ );

			pMover->RemoveInvisible();
		}
		break;
	// 일반 액션.
	case OBJMSG_RESURRECTION:		// 부활.
		ClearState();
		SetState( OBJSTA_DMG_ALL, OBJSTA_RESURRECTION );
		pMover->SetMotion( MTI_ASS_RESURRECTION, ANILOOP_1PLAY, MOP_FIXED );
		break;


#if	defined(_DEBUG) && defined(__CLIENT)
	case OBJMSG_TEMP:
		{
			for( int i=0; i < 1; i ++ )
			{

				CMover* pObj = new CMover;
				D3DXVECTOR3 vPos = pMover->GetPos();
				pObj->SetPos( vPos );
				pObj->SetIndex( g_Neuz.m_pd3dDevice, MI_AIBATT1, TRUE );
				pObj->SetMotion( 0 );
				g_WorldMng.Get()->AddObj( pObj, TRUE ); 
			}
		}
		break;
		
	case OBJMSG_TEMP2:	// 디버깅용 공격동작만 볼때.
		if( CMover::GetActiveMover()->IsAuthHigher( AUTH_GAMEMASTER ) )	// 영자 계정일때
		{
			CObj *pObj = pMover->GetWorld()->GetObjFocus();
			g_DPlay.SendCorrReq( pObj );
			g_DPlay.SendError( FE_GENERAL, 0 );
		}
		break;
	
	case OBJMSG_TEMP3:
		{
		#ifdef __XUZHU			
			g_DPlay.SendError( 0, 0 );
		#endif
		}
		break;
#endif // defined(_DEBUG) && defined(__CLIENT)
		
	}
	return 1;
}