Files
2026-06-01 12:46:52 +02:00

2572 lines
81 KiB
C++

#include "stdafx.h"
#include ".\sgameplayer.h"
#include "GameDefine.h"
#include "KSeqAvatar.h"
#include "KSeqAvatarEx.h"
#include "KRenderObjectEtc.h"
#include "SStringDB.h"
#include "SItemDB.h"
#include "SGameWork.h"
#include "SGameMessage.h"
#include "SGameAniType.h"
#include "SSkillDB.h"
#include <toolkit/XStringUtil.h>
#include "SAvatarProperty.h"
#include "SAvatarStateMachine.h"
#include "SSkillStageType.h"
#include "SGameUtil.h"
#include "SGameCircleShadowFX.h"
#include "SGameForceSphereFX.h"
#include "SGameOption.h"
#include "SGameSystem.h" // 2011.11.04 - servantes
#include "SGameManager.h"
#include "SGame.h"
#include "SGameLocalCreature.h"
#include "SCreatureDB.h"
#include "SMonsterDB.h"
#include "SDebug_Util.h"
extern SGameSystem* g_pCurrentGameSystem; // 2011.11.04 - servantes
SGamePlayer* SGamePlayer::m_pLocalPlayer;
SGamePlayer::SGamePlayer( ENC_INT nContentID ) : SGameAvatarEx ( nContentID )
, m_nPrevAniType ( 0 )
, m_dwIdleTime ( 0 ) // sonador 1.8.13 아바타 IDLE 모션 동작 구현
{
memset( m_NudeItemCode, 0, sizeof(m_NudeItemCode) ); //아무것도 안 입었을때
memset( m_ItemCode , 0, sizeof(m_ItemCode) ); //장착시
memset( m_ItemLevel , 0, sizeof(m_ItemLevel) );
m_bIsUseSkill_complete = true;
m_idPrevState = SObjectState::STATE_NONE;
m_hCreatureMounthandle = 0;
m_nEnhanceCheatLevel = 0;
m_bWaitingAttackCancel = false;
SetRunNWalkAniSpeedDefault(); // sonador #2.1.6 크리쳐 기린(spirit_qilin) 테스트
}
SGamePlayer::~SGamePlayer()
{
}
ANI_LIST_EX SGamePlayer::GetDefaultAnimation()
{
if( IsDead() ) return ANI_DEAD01; //죽었음
if( (GetStatus() & TS_ENTER::PlayerInfo::FLAG_SITDOWN) ) return ANI_SIT;
return SGameAvatarEx::GetDefaultAnimation();
}
void SGamePlayer::SetItemCodeLevel( int nIndex, ItemBase::ItemCode code, int nLevel )
{
if( ItemBase::MAX_ITEM_WEAR > nIndex && nIndex > -1 )
{
m_ItemCode[nIndex] = code;
m_ItemLevel[nIndex] = nLevel;
}
}
ItemBase::ItemCode SGamePlayer::GetItemCode( int nIndex )
{
if( ItemBase::MAX_ITEM_WEAR > nIndex && nIndex > -1 )
return m_ItemCode[nIndex];
return -1;
}
int SGamePlayer::GetItemLevel( int nIndex )
{
if( ItemBase::MAX_ITEM_WEAR > nIndex && nIndex > -1 )
return m_ItemLevel[nIndex];
return -1;
}
ItemBase::ItemClass SGamePlayer::GetItemClass( int nIndex )
{
if( ItemBase::MAX_ITEM_WEAR > nIndex && nIndex > -1 )
return (ItemBase::ItemClass)m_itemClass[nIndex];
return ItemBase::CLASS_ETC;
}
void SGamePlayer::RefreshItemWearEx( class KSeqAvatarEx * pAvatarEx, std::vector< WEAR_DATA >& wearlist )
{
if( !pAvatarEx ) return;
if( wearlist.empty() ) return;
memset( m_itemClass, 0, sizeof( m_itemClass ) );
int nWearSize = (int)wearlist.size();
for( int i(0); nWearSize>i; ++i )
{
ItemWear( wearlist[i], pAvatarEx );
}
bool bAniLock = GetAniLock();
SetAniLock( false );
AttachAnimation( pAvatarEx );
SetAniLock( bAniLock );
}
//Item Wear Info
void SGamePlayer::RefreshItemWear( KSeqAvatarEx * pAvatarEx/* const char * pFileName, int nItemClass, int nWearType, int nItemLevel*/ )
{
// if( !IsActivated() )
// { //아직 로딩이 안된 상태
///* WEAR_DATA wear_data;
// wear_data.strFileName = pFileName;
// wear_data.nItemClass = nItemClass;
// wear_data.nWearType = nWearType;
// wear_data.nItemLevel = nItemLevel;*/
//
// m_vWearList.push_back( WearData );
// return;
// }
if( !pAvatarEx ) return;
if( m_vWearList.empty() ) return;
memset( m_itemClass, 0, sizeof( m_itemClass ) );
int nWearSize = (int)m_vWearList.size();
for( int i(0); nWearSize>i; ++i )
{
ItemWear( m_vWearList[i], pAvatarEx );
}
bool bAniLock = GetAniLock();
SetAniLock( false );
AttachAnimation( pAvatarEx );
SetAniLock( bAniLock );
}
void SGamePlayer::ItemWear( WEAR_DATA& WearData, class KSeqAvatarEx * pAvatarEx )
{
std::string strTexture = WearData.strTextureName;
/// 2011.06.11 mantis 13327 - prodongi
std::string strDecoTexture = WearData.strDecoTextureName;
m_itemClass[WearData.nWearType] = WearData.nItemClass;
ItemBase::ItemWearType nDecoWearType = ItemBase::WEAR_NONE;
switch( WearData.nWearType )
{
case ItemBase::WEAR_WEAPON: nDecoWearType = ItemBase::WEAR_DECO_WEAPON; break;
case ItemBase::WEAR_SHIELD: nDecoWearType = ItemBase::WEAR_DECO_SHIELD; break;
case ItemBase::WEAR_ARMOR: nDecoWearType = ItemBase::WEAR_DECO_ARMOR; break;
case ItemBase::WEAR_HELM: nDecoWearType = ItemBase::WEAR_DECO_HELM; break;
case ItemBase::WEAR_GLOVE: nDecoWearType = ItemBase::WEAR_DECO_GLOVE; break;
case ItemBase::WEAR_BOOTS: nDecoWearType = ItemBase::WEAR_DECO_BOOTS; break;
case ItemBase::WEAR_MANTLE: nDecoWearType = ItemBase::WEAR_DECO_MANTLE; break;
}
if( nDecoWearType != ItemBase::WEAR_NONE )
{
m_itemClass[nDecoWearType] = WearData.nDecoItemClass;
}
bool bAddDecoItem = WearData.bWithDecoItem;
if( bAddDecoItem )
{
//if( GetGameOption().GetAvatarDeco() == 0 ) // 2010.10.11. 게임플레이옵션에서 "꾸미기보이기" 제거.
//{
// bAddDecoItem = false;
//}
}
//Itemcode로 Ani 변경 지원 해야 한다.
switch( WearData.nItemClass )
{
case ItemBase::CLASS_ETCWEAPON : //= 100,// 기타무기
case ItemBase::CLASS_ONEHAND_SWORD : //= 101,// 한손검
m_nThreadAniClass = ANICLS_SWO;
break;
case ItemBase::CLASS_SHIELD :
if( m_itemClass[ItemBase::WEAR_RIGHTHAND] == 0 )// 오른손에 아무것도 없을때, 방패 착용시 한손검 모션
m_nThreadAniClass = ANICLS_SWO;
break;
case ItemBase::CLASS_DAGGER : //= 103,// 단검
m_nThreadAniClass = ANICLS_DGO;
break;
case ItemBase::CLASS_TWOHAND_SWORD : //= 102,// 양손검
m_nThreadAniClass = ANICLS_SWA;
break;
case ItemBase::CLASS_TWOHAND_SPEAR : m_nThreadAniClass = ANICLS_SPA;//= 104,// 창
break;
case ItemBase::CLASS_TWOHAND_AXE : m_nThreadAniClass = ANICLS_AXA;//= 105,// 도끼 => 나중에 리소스 추가 해야 함.
break;
case ItemBase::CLASS_ONEHAND_MACE : m_nThreadAniClass = ANICLS_MAO;//= 106,// 한손메이스
break;
case ItemBase::CLASS_TWOHAND_MACE : m_nThreadAniClass = ANICLS_MAA;//= 107,// 양손메이스
break;
case ItemBase::CLASS_LIGHT_BOW : //= 108,// 활
case ItemBase::CLASS_HEAVY_BOW : //= 109,// 활
m_nThreadAniClass = ANICLS_BWA;
break;
case ItemBase::CLASS_CROSSBOW : m_nThreadAniClass = ANICLS_CBO;//= 110,// 석궁
break;
<<<<<<< HEAD
=======
// AziaMafia Double Crossbow ANICLS_CBT
//case ItemBase::CLASS_DOUBLE_CROSSBOW : m_nThreadAniClass = ANICLS_CBO ;
// break;
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
case ItemBase::CLASS_ONEHAND_STAFF : m_nThreadAniClass = ANICLS_SWO;//ANICLS_SFO;//= 110,// 한손 지팡이 => 나중에 리소스 추가 해야 함.
break;
case ItemBase::CLASS_TWOHAND_STAFF : m_nThreadAniClass = ANICLS_SFA;//= 111,// 두손 지팡이 => 나중에 리소스 추가 해야 함.
break;
case ItemBase::CLASS_ONEHAND_AXE: m_nThreadAniClass = ANICLS_AXO; //113 한손 도끼
break;
}
switch( WearData.nWearType )
{
case ItemBase::WEAR_LEFTHAND :
{
m_bThreadUseLeftWeaponTrail = false;
if( WearData.nItemClass == ItemBase::CLASS_ONEHAND_SWORD )
{
m_nThreadAniClass = ANICLS_SWT; //장검 이도류 6
m_bThreadUseLeftWeaponTrail = true;
}
else if( WearData.nItemClass == ItemBase::CLASS_DAGGER )
{
m_nThreadAniClass = ANICLS_DGT; //단검 이도류 7
m_bThreadUseLeftWeaponTrail = true;
}
else if( WearData.nItemClass == ItemBase::CLASS_ONEHAND_AXE )
{
m_nThreadAniClass = ANICLS_AXT; //도끼 이도류
m_bThreadUseLeftWeaponTrail = true;
}
<<<<<<< HEAD
else if (WearData.nItemClass == ItemBase::CLASS_CROSSBOW) // Double Crossbow
=======
else if (WearData.nItemClass == ItemBase::CLASS_CROSSBOW) // ZONE Double cross bow 02.01.2021 // From ZONE source; dual crossbows
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
{
m_nThreadAniClass = ANICLS_CBT;
m_bThreadUseLeftWeaponTrail = true;
}
// AziaMafia Double Crossbow
//else if (WearData.nItemClass == ItemBase::CLASS_CROSSBOW)
//{
// m_nThreadAniClass = ANICLS_CBO; //µµ³¢ À̵µ·ù
// m_bThreadUseLeftWeaponTrail = true;
//}
// if( WearData.bIsDecoItem ) m_bThreadUseLeftWeaponTrail = false;
}
break;
case ItemBase::WEAR_RIGHTHAND :
{
m_bThreadUseRightWeaponTrail = false;
if( WearData.nItemClass == 0 )
{
m_nThreadAniClass = ANICLS_UNA; //기본
}
else
{
//보우 계열 빼고, 검기 활성화
/*if( WearData.nItemClass != ItemBase::CLASS_LIGHT_BOW &&
WearData.nItemClass != ItemBase::CLASS_HEAVY_BOW &&
WearData.nItemClass != ItemBase::CLASS_CROSSBOW )*/
m_bThreadUseRightWeaponTrail = true;
}
// if( WearData.bIsDecoItem ) m_bThreadUseRightWeaponTrail = false;
}
break;
}
bool bAddMesh = false;
//좀 복잡 하다. 단순화 시키자
//장착 시키자...외향 변경
switch( WearData.nWearType )
{
//Link 변경
case ItemBase::WEAR_LEFTHAND :
{
std::string strFile = WearData.strFileName.c_str();
assert( strFile.length() && "아이템 이름없음" );
std::string strDecoFile = WearData.strDecoFileName;
if( strFile.length() > 5 ) strFile.replace( strFile.size() - 4, 1, "_L." );
if( strDecoFile.length() > 5 ) strDecoFile.replace( strDecoFile.size() - 4, 1, "_L." );
_performance_print( "WEAR_LEFTHAND %s\n", strFile.c_str() );
if( WearData.nItemClass == ItemBase::CLASS_SHIELD )
{
if( bAddDecoItem && isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_SHIELD ) ) // 꾸미기방패.
{
if( WearData.bAttachDecoItem ) bAddMesh = true;
pAvatarEx->AddAttachItem( ANIPART_BIPED, ATTACH_HAND_ARM2L_DECO, WearData.strDecoFileName.c_str() );
}
else
{
bAddMesh = true;
}
if( bAddMesh )
{
pAvatarEx->AddAttachItem( ANIPART_BIPED, ATTACH_HAND_ARM2L , WearData.strFileName.c_str(), strTexture ); //방패
}
pAvatarEx->AddMesh( ANIPART_WEAPON_LEFT, MPART_L_WEAPON, "", strTexture ); //왼손에 장착 된거 사라지게
SetWeaponInfo( pAvatarEx, WearData, NULL );
}
<<<<<<< HEAD
else if (WearData.nItemClass == ItemBase::CLASS_ONEHAND_SWORD ||
WearData.nItemClass == ItemBase::CLASS_DAGGER ||
WearData.nItemClass == ItemBase::CLASS_ONEHAND_AXE ||
WearData.nItemClass == ItemBase::CLASS_CROSSBOW) //Double Crossbow
=======
else if( WearData.nItemClass == ItemBase::CLASS_ONEHAND_SWORD ||
WearData.nItemClass == ItemBase::CLASS_DAGGER ||
WearData.nItemClass == ItemBase::CLASS_ONEHAND_AXE ||
WearData.nItemClass == ItemBase::CLASS_CROSSBOW) // From ZONE source; dual crossbows
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
{ //이도류
pAvatarEx->AddAttachItem( ANIPART_BIPED, ATTACH_HAND_ARM2L , "" ); //방패 사라지게
if( bAddDecoItem && isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_SHIELD ) ) // 꾸미기방패.
{
if( WearData.bAttachDecoItem )
<<<<<<< HEAD
if (WearData.nItemClass == ItemBase::CLASS_CROSSBOW) //Double Crossbow
{
pAvatarEx->AddDecoMesh(ANIPART_WEAPON_LEFT, MDECOPART_L_WEAPON, WearData.strDecoFileName.c_str(), strDecoTexture);
}
else
{
pAvatarEx->AddDecoMesh(ANIPART_WEAPON_LEFT, MDECOPART_L_WEAPON, strDecoFile.c_str(), strDecoTexture);
}
=======
bAddMesh = true;
/// 2011.06.11 mantis 13327 - prodongi
if (WearData.nItemClass == ItemBase::CLASS_CROSSBOW)
{
pAvatarEx->AddDecoMesh(ANIPART_WEAPON_LEFT, MDECOPART_L_WEAPON, WearData.strDecoFileName.c_str(), strDecoTexture);
}
else
{
pAvatarEx->AddDecoMesh(ANIPART_WEAPON_LEFT, MDECOPART_L_WEAPON, strDecoFile.c_str(), strDecoTexture);
}
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
}
else
{
bAddMesh = true;
}
if (bAddMesh)
{
if (WearData.nItemClass == ItemBase::CLASS_CROSSBOW)
{
pAvatarEx->AddMesh(ANIPART_WEAPON_LEFT, MPART_L_WEAPON, WearData.strFileName.c_str(), strTexture); //왼손에 장착 된거 사라지게
}
else
{
pAvatarEx->AddMesh(ANIPART_WEAPON_LEFT, MPART_L_WEAPON, strFile.c_str(), strTexture); //왼손에 장착 된거 사라지게
}
}
}
else
{
<<<<<<< HEAD
if( m_itemClass[ItemBase::WEAR_WEAPON] != ItemBase::CLASS_LIGHT_BOW &&
m_itemClass[ItemBase::WEAR_WEAPON] != ItemBase::CLASS_HEAVY_BOW &&
m_itemClass[ItemBase::WEAR_WEAPON] != ItemBase::CLASS_CROSSBOW ) //Double Crossbow
=======
//if( m_itemClass[ItemBase::WEAR_WEAPON] != ItemBase::CLASS_LIGHT_BOW &&
// m_itemClass[ItemBase::WEAR_WEAPON] != ItemBase::CLASS_HEAVY_BOW
//
// // AziaMafia Double Crossbow
// //&& m_itemClass[ItemBase::WEAR_WEAPON] != ItemBase::CLASS_CROSSBOW
// )
// From ZONE source; dual crossbows
if (m_itemClass[ItemBase::WEAR_WEAPON] != ItemBase::CLASS_LIGHT_BOW &&
m_itemClass[ItemBase::WEAR_WEAPON] != ItemBase::CLASS_HEAVY_BOW &&
m_itemClass[ItemBase::WEAR_WEAPON] != ItemBase::CLASS_CROSSBOW)
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
{
//삭제 하기 위함.
pAvatarEx->AddAttachItem( ANIPART_BIPED, ATTACH_HAND_ARM2L , "" ); //방패
if( bAddDecoItem && isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_SHIELD ) ) // 꾸미기방패.
{
if( WearData.bAttachDecoItem )
bAddMesh = true;
/// 2011.06.11 mantis 13327 - prodongi
pAvatarEx->AddDecoMesh( ANIPART_WEAPON_LEFT, MDECOPART_L_WEAPON, WearData.strDecoFileName.c_str(), strDecoTexture ); //그냥 왼손
}
else
{
bAddMesh = true;
}
if( bAddMesh )
{
pAvatarEx->AddMesh( ANIPART_WEAPON_LEFT, MPART_L_WEAPON, WearData.strFileName.c_str(), strTexture ); //그냥 왼손
}
}
}
if( WearData.nItemClass == 0 )
{
if( m_itemClass[ItemBase::WEAR_WEAPON] != ItemBase::CLASS_LIGHT_BOW &&
m_itemClass[ItemBase::WEAR_WEAPON] != ItemBase::CLASS_HEAVY_BOW )
SetWeaponInfo( pAvatarEx, WearData, NULL );
}
else
{
//방패가 아니라면 추가
if( WearData.nItemClass != ItemBase::CLASS_SHIELD && WearData.nItemClass != 265 )
{
std::string strEffectPosname = "wfx_";
strEffectPosname += strFile;
SetWeaponInfo( pAvatarEx, WearData, strEffectPosname.c_str() );
}
}
}
break; // Item Link 왼손전용 (방패라던가)
case ItemBase::WEAR_RIGHTHAND :
if( WearData.nItemClass == ItemBase::CLASS_LIGHT_BOW || WearData.nItemClass == ItemBase::CLASS_HEAVY_BOW )
{
pAvatarEx->AddAttachItem( ANIPART_BIPED, ATTACH_HAND_ARM2L , "" ); //방패 사라지게 한다.
pAvatarEx->AddMesh( ANIPART_WEAPON_RIGHT, MPART_R_WEAPON, "" ); //오른손 사라지게 한다.
if( bAddDecoItem && isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_WEAPON ) ) // 꾸미기무기.
{
if( WearData.bAttachDecoItem )
bAddMesh = true;
/// 2011.06.11 mantis 13327 - prodongi
pAvatarEx->AddDecoMesh( ANIPART_WEAPON_LEFT, MDECOPART_L_WEAPON, WearData.strDecoFileName.c_str(), strDecoTexture );
}
else
{
bAddMesh = true;
}
if( bAddMesh )
{
pAvatarEx->AddMesh( ANIPART_WEAPON_LEFT, MPART_L_WEAPON, WearData.strFileName.c_str(), strTexture ); //왼손에 활 장착
}
//오른쪽 이펙트 사라지게 하기
WEAR_DATA tempwear = WearData;
tempwear.nItemCode = 0;
tempwear.nWearType = ItemBase::WEAR_RIGHTHAND;
SetWeaponInfo( pAvatarEx, tempwear, NULL );
}
else if( WearData.nItemClass == ItemBase::CLASS_CROSSBOW )
{
<<<<<<< HEAD
// Removed code that clears left-hand attachments to allow shield to remain equipped. //Double Crossbow
//pAvatarEx->AddAttachItem( ANIPART_BIPED, ATTACH_HAND_ARM2L , "" ); //방패 사라지게 한다. // Remove shield from left hand.
//pAvatarEx->AddMesh( ANIPART_WEAPON_LEFT, MPART_L_WEAPON, "" ); //왼손 사라지게 한다. // Clear left hand weapon.
if( bAddDecoItem && isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_WEAPON ) ) // 꾸미기무기. Decoration weapon hiding.
=======
// From ZONE source; dual crossbows
// Removed code that clears left-hand attachments to allow shield to remain equipped.
// pAvatarEx->AddAttachItem( ANIPART_BIPED, ATTACH_HAND_ARM2L , "" ); // Remove shield from left hand.
// pAvatarEx->AddMesh( ANIPART_WEAPON_LEFT, MPART_L_WEAPON, "" ); // Clear left hand weapon.
if( bAddDecoItem && isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_WEAPON ) ) // Decoration weapon hiding.
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
{
if( WearData.bAttachDecoItem )
bAddMesh = true;
pAvatarEx->AddDecoMesh( ANIPART_WEAPON_RIGHT, MDECOPART_R_WEAPON, WearData.strDecoFileName.c_str(), strDecoTexture );
}
else
{
bAddMesh = true;
}
if( bAddMesh )
{
<<<<<<< HEAD
pAvatarEx->AddMesh( ANIPART_WEAPON_RIGHT, MPART_R_WEAPON, WearData.strFileName.c_str(), strTexture ); //오른손에 활 장착 // Equip crossbow on right hand. //Double Crossbo
=======
pAvatarEx->AddMesh( ANIPART_WEAPON_RIGHT, MPART_R_WEAPON, WearData.strFileName.c_str(), strTexture ); // Equip crossbow on right hand.
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
}
}
else
{
if( bAddDecoItem && isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_WEAPON ) ) // 꾸미기무기.
{
if( WearData.bAttachDecoItem )
bAddMesh = true;
/// 2011.06.11 mantis 13327 - prodongi
pAvatarEx->AddDecoMesh( ANIPART_WEAPON_RIGHT, MDECOPART_R_WEAPON, WearData.strDecoFileName.c_str(), strDecoTexture );
}
else
{
bAddMesh = true;
}
if( bAddMesh )
{
pAvatarEx->AddMesh( ANIPART_WEAPON_RIGHT, MPART_R_WEAPON, WearData.strFileName.c_str(), strTexture );
}
}
if( WearData.nItemClass == 0 )
{
m_nThreadAniClass = ANICLS_UNA; //기본
SetWeaponInfo( pAvatarEx, WearData, NULL );
}
else
{
//방패가 아니라면 추가
if( WearData.nItemClass != ItemBase::CLASS_SHIELD )
{
if( WearData.nItemClass == ItemBase::CLASS_LIGHT_BOW || WearData.nItemClass == ItemBase::CLASS_HEAVY_BOW )
WearData.nWearType = ItemBase::WEAR_RIGHTHAND;
std::string strEffectPosname = "wfx_";
strEffectPosname += WearData.strFileName.c_str();
SetWeaponInfo( pAvatarEx, WearData, strEffectPosname.c_str() );
}
}
break; // Item Link 오른손전용
//Skin 변경
case ItemBase::WEAR_ARMOR :
{
std::string strTemp = WearData.strFileName.c_str();
if( bAddDecoItem && isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_ARMOR ) ) // 꾸미기의상.
{
if( WearData.bAttachDecoItem )
bAddMesh = true;
// { sonador 1.8.1 액세서리 확장 표현 슬롯 추가
/// 2011.06.11 mantis 13327 - prodongi
pAvatarEx->AddDecoMesh( ANIPART_BIPED, MDECOPART_BODY, WearData.strDecoFileName.c_str(), strDecoTexture );
strTemp = WearData.strDecoFileName.c_str();
XStringUtil::Replace( strTemp, "body", "shortskirt" );
pAvatarEx->AddMesh( ANIPART_SHORTSKIRT , MDECOPART_S_SKIRT , strTemp.c_str() ); // 짧은 치마
strTemp = WearData.strDecoFileName.c_str();
XStringUtil::Replace( strTemp, "body", "middleskirt" );
pAvatarEx->AddMesh( ANIPART_MIDSKIRT , MDECOPART_M_SKIRT , strTemp.c_str() ); // 중 치마
strTemp = WearData.strDecoFileName.c_str();
XStringUtil::Replace( strTemp, "body", "long" );
pAvatarEx->AddMesh( ANIPART_LONGSKIRT , MDECOPART_L_SKIRT , strTemp.c_str() ); // 긴 치마
strTemp = WearData.strDecoFileName.c_str();
// }
}
else
{
bAddMesh = true;
}
if( bAddMesh )
{
//몸통과 일체형인데, 어떤 것이 올지 모르기 때문에, 모두 찾는다. 몸통과 치마류는 1:1 대응임.
pAvatarEx->AddMesh( ANIPART_BIPED , MPART_BODY , WearData.strFileName.c_str(), strTexture ); // 몸
XStringUtil::Replace( strTemp, "body", "shortskirt" );
pAvatarEx->AddMesh( ANIPART_SHORTSKIRT , MPART_S_SKIRT , strTemp.c_str(), strTexture ); // 짧은 치마
strTemp = WearData.strFileName.c_str();
XStringUtil::Replace( strTemp, "body", "fabric" );
pAvatarEx->AddMesh( ANIPART_FABRIC , MPART_FABRIC , strTemp.c_str(), strTexture ); // 앞가리개
strTemp = WearData.strFileName.c_str();
XStringUtil::Replace( strTemp, "body", "middleskirt" );
pAvatarEx->AddMesh( ANIPART_MIDSKIRT , MPART_M_SKIRT , strTemp.c_str(), strTexture ); // 중 치마
strTemp = WearData.strFileName.c_str();
XStringUtil::Replace( strTemp, "body", "long" );
pAvatarEx->AddMesh( ANIPART_LONGSKIRT , MPART_L_SKIRT , strTemp.c_str(), strTexture ); // 긴 치마
}
}
break;
case ItemBase::WEAR_HELM : // 투구
{
// 2010.05.19 - prodongi
// 수정. 2010.10.08. 게임플레이설정 - 투구보이기 를 해제한 경우에 꾸미기투구가 안보이는 문제때문에 꾸미기투구 조건추가.
if (!isHideEquipInfo(ItemBase::HIDE_EQUIP_HELM) || isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_HELM ) )
//if( GetGameOption().Is
// Helm() ) //투구보이기 옵션에 따른 리소스 추가
{
const ItemBaseEx_info* pItemInfo = NULL;
bool bHideHair = false;
if( bAddDecoItem && isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_HELM ) ) // 꾸미기투구.
{
if( WearData.bAttachDecoItem ) bAddMesh = true;
else
{
bHideHair = true;
pItemInfo = GetItemDB().GetItemData( WearData.nDecoItemCode );
}
/// 2011.06.11 mantis 13327 - prodongi
pAvatarEx->AddDecoMesh( ANIPART_BIPED, MDECOPART_HELM, WearData.strDecoFileName.c_str(), strDecoTexture );
}
else
{
bAddMesh = true;
}
int itemCode;
if( WearData.nAppearanceItemCode )
itemCode = WearData.nAppearanceItemCode;
else
itemCode = WearData.nItemCode;
if( bAddMesh )
{
//헬멧이 제대로 들어가면
bHideHair = pAvatarEx->AddMesh( ANIPART_BIPED, MPART_HELM, WearData.strFileName.c_str(), strTexture );
pItemInfo = GetItemDB().GetItemData( itemCode );
}
if( pItemInfo )
{
// 2010.08.16 - prodongi
/*
int nFlag = 0;
if( GetRace() == GCLAN_GAIA )
{
if( GetSex() == SEX_MALE ) nFlag = pItemInfo->model_type_gam;
else if( GetSex() == SEX_FEMALE ) nFlag = pItemInfo->model_type_gaf;
}
else if( GetRace() == GCLAN_DEVA )
{
if( GetSex() == SEX_MALE ) nFlag = pItemInfo->model_type_dem;
else if( GetSex() == SEX_FEMALE ) nFlag = pItemInfo->model_type_def;
}
else if( GetRace() == GCLAN_ASURA )
{
if( GetSex() == SEX_MALE ) nFlag = pItemInfo->model_type_asm;
else if( GetSex() == SEX_FEMALE ) nFlag = pItemInfo->model_type_asf;
}
*/
int nFlag = getHelmItemModelType(GetRace(), GetSex(), pItemInfo);
// sonador #2.1.22
if( bHideHair )
{
if( nFlag & ItemBaseEx_info::HAIR_FLAG ) // 헤어를 숨김
//pAvatarEx->AddMesh( ANIPART_HAIR, MPART_HAIR, "hide_hair" );
pAvatarEx->AddMesh( ANIPART_BIPED, MPART_HAIR, "hide_hair" );
if( nFlag & ItemBaseEx_info::FACE_FLAG ) // 페이스 숨김
pAvatarEx->AddMesh( ANIPART_BIPED, MPART_FACE, "hide_face" );
// 2010.08.16 - prodongi
if( nFlag & ItemBaseEx_info::EARRING_FLAG ) // 귀걸이 숨김
pAvatarEx->AddMesh( ANIPART_BIPED, MPART_ACCE_EAR, "hide_earring" );
}
}
}
}
break;
case ItemBase::WEAR_GLOVE : // 손
{
if( bAddDecoItem && isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_GLOVE ) ) // 꾸미기장갑.
{
if( WearData.bAttachDecoItem )
bAddMesh = true;
/// 2011.06.11 mantis 13327 - prodongi
pAvatarEx->AddDecoMesh( ANIPART_BIPED, MDECOPART_HAND, WearData.strDecoFileName.c_str(), strDecoTexture );
}
else
{
bAddMesh = true;
}
if( bAddMesh )
pAvatarEx->AddMesh( ANIPART_BIPED, MPART_HAND, WearData.strFileName.c_str(), strTexture );
}
break;
case ItemBase::WEAR_BOOTS : // 발
{
if( bAddDecoItem && isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_BOOTS ) ) // 꾸미기부츠.
{
if( WearData.bAttachDecoItem ) bAddMesh = true;
/// 2011.06.11 mantis 13327 - prodongi
pAvatarEx->AddDecoMesh( ANIPART_BIPED, MDECOPART_FOOT, WearData.strDecoFileName.c_str(), strDecoTexture );
}
else
{
bAddMesh = true;
}
if( bAddMesh )
pAvatarEx->AddMesh( ANIPART_BIPED, MPART_FOOT , WearData.strFileName.c_str(), strTexture );
}
break;
case ItemBase::WEAR_MANTLE :
{
if( GetGameOption().IsShowMantle() ) //망토 보이기 옵션에 따른 리소스 추가
{
if( bAddDecoItem && isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_CLOAK ) ) // 꾸미기망토.
{
if( WearData.bAttachDecoItem ) bAddMesh = true;
/// 2011.06.11 mantis 13327 - prodongi
pAvatarEx->AddDecoMesh( ANIPART_MANTLE, MDECOPART_MANTLE, WearData.strDecoFileName.c_str(), strDecoTexture );
}
else
{
bAddMesh = true;
}
if( bAddMesh )
pAvatarEx->AddMesh( ANIPART_MANTLE , MPART_MANTLE, WearData.strFileName.c_str(), strTexture );
}
}
break; // 망토
case ItemBase::WEAR_EAR : //귀
if (GameRule::GetCurrentLocalBitSet() != GameRule::LOCAL_BITSET::ME) // 귀걸이 감추기. 무슬림 국가에서는 다 막아야 할 듯. 일단 중동만
{
// 2010.08.16 - prodongi
// 투구를 착용 했을 경우에 투구의 "투구 모델 적용 타입"에 따라서 귀걸이 적용/비적용을 결정한다
bool renderEarring = true;
KSeqAvatar* seqAvatar = pAvatarEx->getAvatarPart(ANIPART_BIPED);
if (seqAvatar->isRenderMesh(MPART_HELM))
{
int nWearSize = (int)m_vWearList.size();
for( int i(0); nWearSize>i; ++i )
{
if (ItemBase::WEAR_HELM == m_vWearList[i].nWearType)
{
ItemBaseEx_info const* pItemInfo = GetItemDB().GetItemData( m_vWearList[i].nItemCode );
if (!pItemInfo)
break;
int flag = getHelmItemModelType(GetRace(), GetSex(), pItemInfo);
if (ItemBaseEx_info::EARRING_FLAG & flag)
{
renderEarring = false;
}
break;
}
}
}
if (renderEarring)
pAvatarEx->AddMesh( ANIPART_BIPED , MPART_ACCE_EAR , WearData.strFileName.c_str(), strTexture );
else
pAvatarEx->AddMesh(ANIPART_BIPED, MPART_ACCE_EAR, "hide_earring");
//pAvatarEx->AddMesh( ANIPART_BIPED , MPART_ACCE_EAR , WearData.strFileName.c_str(), strTexture );
}
break;
case ItemBase::WEAR_ARMULET : pAvatarEx->AddMesh( ANIPART_NECKLACE, MPART_ACCE_NECK, WearData.strFileName.c_str() ); break; //목걸이
case ItemBase::WEAR_FACE :
{
// 2010.05.19 - prodongi
if (!isHideEquipInfo(ItemBase::HIDE_EQUIP_HELM))
//if( GetGameOption().IsShowHelm() ) //투구보이기 옵션에 따른 리소스 추가
{
const ItemBaseEx_info* pItemInfo = GetItemDB().GetItemData( WearData.nItemCode );
if( pItemInfo )
{
// 2010.08.16 - prodongi
/*
int nFlag = 0;
if( GetRace() == GCLAN_GAIA )
{
if( GetSex() == SEX_MALE ) nFlag = pItemInfo->model_type_gam;
else if( GetSex() == SEX_FEMALE ) nFlag = pItemInfo->model_type_gaf;
}
else if( GetRace() == GCLAN_DEVA )
{
if( GetSex() == SEX_MALE ) nFlag = pItemInfo->model_type_dem;
else if( GetSex() == SEX_FEMALE ) nFlag = pItemInfo->model_type_def;
}
else if( GetRace() == GCLAN_ASURA )
{
if( GetSex() == SEX_MALE ) nFlag = pItemInfo->model_type_asm;
else if( GetSex() == SEX_FEMALE ) nFlag = pItemInfo->model_type_asf;
}
*/
int nFlag = getHelmItemModelType(GetRace(), GetSex(), pItemInfo);
if( (nFlag & ItemBaseEx_info::HAIR_FLAG) == ItemBaseEx_info::HAIR_FLAG ) //투구가 있을 경우, 투구로 대체
{
if( pAvatarEx->IsExistMesh( ANIPART_BIPED, MPART_HELM ) == 0 &&
pAvatarEx->IsExistDecoMesh( ANIPART_BIPED, MDECOPART_HELM ) == 0 )
{ //투구가 없으므로, 가면 추가
pAvatarEx->AddMesh( ANIPART_BIPED , MPART_ACCE_EYE , WearData.strFileName.c_str(), strTexture );
}
}
else
{
pAvatarEx->AddMesh( ANIPART_BIPED , MPART_ACCE_EYE , WearData.strFileName.c_str(), strTexture );
}
}
}
else
{ //투구 안 보일 경우에는 무조건 표시
pAvatarEx->AddMesh( ANIPART_BIPED , MPART_ACCE_EYE , WearData.strFileName.c_str(), strTexture );
}
}
break; //눈
//예외
// case ItemBase::WEAR_EYE : <- WEAR_FACE로 바뀜
// case ItemBase::WEAR_MOUTH : pAvatarEx->AddMesh( ANIPART_BIPED , MPART_ACCE_LIP , WearData.strFileName.c_str() ); break; //입 MPART_ACCESS
// case ItemBase::WEAR_EAR_EYE : pAvatarEx->AddMesh( ANIPART_BIPED, MPART_ACCE_EAR , WearData.strFileName.c_str() ); break; // 귀+눈
// case ItemBase::WEAR_EAR_MOUTH : pAvatarEx->AddMesh( ANIPART_BIPED, MPART_ACCE_EAR , WearData.strFileName.c_str() ); break; // 귀+입
// case ItemBase::WEAR_EYE_MOUTH : pAvatarEx->AddMesh( ANIPART_BIPED, MPART_ACCE_EYE , WearData.strFileName.c_str() ); break; // 눈+입
// case ItemBase::WEAR_EYE_EAR_MOUTH : pAvatarEx->AddMesh( ANIPART_BIPED, MPART_ACCE_EYE , WearData.strFileName.c_str() ); break; // 눈+귀+입
// case ItemBase::WEAR_TWOFINGER_RING : pAvatarEx->AddMesh( ); break; // 반지 두칸 소모
//보이는거 아님
case ItemBase::WEAR_BELT : break; //
case ItemBase::WEAR_RING : break; //
case (ItemBase::WEAR_RING+1) : break; //
//Link 예외//= 108,// 활//= 109,// 석궁
case ItemBase::WEAR_TWOHAND :
{
pAvatarEx->AddMesh( ANIPART_WEAPON_LEFT, MPART_L_WEAPON, WearData.strFileName.c_str(), strTexture ); //그냥 왼손
if( WearData.nItemClass == 0 )
{
SetWeaponInfo( pAvatarEx, WearData, NULL );
}
else
{
std::string strEffectPosname = "wfx_";
strEffectPosname += WearData.strFileName.c_str();
SetWeaponInfo( pAvatarEx, WearData, strEffectPosname.c_str() );
}
}
break;
//새로 추가됨
case ItemBase::WEAR_BACKPACK: //어깨
{
if (bAddDecoItem && isHideEquipInfo(ItemBase::HIDE_EQUIP_SHOULDER)) // 꾸미기어깨.
{
/// 2011.06.11 mantis 13327 - prodongi
pAvatarEx->AddDecoMesh(ANIPART_BIPED, MDECOPART_SHOULDER2, WearData.strDecoFileName.c_str(), strDecoTexture);
}
}
break;
case ItemBase::WEAR_DECO_SHOULDER: //어깨
{
if( bAddDecoItem && isHideEquipInfo( ItemBase::DECO_HIDE_EQUIP_SHOULDER ) ) // 꾸미기어깨.
{
/// 2011.06.11 mantis 13327 - prodongi
pAvatarEx->AddDecoMesh( ANIPART_BIPED, MDECOPART_SHOULDER, WearData.strDecoFileName.c_str(), strDecoTexture );
}
}
break;
//case ItemBase::WEAR_DECO_HAIR: //머리 카락
// {
// if( bAddDecoItem )
// {
// if( m_itemClass[ItemBase::WEAR_DECO_HELM] != 0 ) //치장용 투구가 있으면 헤어 숨김
// {
// }
// else
// {
// if( !WearData.bAttachDecoItem ) //기존 헤어 없애기
// //pAvatarEx->AddMesh( ANIPART_HAIR, MPART_HAIR, "" );
// pAvatarEx->AddMesh( ANIPART_BIPED, MPART_HAIR, "" );
// /// 2011.06.11 mantis 13327 - prodongi
// pAvatarEx->AddDecoMesh( ANIPART_HAIR, MDECOPART_HAIR, WearData.strDecoFileName.c_str(), strDecoTexture );
// }
// }
// }
// break;
}
}
AR_UNIT SGamePlayer::GetAttackRange()
{
//서버에서 보내준 AttackRange을 적용시키자
return SGameAvatarEx::GetAttackRange();
/* if( m_ItemCode[ItemBase::WEAR_RIGHTHAND] == 0 )
{
return SGameAvatarEx::GetAttackRange();
}
else
{
int nAttackRange = GetItemDB().GetItemData( m_ItemCode[ItemBase::WEAR_RIGHTHAND] )->nRange;
return ( nAttackRange / float(GameRule::ATTACK_RANGE_UNIT) ) * GameRule::DEFAULT_UNIT_SIZE ;
}*/
}
int SGamePlayer::GetItemClass() //현재 장착하고 있는 아이템 클래스 얻기
{
//우선 왼손만 리턴한다.
return m_itemClass[ItemBase::WEAR_RIGHTHAND];
}
int SGamePlayer::GetMaterial() //재질
{
return 1;
}
// 2011.11.07 - servantes : 크리처 소환시 핸들을 넣어준다
// 2010.08.12 - prodongi
void SGamePlayer::SetCreature(AR_HANDLE hCreature, bool enter)
{
if (enter)
{
m_hCreatureTemp = m_hCreature;
m_hCreature = hCreature;
}
else
{
if (m_hCreatureTemp == hCreature)
{
m_hCreatureTemp = 0;
}
else
{
if (m_hCreatureTemp)
{
SGameObject* object = GetGameObject(m_hCreatureTemp);
if (object && object->IsActivated())
{
m_hCreature = m_hCreatureTemp;
m_hCreatureTemp = NULL;
}
else
{
m_hCreature = 0;
m_hCreatureTemp = 0;
}
}
else
{
m_hCreature = 0;
}
}
}
}
void SGamePlayer::SetMountMode()
{
if( m_pStateVM )
m_pStateVM->SetMode( SObjectStateMachine::MODE_MOUNT );
// sonador 7.0.16 Mantis 0002790: [모션] 아바타가 활을 착용하고 오르니토를 탔을 때 모션 문제
//if( IsMountMode() )
// HideWeapon( FALSE );
// sonador #2.1.6 크리쳐 기린(spirit_qilin) 테스트
SetRunNWalkAniSpeedMount();
}
void SGamePlayer::SetAttackMode()
{
if( m_pStateVM )
m_pStateVM->SetMode( SObjectStateMachine::MODE_ATTACK );
}
void SGamePlayer::SetNormalMode()
{
if( m_pStateVM )
m_pStateVM->SetMode( SObjectStateMachine::MODE_NORMAL );
// sonador 7.0.16 Mantis 0002790: [모션] 아바타가 활을 착용하고 오르니토를 탔을 때 모션 문제
//if( !IsMountMode() )
// HideWeapon( TRUE );
// sonador #2.1.6 크리쳐 기린(spirit_qilin) 테스트
// sonador #2.1.15 변신시 모션 연결 적용
switch( GetInnObjType() )
{
case TS_ENTER::GAME_PLAYER:
{
SetRunNWalkAniSpeedDefault();
}
break;
case TS_ENTER::GAME_MOB:
{
_MONSTER_INFO_FILE* pMonsterInfo = GetMonsterDB().GetMonsterData( GetInnContentID() );
if( pMonsterInfo && GetObjType() == TS_ENTER::GAME_PLAYER )
SetRunNWalkAniSpeed( pMonsterInfo );
}
break;
case TS_ENTER::GAME_SUMMON:
{
_SUMMON_INFO_FILE * pSummon = GetCreatureDB().GetCreatureData( GetInnContentID() );
if( pSummon && GetObjType() == TS_ENTER::GAME_PLAYER )
SetRunNWalkAniSpeed( pSummon );
}
break;
}
}
void SGamePlayer::Damage()
{
if( m_pStateVM == NULL ) return;
if( _damage() ) return;
//이미 공격 중이면, 모션 플레이 안됨.
if( GetAttackAniLock() )
return;
////이동 중, 공격 중 에는 영향 안 받는다.
if( GetCurrAnimationID() == ANI_WALK ||
GetCurrAnimationID() == ANI_RUN ||
GetCurrAnimationID() == ANI_DEAD01 ) return;
//공격 모드 인가, 일반 모드 인가 검사 후 따로 처리
if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_ATTACK )
{
if( GetCurrAnimationID() == ANI_DEFAULT02 )
NPlayAnimation( ANI_DAMAGE02, SEQTYPE_NORMAL );
if( GetCurrAnimationID() == ANI_DAMAGE02 && !IsPlaying() )
{
NPlayAnimation( ANI_DAMAGE02, SEQTYPE_NORMAL );
}
}
else if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_NORMAL )
{
int nAniID = GetCurrAnimationID(); // sonador 1.8.13 아바타 IDLE 모션 동작 구현
if( nAniID == ANI_DEFAULT01 || nAniID == ANI_IDLE )
NPlayAnimation( ANI_DAMAGE01, SEQTYPE_NORMAL );
if( nAniID == ANI_DAMAGE01 && !IsPlaying() )
{
NPlayAnimation( ANI_DAMAGE01, SEQTYPE_NORMAL );
}
}
else if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_MOUNT )
{
}
}
void SGamePlayer::Default( bool bForce/*=false*/ )
{
//if( GetHP() <= 0 )
// return;
if( m_pStateVM == NULL ) return;
if( !bForce )
{
if( IsAniLock() )
return;
if( GetAttackAniLock() )
return;
if( CurrentlyAnimationIsAttack() && IsPlaying() )
return;
}
//전투 대기 상태 이면, 전투 대기 기본 애니
if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_ATTACK )
{
if( GetCurrAnimationID() != ANI_DEFAULT02 && m_isKMoving==0)
NPlayAnimation( ANI_DEFAULT02, SEQTYPE_LOOP );
}
else if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_NORMAL )
{ //
_resetIdleTime(); // sonador 1.8.13 아바타 IDLE 모션 동작 구현
if( GetCurrAnimationID() != ANI_DEFAULT01 )
NPlayAnimation( ANI_DEFAULT01, SEQTYPE_LOOP );
}
else if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_MOUNT )
{
switch( GetRideType() )
{
case SGameAvatarEx::RIDE_HIGH_TYPE:
{
if( GetCurrAnimationID() != ANI_M_DEFAULT01_HIGH )
NPlayAnimation( ANI_M_DEFAULT01_HIGH, SEQTYPE_LOOP );
}
break;
case SGameAvatarEx::RIDE_LOW_TYPE:
{
if( GetCurrAnimationID() != ANI_M_DEFAULT01_LOW )
NPlayAnimation( ANI_M_DEFAULT01_LOW, SEQTYPE_LOOP );
}
break;
case SGameAvatarEx::RIDE_QILIN_TYPE: // #2.1.6 sonador
{
if( GetCurrAnimationID() != ANI_M_DEFAULT01_QILIN )
NPlayAnimation( ANI_M_DEFAULT01_QILIN, SEQTYPE_LOOP );
}
break;
case SGameAvatarEx::RIDE_WHITE_TYPE: // #2.1.14
{
if( GetCurrAnimationID() != ANI_M_DEFAULT01_WHITE )
NPlayAnimation( ANI_M_DEFAULT01_WHITE, SEQTYPE_LOOP );
}
break;
case SGameAvatarEx::RIDE_UNICORN_TYPE: // #2.1.14
{
if( GetCurrAnimationID() != ANI_M_DEFAULT01_UNICORN )
NPlayAnimation( ANI_M_DEFAULT01_UNICORN, SEQTYPE_LOOP );
}
break;
case SGameAvatarEx::RIDE_BEAKHO_TYPE: /// 2011.02.08 - prodongi
{
if( GetCurrAnimationID() != ANI_M_DEFAULT01_BEAKHO )
NPlayAnimation( ANI_M_DEFAULT01_BEAKHO, SEQTYPE_LOOP );
}
break;
}
}
SetVisibleWeaponTrail( false );
}
void SGamePlayer::Default3()
{
if( m_pStateVM == NULL ) return;
m_pStateVM->SetMode( SObjectStateMachine::MODE_ATTACK );
//if( GetHP() <= 0 )
// return;
if( !( GetCurrAnimationID() == ANI_DEFAULT01 || GetCurrAnimationID() == ANI_IDLE ) ) return; // sonador 1.8.13 아바타 IDLE 모션 동작 구현
if( CurrentlyAnimationIsAttack() && IsPlaying() )
return;
//전투 대기 상태 이면, 전투 대기 기본 애니
if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_ATTACK )
{
if( GetCurrAnimationID() != ANI_DEFAULT02 )
NPlayAnimation( ANI_DEFAULT02, SEQTYPE_LOOP );
}
SetVisibleWeaponTrail( false );
}
//void SGamePlayer::MDefault()
//{
// if( !m_pSeqAvatar ) return;
//
// if( CurrentlyAnimationIsAttack() && IsPlaying() )
// return;
//
// //전투 대기 상태 이면, 전투 대기 기본 애니
// if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_MOUNT )
// {
// if( GetCurrAnimationID() != ANI_M_DEFAULT01 )
// NPlayAnimation( ANI_M_DEFAULT01, SEQTYPE_LOOP );
// }
//}
void SGamePlayer::Throw() //던지기
{
}
void SGamePlayer::PickUp() //줍기
{
if( m_pStateVM == NULL ) return;
if( IsDead() ) return;
//전투 대기
if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_ATTACK ||
m_pStateVM->GetMode() == SObjectStateMachine::MODE_NORMAL )
{
if( GetCurrAnimationID() == ANI_DEFAULT02 )
NPlayAnimation( ANI_PICKUP01, SEQTYPE_NORMAL );
}
else if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_MOUNT )
{
}
//보통
if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_ATTACK ||
m_pStateVM->GetMode() == SObjectStateMachine::MODE_NORMAL )
{
NPlayAnimation( ANI_PICKUP01, SEQTYPE_NORMAL );
}
else if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_MOUNT )
{
// NPlayAnimation( ANI_PICKUP01, SEQTYPE_NORMAL );
}
}
void SGamePlayer::PickUpEx()
{
NPlayAnimation( ANI_PICKUP01, SEQTYPE_NORMAL );
}
void SGamePlayer::Walk( bool bLoop, int nAniType )
{
if( GetCurrAnimationID() != nAniType )
NPlayAnimation( nAniType, SEQTYPE_LOOP, m_fPlayRate );
}
void SGamePlayer::Run( bool bAutoRun, int nAniType )
{
if( GetCurrAnimationID() != nAniType )
NPlayAnimation( nAniType, SEQTYPE_LOOP, m_fPlayRate );
}
void SGamePlayer::Rush( int nAniType, float fPlayRate )
{
NPlayAnimation( nAniType, SEQTYPE_LOOP, fPlayRate );
}
void SGamePlayer::SitProcess( int nAniType, int nType ) //앉은 상태
{
NPlayAnimation( nAniType, nType );
}
void SGamePlayer::StandUp( DWORD time ) //기본 자세
{
if( m_pStateVM == NULL ) return;
if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_ATTACK )
{
NPlayAnimation( ANI_DEFAULT02, SEQTYPE_LOOP );
}
else if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_NORMAL )
{
NPlayAnimation( ANI_DEFAULT01, SEQTYPE_LOOP );
}
else if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_MOUNT )
{
NPlayAnimation( ANI_DEFAULT01, SEQTYPE_LOOP );
}
}
void SGamePlayer::Cast01() //손 올리기
{
NPlayAnimation( ANI_CAST01_A, SEQTYPE_LOOP );
}
void SGamePlayer::Cast02(bool bLoop) //모으기
{
if( bLoop )
{
if( GetCurrAnimationID() == ANI_CAST01_A )
NPlayAnimation( ANI_CAST01_B, SEQTYPE_LOOP );
}
else
{
if( GetCurrAnimationID() == ANI_CAST01_A )
NPlayAnimation( ANI_CAST01_B );
}
}
void SGamePlayer::Fire( int nAniID )
{
if( ANI_FIRE_MAGIC01 == nAniID ||
ANI_FIRE_MAGIC02 == nAniID ||
ANI_FIRE_MAGIC03 == nAniID ||
ANI_FIRE_MAGIC04 == nAniID ||
ANI_FIRE_MAGIC05 == nAniID )
NPlayAnimation( nAniID );
}
void SGamePlayer::NPlayAnimation( int nType , int nAniType, float fPlayRate )
{
// _oprint( "다른 플레이 Ani 변경 %d\n", nType );
if( IsDead() && GetHP() <= 0 )
{
if( nType == ANI_DEAD01 ||
nType == ANI_DEAD02 )
{
if( nType == m_nPrevAniType )
return;
}
else
return;
}
if( m_pSeqAvatar )
{
m_nPrevAniType = nType;
}
SGameAvatarEx::NPlayAnimation( nType , nAniType, fPlayRate );
}
void SGamePlayer::OnNetInput( struct SGameMessage * pMsg )
{
if( !m_pStateVM ) return;
m_pStateVM->OnNetInput( pMsg );
}
void SGamePlayer::SetPlayerViewVector( const K3DVector& vTargetPos )
{
if( !IsLocalPlayer() )
{
SetViewVector( vTargetPos ); //몸통 방향 바꾸기
}
else
{
if( vTargetPos.y == GetPosition()->y && vTargetPos.x == GetPosition()->x )
return;
m_fTargetRoll = atan2( vTargetPos.y-GetPosition()->y, vTargetPos.x-GetPosition()->x );
m_dwPrevTime = m_dwTime;
m_bUseRot = true;
}
}
void SGamePlayer::OnChangeState( SObjectState::ID stateid, const SStateInfo &info )
{
if( m_pStateVM == NULL ) return;
//STATE_FIRE가 2번째 들어온 상태에서 RUN 에니매이션이면 Default로 바꿔준다
if( m_idPrevState == SObjectState::STATE_FIRE &&
stateid == SObjectState::STATE_FIRE )
{
if( GetCurrAnimationID() == ANI_RUN )
{
SetAniLock( false );
Default();
}
}
if (IsLocalPlayer())
{
if (stateid==SObjectState::STATE_IDLE || stateid==SObjectState::STATE_ATTACK_END || stateid== SObjectState::STATE_SHOOTING || stateid== SObjectState::STATE_FIRE)
setKMoveType(0);
}
// _oprint( "*****상태 머신 : %d\n", stateid );
//상태가 바뀌었다.. 애니메이션 바꾸자, Work 기반으로
switch( stateid )
{
case SObjectState::STATE_IDLE :
{
//_oprint( "*****상태 머신 : 기본 상태 변경\n" );
//서기도 같이 온다.
// SWorkAniStandUp standup( this, m_dwTime );
// standup.Process(0);
//앉기, 줍기 프로세스 되도록 고치자~
if( GetCurrAnimationID() == ANI_SIT )
{
SetAniLock( false );
Default();
}
if( (GetCurrAnimationID() == ANI_RUN ||
GetCurrAnimationID() == ANI_WALK ) && !IsMoving() )
{
// Default();
}
////스킬 취소가 왔을 경우 인데..
//if( GetCurrAnimationID() == ANI_CAST01_B ||
// GetCurrAnimationID() == ANI_FIRE_MAGIC01 ||
// GetCurrAnimationID() == ANI_FIRE_MAGIC02 ||
// GetCurrAnimationID() == ANI_FIRE_MAGIC03 ||
// GetCurrAnimationID() == ANI_FIRE_MAGIC04 ||
// GetCurrAnimationID() == ANI_FIRE_MAGIC05 )
//{
// SetAniLock( false );
// Default();
//}
if( !IsPlaying() && ( CurrentlyAnimationIsAttack() || CurrentlyAnimationIsDamage() ) )
{
// Default();
}
//전투 대기 모션 && 기본 모드, 모드가 바뀌 었다.
if( GetCurrAnimationID() == ANI_DEFAULT02 && m_pStateVM->GetMode() == SObjectStateMachine::MODE_NORMAL )
{
Default();
}
// sonador #2.1.6
if( CurrentlyAnimationIsMRun() || CurrentlyAnimationIsMWalk() && !IsMoving() &&
m_pStateVM->GetMode() == SObjectStateMachine::MODE_MOUNT )
{
Default();
}
break; //기본 상태
}
case SObjectState::STATE_ATTACK :
{
//_oprint( "*****상태 머신 : 공격 상태 시간\n" );
// _oprint( "공격 상태 시간 : %d\n", m_dwTime );
SetPlayerViewVector( info.vTargetPos );
//일반 공격
OnAttack( info );
}
break; // 공격 (1회)
case SObjectState::STATE_ATTACK_END :
{
//_oprint( "SKILL - SObjectState::STATE_CAST_CANCEL\n" );
m_bIsUseSkill_complete = true;
for( unsigned int i(0); m_vAttackEventList.size()>i; i++)
m_vAttackEventList[i]->ForceEnd();
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
m_vCastSkillList[i]->ForceEnd();
// for( unsigned int i(0); m_vFireSkillList.size()>i; i++ )
// m_vFireSkillList[i]->ForceEnd();
SetIng(false);
SetAniLock( false );
Default(true);
break;
}
case SObjectState::STATE_MOVE :
{
if( info.dwSpeed == 0 )
{
//달리다 죽은 것이므로 Ani 처리는 스킵한다.
return;
}
// _oprint( "SObjectState::STATE_MOVE : %f, %f, %f \n", info.vTargetPos.x, info.vTargetPos.y, info.vTargetPos.z );
//ProcessDEF에서 처리한다
// SetPlayerViewVector( info.vTargetPos );
SetAniLock( false );
//_oprint( "*****상태 머신 : 이동\n" );
if( info.dwSpeed >= m_fWalkSpeed )
{
if( GetInnObjType() != TS_ENTER::GAME_PLAYER )
CalcCreatureRunPlayRate( (float)info.dwSpeed );
if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_MOUNT )
{
CalcCreatureRunPlayRate( (float)info.dwSpeed );
Run( false, GetPlayerMRunAniID() ); // sonador #2.1.6 크리쳐 기린(spirit_qilin) 테스트
}
else
{
Run();
}
}
else
{
if( GetInnObjType() != TS_ENTER::GAME_PLAYER )
CalcCreatureWalkPlayRate( (float)info.dwSpeed );
if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_MOUNT )
{
CalcCreatureWalkPlayRate( (float)info.dwSpeed );
Walk( true, GetPlayerMWalkAniID() ); // sonador #2.1.6 크리쳐 기린(spirit_qilin) 테스트
}
else
Walk(true);
}
}
break; // 이동
case SObjectState::STATE_CHASE :
{
//ProcessDEF에서 처리한다
// SetPlayerViewVector( info );
SetAniLock( false );
//_oprint( "*****상태 머신 : 추적\n" );
if( info.dwSpeed >= 10 )
{
if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_MOUNT )
{
Run( false, GetPlayerMRunAniID() ); // sonador #2.1.6
}
else //( m_pStateVM->GetMode() == SObjectStateMachine::MODE_NORMAL || SObjectStateMachine::MODE_ATTACK )
Run();
}
else
{
if( m_pStateVM->GetMode() == SObjectStateMachine::MODE_MOUNT )
{
Walk( true, GetPlayerMWalkAniID() ); // sonador #2.1.6
}
else
Walk(true);
}
}
break; // 추격
case SObjectState::STATE_MOUNT:
{
for( unsigned int i(0); m_vAttackEventList.size()>i; i++)
m_vAttackEventList[i]->ForceEnd();
SWorkMount* pMount = new SWorkMount( this, info.hTarget );
// SWorkMountWithOutAnimation* pMount = new SWorkMountWithOutAnimation( this, info.hTarget );
m_vAttackEventList.push_back( pMount );
}
break;
case SObjectState::STATE_UNMOUNT:
{
/* if( info.UnMountFlag == TS_SC_UNMOUNT_SUMMON::FALL ||
info.UnMountFlag == TS_SC_UNMOUNT_SUMMON::UNSUMMON )*/
{
for( unsigned int i(0); m_vAttackEventList.size()>i; i++)
m_vAttackEventList[i]->ForceEnd();
}
//자동이동 경로 삭제
ClearWayPointList();
SWorkUnMount* pUnMount = new SWorkUnMount( this, info.hTarget, info.UnMountFlag );
// SWorkUnMountWithOutAnimation* pUnMount = new SWorkUnMountWithOutAnimation( this, info.hTarget, info.UnMountFlag );
m_vAttackEventList.push_back( pUnMount );
}
break;
case SObjectState::STATE_AIMING :
{
_oprint( "AIMING - SObjectState::STATE_AIMING\n" );
//활쏘기 예외 처리
if( info.attack_flag & TS_ATTACK_EVENT::ATTACK_FLAG_BOW ||
info.attack_flag & TS_ATTACK_EVENT::ATTACK_FLAG_CROSS_BOW )
{
if( info.attack_action == TS_ATTACK_EVENT::ATTACK_AIMING )
{ //활 조준
SWorkAimingBow * pAiming = new SWorkAimingBow( this, info.hTarget, info.attack_flag );
m_vCastSkillList.push_back( pAiming );
_oprint( "활 조준 Cast \n" );
}
}
}
break;
case SObjectState::STATE_CAST :
{
//_oprint( "SKILL - SObjectState::STATE_CAST\n" );
//_oprint( "*****상태 머신 : 캐스팅\n" );
m_bIsUseSkill_complete = false;
/// 2011.05.09 만약 지면 타겟 스킬이면 타겟 위치로 플레이어의 방향을 바꿔준다 - prodongi
if (info.isRegionTarget)
{
SetPlayerViewVector(info.vTargetPos);
}
//캐스팅 표시
if( IsLocalPlayer() )
UseSkill( GetArID(), info.nSkillID, info.nSkillLv, info.dwSpeed );
//캐스팅 관련 연출 설정
//1) 애니메이션 연출 -> 설정 된 애니메이션의 이벤트 핸들 처리
//2) FX 출력
//New Process
_SKILL_FX* pSkillFXDB = GetSkillStageDB().GetSkillStageData( info.nSkillID );
if( !pSkillFXDB )
{
_oprint( "스킬 연출 데이타 없음!!! [스킬ID:%d]\n", info.nSkillID );
// assert( 0 && "스킬 연출 데이타 없음!!!" );
return;
}
_SKILL_FX* pSkillFX = new _SKILL_FX;
*pSkillFX = *pSkillFXDB;
float fRate = 1.f;
if( pSkillFX->nCasting_Type_Id != 1 && (pSkillFX->nCasting_Start_Motion_Id !=0 || pSkillFX->nCasting_Middle_Motion_Id != 0) )
{
std::string strAniKey;
int nBoneCount = 0;
DWORD dwMinTime, dwMaxTime, totalTime;
dwMinTime = 0;
dwMaxTime = 0;
totalTime = 0;
if( pSkillFX->nCasting_Start_Motion_Id != 0 )
{
strAniKey = GetAniKey( GetObjType(), pSkillFX->nCasting_Start_Motion_Id, true );
if( m_pSeqAvatar )
m_pSeqAvatar->GetFrameInfo( ANIPART_BIPED, strAniKey.c_str(), nBoneCount, dwMinTime, dwMaxTime );
totalTime = dwMaxTime;
}
if( pSkillFX->nCasting_Middle_Motion_Id )
{
strAniKey = GetAniKey( GetObjType(), pSkillFX->nCasting_Middle_Motion_Id, true );
if( m_pSeqAvatar )
m_pSeqAvatar->GetFrameInfo( ANIPART_BIPED, strAniKey.c_str(), nBoneCount, dwMinTime, dwMaxTime );
totalTime += dwMaxTime;
}
float fAttack = GetAttackSpeed( info.dwSpeed*10 );
//기본 배율
fRate = GetAniPlayRate( fAttack, totalTime, false );
}
//switch( pSkillFX->nCasting_Type_Id )
//{
//case _SKILL_FX::SKILLTYPE_NOACT : break;
//case _SKILL_FX::SKILLTYPE_MAGIC : break;
//case _SKILL_FX::SKILLTYPE_INSTANT : break;
//case _SKILL_FX::SKILLTYPE_INSTANT_CONTINUE : break;
//case _SKILL_FX::SKILLTYPE_CHARGE : break;
//case _SKILL_FX::SKILLTYPE_CHARGE_CONTINUE : break;
//}
//pSkillFX->nCasting_Start_Motion_Id; //시작
//pSkillFX->nCasting_Middle_Motion_Id; //시작 Loop
SNewSkill * pSkill_Cast = NULL;
SGameAvatarEx * pTarget = NULL;
if( info.hTarget )
{
pTarget = (SGameAvatarEx *)GetGameObject( info.hTarget );
}
switch( pSkillFX->nStage_Type_Id )
{
//크리처 소환 캐스팅일 경우 타겟 위치를 저장한다
case SS_TYPE_001 : { SWorkSummonCall * pSkill = new SWorkSummonCall( this, pSkillFX ); pSkill->SetPosition( (K3DVector*)&info.vTargetPos ); pSkill_Cast = pSkill; } break;
case SS_TYPE_002 : { SWorkSummonReCall * pSkill = new SWorkSummonReCall( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_101 : { SWorkWeaponSwingHit * pSkill = new SWorkWeaponSwingHit( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_111 : { SWorkShieldSwingHit * pSkill = new SWorkShieldSwingHit( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_121 : { SWorkWeaponSwing_3Motion * pSkill = new SWorkWeaponSwing_3Motion( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_122 : { SWorkWeaponSwing_ContinuousHits * pSkill = new SWorkWeaponSwing_ContinuousHits( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_123 : { SWorkWeaponSwing_Zeal * pSkill = new SWorkWeaponSwing_Zeal( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_151 : { SWorkWeaponSwing_Leech * pSkill = new SWorkWeaponSwing_Leech( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_171 : break;//{ //TODO : 밀기 - 서버 메세지 처리 넣어야 함. SWorkRush_Shove* pSkill = new SWorkRush_Shove( this, pSkillFX ); pSkill_Cast = pSkill; } break;
// case SS_TYPE_172 : { break;
// case SS_TYPE_173 : { break;
// case SS_TYPE_174 : { break;
case SS_TYPE_201 : { SWorkBowShoot* pSkill = new SWorkBowShoot( this, pSkillFX ); pSkill_Cast = pSkill; fRate = 1.f; } break;
case SS_TYPE_212 : { SWorkBowShoot* pSkill = new SWorkBowShoot( this, pSkillFX ); pSkill_Cast = pSkill; fRate = 1.f; } break;
case SS_TYPE_251 : { SWorkBowShoot* pSkill = new SWorkBowShoot( this, pSkillFX ); pSkill_Cast = pSkill; fRate = 1.f; } break;
// case SS_TYPE_211 : { break;
// case SS_TYPE_212 : { SWorkBowShoot_Shove * pSkill = new SWorkBowShoot_Shove( this, pSkillFX ); pSkill_Cast = pSkill; } break;
// case SS_TYPE_251 : { SWorkBowShoot_Leech * pSkill = new SWorkBowShoot_Leech( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_301 : { SWorkSelf * pSkill = new SWorkSelf( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_404 :
case SS_TYPE_401 :
{ SWorkMotion * pSkill = new SWorkMotion( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_402 : { SWorkMotion_Leech * pSkill = new SWorkMotion_Leech( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_403 : { SWorkMotion_SummonMotion_Leech * pSkill = new SWorkMotion_SummonMotion_Leech( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_411 : { SWorkMotion_FXMotion * pSkill = new SWorkMotion_FXMotion( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_412 : { SWorkMotion_FXMotionMultiple * pSkill = new SWorkMotion_FXMotionMultiple( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_501 : { SWorkShoot_FXShoot * pSkill = new SWorkShoot_FXShoot( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_502 : { SWorkShoot_FXShootMultiple * pSkill = new SWorkShoot_FXShootMultiple( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_503 : { SWorkShoot_FXShootPenetrate * pSkill = new SWorkShoot_FXShootPenetrate( this, pSkillFX ); pSkill_Cast = pSkill; } break;
/// 2011.03.23 - prodongi
case SS_TYPE_504 : { SWorkShoot_FXShootChain * pSkill = new SWorkShoot_FXShootChain( this, pSkillFX ); pSkill_Cast = pSkill; } break;
case SS_TYPE_601 :
case SS_TYPE_604 : { SWorkGround_FXContinue * pSkill = new SWorkGround_FXContinue( this, pSkillFX ); pSkill_Cast = pSkill; } break;
// case SS_TYPE_602 : break;
// case SS_TYPE_603 : break;
// case SS_TYPE_701 : break;
case SS_TYPE_1001: { SWorkingSkill* pSkill = new SWorkingSkill( this, pSkillFX ); pSkill_Cast = pSkill; } break;
default:
{
_oprint( "구현 보류 중인 스킬입니다.기획팀에 사용 여부를 확인 후, 프로그램 팀에 구현 여부를 확인 바랍니다.\n" );
// assert( 0 && "구현 보류 중인 스킬입니다.기획팀에 사용 여부를 확인 후, 프로그램 팀에 구현 여부를 확인 바랍니다.\n" );
}
break;
}
if( pSkill_Cast )
{ //변경 되었으면, PlayRate 수정
if( fRate != 1.f && pSkillFX->nCasting_Type_Id != 1 ) //마법류는 PlayRate 수정 하지 않는다.
pSkill_Cast->SetPlayRate( fRate/4.8f );
if( pTarget )
{
pSkill_Cast->SetTarget( info.hTarget, pTarget );
if(pSkillFX->nStage_Type_Id == SS_TYPE_402 )
{
pTarget->SetReservation(true);
}
}
else
{
SkillBaseEx* skillBase = GetSkillDB().GetSkillData(info.nSkillID);
if (skillBase && skillBase->getTargetType() == SkillBase::SKILL_TARGET_POSITION)
{
pSkill_Cast->SetTarget(info.hSelf, (SGameAvatarEx *)GetGameObject(info.hSelf));
}
}
pSkill_Cast->SetStartTime( m_dwTime );
pSkill_Cast->SetSkillMode( SNewSkill::SKILLMODE_CAST );
pSkill_Cast->SetCastingTime( info.dwSpeed );
m_vCastSkillList.push_back( pSkill_Cast );
m_nWeaponSwing_RepeatMotion = 0;
}
else
SAFE_DELETE( pSkillFX );
break; // 캐스팅
}
case SObjectState::STATE_SHOOTING :
{
_oprint( "SHOOTING - SObjectState::STATE_SHOOTING\n" );
//활쏘기 예외 처리
if( info.attack_flag & TS_ATTACK_EVENT::ATTACK_FLAG_BOW ||
info.attack_flag & TS_ATTACK_EVENT::ATTACK_FLAG_CROSS_BOW )
{
if( info.attack_action == TS_ATTACK_EVENT::ATTACK_ATTACK )
{
//돌고 있는 케스팅은 모두 강제 끝
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
m_vCastSkillList[i]->ForceEnd();
//활쏘기
SWorkShootingBow * pShooting = new SWorkShootingBow( this, info.hTarget, info.attack_flag );
pShooting->SetDamegeInfo( &info );
m_vFireSkillList.push_back( pShooting );
_oprint( "활 쏘기 Fire \n" );
return;
}
}
}
break;
case SObjectState::STATE_FIRE :
{
//SkillResult가 0이면 Fire실패 Default모션으로
if(info.vSkillResult.empty())
{
m_bIsUseSkill_complete = true;
/// 2011.05.09 프랍 범위 스킬을 발동 할 때, 발동 모션이 나오도록 수정- prodongi
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
m_vCastSkillList[i]->CastCancel();
_SKILL_FX* pSkillFXDB = GetSkillStageDB().GetSkillStageData( info.nSkillID );
if (pSkillFXDB && pSkillFXDB->nFire_Motion_Id)
{
_SKILL_FX* pSkillFX = new _SKILL_FX;
*pSkillFX = *pSkillFXDB;
SNewSkill* pSkill_Fire = new SNewSkill(this, pSkillFX);
pSkill_Fire->SetTarget(GetArID(), this);
pSkill_Fire->SetStartTime( m_dwTime );
pSkill_Fire->SetSkillMode( SNewSkill::SKILLMODE_FIRE );
m_vFireSkillList.push_back( pSkill_Fire );
}
else
{
SetIng(false);
SetAniLock( false );
Default( true );
}
/*
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
m_vCastSkillList[i]->CastCancel();
SetIng(false);
SetAniLock( false );
Default( true );
*/
return;
}
//_oprint( "SKILL - SObjectState::STATE_FIRE\n" );
// _oprint( "*****상태 머신 : 발사\n" );
//New Process
//Cast 관련 사운드 끄기
//Cast 관련 이펙트 끄기
_SKILL_FX* pSkillFXDB = GetSkillStageDB().GetSkillStageData( info.nSkillID );
if( !pSkillFXDB )
{
_oprint( "스킬 연출 데이타 없음!!! [스킬ID:%d]\n", info.nSkillID );
// assert( 0 && "스킬 연출 데이타 없음!!!" );
return;
}
_SKILL_FX* pSkillFX = new _SKILL_FX;
*pSkillFX = *pSkillFXDB;
SNewSkill * pSkill_Fire = NULL;
SGameAvatarEx * pTarget = NULL;
if( info.hTarget )
{
pTarget = (SGameAvatarEx *)GetGameObject( info.hTarget );
}
switch( pSkillFX->nStage_Type_Id )
{
case SS_TYPE_001 : { SWorkSummonCall * pSkill = new SWorkSummonCall( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_002 : { SWorkSummonReCall * pSkill = new SWorkSummonReCall( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_101 : { SWorkWeaponSwingHit * pSkill = new SWorkWeaponSwingHit( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_111 : { SWorkShieldSwingHit * pSkill = new SWorkShieldSwingHit( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_121 : { SWorkWeaponSwing_3Motion * pSkill = new SWorkWeaponSwing_3Motion( this, pSkillFX ); pSkill_Fire = pSkill; pSkill->SetCurHitCount( m_nWeaponSwing_RepeatMotion ); } break;
case SS_TYPE_122 : { SWorkWeaponSwing_ContinuousHits * pSkill = new SWorkWeaponSwing_ContinuousHits( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_123 : { SWorkWeaponSwing_Zeal * pSkill = new SWorkWeaponSwing_Zeal( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_151 : { SWorkWeaponSwing_Leech * pSkill = new SWorkWeaponSwing_Leech( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_171 : break;//{ //TODO : 밀기 - 서버 메세지 처리 넣어야 함. SWorkRush_Shove* pSkill = new SWorkRush_Shove( this, pSkillFX ); pSkill_Cast = pSkill; } break;
// case SS_TYPE_172 : { break;
// case SS_TYPE_173 : { break;
// case SS_TYPE_174 : { break;
case SS_TYPE_201 : { SWorkBowShoot* pSkill = new SWorkBowShoot( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_212 : { SWorkBowShoot* pSkill = new SWorkBowShoot( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_251 : { SWorkBowShoot* pSkill = new SWorkBowShoot( this, pSkillFX ); pSkill_Fire = pSkill; } break;
// case SS_TYPE_211 : { break;
// case SS_TYPE_212 : { SWorkBowShoot_Shove * pSkill = new SWorkBowShoot_Shove( this, pSkillFX ); pSkill_Fire = pSkill; } break;
// case SS_TYPE_251 : { SWorkBowShoot_Leech * pSkill = new SWorkBowShoot_Leech( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_301 : { SWorkSelf * pSkill = new SWorkSelf( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_401 :
case SS_TYPE_404 :
{ SWorkMotion * pSkill = new SWorkMotion( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_402 : { SWorkMotion_Leech * pSkill = new SWorkMotion_Leech( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_403 : { SWorkMotion_SummonMotion_Leech * pSkill = new SWorkMotion_SummonMotion_Leech( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_411 : { SWorkMotion_FXMotion * pSkill = new SWorkMotion_FXMotion( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_412 : { SWorkMotion_FXMotionMultiple * pSkill = new SWorkMotion_FXMotionMultiple( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_501 : { SWorkShoot_FXShoot * pSkill = new SWorkShoot_FXShoot( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_502 : { SWorkShoot_FXShootMultiple * pSkill = new SWorkShoot_FXShootMultiple( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_503 : { SWorkShoot_FXShootPenetrate * pSkill = new SWorkShoot_FXShootPenetrate( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_504 : { SWorkShoot_FXShootChain * pSkill = new SWorkShoot_FXShootChain( this, pSkillFX ); pSkill_Fire = pSkill; } break;
case SS_TYPE_601 :
case SS_TYPE_604 : { SWorkGround_FXContinue * pSkill = new SWorkGround_FXContinue( this, pSkillFX ); pSkill_Fire = pSkill; } break;
// case SS_TYPE_602 : break;
// case SS_TYPE_603 : break;
// case SS_TYPE_701 : break;
case SS_TYPE_1001: { SWorkingSkill* pSkill = new SWorkingSkill( this, pSkillFX ); pSkill_Fire = pSkill; } break;
default:
{
_oprint( "구현 보류 중인 스킬입니다.기획팀에 사용 여부를 확인 후, 프로그램 팀에 구현 여부를 확인 바랍니다.\n" );
// assert( 0 && "구현 보류 중인 스킬입니다.기획팀에 사용 여부를 확인 후, 프로그램 팀에 구현 여부를 확인 바랍니다.\n" );
}
break;
}
if( pSkillFX->nStage_Type_Id == SS_TYPE_121 )
{
//최대 연타 수 ( DB에 정의됨 )
if( m_nWeaponSwing_RepeatMotion < pSkillFXDB->fStage_Data[9] )
++m_nWeaponSwing_RepeatMotion;
else
m_nWeaponSwing_RepeatMotion = 0;
}
else
m_nWeaponSwing_RepeatMotion = 0;
if( pSkill_Fire )
{
//SAction에서 데미지 처리하고 있기 때문에 데미지 표시가 2번뜬다
switch( pSkillFX->nStage_Type_Id )
{
case SS_TYPE_001 :
case SS_TYPE_002 :
case SS_TYPE_101 :
case SS_TYPE_111 :
case SS_TYPE_121 :
case SS_TYPE_122 :
case SS_TYPE_123 : pSkill_Fire->SetDamegeInfo( &info );
break;
// AziaMafia SkillFix Animation
/*default:
pSkill_Fire->SetActionSkillEvent( &info );
break;*/
}
//돌고 있는 케스팅은 모두 강제 끝
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
m_vCastSkillList[i]->ForceEnd();
if( pSkillFX->nCasting_Type_Id == 1 ) //마법류 스킬이면
{
//5번 타인에게 사용하는 해로운 스킬
pSkill_Fire->SetFireMotionID( 92 ); //나쁜 스킬 설정
//1번 소환/역소환 스킬이면
if( pSkillFX->nStage_Type_Id == SS_TYPE_001 || pSkillFX->nStage_Type_Id == SS_TYPE_002 )
pSkill_Fire->SetFireMotionID( 94 );
else if( pSkillFX->nStage_Type_Id == SS_TYPE_1001 ) //채광 관련
pSkill_Fire->SetFireMotionID( pSkillFX->nFire_Motion_Id );
else
{
SkillBaseEx * pSkill = GetSkillDB().GetSkillData( info.nSkillID );
if( pSkill )
{
//2번 자신에게만 주는 이로운 스킬
if( (pSkill->GetSkillTargetType() == 1 || pSkill->GetSkillTargetType() == 4 || pSkill->GetSkillTargetType() == 31 ) && info.hTarget == GetArID() )
{
pSkill_Fire->SetFireMotionID( 90 );
}
else
{
//3번 자신의 주변에 영향을 주는 스킬
if( info.hTarget == GetArID() )
pSkill_Fire->SetFireMotionID( 93 );
else
{
//4번 타인에게 사용하는 이로운 스킬
if( !pSkill->IsHarmful() )
pSkill_Fire->SetFireMotionID( 91 );
}
}
}
}
}
else //전투 기술임
{
SetVisibleWeaponTrail( true );
}
if( pTarget )
pSkill_Fire->SetTarget( info.hTarget, pTarget );
pSkill_Fire->SetStartTime( m_dwTime );
pSkill_Fire->SetSkillMode( SNewSkill::SKILLMODE_FIRE );
m_vFireSkillList.push_back( pSkill_Fire );
}
else
{
if( pSkillFX->nStage_Type_Id != SS_TYPE_171 )
{
SAFE_DELETE( pSkillFX ); // 무조건 삭제. 이하 fx는 생성해서 사용하기로 한다.
return;
}
}
//RUSH, KNOCK_BACK, DAMAGE 처리
if( pSkillFX->nStage_Type_Id != SS_TYPE_171 ) return;
std::vector<SkillResult>::const_iterator it;
for( it = info.vSkillResult.begin(); it != info.vSkillResult.end(); it++ )
{
_SKILL_FX* ptSkillFX = new _SKILL_FX;
*ptSkillFX = *pSkillFXDB;
if( SkillResult::RUSH == (*it).GetType() )
{
if( (*it).rush.bResult )
{
SWorkRush_Shove* pRushShove = new SWorkRush_Shove( this, ptSkillFX, &info );
m_vFireSkillList.push_back( pRushShove );
return;
}
}
else if( SkillResult::DAMAGE_WITH_KNOCK_BACK == (*it).GetType() )
{
SWorkKnockBack* pWorkKnockBack = new SWorkKnockBack( this, ptSkillFX, &(*it) );
pWorkKnockBack->SetStartTime( m_dwTime );
m_vFireSkillList.push_back( pWorkKnockBack );
}
else if( SkillResult::DAMAGE == (*it).GetType() )
{
SChargeAttack* pChargerAttack = new SChargeAttack( this, ptSkillFX, &(*it) );
pChargerAttack->SetStartTime( m_dwTime );
m_vFireSkillList.push_back( pChargerAttack );
}
}
}
break; // 캐스팅
case SObjectState::STATE_SKILL_END :
{
//_oprint( "SKILL - SObjectState::STATE_SKILL_END\n" );
m_bIsUseSkill_complete = true;
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
m_vCastSkillList[i]->ForceEnd();
// for( unsigned int i(0); m_vFireSkillList.size()>i; i++ )
// m_vFireSkillList[i]->ForceEnd();
break;
}
case SObjectState::STATE_THROW : Throw(); break; // 던지기
{
// _oprint( "상태 머신 : 던지기 상태 변경\n" );
break; // 서기
}
case SObjectState::STATE_SIT :
{
// _oprint( "상태 머신 : 앉기 상태 변경\n" );
SWorkAniSit * pSitSit = new SWorkAniSit( this, m_dwTime );
m_vAttackEventList.push_back( pSitSit );
break; // 앉기
}
case SObjectState::STATE_STAND_UP :
{
SWorkAniStandUp * pSitSit = new SWorkAniStandUp( this, m_dwTime );
m_vAttackEventList.push_back( pSitSit );
break; // 서기
}
case SObjectState::STATE_CAST_CANCEL :
{
//_oprint( "SKILL - SObjectState::STATE_CAST_CANCEL\n" );
m_bIsUseSkill_complete = true;
for( unsigned int i(0); m_vAttackEventList.size()>i; i++)
{
if( ( m_vAttackEventList[i]->GetWorkType() == SGameWork::WORK_ATTACKEX ||
m_vAttackEventList[i]->GetWorkType() == SGameWork::WORK_SHOOTINGBOW ) &&
!m_vAttackEventList[i]->ProcessingDamage() ) //데미지 처리가 아직 안됐다면
{
m_bWaitingAttackCancel = true;
}
else
m_vAttackEventList[i]->CastCancel();
}
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
m_vCastSkillList[i]->CastCancel();
// for( unsigned int i(0); m_vFireSkillList.size()>i; i++ )
// m_vFireSkillList[i]->CastCancel();
if( !m_bWaitingAttackCancel )
{
SetIng(false);
SetAniLock( false );
Default( true );
}
break;
}
}
}
bool SGamePlayer::MotionCancel()
{
if( m_vAttackEventList.empty() && m_vCastSkillList.empty() && m_vFireSkillList.empty() )
{
m_bIsUseSkill_complete = true;
SetIng(false);
SetAniLock( false );
Default();
return true;
}
//애니메이션 진행과 상관없이 히트 후 바로 캔슬 가능
/*
int nBoneCnt = 0;
DWORD dwMinTime = 0, dwMaxTime = 0;
DWORD dwCurAniTime = 0;
GetCurrentAnimationInfo( nBoneCnt, dwMinTime, dwMaxTime, dwCurAniTime );
dwMaxTime = dwMaxTime / 160;
dwCurAniTime = (dwCurAniTime / 160) * 4.8f;
float fPlayProgress = (dwCurAniTime / (float)dwMaxTime);
//80프로 애니메이션 진행되면 모션 캔슬 가능
if( fPlayProgress < 0.13f )
return;
*/
//데미지 처리 완료했는지 체크
for( unsigned int i(0); m_vAttackEventList.size()>i; i++)
{
if( !m_vAttackEventList[i]->ProcessingDamage() )
return false;
}
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
{
if( !m_vCastSkillList[i]->ProcessingDamage() )
return false;
}
for( unsigned int i(0); m_vFireSkillList.size()>i; i++ )
{
if( !m_vFireSkillList[i]->ProcessingDamage() )
return false;
}
for( unsigned int i(0); m_vAttackEventList.size()>i; i++)
m_vAttackEventList[i]->ForceEnd();
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
m_vCastSkillList[i]->ForceEnd();
for( unsigned int i(0); m_vFireSkillList.size()>i; i++ )
m_vFireSkillList[i]->ForceEnd();
m_bIsUseSkill_complete = true;
SetIng(false);
SetAniLock( false );
Default();
return true;
}
//방향 설정
void SGamePlayer::SetViewVector( const K3DVector &tpos )
{
if( IsMount() || IsMountMode() ) return;
m_fTargetRoll = atan2( tpos.y-GetPosition()->y, tpos.x-GetPosition()->x );
m_dwPrevTime = m_dwTime;
m_bUseRot = true;
}
// sonador 1.8.13 아바타 IDLE 모션 동작 구현
void SGamePlayer::_processIdle()
{
if( GetCurrAnimationID() == ANI_IDLE )
{
if( !IsPlaying() )
NPlayAnimation( ANI_DEFAULT01, SEQTYPE_LOOP );
}
else if( GetCurrAnimationID() == ANI_DEFAULT01 )
{
int timeDiff = m_dwTime - m_dwIdleTime;
int rand = XFastRandom( 1, 10000000 );
if( rand < (int)timeDiff )
{
NPlayAnimation( ANI_IDLE, SEQTYPE_NORMAL );
_resetIdleTime();
}
}
}
bool SGamePlayer::Process( DWORD time, unsigned long uProcessBitVector )
{
if( m_bWaitingAttackCancel )
{
m_bWaitingAttackCancel = false;
for( unsigned int i(0); m_vAttackEventList.size()>i; ++i)
{
if( m_vAttackEventList[i]->GetWorkType() == SGameWork::WORK_ATTACKEX ||
m_vAttackEventList[i]->GetWorkType() == SGameWork::WORK_SHOOTINGBOW )
m_bWaitingAttackCancel = true;
}
if( !m_bWaitingAttackCancel )
{
if( m_vCastSkillList.empty() && m_vCastSkillList.empty() )
{
SetIng(false);
SetAniLock( false );
Default( true );
}
}
}
SGameAvatarEx::Process( time, uProcessBitVector );
_processIdle(); // sonador 1.8.13 아바타 IDLE 모션 동작 구현
if( !m_vCastSkillList.empty() )
CheckWorkDel( m_vCastSkillList );
if( !m_vFireSkillList.empty() )
CheckWorkDel( m_vFireSkillList );
for( unsigned int i(0); m_vCastSkillList.size()>i; i++ )
m_vCastSkillList[i]->Process( m_dwTime );
for( unsigned int i(0); m_vFireSkillList.size()>i; i++ )
m_vFireSkillList[i]->Process( m_dwTime );
return true;
}
//플레이어만 탑승 가능
//크리처에 탑승한 상태냐
bool SGamePlayer::IsStateRide()
{
if( GetRiderCreatureObject() == NULL )
return false;
return true;
}
SGameAvatarEx* SGamePlayer::GetRiderCreatureObject( bool bOnlyTransportCreature )
{
AR_HANDLE hCreature = m_RiderCreatureInfo.GetCreatureMountHandle();
if( hCreature != 0 )
{
if( bOnlyTransportCreature)
{
if( m_RiderCreatureInfo.IsTransportCreature() )
return (SGameAvatarEx*)GetGameTransportCreatureObject( hCreature );
else
return NULL;
}
else
{
if( m_RiderCreatureInfo.IsTransportCreature() )
{
return (SGameAvatarEx*)GetGameTransportCreatureObject( hCreature );
}
else
{
return (SGameAvatarEx*)GetGameObject( hCreature );
}
}
}
return NULL;
}
//소환수에 의한 플레이어 프러스텀 체크
void SGamePlayer::AvatarClipTestByCreature( struct K3DVector *pFrustum )
{
SGameAvatarEx* pCreature = GetRiderCreatureObject();
if( !pCreature ) return;
K3DMatrix matPlayer = *GetTransform();
K3DMatrix matCreature = *pCreature->GetTransform();
K3DMatrix matTransform = matPlayer;
matTransform._41 = matCreature._41;
matTransform._42 = matCreature._42;
matTransform._43 = matCreature._43;
m_pSeqAvatar->SetTransform( matTransform );
m_pSeqAvatar->ClipTest( pFrustum );
m_pSeqAvatar->SetTransform( matPlayer );
}
//소환수에 의한 플레이어 회전
void SGamePlayer::AvatarRotationByCreature()
{
SGameAvatarEx* pCreature = GetRiderCreatureObject();
if( !pCreature ) return;
K3DMatrix mat, matResult;
mat = *GetTransform();
m_pSeqRideLink = pCreature->GetSaddleEffectPos();
if( m_pSeqRideLink )
{
K3DMatrix* pAttachMatrix = (K3DMatrix*)m_pSeqRideLink->GetAttachTransform();
K3DMatrix* pPointMatrix = (K3DMatrix*)&m_pSeqRideLink->GetPoint();
K3DMatrix* pMatCreature = pCreature->GetTransform();
if( pAttachMatrix && pPointMatrix && pMatCreature )
{
// sonador #2.1.6 크리쳐 기린(spirit_qilin) 테스트
if( m_RiderCreatureInfo.GetRideType() == RIDE_LOW_TYPE || m_RiderCreatureInfo.GetRideType() == RIDE_HIGH_TYPE )
{
// 기존 탈것
K3DMatrixMultiply( matResult, *pAttachMatrix, *pMatCreature );
K3DMatrixMultiply( mat, *pPointMatrix, matResult );
}
else if( m_RiderCreatureInfo.GetRideType() == RIDE_UNICORN_TYPE)
{
K3DMatrixTranslation( matResult, pAttachMatrix->_41 + 0.001f, pAttachMatrix->_42 - 2.4f, pAttachMatrix->_43 + 3.1f );
K3DMatrixMultiply( mat, matResult, *pMatCreature );
}
else
{
// sonador
// 변경된 탈것
// 데이터 타입에 의해 코드가 영향을 받으면 안되지만 ... -_ㅜ
// RIDE_QILIN_TYPE & RIDE_WHITE_TYPE 은 아바타가 타야하는 위치가
// AttachMatrix 의 회전 행렬에 영향을 받으면 안된다.
// translation of [ Mp x Ma ] = Tp x Ra + Ta : Ra = I
// hence, Tp x I + Ta = Tp + Ta
K3DMatrixTranslation( matResult, pAttachMatrix->_41 + pPointMatrix->_41, pAttachMatrix->_42 + pPointMatrix->_42, pAttachMatrix->_43 + pPointMatrix->_43 );
//K3DMatrixTranslation( matResult, pAttachMatrix->_41, pAttachMatrix->_42, pAttachMatrix->_43);
//K3DMatrixTranslation( matResult, pPointMatrix->_41, pPointMatrix->_42, pPointMatrix->_43 );
K3DMatrixMultiply( mat, matResult, *pMatCreature );
}
//mat = *pMatCreature;
//mat._41 += pAttachMatrix->_41 - pPointMatrix->_41;
//mat._42 += pAttachMatrix->_42 - pPointMatrix->_42;
//mat._43 += pAttachMatrix->_43 - pPointMatrix->_43;
/*K3DMatrixTranslation( matResult, pAttachMatrix->_41 + pPointMatrix->_41, pAttachMatrix->_42 + pPointMatrix->_42, pAttachMatrix->_43 + pPointMatrix->_43 );
K3DMatrixMultiply( mat, matResult, *pMatCreature );*/
//mat = *pPointMatrix;
//mat._41 *= -1.f;
//mat._42 *= -1.f;
//mat._43 *= -1.f;
//K3DMatrixMultiply( matResult, mat, matResult );
//mat = *pMatCreature;
//mat._41 = matResult._41;
//mat._42 = matResult._42;
//mat._43 = matResult._43;
/*mat._41 = pos.x;
mat._42 = pos.y;
mat._43 = pos.z;*/
}
else if( pAttachMatrix && pMatCreature )
{
K3DMatrixMultiply( matResult, *pAttachMatrix, *pMatCreature );
mat = *pMatCreature;
mat._41 = matResult._41;
mat._42 = matResult._42;
mat._43 = matResult._43;
}
else if( pMatCreature )
{
mat = *pMatCreature;
}
m_fTargetRoll = pCreature->GetTargetRoll();
m_fPresentRoll = pCreature->GetPresentRoll();
K3DMatrix zRollMat;
if( pCreature->IsActivateTerrainDegree() )
{
float fAngleX = pCreature->GetCurAngleX();
float fAngleY = pCreature->GetCurAngleY();
K3DMatrixRotationYawPitchRoll( zRollMat, (fAngleX-3.1415926f/2), (fAngleY-3.1415926f/2), m_fPresentRoll + 3.1415926f/2 );
}
else
K3DMatrixRotationZ( zRollMat, m_fPresentRoll + 3.1415926f/2 );
m_vView = K3DVector( 0.0f, 1.0f, 0.0f );
K3DVectorTransform( m_vView, m_vView, zRollMat );
zRollMat._41 = mat._41;
zRollMat._42 = mat._42;
zRollMat._43 = mat._43;
mat = zRollMat;
SetTransform( mat );
}
m_pAddOnMgr->SetCreatureHandle( SGameAvatarAddOnMgr::SGAME_CIRCLE_SHADOW_FX, pCreature->GetArID() );
m_pAddOnMgr->SetCreatureHandle( SGameAvatarAddOnMgr::SGAME_FORCE_SPHERE_FX, pCreature->GetArID() );
}
void SGamePlayer::SetDefaultView()
{
m_dwPrevTime = m_dwTime;
m_bUseRot = true;
}
void SGamePlayer::CheatWhirlWindSkill( std::vector< AR_HANDLE > & vTargetList )
{
SWorkMultiAttack* pMultiAttack = new SWorkMultiAttack( this );
pMultiAttack->SetTargetList( vTargetList );
m_vFireSkillList.push_back( pMultiAttack );
}
void SGamePlayer::AddMeshPart( ANIPART nAniPart, MPART nMeshPart, const char* szMeshFileName )
{
if( m_pSeqAvatar && szMeshFileName )
m_pSeqAvatar->AddMesh( nAniPart, nMeshPart, szMeshFileName );
}
void SGamePlayer::AddDecoMeshPart( ANIPART nAniPart, MDECOPART nDecoMeshPart, const char* szMeshFileName )
{
if( m_pSeqAvatar && szMeshFileName )
m_pSeqAvatar->AddDecoMesh( nAniPart, nDecoMeshPart, szMeshFileName );
}
void SGamePlayer::AddAttachItemPart( ANIPART nAniPart, ATTACH nAttachPart, const char* szMeshFileName )
{
if( m_pSeqAvatar && szMeshFileName )
m_pSeqAvatar->AddAttachItem( nAniPart, nAttachPart, szMeshFileName );
}
// sonador #2.1.6 크리쳐 기린(spirit_qilin) 테스트
void SGamePlayer::SetRunNWalkAniSpeedDefault()
{
m_fPlayRate = DEFAULT_ANI_PLAY_RATE;
m_fStandardWalkPlayRate = DEFAULT_ANI_PLAY_RATE;
m_fStandardRunPlayRate = DEFAULT_ANI_PLAY_RATE;
m_fRdbScale = 1.0f;
m_fWalkSpeed = (float)DEF_SPEED;
}
void SGamePlayer::SetRunNWalkAniSpeedMount()
{
if( !m_pMsgHandler )
return;
SGameAvatarEx* Creature = 0;
//추가 : 탑승 유닛일 경우
// OnMount : 페킷을 받은 탈거인 경우 AddTransportCreature 함수를 통하여 탑승 전용 해쉬를 만들지만
// 탑승 가능 크리쳐인 경우는 그냥 오브젝트 해쉬에 집어 넣는다.
// 따라서 플레이어의 타기 애니메이션의 재생 시간이 적용되지 않아서 빠른속도로 애니메이션을
// 하고 있었다.
// 탑승 크리쳐 (대여용) 우선 검사후 애니메이션 속도룰 적용 하였다.
// 2009-11-20 : hunee
Creature = (SGameAvatarEx*)m_pMsgHandler->GetGameTransportCreatureObject( this->GetCreatureMountHandle() );
if( !Creature )
{
Creature = (SGameAvatarEx*)m_pMsgHandler->GetGameObject( this->GetCreatureMountHandle() );
if( !Creature )
return;
}
_SUMMON_INFO_FILE* SummonInfo = 0;
SummonInfo = GetCreatureDB().GetCreatureData( Creature->GetContentID() );
if( SummonInfo )
this->SetRunNWalkAniSpeed( SummonInfo );
}
void SGamePlayer::SetRunNWalkAniSpeed( _MONSTER_INFO_FILE* pMonsterInfo )
{
if( pMonsterInfo == NULL ) return;
m_fStandardWalkPlayRate = (float)pMonsterInfo->standard_walk_speed / 7.0f;
m_fStandardRunPlayRate = (float)pMonsterInfo->standard_run_speed / 7.0f;
m_fWalkSpeed = (float)((pMonsterInfo->standard_walk_speed + pMonsterInfo->standard_run_speed) / 2.0f) / 7.0f;
m_fRdbScale = GetScale();
}
void SGamePlayer::SetRunNWalkAniSpeed( _SUMMON_INFO_FILE* pSummonInfo )
{
if( pSummonInfo == NULL ) return;
m_fStandardWalkPlayRate = (float)pSummonInfo->standard_walk_speed / 7.0f;
m_fStandardRunPlayRate = (float)pSummonInfo->standard_run_speed / 7.0f;
m_fWalkSpeed = (float)((pSummonInfo->standard_walk_speed + pSummonInfo->standard_run_speed) / 2.0f) / 7.0f;
m_fRdbScale = pSummonInfo->scale;
}
void SGamePlayer::CalcCreatureRunPlayRate( float fSpeed )
{
m_fPlayRate = DEFAULT_ANI_PLAY_RATE * ( (fSpeed / m_fStandardRunPlayRate) / m_fRdbScale );
}
void SGamePlayer::CalcCreatureWalkPlayRate( float fSpeed )
{
m_fPlayRate = DEFAULT_ANI_PLAY_RATE * ( (fSpeed / m_fStandardWalkPlayRate) / m_fRdbScale );
}
// 2.1.16 변신 효과 중첩시 아바타 사라지는 오류 수정
void SGamePlayer::UnDisguise( unsigned int stateHandle )
{
if( SGameAvatarEx::IsLastDisguise() )
{
m_fPlayRate = DEFAULT_ANI_PLAY_RATE;
m_fStandardWalkPlayRate = DEFAULT_ANI_PLAY_RATE;
m_fStandardRunPlayRate = DEFAULT_ANI_PLAY_RATE;
m_fRdbScale = 1.0f;
m_fWalkSpeed = (float)DEF_SPEED;
}
SGameAvatarEx::UnDisguise( stateHandle );
//if( IsMountMode() ) // 2.1.15 변신시 모션 연결 적용
// HideWeapon( FALSE );
}
// sonador #2.1.6
int SGamePlayer::GetPlayerMDefAniID() const
{
switch( GetRideType() )
{
case RIDE_LOW_TYPE:
return ANI_M_DEFAULT01_LOW;
case RIDE_HIGH_TYPE:
return ANI_M_DEFAULT01_HIGH;
case RIDE_QILIN_TYPE:
return ANI_M_DEFAULT01_QILIN;
case RIDE_WHITE_TYPE:
return ANI_M_DEFAULT01_WHITE;
case RIDE_UNICORN_TYPE:
return ANI_M_DEFAULT01_UNICORN;
/// 2011.02.08 - prodongi
case RIDE_BEAKHO_TYPE:
return ANI_M_DEFAULT01_BEAKHO;
default:
return ANI_M_DEFAULT01_HIGH;
}
}
// sonador #2.1.6
int SGamePlayer::GetPlayerMWalkAniID() const
{
switch( GetRideType() )
{
case RIDE_QILIN_TYPE:
return ANI_M_WALK_QILIN;
case RIDE_WHITE_TYPE:
return ANI_M_WALK_WHITE;
case RIDE_UNICORN_TYPE:
return ANI_M_WALK_UNICORN;
/// 2011.02.08 - prodongi
case RIDE_BEAKHO_TYPE:
return ANI_M_WALK_BEAKHO;
default:
return ANI_M_WALK;;
}
}
// sonador #2.1.6
int SGamePlayer::GetPlayerMRunAniID() const
{
switch( GetRideType() )
{
case RIDE_LOW_TYPE:
return ANI_M_RUN_LOW;
case RIDE_HIGH_TYPE:
return ANI_M_RUN_HIGH;
case RIDE_QILIN_TYPE:
return ANI_M_RUN_QILIN;
case RIDE_WHITE_TYPE:
return ANI_M_RUN_WHITE;
case RIDE_UNICORN_TYPE:
return ANI_M_RUN_UNICORN;
/// 2011.02.08 - prodongi
case RIDE_BEAKHO_TYPE:
return ANI_M_RUN_BEAKHO;
default:
return ANI_M_RUN_HIGH;
}
}