DragonNest/Server/DNGameServer/DnSkillPropComponent.cpp
2024-12-20 16:56:44 +08:00

243 lines
No EOL
17 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "DnSkillPropComponent.h"
#include "DnTableDB.h"
#include "EtMatrixEx.h"
#include "DnWorldProp.h"
#include "DnProjectile.h"
#include "DnMonsterActor.h"
CDnSkillPropComponent::CDnSkillPropComponent(void)
{
}
CDnSkillPropComponent::~CDnSkillPropComponent(void)
{
SAFE_RELEASE_SPTR( m_hSkill );
}
void CDnSkillPropComponent::Initialize( int iSkillID, int iSkillLevel )
{
if( iSkillID == 0 || iSkillLevel == 0 )
return;
// 사용할 상태효과를 미리 생성해 놓는다.
DNTableFileFormat* pSkillTable = GetDNTable( CDnTableDB::TSKILL );
DNTableFileFormat* pSkillLevelTable = GetDNTable( CDnTableDB::TSKILLLEVEL );
vector<int> vlSkillLevelList;
if( pSkillLevelTable->GetItemIDListFromField( "_SkillIndex", iSkillID, vlSkillLevelList ) <= 0 )
{
_ASSERT( !"프랍이 사용하는 스킬에서 스킬 인덱스를 스킬 레벨 테이블에서 찾을 수 없음." );
//return false;
}
int iSkillLevelTableID = -1;
for( int i = 0; i < (int)vlSkillLevelList.size(); ++i )
{
int iNowLevel = pSkillLevelTable->GetFieldFromLablePtr( vlSkillLevelList.at(i), "_SkillLevel" )->GetInteger();
if( iNowLevel == iSkillLevel )
{
iSkillLevelTableID = vlSkillLevelList.at( i );
break;
}
}
_ASSERT( -1 != iSkillLevelTableID && "프랍이 사용하는 스킬의 해당 레벨이 없음." );
// 상태 효과 정보 로딩
CDnSkill::StateEffectStruct StateEffect;
char caLable[ 64 ];
ZeroMemory( caLable, sizeof(caLable) );
for( int i = 0; i < CDnSkill::MAX_STATE_EFFECT_COUNT; ++i )
{
sprintf_s( caLable, "_EffectClass%d", i + 1 );
StateEffect.nID = pSkillTable->GetFieldFromLablePtr( iSkillID, caLable )->GetInteger();
if( StateEffect.nID < 1 )
continue;
sprintf_s( caLable, "_EffectClass%dApplyType", i + 1 );
StateEffect.ApplyType = (CDnSkill::StateEffectApplyType)pSkillTable->GetFieldFromLablePtr( iSkillID, caLable )->GetInteger();
sprintf_s( caLable, "_EffectClassValue%d", i + 1 );
StateEffect.szValue = pSkillLevelTable->GetFieldFromLablePtr( iSkillLevelTableID, caLable )->GetString();
sprintf_s( caLable, "_EffectClassValue%dDuration", i + 1 );
StateEffect.nDurationTime = pSkillLevelTable->GetFieldFromLablePtr( iSkillLevelTableID, caLable )->GetInteger();
m_vlStateEffectList.push_back( StateEffect );
}
m_SkillInfo.iSkillID = iSkillID;
m_SkillInfo.iSkillLevelID = iSkillLevelTableID;
m_SkillInfo.iLevel = iSkillLevel;
m_SkillInfo.eDurationType = (CDnSkill::DurationTypeEnum)pSkillTable->GetFieldFromLablePtr( iSkillID, "_DurationType" )->GetInteger();
m_SkillInfo.eTargetType = (CDnSkill::TargetTypeEnum)pSkillTable->GetFieldFromLablePtr( iSkillID, "_TargetType" )->GetInteger();
m_SkillInfo.iSkillDuplicateMethod = pSkillTable->GetFieldFromLablePtr( iSkillID, "_SkillDuplicate" )->GetInteger();
m_SkillInfo.iDuplicateCount = pSkillTable->GetFieldFromLablePtr( iSkillID, "_EffectAmassCount" )->GetInteger();
m_SkillInfo.iDissolvable = pSkillTable->GetFieldFromLablePtr( iSkillID, "_Dissolvable" )->GetInteger();
// 버프 프랍에서 사용하는 모듈이므로 프랍에서 비롯된 스킬이라는 정보를 셋팅.
m_SkillInfo.bFromBuffProp = true;
}
void CDnSkillPropComponent::OnSignal( DnActorHandle hActor, DnPropHandle hProp, SignalTypeEnum Type, void *pPtr, LOCAL_TIME LocalTime,
LOCAL_TIME SignalStartTime, LOCAL_TIME SignalEndTime, int nSignalIndex )
{
switch( Type )
{
case STE_Projectile:
{
ProjectileStruct *pStruct = (ProjectileStruct *)pPtr;
MatrixEx LocalCross = *hProp->GetMatEx();
CDnProjectile *pProjectile = CDnProjectile::CreateProjectile( hProp->GetRoom(), hActor, LocalCross, pStruct );
if( pProjectile == NULL ) break;
pProjectile->SetShooterProp( hProp );
if( m_SkillInfo.iSkillID != 0 )
{
int iNumStateEffect = (int)m_vlStateEffectList.size();
for( int iStateEffect = 0; iStateEffect < iNumStateEffect; ++iStateEffect )
pProjectile->AddStateEffect( m_vlStateEffectList.at(iStateEffect) );
if( !m_hSkill )
m_hSkill = CDnSkill::CreateSkill( hActor, m_SkillInfo.iSkillID, m_SkillInfo.iLevel );
pProjectile->SetParentSkill( m_hSkill );
pProjectile->SetParentSkillInfo( m_SkillInfo );
//bool bActorAttachWeapon = false;
//if( pStruct->nWeaponTableID == 0 && GetWeapon(1) ) bActorAttachWeapon = true;
//OnProjectile( pProjectile, bActorAttachWeapon );
//OnSkillProjectile( pProjectile );
}
}
break;
default:
hActor->OnSignal( Type, pPtr, LocalTime, SignalStartTime, SignalEndTime, nSignalIndex );
break;
}
}
#ifdef PRE_ADD_HIT_PROP_ADD_SE
//void CDnSkillPropComponent::ApplyStateBlowsToTheseTargets( DnActorHandle hPropActor, DNVector(DnActorHandle)& vlhActors )
void CDnSkillPropComponent::ApplyStateBlowsToTheseTargets( DnActorHandle hPropActor, DNVector(DnActorHandle)& vlhActors, HitStruct * pStruct )
{
if( !m_hSkill )
m_hSkill = CDnSkill::CreateSkill( hPropActor, m_SkillInfo.iSkillID, m_SkillInfo.iLevel );
if( !m_hSkill )
return;
int iNumActorApplyStateEffect = (int)vlhActors.size();
for( int i = 0; i < iNumActorApplyStateEffect; ++i )
{
// 대상이 얼음감옥 상태일때는 상태효과 적용 무시
if (vlhActors[ i ]->IsAppliedThisStateBlow(STATE_BLOW::BLOW_149))
continue;
// 프랍에서는 히트 시그널을 통과한 대상에게
// 상태효과를 넣어주도록 처리한다.
// 나중에 몬스터나 플레이어처럼 스킬 중첩 처리 등 복잡한 기능이 요구되면
// 액터의 hit signal 처리와 동일한 형식으로 가져가야 한다.
//// 스킬 대상 설정이 아군인가 타겟인가에 따라 상태효과 적용을 구분한다.
//switch( m_hSkill->GetTargetType() )
//{
// case CDnSkill::Enemy:
// case CDnSkill::Self:
// if( hPropActor->GetTeam() == vlhActors[ i ]->GetTeam() )
// continue;
// break;
// case CDnSkill::Friend:
// case CDnSkill::Party:
// if( hPropActor->GetTeam() != vlhActors[ i ]->GetTeam() )
// continue;
// break;
// // 스킬 적용 대상이 아군/적군 전부 다 라면 상태효과 적용 쪽에서 적용 여부를 구분해야 한다.
// case CDnSkill::All:
// break;
//}
// // 상태이상 Add 시에 지속 구분 인덱스 처리 필요.
// // 해당 Actor의 지속효과 구분 인덱스를 구분하여 성공한 경우에 상태이상 추가 시킴.
// map<int, bool> mapDuplicateResult;
// CDnSkill::CanApply eResult = CDnSkill::CanApplySkillStateEffect( vlhActors[i], m_hSkill, mapDuplicateResult );
// if( CDnSkill::CanApply::Fail != eResult )
// {
for( DWORD k = 0; k < m_hSkill->GetStateEffectCount(); k++ )
{
CDnSkill::StateEffectStruct *pLocalStruct = m_hSkill->GetStateEffectFromIndex(k);
//
//#if defined(PRE_ADD_SKIP_STATEBLOW)
// #74389 [데저트 드래곤] HitStateEffect 속성 프랍 버그.
if( pStruct && pStruct->szSkipStateBlows && CDnSkill::IsSkipStateBlow(pStruct->szSkipStateBlows, (STATE_BLOW::emBLOW_INDEX)pLocalStruct->nID) )
continue;
//#endif // PRE_ADD_SKIP_STATEBLOW
//
// // 아군까지 힐 시켜주는 스킬의 경우엔 Self 힐과 Target 힐 두 개의 상태효과가 선언되어있다.
// // Self 상태효과는 자신에게 이미 적용되었고 여긴 Hit 시그널 판정되는 곳이기 ‹š문에 Target 만 적용된다.
// switch( pLocalStruct->ApplyType )
// {
// case CDnSkill::ApplySelf:
// continue;
// break;
//
// case CDnSkill::ApplyTarget:
// break;
//
// case CDnSkill::ApplyEnemy:
// if( hPropActor->GetTeam() == vlhActors[ i ]->GetTeam() )
// continue;
// break;
//
// case CDnSkill::ApplyFriend:
// if( hPropActor->GetTeam() != vlhActors[ i ]->GetTeam() )
// continue;
// break;
// }
//
// // 같은 스킬 중첩일 경우엔 스킬 효과 중에 확률 체크하는 것들은 이미 CanApplySkillStateEffect 에서 확률체크되고
// // 통과된 상태이다. 따라서 여기선 확률 체크 된건지 확인하고 된거라면 다시 확률 체크 안하도록 함수 호출 해준다.
// bool bAllowAddThisSE = true;
// bool bCheckCanBegin = true;
// if( CDnSkill::ApplyDuplicateSameSkill == eResult )
// {
// map<int, bool>::iterator iter = mapDuplicateResult.find( pLocalStruct->nID );
// // 맵에 없는 경우 현재 액터가 상태효과에 걸려있지 않으므로 그냥 정상적으로 상태효과 추가 루틴 실행.
// if( mapDuplicateResult.end() != iter )
// {
// // 같은 스킬의 확률있는 상태효과가 현재 걸려있어서 CanAdd 를 호출해보았으나 실패했음.
// // 이런 경우엔 상태효과 추가하지 않는다.
// if( false == (iter->second) )
// bAllowAddThisSE = false;
// else
// // 이미 CanAdd 를 통과한 상태이므로 CmdAddStateEffect 호출 시 따로 체크하지 않도록 해준다.
// bCheckCanBegin = false;
// }
// }
//if( bAllowAddThisSE )
//{
//// 여기서 등록되어 있는 제거 되어야할 상태효과들 없앤다. [2010/12/08 semozz]
//vlhActors[i]->RemoveResetStateBlow();
vlhActors[i]->CmdAddStateEffect( m_hSkill->GetInfo(), (STATE_BLOW::emBLOW_INDEX)pLocalStruct->nID,
pLocalStruct->nDurationTime, pLocalStruct->szValue.c_str()/*, false, bCheckCanBegin*/ );
//}
}
//}
// 스킬 사용 끝났으면 리셋리스트 초기화 [2010/12/09 semozz]
//vlhActors[i]->InitStateBlowIDToRemove();
}
}
#endif // #ifdef PRE_ADD_HIT_PROP_ADD_SE