Files
Leviathan/Client/Game/game/Main/SGame.cpp
T
2026-06-01 12:46:52 +02:00

1332 lines
33 KiB
C++

#include "StdAfx.h"
#include <network/XSyncStreamConnection.h>
#include "KRenderObjectBone.h"
#include "KRenderObjectEtc.h"
#include "SGameViewPort.h"
#include "KDeviceManager.h"
#include "KRenderDeviceDX.h"
#include "KResourceManager.h"
#include "K3DCamera.h"
#include "SGameEnhanceFx.h"
#include "resource.h"
#include "SGameManager.h"
#include "sgame.h"
#include "SGameSound.h"
#include "SGameEffect.h"
#include "GameDefine.h"
#include "SGameOption.h"
#include "SGameAvatarEx.h"
#include <network/XNetworkUtil.h>
#include <toolkit/XConsole.h>
#include <toolkit/XStringUtil.h>
#include "SGameMessage.h"
//#include "SGameMessageUI.h"
#include "SNetMessage.h"
#include "SGameUtil.h"
#include "SkillBaseFile.h"
#include "STenacityDB.h"
#include "SMotionDB.h"
//#include "SEnhanceFXDB.h"
#include "SUIDisplayInfo.h"
#include "SGameMilesSoundMgr.h"
/// 2010.11.10 - prodongi
#include "SGameLobbyDefine.h"
//Explorer
#include <exdisp.h>
#include <comutil.h>
#define S_USER 1000
const char * pEP_Name[] =
{
"ep_top01_main",
"ep_middle01_main",
"ep_damage01_main",
"ep_bottom01",
"ep_ride01_main",
"ep_wfx_00_l",
"ep_wfx_00",
"ep_wfx_00_th",
};
const char * pEffectAniKey[] =
{
"effect_start",
"effect_middle",
"effect_end"
};
extern void SetNavigate( const char * pURL, bool bVisible, int nAddWidth, int nAddHeight );
extern void SetVisibleNavigate( bool bVisible );
extern IWebBrowser2* GetWebBrowser( int nWidth, int nHeight, int nAddWidth, int nAddHeight );
extern void InitWebBrowser( IWebBrowser2* pWebBrowser );
extern void SetWebWindowStyle( HWND hWebBrowser );
extern void SetWebBrowserMovePos( IWebBrowser2* pWebBrowser, int nX, int nY );
extern void SetWebBrowserCenterPos( IWebBrowser2* pWebBrowser, int nW, int nY );
extern void SetWebBrowserVisible( IWebBrowser2* pWebBrowser, bool bVisible );
extern void SetURLNavigate( IWebBrowser2* pWebBrowser, const char * pURL );
extern void CurURLRefresh( IWebBrowser2* pWebBrowser );
extern void CloseWebBrowser( IWebBrowser2* pWebBrowser );
typedef struct _Web_Window_
{
_Web_Window_()
{
nWindowID = 0;
pWebBrowserOther = NULL;
}
int nWindowID;
IWebBrowser2* pWebBrowserOther;
} WEB_WINDOW;
std::vector< WEB_WINDOW > g_vWebWinList;
extern HWND g_hWnd;
extern IWebBrowser2* g_pWebBrowser;
extern VARIANT_BOOL g_IsShowWebBrowser;
extern bool g_IsShowWebBrowserChanged;
void EraseWebWindow( int nWinID )
{
for( unsigned int i(0); g_vWebWinList.size()>i; i++ )
{
if( g_vWebWinList[i].nWindowID == nWinID )
{
g_vWebWinList.erase( g_vWebWinList.begin()+i );
return;
}
}
}
IWebBrowser2* GetWebWindow( int nWinID )
{
for( unsigned int i(0); g_vWebWinList.size()>i; i++ )
{
if( g_vWebWinList[i].nWindowID == nWinID )
return g_vWebWinList[i].pWebBrowserOther;
}
return NULL;
}
void CurOtherURLRefresh( int nWinID )
{
IWebBrowser2* pWebBrowserOther = GetWebWindow( nWinID );
if( pWebBrowserOther )
CurURLRefresh( pWebBrowserOther );
}
void SetOtherNavigateMove( int nWinID, int nX, int nY )
{
IWebBrowser2* pWebBrowserOther = GetWebWindow( nWinID );
if( pWebBrowserOther )
{
SetWebBrowserMovePos( pWebBrowserOther, nX, nY );
}
}
void SetOtherNavigateClose( int nWinID )
{
IWebBrowser2* pWebBrowserOther = GetWebWindow( nWinID );
if( pWebBrowserOther )
{
SetWebBrowserVisible( pWebBrowserOther, false );
CloseWebBrowser( pWebBrowserOther );
EraseWebWindow( nWinID );
}
}
void SetOtherNavigate( int nWinID, const char * pURL, int nWidth, int nHeight )
{
IWebBrowser2* pWebBrowserOther = GetWebWindow( nWinID );
if( pWebBrowserOther )
{
SetWebBrowserVisible( pWebBrowserOther, true );
SetURLNavigate( pWebBrowserOther, pURL );
HWND hWnd = NULL;
HRESULT hrGetHWN = pWebBrowserOther->get_HWND( (long*)&hWnd );
if( hrGetHWN == S_OK )
::BringWindowToTop( hWnd );
}
else
{
WEB_WINDOW web_window;
web_window.pWebBrowserOther = GetWebBrowser( nWidth, nHeight, 0, 0 );
web_window.nWindowID = nWinID;
g_vWebWinList.push_back( web_window );
if( web_window.pWebBrowserOther )
{
InitWebBrowser( web_window.pWebBrowserOther );
HWND hWnd = NULL;
HRESULT hrGetHWN = web_window.pWebBrowserOther->get_HWND( (long*)&hWnd );
if( hrGetHWN == S_OK )
{
SetWebWindowStyle( hWnd );
::BringWindowToTop( hWnd );
}
SetWebBrowserCenterPos( web_window.pWebBrowserOther, nWidth, nHeight );
SetURLNavigate( web_window.pWebBrowserOther, pURL );
SetWebBrowserVisible( web_window.pWebBrowserOther, true );
}
}
}
//=============================================================================
//SGame
SGame::SGame
( SGameManager* pGameMng
, int nGameType
, K3DRenderDeviceDX* pRenderDevice
, SSoundManager* pSoundMng
, KTextureManager* pTextureMng
, KNX3Manager* pNX3Mng
, SGameMilesSoundMgr* pMSoundMgr )
: m_pGameMng(pGameMng)
,m_nGameType(nGameType)
,m_pRenderDevice(pRenderDevice)
,m_pSoundMng(pSoundMng)
,m_pTextureMng(pTextureMng)
,m_pNX3Mng(pNX3Mng)
,m_pMSoundMgr(pMSoundMgr)
{
m_pCamera = new K3DCamera;
m_pCamera->Reset();
m_pArObject = NULL;
m_dwTime = 0;
m_nCurSelect = -1;
m_nSpecialSelect = -1;
m_nDeltaSpeed = 1;
m_fTime = 0.0f; // Current time in seconds
m_fAccumTime = 0.0f; // the global time - Speed Tree
m_fElapsedTime = 0.0f; // Time elapsed since last frame
m_nGameRef = STAGE_LOADING;
m_nCheatMode = CHEAT_NONE;
m_nEffectID = 0;
m_nNewEffectID = 0;
m_nAttackEffectID = 0;
m_bStopProc = false;
m_pViewPort = NULL;
m_nNewEnhanceFxID = 0;
}
SGame::~SGame(void)
{
SAFE_DELETE(m_pCamera);
_AllDelEffect();
AllDelParticle();
}
void SGame::SetViewPort( SGameViewPort* pViewPort )
{
m_pViewPort = pViewPort;
}
void SGame::_AllDelEffect()
{
for( unsigned int i(0); m_vEffectList.size()>i; i++ )
delete m_vEffectList[i];
m_vEffectList.erase( m_vEffectList.begin(), m_vEffectList.end() );
for( unsigned int i(0); m_vNewEffectList.size()>i; i++ )
delete m_vNewEffectList[i];
m_vNewEffectList.erase( m_vNewEffectList.begin(), m_vNewEffectList.end() );
for( unsigned int i(0); m_vAttackEffectList.size()>i; i++ )
delete m_vAttackEffectList[i];
m_vAttackEffectList.erase( m_vAttackEffectList.begin(), m_vAttackEffectList.end() );
}
void SGame::AllDelParticle()
{
std::vector< SGameEnhanceFx* >::iterator iter = m_vEnhanceFxList.begin();
for( ; iter != m_vEnhanceFxList.end(); )
{
SAFE_DELETE( (*iter) );
iter = m_vEnhanceFxList.erase(iter);
}
m_vEnhanceFxList.clear();
m_nNewEnhanceFxID = 0;
while( !m_RecycleID.empty() )
m_RecycleID.pop();
}
bool SGame::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount )
{
//Camera Render
for(int vit = 0; vit < nViewportCount; ++vit) {
//if(ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME)
// m_pCamera->Render( ppViewportList[vit] );
ppViewportList[vit]->SetCamera(m_pCamera);
}
return true;
}
bool SGame::Process( DWORD time, unsigned long uProcessBitVector )
{
m_dwTime = time;
return true;
}
void SGame::SetCheatMode( int nMode )
{
m_nCheatMode = nMode;
}
void SGame::SetGameRef( int nGameRef )
{
_oprint( "!!!!! SetGameRef : %d\n", nGameRef );
m_nGameRef = nGameRef;
}
void SGame::SendMsg( SGameObject *pGO, const TS_MESSAGE *msg )
{
TS_MESSAGE * pMsg = NULL;
//TS_MESSAGE를 구성하여, 보낸다.
PendMessage( pMsg );
}
void SGame::SendMsg( const TS_MESSAGE *msg )
{
PendMessage( msg );
}
bool SGame::IsUIWindowOpened( int nWindowID )
{
return m_pGameMng->IsUIWindowOpened( nWindowID );
}
bool SGame::IsWebPageWndOpened()
{
return m_pGameMng->IsWebPageWndOpened();
}
void SGame::PendMessage( const TS_MESSAGE * pMessage )
{
if( IsStopProcess() ) return;
// _oprint( "PendMessage : %d\n", pMessage->id );
m_pGameMng->PendMessage( pMessage );
}
void SGame::DelOwnerEffect( AR_HANDLE hOwner )
{
for( unsigned int i(0); m_vEffectList.size()>i; i++ )
{
if( m_vEffectList[i]->GetHandle() == hOwner )
m_vEffectList[i]->SetEnd();
}
for( unsigned int i(0); m_vNewEffectList.size()>i; i++ )
{
if( m_vNewEffectList[i]->GetOwner() == hOwner )
m_vNewEffectList[i]->ForceEnd();
}
for( unsigned int i(0); m_vAttackEffectList.size()>i; i++ )
{
if(m_vAttackEffectList[i]->GetCastHandle() == hOwner)
m_vAttackEffectList[i]->SetEnd();
}
}
void SGame::DelEffect( int nEffectID )
{
for( unsigned int i(0); m_vEffectList.size()>i; i++ )
{
if( m_vEffectList[i]->GetEffectID() == nEffectID )
{
m_vEffectList[i]->SetEnd();
break;
}
}
}
void SGame::EndLoopFx( int nEffectID )
{
for( unsigned int i(0); m_vNewEffectList.size()>i; i++ )
{
if( m_vNewEffectList[i]->GetEffectID() == nEffectID )
{
m_vNewEffectList[i]->IsLoopFx(false);
break;
}
}
}
void SGame::AddStateEffect( SGameMessage * pGameMsg )
{
if( pGameMsg->nType == MSG_STATE )
{
SMSG_STATE * pStateMsg = reinterpret_cast<SMSG_STATE*>(pGameMsg);
SGameAvatarEx* pTarget = (SGameAvatarEx*)GetGameObject( pStateMsg->handle );
if( !pTarget ) return;
if( pTarget->IsPendLoading() ) return;
StateInfoEx * pState = GetTenacityDB().GetTenacityData( pStateMsg->state_code );
if( !pState ) return;
int nFXID = GetTenacityDB().GetFXID( pStateMsg->state_code );
FX_DATA fx_data;
fx_data.nStateCode = pStateMsg->state_code;
fx_data.nMode = SGameEffectEx::STATE_MODE;
fx_data.end_time = pStateMsg->end_time; //상태 이상 종료 시간
fx_data.state_handle = pStateMsg->state_handle;//상태 이상 핸들
fx_data.owner = pStateMsg->handle;
fx_data.attack = pStateMsg->handle;
fx_data.target = pStateMsg->handle;
fx_data.nEffPos = pState->pos_id;
fx_data.nFX_ID = nFXID;
AddEffect( &fx_data );
}
}
void SGame::UpdateStateEffect( SGameMessage * pGameMsg )
{
if( pGameMsg == NULL ) return;
if( pGameMsg->nType == MSG_STATE )
{
SMSG_STATE * pStateMsg = reinterpret_cast<SMSG_STATE*>(pGameMsg);
std::vector< SGameEffectEx* >::iterator iter = m_vNewEffectList.begin();
for( ; iter != m_vNewEffectList.end(); ++iter )
{
if( (*iter)->GetMode() == SGameEffectEx::STATE_MODE )
{
if( (*iter)->GetOwner() == pStateMsg->handle && (*iter)->GetStateHandle() == pStateMsg->state_handle )
{
(*iter)->SetEndTime( pStateMsg->end_time );
}
}
}
}
}
void SGame::DelStateEffect( SGameMessage * pGameMsg )
{
if( pGameMsg->nType == MSG_STATE )
{
SMSG_STATE * pState = reinterpret_cast<SMSG_STATE*>(pGameMsg);
for( unsigned int i(0); m_vEffectList.size()>i; i++ )
{
if( m_vEffectList[i]->GetHandle() == pState->handle && m_vEffectList[i]->GetStateHandle() == pState->state_handle )
{
m_vEffectList[i]->SetEnd();
}
}
std::vector< class SGameEffectEx* >::iterator iter = m_vNewEffectList.begin();
for( ; iter != m_vNewEffectList.end(); ++iter )
{
if( (*iter)->GetOwner() == pState->handle && (*iter)->GetStateHandle() == pState->state_handle )
{
(*iter)->ForceEnd();
}
}
}
}
void SGame::DelStateEffect( int nDelObjType )
{
for( unsigned int i(0); m_vEffectList.size()>i; i++ )
{
unsigned char Type;
int ObjType = IsFriend( m_vEffectList[i]->GetHandle(), Type );
if( ObjType & nDelObjType )
{
m_vEffectList[i]->SetEnd();
}
}
std::vector< class SGameEffectEx* >::iterator iter = m_vNewEffectList.begin();
for( ; iter != m_vNewEffectList.end(); ++iter )
{
unsigned char Type;
int ObjType = IsFriend( (*iter)->GetOwner(), Type );
if( ObjType & nDelObjType )
{
(*iter)->ForceEnd();
}
}
}
SGameEffect* SGame::CreateEffect( const char * pEffectName, int nFlag, AR_HANDLE owner, AR_HANDLE caster, AR_HANDLE target, int nUseBoneIndex, int nAniType, float fPlayRate, AR_TIME end_time, bool bIsOwnerDir )
{
// _oprint( "SGame::CreateEffect [c-%u] [o-%u]\n", caster, owner );
SGameAvatarEx* pOwner = (SGameAvatarEx*)GetGameObject( owner );
if( !pOwner ) return NULL;
SGameAvatarEx* pCaster = (SGameAvatarEx*)GetGameObject( caster );
if( !pCaster ) return NULL;
SGameAvatarEx* pTarget = (SGameAvatarEx*)GetGameObject( target );
if( !pTarget ) return NULL;
if( pOwner->GetEffectRef() > 7 ) return NULL;
if( CheckCameraDistance( pOwner ) == false )
return NULL;
pOwner->EffectAddRef();
SGameEffect * pEffect = new SGameEffect( owner );
pEffect->SetOwner( owner );
pEffect->SetFlag( nFlag ); //따라가기 1, 보통 0
if( m_nCheatMode == CHEAT_NONE )
{
pEffect->AddEffect( pEffectName ); //모양 종류
}
else
{
std::string strFileName = pEffectName;
if( m_nCheatMode == CHEAT_MODE01 )
{
if( strcmp( strFileName.c_str(), "rcfx_ch_standard_damage_01.nx3" ) == 0 )
strFileName = "rcfx_ch_standard_criticaldamage_01.nx3";
}
else if( m_nCheatMode == CHEAT_MODE02 )
{
if( strcmp( strFileName.c_str(), "rcfx_ch_standard_damage_01.nx3" ) == 0 )
strFileName = "rcfx_ch_standard_damage_plusalpha_01.nx3";
}
pEffect->AddEffect( strFileName.c_str() );
}
pEffect->PlayAnimation( m_dwTime, nAniType, fPlayRate ); //시작
assert( nUseBoneIndex <= EFFECT_POS_MAX && "The effect position is outdated" );
const K3DMatrix* pEvpMatrix = pOwner->GetEventPointMatrix( nUseBoneIndex );
const K3DMatrix* pEvpAttachMatrix = pOwner->GetEventPointAttachMatrix( nUseBoneIndex );
K3DMatrix mat; //뼈는 위치만 참조
K3DMatrixIdentity( mat );
//방향 구하기
if( bIsOwnerDir )
{
pEffect->SetOwnerDirection( pCaster->GetTransform(), (K3DVector*)&pCaster->GetViewVector() );
}
else if( caster != target )
{
//방향은 caster -> target
pEffect->SetDirection( *pCaster->GetPosition(), *pTarget->GetPosition() );
}
else
{
K3DVector spos = pCaster->GetViewVector();
K3DVector tpos = spos;
tpos *= 3;
pEffect->SetDirection( spos, tpos );
}
if( nFlag == 1 ) //따라가기 설정
{
if( pEvpAttachMatrix && pEvpMatrix )
pEffect->SetParentMat( pOwner->GetTransform(), pEvpAttachMatrix, pEvpMatrix );
else
pEffect->SetParentMat( pOwner->GetTransform(), NULL, NULL );
}
else
{
if( pEvpAttachMatrix && pEvpMatrix )
{
K3DMatrixMultiply( mat, *pEvpAttachMatrix, *pOwner->GetTransform() );
K3DMatrixMultiply( mat, *pEvpMatrix, mat );
}
else
mat = *pOwner->GetTransform();
pEffect->SetTransform( mat );
}
if( pOwner->GetArID() != pTarget->GetArID() && nFlag != 2 )
{
pEffect->SetTargetScale(pTarget->GetScale(), mat);
}
pEffect->SetMessageHandler( this );
//상태 이상 지속 시간
if( end_time > 0 )
{
pEffect->SetEndTime( end_time );
}
if (fabs(pTarget->GetAdjustedScale() - 1.0f) > FLT_EPSILON)
{
pEffect->SetScalePure(pTarget->GetAdjustedScale());
}
return pEffect;
}
int SGame::AddEffectTest( const char * pFileName, AR_HANDLE hOwner )
{
SGameEffect * pEffect = CreateEffect( pFileName, 1,
hOwner, hOwner, hOwner,
EFFECT_POS_TOP, SEQTYPE_LOOP, 4.8f, 0, 0 );
if( pEffect )
{
m_nEffectID++;
pEffect->SetEffectID( m_nEffectID );
m_vEffectList.push_back( pEffect );
return m_nEffectID;
}
return -1;
}
int SGame::AddEffect( FX_DATA * pFX_data )
{
_MOTION_FX_SET* pFXSET = GetMotionFxSetDB().GetFXSet( pFX_data->nFX_ID );
if( pFXSET )
{
SGameAvatarEx* pOwner = (SGameAvatarEx*)GetGameObject( pFX_data->owner );
if( !pOwner ) return NULL;
SGameAvatarEx* pCaster = (SGameAvatarEx*)GetGameObject( pFX_data->attack );
if( !pCaster ) return NULL;
SGameAvatarEx* pTarget = (SGameAvatarEx*)GetGameObject( pFX_data->target );
if( !pTarget ) return NULL;
if( pOwner->GetEffectRef() > 7 ) return NULL;
if( pFX_data->state_handle == 0 )
{
if( CheckCameraDistance( pOwner ) == false )
return NULL;
}
pOwner->EffectAddRef();
SGameEffectEx * pEffect = new SGameEffectEx( pFX_data, pFXSET );
++m_nNewEffectID;
pEffect->SetOwner( pFX_data->owner ); //지울때 사용
pEffect->SetCaster( pFX_data->attack );
/*
KEventPointSeq * pEv = NULL;
bool bFindSuc = false;
{
_CID( REQ_EVPOINT );
KMsgREQ_EVPOINT effect_pos_msg;
pOwner->Perform( ANIPART_WEAPON_LEFT , id_REQ_EVPOINT, effect_pos_msg );
pOwner->Perform( ANIPART_WEAPON_RIGHT, id_REQ_EVPOINT, effect_pos_msg );
pOwner->Perform( ANIPART_BIPED, id_REQ_EVPOINT, &effect_pos_msg );
//Effect Pos 위치 계산 해야 한다.
for( int i(0); effect_pos_msg.GetPointCount()>i; i++ )
{
pEv = effect_pos_msg.GetPoint(i);
const char * pName = pEv->GetName();
if( strlen(pName) && _stricmp( pName, pEP_Name[pFX_data->nEffPos] ) == 0 )
{
pEffect->SetEventPointSequencer( pEv );
bFindSuc = true;
break;
}
}
}*/
const K3DMatrix* pEvpMatrix = pOwner->GetEventPointMatrix( pFX_data->nEffPos );
const K3DMatrix* pEvpAttachMatrix = pOwner->GetEventPointAttachMatrix( pFX_data->nEffPos );
K3DMatrix mat;
if( pFX_data->nMode == SGameEffectEx::NORMAL_MODE )
{
if( pFX_data->bDir )
{
//방향 구하기
if( pFX_data->attack != pFX_data->target )
{
//방향은 caster -> target
pEffect->SetDirection( *pCaster->GetPosition(), *pTarget->GetPosition() );
}
else
{
K3DVector spos = pCaster->GetViewVector();
K3DVector tpos = spos;
tpos *= 3;
pEffect->SetDirection( spos, tpos );
}
}
if( pFXSET->nFollowing == 1 )
{
if( pFX_data->nEffPos == EFFECT_POS_W_LEFT ||
pFX_data->nEffPos == EFFECT_POS_W_RIGHT ||
pFX_data->nEffPos == EFFECT_POS_W_TWOHAND )
{
pEffect->IsWeaponEffectPos();
}
pEffect->SetParentMat( pOwner->GetTransform(), pEvpAttachMatrix, pEvpMatrix );
mat = *pOwner->GetTransform();
}
else
{
if( pEvpAttachMatrix && pEvpMatrix )
{
K3DMatrixMultiply( mat, *pEvpAttachMatrix, *pOwner->GetTransform() );
K3DMatrixMultiply( mat, *pEvpMatrix, mat );
}
else
mat = *pOwner->GetTransform();
}
}
else if( pFX_data->nMode == SGameEffectEx::STATE_MODE )
{
pEffect->SetParentMat( pOwner->GetTransform(), pEvpAttachMatrix, pEvpMatrix );
mat = *pOwner->GetTransform();
}
if( pOwner->GetArID() != pTarget->GetArID() )
{
pEffect->SetTargetScale(pTarget->GetScale(), mat);
}
pEffect->SetEndTime( pFX_data->end_time );
pEffect->SetMode( pFX_data->nMode );
pEffect->SetStateHandle( pFX_data->state_handle );
pEffect->SetMessageHandler( this );
pEffect->SetTransform( mat );
pEffect->SetEffectID( m_nNewEffectID );
pEffect->PlayAnimation( m_dwTime ); //시작
pEffect->IsLoopFx(pFX_data->bIsLoop);
if (fabs(pTarget->GetAdjustedScale() - 1.0f) > FLT_EPSILON)
{
pEffect->SetScaleAdjust(pTarget->GetAdjustedScale());
}
pEffect->setTarget(pFX_data->target); /// 2011.04.04 - prodongi
m_vNewEffectList.push_back( pEffect );
return m_nNewEffectID;
}
return -1;
}
int SGame::AddEffect( FX_DATA_EX * pFX_data ) //Follow Effect
{
// _oprint( "AddEffect %s, %d\n", pEffectName, end_time );
SGameEffect * pEffect = CreateEffect( pFX_data->m_pEffectName, pFX_data->m_nFlag,
pFX_data->m_owner, pFX_data->m_caster, pFX_data->m_target,
pFX_data->m_nUseBoneIndex, pFX_data->m_nAniType, pFX_data->m_fPlayRate, pFX_data->m_end_time, pFX_data->m_bIsOwnerDir );
if( pEffect )
{
m_nEffectID++;
pEffect->SetEffectID( m_nEffectID );
m_vEffectList.push_back( pEffect );
return m_nEffectID;
}
return -1;
}
int SGame::AddEffect( AR_HANDLE hAttacker, AR_HANDLE hTarget, AR_HANDLE hOwner, int nEffectID, int nEffectPos, bool bIsLoopFx )
{
FX_DATA fxdata;
fxdata.attack = hAttacker;
fxdata.target = hTarget;
fxdata.owner = hOwner;
fxdata.nFX_ID = nEffectID;
fxdata.nEffPos = nEffectPos;
fxdata.bIsLoop = bIsLoopFx;
return AddEffect( &fxdata );
}
int SGame::AddAttackEffect( FX_DATA * fxdata )
{
SGameAvatarEx* pCaster = (SGameAvatarEx*)GetGameObject(fxdata->attack);
if(pCaster)
{
if(pCaster->GetObjType() != TS_ENTER::GAME_PLAYER || fxdata->keyhandleid == SMotionEventHanderDB::EV_HIT)
{
if( CheckCameraDistance( pCaster ) )
return AddEffect( fxdata );
else
return -1;
}
if(fxdata->keyhandleid != SMotionEventHanderDB::EV_LEFT_HAND_HIT &&
fxdata->keyhandleid != SMotionEventHanderDB::EV_RIGHT_HAND_HIT &&
fxdata->keyhandleid != SMotionEventHanderDB::EV_TWO_HAND_HIT)
{
if( CheckCameraDistance( pCaster ) )
return AddEffect( fxdata );
else
return -1;
}
}
else
{
return -1;
}
_MOTION_FX_SET* pFXSET = GetMotionFxSetDB().GetFXSet(fxdata->nFX_ID);
if( pFXSET )
{
SGameAvatarEx* pTarget = (SGameAvatarEx*)GetGameObject(fxdata->target);
if( !pTarget ) return NULL;
if( CheckCameraDistance( pCaster ) == false )
return -1;
if( pCaster->GetEffectRef() > 7 ) return NULL;
const K3DMatrix* pmatEPParent;
const K3DMatrix* pmatEpAttach;
const K3DMatrix* pmatEpPoint;
EFFECT_POS_WEAPON nEffectPosWp;
switch(fxdata->keyhandleid)
{
case SMotionEventHanderDB::EV_LEFT_HAND_HIT: nEffectPosWp = EFFECT_POS_LEFT_WEAPON; break;
case SMotionEventHanderDB::EV_RIGHT_HAND_HIT: nEffectPosWp = EFFECT_POS_RIGHT_WEAPON; break;
case SMotionEventHanderDB::EV_TWO_HAND_HIT: nEffectPosWp = EFFECT_POS_TWOHAND_WEAPON; break;
default:
{
assert( false );
return AddEffect( fxdata );
}
}
if(!pCaster->GetWeaponEventPoint(nEffectPosWp) || fxdata->keytime == -1)
{
return AddEffect( fxdata );
}
float fFrame = ((fxdata->keytime*4.8f)/160.0f)+0.05f; //반올림
if(!pCaster->SetFrame((int)fFrame))
{
return AddEffect( fxdata );
}
pmatEPParent = pCaster->GetWeaponEventPointParentMatrix(nEffectPosWp, EFFECT_POS_WEAPON_EP_END);
pmatEpAttach = pCaster->GetWeaponEventPointAttachMatrix(nEffectPosWp, EFFECT_POS_WEAPON_EP_END);
pmatEpPoint = pCaster->GetWeaponEventPointMatrix(nEffectPosWp, EFFECT_POS_WEAPON_EP_END);
K3DMatrix matWpTransform;
K3DMatrixIdentity(matWpTransform);
K3DMatrixMultiply(matWpTransform, *pmatEpPoint, *pmatEpAttach);
K3DMatrixMultiply(matWpTransform, matWpTransform, *pmatEPParent);
K3DVector vWpPos;
vWpPos.x = matWpTransform._41;
vWpPos.y = matWpTransform._42;
vWpPos.z = 0.0f;//matWpTransform._43;
K3DVector vCasterPos = *pCaster->GetPosition();
K3DVector vTargetPos = *pTarget->GetPosition();
float fCasterLength = K3DVectorLength((vCasterPos - vWpPos));
float fTargetLength = K3DVectorLength((vCasterPos - vTargetPos));
K3DMatrix matTransform;
K3DMatrixIdentity(matTransform);
if(fCasterLength < fTargetLength)
{ //무기 위치와 타겟 위치 중간점에서 이펙트 발생됨
K3DVector vWpPos = K3DVector( matWpTransform._41, matWpTransform._42, 0.0f );
vWpPos = vWpPos + ((vTargetPos-vWpPos)/2.0f);
matTransform._41 = vWpPos.x;
matTransform._42 = vWpPos.y;
matTransform._43 = matWpTransform._43;
}
else
{ //위치는 타겟위치 높이는 무기 높이
matTransform._41 = vTargetPos.x;
matTransform._42 = vTargetPos.y;
matTransform._43 = matWpTransform._43;
}
SGameEffectEx * pEffect = new SGameEffectEx( fxdata, pFXSET );
++m_nNewEffectID;
pCaster->EffectAddRef();
pEffect->SetOwner( fxdata->attack ); //지울때 사용
if( pCaster->GetArID() != pTarget->GetArID() )
{
pEffect->SetTargetScale(pTarget->GetScale(), matTransform);
}
pEffect->SetEndTime(fxdata->end_time );
pEffect->SetMode(fxdata->nMode);
pEffect->SetStateHandle(fxdata->state_handle);
pEffect->SetMessageHandler(this);
pEffect->SetTransform(matTransform);
pEffect->SetEffectID(m_nNewEffectID);
pEffect->PlayAnimation(m_dwTime); //시작
pEffect->IsLoopFx(fxdata->bIsLoop);
if (fabs(pTarget->GetAdjustedScale() - 1.0f) > FLT_EPSILON)
{
pEffect->SetScalePure(pTarget->GetAdjustedScale());
}
m_vNewEffectList.push_back(pEffect);
return m_nNewEffectID;
}
return -1;
}
bool SGame::CheckCameraDistance( SGameObject* pObject )
{
if( m_pViewPort )
{
const K3DVector& vCameraPos = m_pViewPort->GetCameraPos();
float fLength = K3DVectorLength( vCameraPos - *pObject->GetPosition() );
if( fLength > GAME_EFFECT_DISTANCE )
return false;
}
return true;
}
void SGame::SendGameInterfaceMsg( struct SGameMessage * game_msg )
{
if( m_pGameMng ) m_pGameMng->InterfaceMsg( game_msg );
}
unsigned g_userCamStates = 0;
enum
{
PAN_UP = 1<<0,
PAN_DOWN = 1<<1,
PAN_LEFT = 1<<2,
PAN_RIGHT = 1<<3,
ZOOM_IN = 1<<4,
ZOOM_OUT = 1<<5,
TURN_LEFT = 1<<6,
TURN_RIGHT = 1<<7,
TURN_UP = 1<<8,
TURN_DOWN = 1<<9
};
static inline unsigned GetUserCamStateFlag( int key )
{
switch ( key )
{
case VK_UP: return PAN_UP;
case VK_DOWN: return PAN_DOWN;
case VK_LEFT: return PAN_LEFT;
case VK_RIGHT: return PAN_RIGHT;
case VK_PRIOR: return ZOOM_IN;
case VK_NEXT: return ZOOM_OUT;
case 188: return TURN_LEFT; // '<'
case 190: return TURN_RIGHT; // '>'
case 191: return TURN_UP; // '/'
case 222: return TURN_DOWN; // '/'
}
return 0;
}
void SGame::ProcMsgAtStatic( SGameMessage * pGameMsg )
{
/// 2010.11.10 - prodongi
/*
extern bool g_bUserCamMode;
if ( !g_bUserCamMode )
return;
*/
if (g_UserInfo.isMonkeyTail())
{
extern bool g_bUserCamMode;
if ( !g_bUserCamMode )
return;
}
switch( pGameMsg->nType )
{
case IMSG_KEYDOWN:
{
SIMSG_KEYDOWN* pMsg = (SIMSG_KEYDOWN*)pGameMsg;
g_userCamStates |= GetUserCamStateFlag( LOWORD( pMsg->wParam ) );
break;
}
case IMSG_KEYUP:
{
SIMSG_KEYUP* pMsg = (SIMSG_KEYUP*)pGameMsg;
g_userCamStates &= ~GetUserCamStateFlag( LOWORD( pMsg->wParam ) );
break;
}
}
int nDeltaSpeed = 1*m_nDeltaSpeed;
/// 2010.11.11 - prodongi
/*
if( g_userCamStates & PAN_UP )
m_pCamera->Pan(0,nDeltaSpeed,0);
if( g_userCamStates & PAN_DOWN )
m_pCamera->Pan(0,-nDeltaSpeed,0);
if( g_userCamStates & PAN_LEFT )
m_pCamera->Pan(-nDeltaSpeed,0,0);
if( g_userCamStates & PAN_RIGHT )
m_pCamera->Pan(nDeltaSpeed,0,0);
*/
if( g_userCamStates & PAN_UP )
m_pCamera->PanWithCamDir(0, 0, nDeltaSpeed);
if( g_userCamStates & PAN_DOWN )
m_pCamera->PanWithCamDir(0,0, -nDeltaSpeed);
if( g_userCamStates & PAN_LEFT )
m_pCamera->PanWithCamDir(-nDeltaSpeed,0,0);
if( g_userCamStates & PAN_RIGHT )
m_pCamera->PanWithCamDir(nDeltaSpeed,0,0);
if( g_userCamStates & ZOOM_IN )
m_pCamera->Pan(0,0,nDeltaSpeed);
if( g_userCamStates & ZOOM_OUT )
m_pCamera->Pan(0,0,-nDeltaSpeed);
if( g_userCamStates & TURN_LEFT ) //'<'
m_pCamera->Turn( (float)(-(float)1 * 3.14/m_nDeltaX) );
if( g_userCamStates & TURN_RIGHT ) //'>'
m_pCamera->Turn( (float)( (float)1 * 3.14/m_nDeltaX) );
if( g_userCamStates & TURN_UP ) //'/'
m_pCamera->Elevation( (float)( (float)1 * 3.14/m_nDeltaY) );
if( g_userCamStates & TURN_DOWN ) //'/'
m_pCamera->Elevation( (float)( -(float)1 * 3.14/m_nDeltaY) );
}
void SGame::ReqMove( AR_HANDLE handle, const ArPosition & target, const ArPosition * targetposdata, int count, bool bSpeedSync )
{
if( IsStopProcess() ) return;
m_pArObject->ReqMove( handle, target, targetposdata, count, bSpeedSync );
}
void SGame::Game_Sound_Set_Volume( int nVolume )
{
if( m_pMSoundMgr ) m_pMSoundMgr->SetMasterVolume( nVolume );
}
void SGame::Game_Env_Off( bool bOnOff )
{
if( m_pMSoundMgr ) m_pMSoundMgr->SetEnvMute( bOnOff );
}
void SGame::Game_Music_Off( bool bOnOff )
{
if( m_pMSoundMgr ) m_pMSoundMgr->SetBgmMute( bOnOff );
}
K3DTexture * SGame::CreateBump(K3DRenderDeviceDX *pDevice)
{
K3DTexture * pBumpTex = NULL;
pBumpTex = pDevice->CreateTexture( 512, 512, K3DFMT_V8U8 );
if( pBumpTex == NULL )
return NULL;
char *pBuf;
int nStride;
pBumpTex->LockRect( NULL, (void**)&pBuf, nStride );
assert(pBuf && "pBumpTex->LockRect( NULL, (void**)&pBuf, nStride );");
CHAR* pDst = (CHAR*)pBuf;
CHAR iDu, iDv;
unsigned int dwHeight, dwWidth;
dwHeight = dwWidth = 512;
for( DWORD y=0; y<dwHeight; y++ )
{
CHAR* pPixel = pDst;
for( DWORD x=0; x<dwWidth; x++ )
{
FLOAT fx = x/(FLOAT)dwWidth - 0.5f;
FLOAT fy = y/(FLOAT)dwHeight - 0.5f;
iDu = (CHAR)(6.4*cosf(4.0f*(fx+fy)*D3DX_PI));
iDv = (CHAR)(6.4*sinf(4.0f*(fx+fy)*D3DX_PI));
pDst[2*x+0] = iDu;
pDst[2*x+1] = iDv;
}
pDst += nStride;
}
pBumpTex->Unlock();
return pBumpTex;
}
void SGame::OnSysCommand( const char *pChat, std::vector< std::string > & vToken )
{
std::string strCheat;
std::string strCommand = vToken[0].c_str()+2;
char szShortTmp[32]; memset( szShortTmp, 0, sizeof(szShortTmp) );
if( strCommand == "set_r" ) //해상도 변경
{
if( vToken.size() > 2 )
{
if( m_pGameMng ) m_pGameMng->SetResolution( atoi(vToken[1].c_str()), atoi(vToken[2].c_str()) );
GetGameOption().SetResolution_Width ( atoi(vToken[1].c_str()) );
GetGameOption().SetResolution_Height( atoi(vToken[2].c_str()) );
}
return;
}
if( strCommand == "set_w" ) //창/풀 스크린 변경
{
((K3DRenderDeviceDX*) KDeviceManagerDX::GetDeviceManager()->GetRenderDevice())->ToggleFullscreen( (bool) atoi(vToken[1].c_str()) );
GetGameOption().SetWinMode( atoi(vToken[1].c_str()) );
return;
}
else if( strCommand == "web_toggle")
{
if( g_pWebBrowser )
{
//SetNavigate( "http://itemshop.rappelz.com/" );
if( g_IsShowWebBrowser )
SetVisibleNavigate( false );
else
SetVisibleNavigate( true );
}
}
else if( strCommand == "web_url")
{
if( vToken.size() > 1 && g_pWebBrowser )
{
SetNavigate( vToken[1].c_str(), true, 0, 0 );
}
}
else if( strCommand == "guild_close" || strCommand == "web_close" )
{
SetOtherNavigateClose( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_GUILD_TITLE );
SendGameInterfaceMsg( &SIMSG_SHOW_UIWINDOW( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_GUILD_TITLE, false) );
SendGameInterfaceMsg( &SMSG_SEND_DATA( "web_close" ) );
}
else if( strCommand == "web_open")
{
if( vToken.size() <= 1 ) return;
SetOtherNavigate( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_GUILD_TITLE, vToken[1].c_str(), 240, 330 );
}
}
void SGame::ProcConsole( SGameMessage* pGameMsg )
{
if( pGameMsg->nType == MSG_CONSOLE_BUILDER )
{
SMSG_CONSOLE_BUILDER* pMsg = static_cast<SMSG_CONSOLE_BUILDER*>(pGameMsg);
}
}
int SGame::AddEnhanceEffect( SGameAvatarEx* pAvatar, int nWeaponEffectPos, EnhanceFX* pEnhanceFx, int nItemClass )
{
int nRecycleID = GetEnhanceRecycleID();
if( nRecycleID == -1 ) nRecycleID = ++m_nNewEnhanceFxID;
SGameEnhanceFx* pGameEnhanceFx = new SGameEnhanceFx;
pGameEnhanceFx->Init( pAvatar, nWeaponEffectPos, nItemClass );
pGameEnhanceFx->SetEnhanceFxID( nRecycleID );
m_vEnhanceFxList.push_back( pGameEnhanceFx );
return nRecycleID;
}
void SGame::RemoveEnhanceEffect( int nEnhanceFxID )
{
std::vector< SGameEnhanceFx* >::iterator iter = m_vEnhanceFxList.begin();
for( ; iter != m_vEnhanceFxList.end(); ++iter )
{
if( nEnhanceFxID == (*iter)->GetEnhanceFxID() )
{
(*iter)->SetEnd(true);
m_RecycleID.push( nEnhanceFxID );
break;
}
}
}
int SGame::GetEnhanceRecycleID()
{
int nRecycleID = -1;
if( !m_RecycleID.empty() )
{
nRecycleID = m_RecycleID.front();
m_RecycleID.pop();
}
return nRecycleID;
}
void SGame::SetRenderEnhanceFx( int nEnhanceFxID, bool bRender )
{
std::vector< SGameEnhanceFx* >::iterator iter = m_vEnhanceFxList.begin();
for( ; iter != m_vEnhanceFxList.end(); iter++ )
{
if( nEnhanceFxID == (*iter)->GetEnhanceFxID() )
{
(*iter)->SetRenderFlag( bRender );
break;
}
}
}
//파티클 치트 모드 고쳐야하는데
void SGame::ParticleQuality( int nQuality )
{
std::vector< class SGameEnhanceFx* >::iterator iter = m_vEnhanceFxList.begin();
for( ; iter != m_vEnhanceFxList.end(); iter++ )
(*iter)->SetParticleQuality( nQuality );
}
void SGame::ParticleLifeTime( DWORD dwLifeTime )
{
std::vector< class SGameEnhanceFx* >::iterator iter = m_vEnhanceFxList.begin();
for( ; iter != m_vEnhanceFxList.end(); iter++ )
(*iter)->SetLifeTime( dwLifeTime );
}
void SGame::ParticleMoveSpeed( float fSpeed )
{
std::vector< class SGameEnhanceFx* >::iterator iter = m_vEnhanceFxList.begin();
for( ; iter != m_vEnhanceFxList.end(); iter++ )
(*iter)->SetMoveSpeed( fSpeed );
}
void SGame::ParticleSize( float fStartSize, float fEndSize )
{
std::vector< class SGameEnhanceFx* >::iterator iter = m_vEnhanceFxList.begin();
for( ; iter != m_vEnhanceFxList.end(); iter++ )
(*iter)->SetSize( fStartSize, fEndSize );
}
void SGame::ParticleEmitRadius( K3DVector vEmitRadius )
{
std::vector< class SGameEnhanceFx* >::iterator iter = m_vEnhanceFxList.begin();
for( ; iter != m_vEnhanceFxList.end(); iter++ )
(*iter)->SetEmitRadius( vEmitRadius );
}
void SGame::ParticleEmitRate( float fMin, float fMax )
{
std::vector< class SGameEnhanceFx* >::iterator iter = m_vEnhanceFxList.begin();
for( ; iter != m_vEnhanceFxList.end(); iter++ )
(*iter)->SetEmitRate( fMin, fMax );
}
void SGame::ParticleCreateInterval( float fInterval )
{
std::vector< class SGameEnhanceFx* >::iterator iter = m_vEnhanceFxList.begin();
for( ; iter != m_vEnhanceFxList.end(); iter++ )
(*iter)->SetCreateInterval( fInterval );
}
void SGame::ParticleMinDirection( K3DVector vMinDirection )
{
std::vector< class SGameEnhanceFx* >::iterator iter = m_vEnhanceFxList.begin();
for( ; iter != m_vEnhanceFxList.end(); iter++ )
(*iter)->SetMinDirection( vMinDirection );
}
void SGame::ParticleMaxDirection( K3DVector vMaxDirection )
{
std::vector< class SGameEnhanceFx* >::iterator iter = m_vEnhanceFxList.begin();
for( ; iter != m_vEnhanceFxList.end(); iter++ )
(*iter)->SetMaxDirection( vMaxDirection );
}
void SGame::EnhanceFxType( int nType )
{
std::vector< class SGameEnhanceFx* >::iterator iter = m_vEnhanceFxList.begin();
for( ; iter != m_vEnhanceFxList.end(); iter++ )
(*iter)->SetEnhanceFxType( nType );
}
/* return value
1: 자기자신 2: 파티원
3: 던전시즈 중 길드원 4: NPC
5: 소환크리처 6: 파티원 크리처
7: 던전시즈 중 길드원 크리처*/
//Handle에 해당하는 대상이 친구인지 알아보는 함수 -N4-
//평상시엔 파티워 아바타와 크리처 자신의 크리처, 던전 시즈중에는 길드원과 길드원의 크리처도 동료에 포함
int SGame::IsFriend( AR_HANDLE Handle, unsigned char& rType )
{
return m_pGameMng->IsFriend(Handle, rType);
}