示例#1
0
//1表示增益
//2表示减益
BOOL CPKSys::JudgeAttackRelation(CMoveShape *pAttacker,CMoveShape *pBeenAttacker,int nAddSub)
{
	if (pBeenAttacker->IsGod())
	{
		//((CPlayer*)pAttacker)->SendNotifyMessage(AppFrame::GetText("STR_WS_SKILL_FIFTEENTH"),0xffff0000,0,eNOTIFYPOS_CENTER);
		return FALSE;
	}

	if (!IsAttackAble(pAttacker,pBeenAttacker))
	{
		return FALSE;
	}
	CServerRegion* pRegion = dynamic_cast<CServerRegion*>( pAttacker->GetFather() );
	if( !pRegion ) 
		return FALSE;
	//PVP
	if (pAttacker->GetType()==TYPE_PLAYER && pBeenAttacker->GetType()==TYPE_PLAYER && nAddSub==2)
	{		
		CPlayer* pPlayerAttacker	 = dynamic_cast<CPlayer*>( pAttacker );
		CPlayer* pPlayerBeenAttacker = dynamic_cast<CPlayer*>( pBeenAttacker );

		// 如果在nopk场景,玩家不能PK的
		if(0 == pRegion->IsNoPk())
			return FALSE;

		CRegion::eSecurity eBSecurityType =
			pRegion->GetSecurity(pPlayerBeenAttacker->GetTileX(),pPlayerBeenAttacker->GetTileY());
		CRegion::eSecurity eSecurityType = pRegion->GetSecurity(pPlayerAttacker->GetTileX(),pPlayerAttacker->GetTileY());
		if (eSecurityType == CRegion::SECURTIY_SAFE || eBSecurityType == CRegion::SECURTIY_SAFE)
		{
			return FALSE;
		}
		//组队
		if (pPlayerAttacker->IsPk_Team())
		{
			if (pPlayerAttacker->GetTeamID()!=NULL_GUID && pPlayerAttacker->GetTeamID()==pPlayerBeenAttacker->GetTeamID())
			{
				return FALSE;
			}
		}
		//帮会
		if (pPlayerAttacker->IsPk_Union())
		{
			if (pPlayerAttacker->GetFactionID()!=NULL_GUID && pPlayerAttacker->GetFactionID()==pPlayerBeenAttacker->GetFactionID())
			{
				return FALSE;
			}
		}
		//本国
		if (pPlayerAttacker->IsPk_Country())
		{
			//  [9/7/2009 chenxianj]
			//只保护本国白名玩家
			if (pPlayerAttacker->GetCountry()==pPlayerBeenAttacker->GetCountry() && pPlayerBeenAttacker->GetPkValue()==0)
			{
				return FALSE;
			}
		}
		//阵营
		if (pPlayerAttacker->IsPk_Camp())
		{
			//  [9/7/2009 chenxianj]
			//只保护本阵营白名玩家
			if (IsSameCamp(pPlayerAttacker,pPlayerBeenAttacker) && pPlayerBeenAttacker->GetPkValue()==0)
			{
				return FALSE;
			}
		}
		//全体
		if (pPlayerAttacker->IsPk_Normal())
		{
			if(!IsSameCamp(pPlayerAttacker,pPlayerBeenAttacker) && pPlayerBeenAttacker->GetPkValue()==0 && pPlayerBeenAttacker->GetPVPValue()==0)
			{
				return FALSE;
			}			
		}
		//红名
		if (pPlayerAttacker->IsPk_Badman())
		{
			if (pPlayerBeenAttacker->GetPkValue()>0)
			{
				return FALSE;
			}
		}
		//海盗
		if ( pPlayerAttacker->IsPk_Pirate())
		{
			if (pPlayerBeenAttacker->GetPVPValue()>0)
			{
				return FALSE;
			}
		}		
	}
	//PVM
	if (pAttacker->GetType()==TYPE_PLAYER && pBeenAttacker->GetType()==TYPE_MONSTER)
	{
		CPlayer* pPlayerAttacker	 = dynamic_cast<CPlayer*>( pAttacker );
		CMonster* pPlayerBeenAttacker = dynamic_cast<CMonster*>( pBeenAttacker );

		CRegion::eSecurity SecurityType =
			pRegion->GetSecurity(pPlayerBeenAttacker->GetTileX(),pPlayerBeenAttacker->GetTileY());

		if (SecurityType == CRegion::SECURTIY_SAFE && nAddSub==1)
		{
			//人对怪在安全区不能使用增益技能
			return FALSE;
		}	
		if (((CMonster*)pBeenAttacker)->GetNpcType()==NT_Guard)
		{
			//国家
			if (pPlayerAttacker->IsPk_Country())
			{
				if (pAttacker->GetCountry()==pBeenAttacker->GetCountry())
				{
					return FALSE;
				}
			}
			//阵营
			if (pPlayerAttacker->IsPk_Camp())
			{
				if (IsSameCamp(pPlayerAttacker,pPlayerBeenAttacker))
				{
					return FALSE;
				}
			}
			//全体
			if (pPlayerAttacker->IsPk_Normal())
			{
				return FALSE;
			}
		}	
	}
	//MVP
	if (pAttacker->GetType()==TYPE_MONSTER && pBeenAttacker->GetType()==TYPE_PLAYER)
	{
		CMonster* pPlayerAttacker	 = dynamic_cast<CMonster*>( pAttacker );
		CPlayer* pPlayerBeenAttacker = dynamic_cast<CPlayer*>( pBeenAttacker );
		CRegion::eSecurity SecurityType =
			pRegion->GetSecurity(pPlayerBeenAttacker->GetTileX(),pPlayerBeenAttacker->GetTileY());
		if (SecurityType == CRegion::SECURTIY_SAFE && nAddSub==1)
		{
			//怪对人在安全区不能使用增益技能
			return FALSE;
		}	

	}
	return TRUE;
}
示例#2
0
//
// 외부에서 UseSkill을 명령할땐 이것으로 호출하자.
// sutType : 스킬을 사용할때 스킬큐에서 연타로 사용한건가 일반적인 사용을 한건가.c
//
int	CMover::CMD_SetUseSkill( OBJID idTarget, int nSkillIdx, SKILLUSETYPE sutType )
{
	m_oaCmd = OBJACT_NONE;
	TRACE( "CMD_SetUseSkill( " );
	if( m_pActMover->IsFly() )	return 0;				// 비행중엔 스킬사용 금지.
	if( m_pActMover->IsActAttack() )	return 0;
	if( m_pActMover->IsActJump() )	return 0;			// 점프중엔 사용금지.
	if( m_pActMover->GetState() & OBJSTA_DMG_FLY_ALL )		return 0;	// 데미지 플라이중엔 스킬사용금지.
	if( IsDie() )	return 0;		// 죽었을때 사용금지.

	LPSKILL pSkill	= GetSkill( 0, nSkillIdx );		// this가 가진 스킬중 nIdx에 해당하는 스킬을 꺼낸다.
	if( pSkill == NULL )
	{
		Error( "CMD_SetUseSkill : %s skill(%d) not found", m_szName, nSkillIdx );
		return 0;	// 
	}

	ItemProp* pSkillProp = pSkill->GetProp();
	if( pSkillProp == NULL )		// JobSkill 리스트에서 꺼낸 스킬의 프로퍼티를 꺼냄.
	{
		Error( "CMD_SetUseSkill : %s. skill(%d) property not found", m_szName, pSkill->dwSkill );
		return 0;	// 
	}
	
	if( IsPlayer() && IsStateMode( STATE_BASEMOTION_MODE ) )	// 시전중(준비시간)일땐 사용금지.
	{
	#ifdef __CLIENT
		g_DPlay.SendStateModeCancel( STATE_BASEMOTION_MODE, STATEMODE_BASEMOTION_CANCEL );
	#endif 
		return 0;		
	}

	// 도달범위 - 얼마나 가까이 근접해야하는가. 미터단위
	float	fArrivalRange = 0.0f;		
	fArrivalRange = GetAttackRange( pSkillProp->dwAttackRange );
	
	switch( pSkillProp->dwUseChance )
	{
	case WUI_NOW:	// 타겟팅과 상관없이 자기자신에게 쓰는 방식.
		idTarget = GetId();
		break;
	case WUI_TARGETINGOBJ:	// 셀렉트 되어 있는 타겟에게 사용.
		{
#ifdef __CLIENT
		CObj *pFocusObj = GetWorld()->GetObjFocus();
		if( pFocusObj && pFocusObj->GetType() == OT_MOVER )
			idTarget = ((CMover*)pFocusObj)->GetId();
#else
		if( IsPlayer() )
			idTarget = ((CUser *)this)->m_idSetTarget;
#endif // __CLIENT
		}

		break;
#ifdef __CLIENT
	case WUI_TARGETCURSORPTZ:
		{
			idTarget = GetId();
			
			CRect rect;
			D3DXVECTOR3 vPos;
			CWndWorld* pWndWorld;
			
			pWndWorld = (CWndWorld*)g_WndMng.GetWndBase( APP_WORLD );

			rect = pWndWorld->GetClientRect();

			if( GetWorld()->ClientPointToVector( NULL, rect, pWndWorld->GetMousePoint(), &GetWorld()->m_matProj, &GetWorld()->GetCamera()->m_matView, &vPos, TRUE ) )
			{
#ifdef __SKILL0517
				AddSkillProp* pAddSkillProp = prj.GetAddSkillProp( pSkillProp->dwSubDefine, GetSkillLevel( pSkill ) );		// UseSkill에서 사용한 스킬의 프로퍼티 꺼냄
#else	// __SKILL0517
				AddSkillProp* pAddSkillProp = prj.GetAddSkillProp( pSkillProp->dwSubDefine, pSkill->dwLevel );		// UseSkill에서 사용한 스킬의 프로퍼티 꺼냄
#endif	// __SKILL0517
				if( pAddSkillProp == NULL )
				{
					Error( "CMover::OnMagicSkill : %s. add스킬(%d)의 프로퍼티가 없다.", m_szName, nSkillIdx );
					return 0;	// property not found
				}
				
				FLOAT	fDist;
				FLOAT	fMaxDistSq;
				D3DXVECTOR3	vDist;
				fMaxDistSq  = (float)pAddSkillProp->dwSkillRange;
				fMaxDistSq *= fMaxDistSq;
				vDist = vPos - GetPos();
				fDist = D3DXVec3LengthSq( &vDist );	

				SetAngle( GetDegree(vPos, GetPos()) );		// 목표쪽으로 몸을 돌림.
				
				// 텔레포트 할 위치가 멀경우 현제 스킬에 해당하는 거리로 바꿔준다
				if( fDist > fMaxDistSq )
				{
					FLOAT fLength;
					D3DXVECTOR3 vDirNor;
					D3DXVec3Normalize( &vDirNor, &vDist );
					fLength = (float)pAddSkillProp->dwSkillRange;
					float y = vPos.y;
					vPos = GetPos() + (vDirNor * fLength);
					vPos.y	= y;

					// 스킬에 해당하는 거리로 바꾼곳이 못가는 지역이라면 갈수 있는 지역을 검사한다.
					int nAttr = GetWorld()->GetHeightAttribute( vPos.x, vPos.z );

					if( nAttr != HATTR_NONE ) 
					{
						while( nAttr != HATTR_NONE )
						{
							if( nAttr == HATTR_NOFLY )
								break;
							
							fLength -= 1.0f; // 1미터씩 줄여가며 계산한다.
							vPos  = GetPos() + (vDirNor * fLength);
							nAttr = GetWorld()->GetHeightAttribute( vPos.x, vPos.z );

							// 캐릭터의 앞 뒤로 이동불가 일 경우 뒷쪽이 이동불가 해제 될때 까지 계속 계산하여 이동시킴
							// 그러므로 텔레포트 스킬 범위를 넘어설 경우 원래 자리로 텔레포트 하도록 처리
							D3DXVECTOR3 vTemp = vPos - GetPos();
							float fTemp = D3DXVec3LengthSq( &vTemp );
							if(fTemp > fMaxDistSq)
							{
								vPos = GetPos();
								break;
							}
						}
						
						// 한번더 줄여줌
						fLength -= 1.0f; 
						vPos = GetPos() + (vDirNor * fLength);

						// 줄인 곳이 이동불가 지역일 수 있다.
						nAttr = GetWorld()->GetHeightAttribute( vPos.x, vPos.z );
						if( nAttr != HATTR_NONE )
						{
							vPos = GetPos();
						}
					}
				}
				else // 텔레포트 할 위치가 해당스킬 거리보다 작을경우
				{
					int nAttr = GetWorld()->GetHeightAttribute( vPos.x, vPos.z );

					FLOAT fLength;
					D3DXVECTOR3 vDirNor;
					D3DXVec3Normalize( &vDirNor, &vDist );
					fLength = 0.0f;

					while( nAttr != HATTR_NONE )
					{
						if( nAttr == HATTR_NOFLY )
							break;

						fLength -= 1.0f;
						vPos = GetPos() + (vDirNor * fLength);
						
						nAttr = GetWorld()->GetHeightAttribute( vPos.x, vPos.z );

						// 캐릭터의 앞 뒤로 이동불가 일 경우 뒷쪽이 이동불가 해제 될때 까지 계속 계산하여 이동시킴
						// 그러므로 텔레포트 스킬 범위를 넘어설 경우 원래 자리로 텔레포트 하도록 처리
						D3DXVECTOR3 vTemp = vPos - GetPos();
						float fTemp = D3DXVec3LengthSq( &vTemp );
						if(fTemp > fMaxDistSq)
						{
							vPos = GetPos();
							break;
						}
					}
				}

				if( IsActiveMover() && g_eLocal.GetState( EVE_SCHOOL ) )	// 학교이벤섭이면.
				{
					D3DXVECTOR3 v1, v2;
					v1 = GetPos();	v1.y += 0.1f;
					v2 = vPos;		v2.y += 0.1f;
					if( GetWorld()->IntersectObjLine( NULL, v1, v2, FALSE, FALSE ) )	// 텔레포트는 라인체크함.
					{
						g_WndMng.PutString( prj.GetText(TID_GAME_NOMOVING), NULL, prj.GetTextColor(TID_GAME_NOMOVING) );
						g_WndMng.m_pWndWorld->SetNextSkill( NEXTSKILL_NONE );
						return 0;
					}
				}

				pWndWorld->m_vTelePos = vPos;
			}
			else
			{
				g_WndMng.m_pWndWorld->SetNextSkill( NEXTSKILL_NONE );
				g_WndMng.PutString( prj.GetText(TID_GAME_NOMOVING), NULL, prj.GetTextColor(TID_GAME_NOMOVING) );
				return 0;
			}
		}
		break;
#endif // __CLIENT
	}

	// 타인에게 쓰는경우에만 검사...
	if( idTarget != GetId() )		
	{
		CMover *pTarget = prj.GetMover( idTarget );
		if( IsValidObj(pTarget) )
		{
			if( pSkillProp->nEvildoing < 0 )	// 나쁜 스킬은 
				if( IsAttackAble(pTarget) == FALSE )	// 공격허용이 되지 않으면 사용할 수 없음.
					return 0;
				
			if( pSkill->dwSkill == SI_ASS_HEAL_RESURRECTION )	// 부활을 사용했을때
			{
				if( pTarget->IsNPC() || pTarget->IsDie() == FALSE )		// 상대가 NPC거나 상대가 죽어있지 않다면 취소
					return 0;
			} else
			{
				if( pTarget->IsDie() )		// 부활이 아닌 스킬을 사용했을때 상대가 죽어있으면 사용안됨.
					return 0;
			}
		}
	}

	// 타겟 근접 방식.
	switch( pSkillProp->dwExeTarget )
	{
	case EXT_SELFCHGPARAMET:	// 시전자 자신에게 사용하는 종류
		idTarget = GetId();		// 타겟을 자기자신으로 설정.
		SetDestObj( idTarget, fArrivalRange, TRUE );		// 이동할 목표물을 idTarget으로 설정. << 이게 왜 필요하지? ㅡ.ㅡ?
		break;
	case EXT_MAGICATKSHOT:
	case EXT_MAGICATK:			// 원거리에서 마법으로 타겟을 공격
	case EXT_MAGICSHOT:
		if( idTarget == NULL_ID )	return 0;			// 타겟이 없거나 유효하지 않으면 실패.
		SetDestObj( idTarget, fArrivalRange, TRUE );		// 이동할 목표물을 idTarget으로 설정. 다가가는 범위는 fArrivalRange값으로..
		break;
	case EXT_ANOTHERWITH:		// 나 혹은 다른사람에게 시전
		if( idTarget == NULL_ID )	// 타겟이 잡혀있지 않으면
			idTarget = GetId();		// 자신을 타겟으로 잡음
		SetDestObj( idTarget, fArrivalRange, TRUE );		// 이동할 목표물을 idTarget으로 설정.
		break;
	case EXT_AROUNDATK:			// 내 주위적들을 대상.
		idTarget = GetId();		// 타겟을 자기자신으로 설정.
		SetDestObj( idTarget, fArrivalRange, TRUE );		// 이동할 목표물을 idTarget으로 설정.
		break;
	case EXT_OBJCHGPARAMET:		// 타인에게 사용
	default:	// 그외는 모두 근접하자.
		if( idTarget == NULL_ID )	return 0;			// 타겟이 없거나 유효하지 않으면 실패.
		SetDestObj( idTarget, fArrivalRange, TRUE );		// 이동할 목표물을 idTarget으로 설정.
		break;
	}
	
	ClearActParam();
	SetCmd( OBJACT_USESKILL, nSkillIdx, idTarget, sutType );		// 사정거리가 되었을때 실행할 명령 셋팅.
	TRACE( "\n)CMD_SetUseSkill\n" );

	return 1;
}