//========================================================= // load the SkillData struct with the proper values based on the skill level. //========================================================= void CGameRules::RefreshSkillData ( bool forceUpdate ) { #ifndef CLIENT_DLL if ( !forceUpdate ) { if ( GlobalEntity_IsInTable( "skill.cfg" ) ) return; } GlobalEntity_Add( "skill.cfg", STRING(gpGlobals->mapname), GLOBAL_ON ); char szExec[256]; ConVarRef skill( "skill" ); SetSkillLevel( skill.IsValid() ? skill.GetInt() : 1 ); #ifdef HL2_DLL // HL2 current only uses one skill config file that represents MEDIUM skill level and // synthesizes EASY and HARD. (sjb) Q_snprintf( szExec,sizeof(szExec), "exec skill_manifest.cfg\n" ); engine->ServerCommand( szExec ); engine->ServerExecute(); #else Q_snprintf( szExec,sizeof(szExec), "exec skill%d.cfg\n", GetSkillLevel() ); engine->ServerCommand( szExec ); engine->ServerExecute(); #endif // HL2_DLL #endif // CLIENT_DLL }
void CPythonPlayer::SetComboSkillFlag(BOOL bFlag) { DWORD dwSlotIndex; if (!GetSkillSlotIndex(c_iSkillIndex_Combo, &dwSlotIndex)) { Tracef("CPythonPlayer::SetComboSkillFlag(killIndex=%d) - Can't Find Slot Index\n", c_iSkillIndex_Combo); return; } int iLevel = GetSkillLevel(dwSlotIndex); if (iLevel <= 0) { Tracef("CPythonPlayer::SetComboSkillFlag(skillIndex=%d, skillLevel=%d) - Invalid Combo Skill Level\n", c_iSkillIndex_Combo, iLevel); return; } iLevel = MIN(iLevel, 2); CInstanceBase* pkInstMain = NEW_GetMainActorPtr(); if (!pkInstMain) return; if (bFlag) { pkInstMain->SetComboType(iLevel); __ActivateSkillSlot(dwSlotIndex); } else { pkInstMain->SetComboType(0); __DeactivateSkillSlot(dwSlotIndex); } }
void KSkillList::OnPlayerLevelUp() { BOOL bRetCode = false; DWORD dwSkillID = 0; DWORD dwSkillLevel = 0; KSkill* pSkill = NULL; std::vector<DWORD> LevelUpSkillIDVector; LevelUpSkillIDVector.reserve(8); for ( PLAYER_SKILL_LIST::iterator it = m_PlayerSkillList.begin(), itEnd = m_PlayerSkillList.end(); it != itEnd; ++it ) { dwSkillID = it->first; dwSkillLevel = GetSkillLevel(dwSkillID); KGLOG_PROCESS_ERROR(dwSkillLevel > 0); pSkill = g_pSO3World->m_SkillManager.GetSkill_RAW(dwSkillID, dwSkillLevel); KGLOG_PROCESS_ERROR(pSkill); if (pSkill->m_pBaseInfo->dwBelongKungfu == INVALID_SKILL_ID) { continue; } if (!pSkill->m_pBaseInfo->bIsExpSkill) { continue; } bRetCode = CanRealizeSkill(dwSkillID); if (bRetCode) { LevelUpSkillIDVector.push_back(dwSkillID); } } for ( std::vector<DWORD>::iterator it = LevelUpSkillIDVector.begin(), itEnd = LevelUpSkillIDVector.end(); it != itEnd; ++it ) { if (CanRealizeSkill(*it)) { LearnSkill(*it, true); } } Exit0: return; }
/** @brief 첫번째 보유스킬을 사용한다 그냥 편의 함수. */ XSkillUser::xUseSkill XSkillUser::UseSkill( XSkillReceiver *pTarget, const XE::VEC2& vPos ) { xUseSkill info; if( XBREAK( m_listUseSkill.empty() ) ) { info.errCode = xCANCEL; return info; } XSkillDat *pUseSkill = m_listUseSkill.GetFirst(); int level = GetSkillLevel( pUseSkill ); return UseSkill( pUseSkill, level, pTarget, vPos ); }
BOOL KSkillList::IsSkillExist(DWORD dwID, DWORD dwLevel) { BOOL bResult = false; DWORD dwLearnLevel = GetSkillLevel(dwID); KG_PROCESS_ERROR(dwLevel > 0); KG_PROCESS_ERROR(dwLearnLevel > 0); KG_PROCESS_ERROR(dwLevel == dwLearnLevel); bResult = true; Exit0: return bResult; }
void FireProjectile::HandlePlayerCollision(Player* pPlayer, BaseArena* pArena, ItemLoaderXML* pItemLoader) { // Add a "impulse" to the player. XMFLOAT3 dir = GetDirection(); dir.y = 0.0f; pPlayer->SetVelocity(dir * GetImpactImpulse() * (1-pPlayer->GetKnockBackResistance())); pPlayer->ClearTargetQueue(); // Get item data. Item* item = pItemLoader->GetItem(ItemKey(GetSkillType(), GetSkillLevel())); Player* caster = (Player*)GetWorld()->GetObjectById(GetOwner()); // Damage the player. pPlayer->TakeDamage(item->GetAttributes().damage + caster->GetBonusDamage()); pPlayer->SetLastHitter((Player*)GetWorld()->GetObjectById(GetOwner())); }
bool CPythonPlayer::__CanUseSkill() { CInstanceBase* pkInstMain=NEW_GetMainActorPtr(); if (!pkInstMain) return false; if (IsObserverMode()) return false; // Fix me // 뉴마운트. 승마스킬레벨 20 미만인 경우, 고급 마운트를 타고 승마 관련 스킬 못 쓰도록 못하도록 하드 코딩... // 나중에 시간 나면 can use skill 체크를 서버에서 해주자... if (pkInstMain->IsMountingHorse() && (GetSkillGrade(109) < 1 && GetSkillLevel(109) < 20)) { return false; } return pkInstMain->CanUseSkill(); }
bool CPythonPlayer::__CheckSpecialSkill(DWORD dwSkillIndex) { CInstanceBase* pkInstMain = NEW_GetMainActorPtr(); if (!pkInstMain) return false; // Fishing if (c_iSkillIndex_Fishing == dwSkillIndex) { if (pkInstMain->IsFishingMode()) { NEW_Fishing(); } else { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "EQUIP_FISHING_ROD")); } return true; } // Combo else if (c_iSkillIndex_Combo == dwSkillIndex) { DWORD dwSlotIndex; if (!GetSkillSlotIndex(dwSkillIndex, &dwSlotIndex)) return false; int iLevel = GetSkillLevel(dwSlotIndex); if (iLevel > 0) { CPythonNetworkStream::Instance().SendUseSkillPacket(dwSkillIndex); } else { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "NOT_YET_LEARN")); } return true; } return false; }
void CSingleplayRules::NPCKilled(CBaseEntity *pVictim, const CTakeDamageInfo &info) { CBasePlayer *pEntity = UTIL_GetLocalPlayer(); if (pVictim->m_isRareEntity) { switch (GetSkillLevel()) { case SKILL_EASY: if (g_fr_economy.GetBool()) { pEntity->AddMoney(3 * sk_money_multiplier1.GetInt()); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(5 * sk_exp_multiplier1.GetInt()); } break; case SKILL_MEDIUM: if (g_fr_economy.GetBool()) { pEntity->AddMoney(3 * sk_money_multiplier2.GetInt()); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(5 * sk_exp_multiplier2.GetInt()); } break; case SKILL_HARD: if (g_fr_economy.GetBool()) { pEntity->AddMoney(3 * sk_money_multiplier3.GetInt()); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(5 * sk_exp_multiplier3.GetInt()); } break; case SKILL_VERYHARD: if (g_fr_economy.GetBool()) { pEntity->AddMoney(3 * sk_money_multiplier4.GetInt()); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(5 * sk_exp_multiplier4.GetInt()); } break; case SKILL_NIGHTMARE: if (g_fr_economy.GetBool()) { pEntity->AddMoney(3 * sk_money_multiplier5.GetInt()); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(5 * sk_exp_multiplier5.GetInt()); } break; } } else { switch (GetSkillLevel()) { case SKILL_EASY: if (g_fr_economy.GetBool()) { pEntity->AddMoney(2 * sk_money_multiplier1.GetInt()); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(3 * sk_exp_multiplier1.GetInt()); } break; case SKILL_MEDIUM: if (g_fr_economy.GetBool()) { pEntity->AddMoney(2 * sk_money_multiplier2.GetInt()); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(3 * sk_exp_multiplier2.GetInt()); } break; case SKILL_HARD: if (g_fr_economy.GetBool()) { pEntity->AddMoney(2 * sk_money_multiplier3.GetInt()); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(3 * sk_exp_multiplier3.GetInt()); } break; case SKILL_VERYHARD: if (g_fr_economy.GetBool()) { pEntity->AddMoney(2 * sk_money_multiplier4.GetInt()); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(3 * sk_exp_multiplier4.GetInt()); } break; case SKILL_NIGHTMARE: if (g_fr_economy.GetBool()) { pEntity->AddMoney(2 * sk_money_multiplier5.GetInt()); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(3 * sk_exp_multiplier5.GetInt()); } break; } } pEntity->IncrementFragCount(1); #define KILLING_SPREE_AMOUNT 5 #define KILLING_FRENZY_AMOUNT 10 #define OVERKILL_AMOUNT 15 #define RAMPAGE_AMOUNT 20 #define UNSTOPPABLE_AMOUNT 25 #define INCONCEIVABLE_AMOUNT 30 #define INVINCIBLE_AMOUNT 35 #define GODLIKE_AMOUNT 40 if (info.GetInflictor() == pEntity) { if (sv_player_voice.GetBool()) { if (sv_player_voice_kill.GetBool()) { int killvoicerandom = random->RandomInt(0, sv_player_voice_kill_freq.GetInt()); if (killvoicerandom == 0) { pEntity->EmitSound("Player.VoiceKill"); } } } } if (sv_killingspree.GetBool()) { int m_iKillsInSpree = pEntity->FragCount(); if (m_iKillsInSpree == KILLING_SPREE_AMOUNT) { CFmtStr hint; hint.sprintf("#Valve_Hud_KILLINGSPREE"); pEntity->ShowLevelMessage(hint.Access()); if (g_fr_economy.GetBool()) { pEntity->AddMoney(2); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(3); } } if (m_iKillsInSpree == KILLING_FRENZY_AMOUNT) { CFmtStr hint; hint.sprintf("#Valve_Hud_KILLINGFRENZY"); pEntity->ShowLevelMessage(hint.Access()); if (g_fr_economy.GetBool()) { pEntity->AddMoney(4); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(6); } } if (m_iKillsInSpree == OVERKILL_AMOUNT) { CFmtStr hint; hint.sprintf("#Valve_Hud_OVERKILL"); pEntity->ShowLevelMessage(hint.Access()); if (g_fr_economy.GetBool()) { pEntity->AddMoney(6); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(9); } } if (m_iKillsInSpree == RAMPAGE_AMOUNT) { CFmtStr hint; hint.sprintf("#Valve_Hud_RAMPAGE"); pEntity->ShowLevelMessage(hint.Access()); if (g_fr_economy.GetBool()) { pEntity->AddMoney(8); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(12); } } if (m_iKillsInSpree == UNSTOPPABLE_AMOUNT) { CFmtStr hint; hint.sprintf("#Valve_Hud_UNSTOPPABLE"); pEntity->ShowLevelMessage(hint.Access()); if (g_fr_economy.GetBool()) { pEntity->AddMoney(10); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(15); } } if (m_iKillsInSpree == INCONCEIVABLE_AMOUNT) { CFmtStr hint; hint.sprintf("#Valve_Hud_INCONCEIVABLE"); pEntity->ShowLevelMessage(hint.Access()); if (g_fr_economy.GetBool()) { pEntity->AddMoney(12); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(18); } } if (m_iKillsInSpree == INVINCIBLE_AMOUNT) { CFmtStr hint; hint.sprintf("#Valve_Hud_INVINCIBLE"); pEntity->ShowLevelMessage(hint.Access()); if (g_fr_economy.GetBool()) { pEntity->AddMoney(14); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(21); } } if (m_iKillsInSpree == GODLIKE_AMOUNT) { CFmtStr hint; hint.sprintf("#Valve_Hud_GODLIKE"); pEntity->ShowLevelMessage(hint.Access()); if (g_fr_economy.GetBool()) { pEntity->AddMoney(16); } if (!g_fr_classic.GetBool()) { pEntity->AddXP(24); } } } if (pVictim->m_isRareEntity) { if (g_fr_classic.GetBool()) { pEntity->LevelUpClassic(); } } }
BOOL cActiveSkillObject::Consume(CObject& object) const { if(FALSE == mSkillInfo->IsExcutableSkillState( object, mSkillObjectInfo.usedItem)) { return FALSE; } else if(eObjectKind_Player == object.GetObjectKind()) { CPlayer& player = (CPlayer&)object; if(0 < GetInfo().Money) { player.SetMoney( GetInfo().Money, MONEY_SUBTRACTION, MF_LOST); LogItemMoney( player.GetID(), player.GetObjectName(), GetInfo().Index, "*skill", eLog_SkillMoneyUse, player.GetMoney() + GetInfo().Money, player.GetMoney(), GetInfo().Money, 0, 0, 0, 0, 0, 0); } const eItemUse_Err itemUseError = ITEMMGR->UseItem( &player, mSkillObjectInfo.usedItem.Position, mSkillObjectInfo.usedItem.wIconIdx); if(eItemUseSuccess == itemUseError) { MSG_ITEM_USE_ACK message; ZeroMemory( &message, sizeof(message)); message.Category = MP_ITEM; message.Protocol = MP_ITEM_USE_ACK; message.TargetPos = mSkillObjectInfo.usedItem.Position; message.dwItemIdx = mSkillObjectInfo.usedItem.wIconIdx; message.eResult = itemUseError; player.SendMsg( &message, sizeof(message)); } switch(GetInfo().mConsumePoint.mType) { case ACTIVE_SKILL_INFO::ConsumePoint::TypeExperience: { player.ReduceExpPoint( GetInfo().mConsumePoint.mValue, eExpLog_LoseBySkillUse); break; } case ACTIVE_SKILL_INFO::ConsumePoint::TypePlayerKill: { const DWORD badFame = player.GetBadFame() - GetInfo().mConsumePoint.mValue; player.SetBadFame( badFame); BadFameCharacterUpdate( player.GetID(), badFame); MSG_FAME message; message.Category = MP_CHAR; message.Protocol = MP_CHAR_BADFAME_NOTIFY; message.dwObjectID = player.GetID(); message.Fame = badFame; PACKEDDATA_OBJ->QuickSend( &player, &message, sizeof(message)); break; } } // LUJ, 전역 스킬이 실행될 경우 패킷을 전송한다 if(TARGET_KIND_WORLD == GetInfo().Area) { MSG_ITEM_SKILL_START_TO_MAP message; ZeroMemory( &message, sizeof(message)); message.Category = MP_SKILL; message.Protocol = MP_SKILL_START_TO_MAP; message.mGuildIndex = player.GetGuildIdx(); message.mFamilyIndex = player.GetFamilyIdx(); switch(GetInfo().AreaTarget) { case eSkillAreaTargetGuild: { message.dwObjectID = player.GetGuildIdx(); break; } case eSkillAreaTargetFamily: { message.dwObjectID = player.GetFamilyIdx(); break; } case eSkillAreaTargetParty: { message.dwObjectID = player.GetPartyIdx(); break; } } message.mSkill.wSkillIdx = GetSkillIdx(); message.mSkill.Level = GetSkillLevel(); SKILLMGR->NetworkMsgParse( message.Protocol, &message); g_Network.Broadcast2AgentServer( (char*)&message, sizeof(message)); } } const float manaBonus = 1.0f + object.GetRateBuffStatus()->DecreaseManaRate / 100.0f; const float usedMana = float(object.GetMana()) * GetInfo().mMana.mPercent + GetInfo().mMana.mPlus; const float usedLife = float(object.GetLife()) * GetInfo().mLife.mPercent + GetInfo().mLife.mPlus; object.ReduceMana( DWORD(manaBonus * usedMana)); object.ReduceLife( DWORD(usedLife)); return TRUE; }
BOOL KSkillList::CanLearnSkill(DWORD dwSkillID, DWORD dwMasterID) { BOOL bResult = false; BOOL bRetCode = false; DWORD dwSkillLevel = 0; DWORD dwSkillExp = 0; KSKILL_LEARNING_INFO* pSkillLearningInfo = NULL; PLAYER_SKILL_LIST::iterator it; KGLOG_PROCESS_ERROR(dwSkillID != INVALID_SKILL_ID); it = m_PlayerSkillList.find(dwSkillID); if (it == m_PlayerSkillList.end()) { int nSkillCount = 0; KSkill* pSkill = NULL; nSkillCount = (int)m_PlayerSkillList.size(); KGLOG_PROCESS_ERROR(nSkillCount < MAX_PLAYER_SKILL_COUNT); pSkill = g_pSO3World->m_SkillManager.GetSkill_RAW(dwSkillID, 1); KGLOG_PROCESS_ERROR(pSkill); if (pSkill->m_pBaseInfo->dwBelongKungfu != INVALID_SKILL_ID) { DWORD dwKungfuLevel = GetSkillLevel(pSkill->m_pBaseInfo->dwBelongKungfu); KG_PROCESS_ERROR(dwKungfuLevel); } dwSkillLevel = 1; } else { KPlayerSkill* pPlayerSkill = NULL; pPlayerSkill = &it->second; dwSkillLevel = pPlayerSkill->dwLevel + 1; dwSkillExp = pPlayerSkill->dwExp; } pSkillLearningInfo = g_pSO3World->m_SkillManager.GetSkillLearningInfo(dwMasterID, dwSkillID, dwSkillLevel); KG_PROCESS_ERROR(pSkillLearningInfo); KG_PROCESS_ERROR(dwSkillLevel == 1 || dwSkillExp >= pSkillLearningInfo->dwRequireExp); KG_PROCESS_ERROR(m_pPlayer->m_nLevel >= pSkillLearningInfo->nRequirePlayerLevel); if (pSkillLearningInfo->dwReputationID) { int nReputationLevel = m_pPlayer->m_ReputeList.GetReputeLevel(pSkillLearningInfo->dwReputationID); KG_PROCESS_ERROR(nReputationLevel >= pSkillLearningInfo->nReputationLevel); } if (pSkillLearningInfo->nPrice) { int nMoney = m_pPlayer->m_ItemList.GetMoney(); KG_PROCESS_ERROR(nMoney >= pSkillLearningInfo->nPrice); } if (pSkillLearningInfo->nCostTrain) { KG_PROCESS_ERROR(m_pPlayer->m_nCurrentTrainValue >= pSkillLearningInfo->nCostTrain); } bResult = true; Exit0: return bResult; }
BOOL KSkillList::LearnSkill(DWORD dwSkillID, BOOL bNotifyPlayer, DWORD dwMasterID /* = 0 */) { BOOL bResult = false; BOOL bRetCode = false; DWORD dwNewLevel = 0; const KPlayerSkill* cpPlayerSkill = NULL; KSkill* pOldSkill = NULL; KSkill* pNewSkill = NULL; int nSkillCount = 0; PLAYER_SKILL_LIST::const_iterator cit; KGLOG_PROCESS_ERROR(dwSkillID != INVALID_SKILL_ID); cit = m_PlayerSkillList.find(dwSkillID); if (cit == m_PlayerSkillList.end()) { nSkillCount = (int)m_PlayerSkillList.size(); KGLOG_PROCESS_ERROR(nSkillCount < MAX_PLAYER_SKILL_COUNT); pNewSkill = g_pSO3World->m_SkillManager.GetSkill_RAW(dwSkillID, 1); KGLOG_PROCESS_ERROR(pNewSkill); if (pNewSkill->m_pBaseInfo->dwBelongKungfu != INVALID_SKILL_ID) { DWORD dwKungfuLevel = GetSkillLevel(pNewSkill->m_pBaseInfo->dwBelongKungfu); KGLOG_PROCESS_ERROR(dwKungfuLevel); } dwNewLevel = 1; } else { cpPlayerSkill = &cit->second; pOldSkill = g_pSO3World->m_SkillManager.GetSkill_RAW(dwSkillID, cpPlayerSkill->dwLevel); KGLOG_PROCESS_ERROR(pOldSkill); KG_PROCESS_ERROR(cpPlayerSkill->dwLevel < pOldSkill->m_pBaseInfo->dwMaxLevel); pNewSkill = g_pSO3World->m_SkillManager.GetSkill_RAW(dwSkillID, cpPlayerSkill->dwLevel + 1); KGLOG_PROCESS_ERROR(pNewSkill); dwNewLevel = cpPlayerSkill->dwLevel + 1; } bRetCode = UpdateSkill(dwSkillID, dwNewLevel, 0, bNotifyPlayer); KGLOG_PROCESS_ERROR(bRetCode); bRetCode = pNewSkill->CallLevelUpScript(m_pPlayer); KGLOG_CHECK_ERROR(bRetCode); if (dwSkillID == m_dwMountKungfuID) // 如果升级的技能是目前装备的内功,则更换内功 { m_pPlayer->UmountKungfu(); m_pPlayer->MountKungfu(dwSkillID, dwNewLevel); } if (dwMasterID) { KSKILL_LEARNING_INFO* pSkillLearningInfo = NULL; int nPlayerMoney = 0; int nCostTrain = 0; pSkillLearningInfo = g_pSO3World->m_SkillManager.GetSkillLearningInfo( dwMasterID, dwSkillID, dwNewLevel ); KGLOG_PROCESS_ERROR(pSkillLearningInfo); nPlayerMoney = m_pPlayer->m_ItemList.GetMoney(); nPlayerMoney -= pSkillLearningInfo->nPrice; nPlayerMoney = max(nPlayerMoney, 0); nCostTrain = min(m_pPlayer->m_nCurrentTrainValue, pSkillLearningInfo->nCostTrain); if (nCostTrain) { m_pPlayer->AddTrain(-nCostTrain); } bRetCode = m_pPlayer->m_ItemList.SetMoney(nPlayerMoney); KGLOG_CHECK_ERROR(bRetCode); g_LogClient.LogPlayerMoneyChange(-pSkillLearningInfo->nPrice, m_pPlayer, "learn skill"); } bResult = true; Exit0: return bResult; }
// // 외부에서 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; }