#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 #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::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; } }