Files
2022-10-26 12:25:11 +08:00

465 lines
13 KiB
C++

#include "SunClientPrecompiledHeader.h"
#include "ObjectEffectData.h"
#include "GlobalData.h"
#include <client/3dengine/3dfileaccess/wzunit/wzunitdraw.h>
#include "EventInfo.h"
#include "GameFunc.h"
#include "GlobalFunc.h"
ObjectEffectData::ObjectEffectData()
{
}
void ObjectEffectData::Initialize()
{
for( int i=0;i!=MAX_TRAIL; ++i )
{
m_bTrailActivate[i] = FALSE;
m_hTrailEffect[i] = INVALID_HANDLE_VALUE;
ZeroMemory(&m_arTrailParam[i], sizeof(TRAIL_PARAM) );
}
for ( int i = 0; i < MAX_EFFECT_BUFFER; ++i)
{
for (int j = 0; j < MAX_OBJECT_EFFECT; ++j)
{
m_EffectParam[i][j].hEffect = INVALID_HANDLE_VALUE;
m_EffectParam[i][j].iBoneIndex = 0;
m_EffectParam[i][j].bRotateWithBone = FALSE;
m_EffectParam[i][j].bLoopEffect = FALSE;
m_EffectParam[i][j].bOnlyPosition = FALSE;
m_EffectParam[i][j].bRotateWithBone = FALSE;
m_EffectParam[i][j].EffectID = 0;
ZeroMemory(&m_EffectParam[i][j].quatRot, sizeof(WzQuaternion));
ZeroMemory(&m_EffectParam[i][j].vOffset, sizeof(WzVector));
ZeroMemory(&m_EffectParam[i][j].vScale, sizeof(WzVector));
}
}
}
void ObjectEffectData::Release()
{
EndTrail(0);
EndTrail(1);
ReleaseAllEffect();
}
void ObjectEffectData::StartTrail( int TrailIndex, const TRAIL_PARAM& TrailParam, HANDLE hEffect )
{
//assert(TrailIndex >= 0 && TrailIndex < MAX_TRAIL);
m_arTrailParam[TrailIndex] = TrailParam;
m_hTrailEffect[TrailIndex] = hEffect;
CEffectBody* pBody = g_pEffectManager->GetEffectPtrHandle( hEffect );
if( pBody == NULL )
{
//! frame에 따라서 effect를 생성 안할수도 있음.(주석제거)
//assert(!"검기 이펙트를 생성하지 못했습니다");
return;
}
pBody->SetRenderType(AR_REFRACTION_GLASS);
pBody->SetRefractionRate(1.0f); // 굴절률.(0에 가까워 질수록 투명)
pBody->SetRefractionAlpha(1.0f); // 1.0 에 가까워질수록 본 이미지에 가까워짐
m_bTrailActivate[TrailIndex] = TRUE;
if( CEElementFlatChain* pFChain = pBody->GetFlatChainPtr() )
{
pFChain->SetLifeInfo(0, 30000);
pFChain->SetTailNum(TrailParam.iTailNum);
pFChain->SetSplineLength(0.1f);
}
else
{
//assert(!"검기 이펙트를 생성하지 못했습니다");
return;
}
}
void ObjectEffectData::EndTrail( int TrailIndex )
{
assert(TrailIndex >= 0 && TrailIndex < MAX_TRAIL);
if ( m_hTrailEffect[TrailIndex] != INVALID_HANDLE_VALUE)
{
if (m_bTrailActivate[TrailIndex] == TRUE )
{
g_pEffectManager->RemoveEffectPtr(m_hTrailEffect[TrailIndex]);
m_hTrailEffect[TrailIndex] = INVALID_HANDLE_VALUE;
m_bTrailActivate[TrailIndex] = FALSE;
}
}
}
int ObjectEffectData::GetTrailAttachmentIndex( int TrailIndex )
{
TrailIndex = min( TrailIndex, MAX_TRAIL-1 );
TrailIndex = max( 0, TrailIndex);
return m_arTrailParam[TrailIndex].iAttachmentIndex;
}
void ObjectEffectData::UpdateTrail( int TrailIndex, const WzVector& Position1, const WzVector& Position2 )
{
HANDLE hEffect = m_hTrailEffect[TrailIndex];
if( hEffect == INVALID_HANDLE_VALUE )
return;
if( CEffectBody* pBody = g_pEffectManager->GetEffectPtrHandle(hEffect) )
{
if( CEElementFlatChain* pFChain = pBody->GetFlatChainPtr() )
{
pFChain->SetPosition( Position1, Position2 );
}
}
else
{
m_hTrailEffect[TrailIndex] = INVALID_HANDLE_VALUE;
m_bTrailActivate[TrailIndex] = FALSE;
}
}
void ObjectEffectData::ReleaseAllEffect()
{
for (int i = 0; i < MAX_EFFECT_BUFFER; ++i)
{
for (int j = 0; j < MAX_OBJECT_EFFECT; ++j)
{
ReleaseEffect( j, i );
}
}
}
void ObjectEffectData::ReleaseLoopEffect()
{
for (int i = 0; i < MAX_EFFECT_BUFFER; ++i)
{
for (int j = 0; j < MAX_OBJECT_EFFECT; ++j)
{
if( m_EffectParam[i][j].hEffect != INVALID_HANDLE_VALUE )
{
if( CEffectBody* pBody = g_pEffectManager->GetEffectPtrHandle(m_EffectParam[i][j].hEffect) )
{
if( pBody->IsLoop() == true )
{
ReleaseEffect(j,i);
}
}
}
}
}
}
void ObjectEffectData::ReleaseEffect( int Index, int BufferIndex )
{
//assert(Index >= 0 && Index < MAX_OBJECT_EFFECT);
if (m_EffectParam[BufferIndex][Index].hEffect != INVALID_HANDLE_VALUE)
{
g_pEffectManager->RemoveEffectPtr(m_EffectParam[BufferIndex][Index].hEffect);
m_EffectParam[BufferIndex][Index].hEffect = INVALID_HANDLE_VALUE;
m_EffectParam[BufferIndex][Index].iBoneIndex = 0;
m_EffectParam[BufferIndex][Index].bRotateWithBone = FALSE;
m_EffectParam[BufferIndex][Index].EffectID = 0;
m_EffectParam[BufferIndex][Index].bLoopEffect = FALSE;
}
}
void ObjectEffectData::ReleaseCurEffect(int Index)
{
//라이프타임이 살아있는 이펙트일때는 바로 제거하지말구
//소멸할때까지 PRE_EFFECT에 저장한뒤 소멸시킨다.
if(m_EffectParam[CUR_EFFECT][Index].hEffect!=INVALID_HANDLE_VALUE)
{
if( CEffectBody* pBody = g_pEffectManager->GetEffectPtrHandle(m_EffectParam[CUR_EFFECT][Index].hEffect) )
{
//중복해서 또 이펙트 들어온다면 PRE_EFFECT는 해제한다
ReleaseEffect( Index, PRE_EFFECT );
//중복이펙트는 제거한다.
if(pBody->IsLoop())
{
return;
}
m_EffectParam[PRE_EFFECT][Index].iBoneIndex = m_EffectParam[CUR_EFFECT][Index].iBoneIndex;
m_EffectParam[PRE_EFFECT][Index].vOffset = m_EffectParam[CUR_EFFECT][Index].vOffset;
m_EffectParam[PRE_EFFECT][Index].quatRot = m_EffectParam[CUR_EFFECT][Index].quatRot;
m_EffectParam[PRE_EFFECT][Index].vScale = m_EffectParam[CUR_EFFECT][Index].vScale;
m_EffectParam[PRE_EFFECT][Index].bRotateWithBone= m_EffectParam[CUR_EFFECT][Index].bRotateWithBone;
m_EffectParam[PRE_EFFECT][Index].bOnlyPosition = m_EffectParam[CUR_EFFECT][Index].bOnlyPosition;
m_EffectParam[PRE_EFFECT][Index].hEffect = m_EffectParam[CUR_EFFECT][Index].hEffect;
}
}
}
BOOL ObjectEffectData::BeginEffect( CWzUnitDraw* pUnitDraw, const WzVector& Position, const WzVector& Direction, const EffectEventInfo& EffectEventInfo, DWORD ObjectKey )
{
int EffectIndex = EffectEventInfo.GetEventIndex();
EFFECT_PARAM& CurEffectParam = m_EffectParam[CUR_EFFECT][EffectIndex];
// 1. 이펙트 핸들에 대한 처리
HANDLE hEffect = INVALID_HANDLE_VALUE;
if (CurEffectParam.bLoopEffect == TRUE &&
(CurEffectParam.EffectID == EffectEventInfo.GetEffectID()))
{
// 루프 이펙트이며, 현재 이펙트와 같으면 그대로 사용
hEffect = CurEffectParam.hEffect;
}
else
{
// 현재 진행중인 이펙트를 제거한다.
ReleaseEffect( EffectIndex, CUR_EFFECT );
WzVector EffectPosition = Position;
// 본 위치를 사용 하는 경우 본의 위치를 구한다.
if( EffectEventInfo.GetBoneIndex() > 0 )
{
if( GameFunc::GetBonePos( pUnitDraw, EffectEventInfo.GetBoneIndex(), &EffectPosition) == FALSE )
{
return FALSE;
}
}
// 이펙트 생성
hEffect = GlobalFunc::CreateEffectBeUpToOption( EffectEventInfo.GetEffectID(), EffectPosition, ObjectKey );
}
// 2. 핸들과 이벤트의 성정된 정보를 설정
CurEffectParam.hEffect = hEffect;
CurEffectParam.iBoneIndex = EffectEventInfo.GetBoneIndex();;
CurEffectParam.vOffset = EffectEventInfo.GetEffectPosition();
CurEffectParam.vScale = EffectEventInfo.GetEffectScale();
CurEffectParam.quatRot = EffectEventInfo.GetEffectQuaternion();
// 3. 옵션에 따른 적용
// 200일때 회전적용무 오직 위치로만
if ( EffectEventInfo.IsLocationOnly() == true )
{
CurEffectParam.bOnlyPosition = TRUE;
CurEffectParam.bRotateWithBone = FALSE;
}
else if ( EffectEventInfo.IsRotate() == true )
{
CurEffectParam.bOnlyPosition = FALSE;
CurEffectParam.bRotateWithBone = TRUE;
}
else
{
CurEffectParam.bRotateWithBone = CurEffectParam.bOnlyPosition = FALSE;
}
// 4. 실제 이펙트에 적용
if( CEffectBody* effect_body = g_pEffectManager->GetEffectPtrHandle( hEffect) )
{
CurEffectParam.EffectID = EffectEventInfo.GetEffectID(); // 이펙트가 생성 된 후에 이펙트 아이디를 설정
CurEffectParam.bLoopEffect = effect_body->IsLoop(); // 루프 여부는 이펙트의 설정에서 가져옴
WzVector world_pos;
WzMatrix mat_rot;
MatrixIdentity(&mat_rot);
if( CurEffectParam.iBoneIndex == -1 ) // 기본 위치에 생성하는 경우
{
world_pos = Position;
if (CurEffectParam.bOnlyPosition)
{
//본 회전적용안함
MatrixIdentity(&mat_rot);
}
else
{
WzVector rotation = {0.f, 0.f, Math_GetAngleFromVector(&Direction)};
MatrixRotationZYX(&mat_rot, &rotation);
// 로테이션이 적용된 Offset만큼 이동
VectorTransformCoord(&rotation, &CurEffectParam.vOffset, &mat_rot);
world_pos += rotation;
}
}
else if( CurEffectParam.iBoneIndex == -2 ) // 고정된 위치에 생성하는 경우
{
world_pos = Position + CurEffectParam.vOffset;
CurEffectParam.bOnlyPosition = FALSE;
CurEffectParam.bRotateWithBone = FALSE;
WzVector rotation = {0.f, 0.f, Math_GetAngleFromVector(&Direction)};
MatrixRotationZYX(&mat_rot, &rotation);
// 로테이션이 적용된 Offset만큼 이동
VectorTransformCoord(&rotation, &CurEffectParam.vOffset, &mat_rot);
world_pos += rotation;
}
else // 본위치를 기준으로 생성하는 경우
{
WzMatrix mat;
if( GameFunc::GetBoneMatrix( pUnitDraw, EffectEventInfo.GetBoneIndex(), &mat ) == FALSE )
{
return FALSE;
}
VectorTransformCoord(&world_pos, &CurEffectParam.vOffset, &mat );
if (CurEffectParam.bOnlyPosition)
{
//본 회전적용안함
MatrixIdentity(&mat_rot);
}
else if(CurEffectParam.bRotateWithBone)
{
//본 회전적용
WzMatrix tmep_mat;
QuaternionToMatrix(&tmep_mat, &CurEffectParam.quatRot);
MatrixMultiply( &mat_rot, &tmep_mat, &mat);
mat_rot._42 =mat_rot._41 = mat_rot._43 = 0.0f;
}
else
{
// 회전적용
WzVector rotation = {0.f, 0.f, Math_GetAngleFromVector(&Direction)};
MatrixRotationZYX(&mat_rot, &rotation);
}
}
// 위치행렬
WzMatrix mat_pos;
MatrixTranslation( &mat_pos, world_pos.x, world_pos.y, world_pos.z );
// 스케일
WzMatrix mat_scale;
MatrixScaling(&mat_scale, CurEffectParam.vScale.x, CurEffectParam.vScale.y, CurEffectParam.vScale.z);
effect_body->SetResultMatrix( &mat_pos, &mat_rot, &mat_scale);
return TRUE;
}
return FALSE;
}
void ObjectEffectData::UpdateEffect( CWzUnitDraw* pUnitDraw, const WzVector& Position, const WzVector& Direction )
{
static const int FORCE_TRANSFROM = -2;
for ( int i=0; i < GetEffectBufferCount(); ++i )
{
for ( int j = 0; j < GetEffectCount(); ++j )
{
EFFECT_PARAM& EffectParam = m_EffectParam[i][j];
if (EffectParam.hEffect != INVALID_HANDLE_VALUE)
{
if ( CEffectBody* pBody = g_pEffectManager->GetEffectPtrHandle(EffectParam.hEffect) )
{
// 본인스값이 강제 변환일때는 갱신하지않는다
if (EffectParam.iBoneIndex == FORCE_TRANSFROM)
{
continue;
}
WzVector wvPos, wvWorldPos;
WzMatrix wmPosMat, wmRotMat, wmRot, wmScale, mat;
wvPos = EffectParam.vOffset;
if( EffectParam.iBoneIndex == -1 )
{
wvWorldPos = Position;
WzVector rotation = {0.f, 0.f, Math_GetAngleFromVector(&Direction)};
MatrixRotationZYX(&wmRotMat, &rotation);
// 로테이션이 적용된 Offset만큼 이동
VectorTransformCoord(&rotation, &EffectParam.vOffset, &wmRotMat);
wvWorldPos += rotation;
}
else
{
if( GameFunc::GetBoneMatrix( pUnitDraw, EffectParam.iBoneIndex, &mat ) == FALSE )
{
continue;
}
VectorTransformCoord( &wvWorldPos, &wvPos, &mat );
}
MatrixTranslation( &wmPosMat, wvWorldPos.x, wvWorldPos.y, wvWorldPos.z );
if(EffectParam.bOnlyPosition)
{
MatrixIdentity( &wmRotMat );
}
else if( EffectParam.bRotateWithBone )
{
QuaternionToMatrix( &wmRot, &EffectParam.quatRot );
MatrixMultiply( &wmRotMat, &wmRot, &mat );
wmRotMat._41 = 0.0f;
wmRotMat._42 = 0.0f;
wmRotMat._43 = 0.0f;
}
else
{
MatrixIdentity( &wmRotMat );
WzVector vPos;
vPos = wvWorldPos;
WzVector vDest,vTemp;
vDest = vPos + Direction*10.0f;
vDest = vDest - vPos;
vTemp = vDest;
vTemp.z = 0.0f;
float fLength;
if (vTemp.x == 0.0f && vTemp.y == 0.0f)
{
fLength = 0.0f;
}
else
{
fLength = VectorLength(&vTemp);
}
WzVector vRot;
vRot.x = -atan2(vDest.z,fLength);
vRot.z = Math_GetAngleFromVector(&vDest);
vRot.y = 0.0f;
MatrixRotationZYX(&wmRotMat,&vRot);
}
MatrixScaling( &wmScale, EffectParam.vScale.x, EffectParam.vScale.y, EffectParam.vScale.z );
pBody->SetResultMatrix( &wmPosMat, &wmRotMat, &wmScale );
}
else
{
//자동 NULL셋팅
EffectParam.hEffect = INVALID_HANDLE_VALUE;
}
}
}
}
}