BOOL CWndIndirectTalk::OnChildNotify( UINT message, UINT nID, LRESULT* pLResult ) { CWorld* pWorld = g_WorldMng(); CObj* pObj = pWorld->GetObjFocus(); if( pObj && pObj->GetType() == OT_MOVER ) { switch( nID ) { case WIDC_EDIT2: // 본문 if( message != EN_RETURN ) break; case WIDC_BUTTON1: { CWndEdit* pWndEdit1 = (CWndEdit*)GetDlgItem( WIDC_EDIT1 ); CWndEdit* pWndEdit2 = (CWndEdit*)GetDlgItem( WIDC_EDIT2 ); LPCTSTR lpId = pWndEdit1->m_string; LPCTSTR lpText = pWndEdit2->m_string; CString string; string.Format( "/id %s %s", lpId, lpText ); ParsingCommand( string.LockBuffer(), g_pPlayer ); string.UnlockBuffer(); pWndEdit2->Empty(); } break; } } if( nID == WTBID_CLOSE ) { Destroy( TRUE ); return TRUE; } return CWndNeuz::OnChildNotify( message, nID, pLResult ); }
void CPartyQuestProcessor::RemoveAllDynamicObj( DWORD dwWorldID, D3DXVECTOR3 vPos, int nRange ) { CWorld* pWorld = g_WorldMng.GetWorld( dwWorldID ); if( !pWorld ) return; CObj* pObj; D3DXVECTOR3 vDist; FOR_LINKMAP( pWorld, vPos, pObj, nRange, CObj::linkDynamic, nTempLayer ) { if( pObj ) { if( pObj->GetType() == OT_MOVER && ((CMover *)pObj)->IsPeaceful() == FALSE ) { pObj->Delete(); } } } END_LINKMAP D3DXVECTOR3 vPos2 = D3DXVECTOR3( 6968.0f, 0, 3328.8f ); FOR_LINKMAP( pWorld, vPos, pObj, nRange, CObj::linkPlayer, nTempLayer ) { if( pObj ) { CUser* pUser = (CUser*)pObj; pUser->AddQuestTextTime( 0, 0, 0xffffffff ); ( (CUser*)pObj )->REPLACE( g_uIdofMulti, WI_WORLD_MADRIGAL, vPos2, REPLACE_NORMAL, nDefaultLayer ); } } END_LINKMAP }
BOOL CWndCoupleTalk::OnChildNotify( UINT message, UINT nID, LRESULT* pLResult ) { CWorld* pWorld = g_WorldMng(); CObj* pObj = pWorld->GetObjFocus(); if( pObj && pObj->GetType() == OT_MOVER ) { switch( nID ) { case WIDC_EDIT2: // 본문 if( message != EN_RETURN ) break; case WIDC_BUTTON1: { CWndEdit* pWndEdit2 = (CWndEdit*)GetDlgItem( WIDC_EDIT2 ); CString stPropose( pWndEdit2->m_string); if(stPropose.GetLength()>30) g_WndMng.PutString( "뚤꼇폅,멩겜코휭꼇콘낚법15몸櫓匡俚륜。", NULL, prj.GetTextColor( TID_GAME_NOTCOUPLETARGET ) ); else { //警속랙箇句口 g_DPlay.SendPropose(((CMover*)pObj)->GetName(),stPropose); Destroy( TRUE ); return TRUE; } pWndEdit2->Empty(); } break; } } if( nID == WTBID_CLOSE ) { Destroy( TRUE ); return TRUE; } return CWndNeuz::OnChildNotify( message, nID, pLResult ); }
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; }
// 싸이킥 월 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 ); } } } } } }
// // 외부에서 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; }