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

8415 lines
222 KiB
C++

#include "stdafx.h"
#include <deque> // 2.1.16 변신 효과 중첩시 아바타 사라지는 오류 수정
#include "K3DTypes.h"
#include "SEventKeyRes.h"
#include "KSeqAvatarEx.h"
#include "KSeqAvatar.h"
#include "KSeqModel.h"
#include "KRenderObjectBone.h"
#include "KRenderObjectEtc.h"
#include "KRenderObjectMesh.h"
#include "SGameUtil.h"
#include "SAvatarProperty.h"
#include "SGameAvatarEx.h"
#include "SGame.h"
#include "SCobManager.h"
#include "SBasicStat.h"
//#include "Util.h"
//#include "GameDefine.h"
#include "SGameWork.h"
#include "SGameMessage.h"
#include "LuaVM.h"
#include "SGameViewPort.h"
#include <toolkit/XStringUtil.h>
#include "SMonsterDB.h"
#include "SCreatureDB.h"
#include "SNpcDB.h"
#include "SPetDB.h" // sonador 10.2.1 팻 시스템 구현
#include "SNpcResourceDB.h"
#include "SItemDB.h"
#include "SDefaultTextureResourceDB.h"
#include "SStringDB.h"
#include "SSkillDB.h"
#include "SMotionDB.h"
//#include "SEnhanceFXDB.h"
#include "SModelEffectResourceDB.h"
#include "STenacityDB.h"
#include "SSoundResourceDB.h"
//#include "Smove_filter.h"
//#include "SGameMessageUI.h"
#include "SDebug_Util.h"
#include "SGameSystem.h"
#include "SBotManager.h"
#include "SGameAvatarAddOnMgr.h"
#include "SGameForceSphereFX.h"
#include "SGameCircleShadowFX.h"
#include "SGameAvatarFx.h"
#include "SGameAvatarTerrainDegree.h"
#include "SGameFxSwordSlash.h"
#include "SGameFxWeaponPowerup.h"
#include "SGameOption.h"
#include <toolkit/bits_scramble.h>
#include "SSKillStageType.h"
#include "SPlayerInfoMgr.h"
//#include "SGameMessageUI.h"
#include "SUISysMsgDefine.h"
#include "SGameOption.h"
// 2010.04.22 - prodongi
#include "SSelectedAvatarInfo.h"
// 2010.05.11 - prodongi
#include "ItemBase.h"
#include "SGameWorld.h"
#include "WorldLocation.h"
#include "Arena\\ArenaSystem.h"
#include "SGameLocalPlayer.h"
extern SGameSystem* g_pCurrentGameSystem;
extern SBotManager* g_pSBotMng;
unsigned int g_pEnhanceColor[26][4]
= {
#include "EnhanceColor.txt"
};
#ifdef _DEV
void _EnhanceColorReload(void)
{
FILE* fp = fopen("EnhanceColor.txt", "rt");
if (fp == NULL) return;
memset(g_pEnhanceColor, 0, sizeof(g_pEnhanceColor));
for (int i = 0; i < 26; i++)
{
while (TRUE)
{
char buf[256];
char* ret = fgets(buf, 255, fp);
if (ret <= 0) break;
int len = strlen(buf);
for (int j = 0; j < len; j++)
{
if (buf[j] == '\"' || buf[j] == ',' || buf[j] < ' ') buf[j] = ' ';
}
char token[4][256];
sscanf(buf, "%s %s %s %s", token[0], token[1], token[2], token[3]);
if (token[0][0] == '/') continue;
int mode = _tcstoul(token[0], NULL, 16);
g_pEnhanceColor[i][0] = mode;
mode = _tcstoul(token[1], NULL, 16);
g_pEnhanceColor[i][1] = mode;
mode = _tcstoul(token[2], NULL, 16);
g_pEnhanceColor[i][2] = mode;
mode = _tcstoul(token[3], NULL, 16);
g_pEnhanceColor[i][3] = mode;
break;
};
}
fclose(fp);
}
#endif
// #include <typeinfo.h>
/// 2010.11.04 안 쓰는 것 같음 - prodongi
/*
const char * pEffPos[] =
{
"_top.nx3",
"_middle.nx3",
"_damage.nx3",
"_etc.nx3",
"_saddle.nx3",
};
*/
unsigned int g_pWeaponLength[12][8] =
{
0, 11, 12, 13, 13, 14, 15, 16, //< 한손검 101
0, 14, 15, 16, 17, 18, 20, 22, //< 한손검x->양손검 102
0, 8, 8, 9, 10, 11, 12, 13, //< 단검 103
0, 14, 16, 17, 18, 19, 21, 22, //< 창 104
0, 11, 11, 12, 13, 13, 14, 14, //< 도끼 105
0, 7, 8, 9, 10, 11, 12, 13, //< 한손메이스 106
0, 11, 11, 11, 12, 13, 14, 15, //< 양손메이스 107
0, 10, 10, 10, 10, 10, 10, 10, //< 헤비 보우 108 //10, 11, 12, 13, 14, 15, 16, 18, //< 라이트 보우 108 - 109
0, 10, 10, 10, 10, 10, 10, 10, //< 석궁 109 - 110
0, 10, 10, 11, 12, 12, 13, 13, //< 한손 지팡이 110 - 111
0, 12, 13, 14, 14, 15, 15, 16, //< 양손 지팡이 111 - 112
0, 7, 7, 8, 8, 9, 9, 9, //< 한손도끼 112 - 113
};
extern const char* pEP_Name[];
const char* pPartExt[] = { "_biped.naf","_hair.naf","_necklace.naf", "_earring.naf","_mantle.naf","_fabric.naf","_longskirt.naf","_middleskirt.naf","_shortskirt.naf","_weaponl.naf","_weaponr.naf", };
const char* pPart[] = { "biped","hair","necklace", "earring","mantle","fabric","longskirt","middleskirt","shortskirt","weaponl","weaponr", };
const char* pSex[] = { "n", "f", "m", };
const char* pRace[] = { "non", "mob", "npc", "ga", "de", "as", "af", "gi", "am", };
const char* pLeftHandEpName[2] =
{
"ep_wfx_00_l",
"ep_wfx_01_l",
};
const char* pRightHandEpName[2] =
{
"ep_wfx_00",
"ep_wfx_01",
};
const char* pTwoHandEpName[2] =
{
"ep_wfx_00_th",
"ep_wfx_01_th",
};
const char* pWeaponEpName[EFFECT_POS_WEAPON_MAX][EFFECT_POS_WEAPON_EP_MAX] =
{
{ "ep_wfx_00_l", "ep_wfx_01_l" },
{ "ep_wfx_00", "ep_wfx_01" },
{ "ep_wfx_00_th", "ep_wfx_01_th" },
};
const int WEAPON_SLASH_RECORD_SUBDIVISION = 16; // 각 frame을 sub분할하는 횟수
const int WEAPON_SLASH_RECORD_ARROW_SUBDIVISION = 1; // 각 frame을 sub분할하는 횟수
const short c_WINK_TIME = 1000; //Face Ani
const int RAMADAN_ITEM_ARMOR = 2520016;
const int RAMADAN_ITEM_HAT = 2520017;
const int RAMADAN_ITEM_GLOVE = 2520018;
const int RAMADAN_ITEM_BOOTS = 2520019;
extern K3DTexture* _getTexture(const char* texname, DWORD skin_color = 0);
//GameDefine.h 참조
#define _WEAPON_FX_
//레이저를 쏴서, 이동 리스트를 만들어서, 단계별 이동.
//namespace
//{
// struct intf_move_filter
// {
// static bool is_empty_at( SGameObject *pObj, float x, float y )
// {
// return pObj->IsBlockedAttribute( x, y );
// }
// };
//
// typedef move_filter<intf_move_filter, 16, 16> SPATHFINDER;
//};
bool SGameAvatarEx::m_sCubeRender = false;
bool SGameAvatarEx::m_sMoveSound = true;
bool SGameAvatarEx::m_sEnhanceTest = true;
volatile bool SGameAvatarEx::s_bStopThread = false;
static XCriticalSection s_AvatarLoadingLock;
static std::list< SGameAvatarEx* > s_lstThreadLoadingAvatar;
const float c_fStateCheckTime = 1000.f;
// Bone recorder
// 검광용으로 bone 위치를 보간하여 world에 대한 무기 위치 matrix를 얻어옴
class BoneRecorder {
public:
BoneRecorder() { avatar = NULL; starttime = endtime = 0; subdivision = 0; matrix_left = matrix_right = NULL; }
BoneRecorder(SGameAvatarEx* _avatar, int _subdivision) {
avatar = NULL; starttime = endtime = 0; subdivision = 0; matrix_left = matrix_right = NULL;
init(_avatar, _subdivision);
}
virtual ~BoneRecorder() { clear(); }
void init(SGameAvatarEx* _avatar, int _subdivision) {
clear();
avatar = _avatar;
if (_subdivision > 0) {
matrix_left = new K3DMatrix[_subdivision];
matrix_right = new K3DMatrix[_subdivision];
subdivision = _subdivision;
}
}
void clear() {
if (matrix_left != NULL) { delete[] matrix_left; matrix_left = NULL; }
if (matrix_right != NULL) { delete[] matrix_right; matrix_right = NULL; }
subdivision = 0;
starttime = endtime = 0;
avatar = NULL;
}
void record(DWORD _starttime, DWORD _endtime)
{
while (true)
{
if (avatar == NULL) break;
KSeqAvatarEx* seqAvatar = avatar->GetSeqForm();
if (seqAvatar == NULL) break;
KSeqAvatar* bipedSeq = seqAvatar->getAvatarPart(ANIPART_BIPED); // biped animation part
if (bipedSeq == NULL) break;
KBoneSeqObject* pBoneSeq = bipedSeq->getBoneSequencer(); // biped bone
if (pBoneSeq == NULL) break;
KBoneSeqObject* boneSeqRightWeapon = NULL; // 무기의 animation bone
KBoneSeqObject* boneSeqLeftWeapon = NULL;
KSeqAvatar* rightHandSeq = seqAvatar->getAvatarPart(ANIPART_WEAPON_RIGHT); // 오른손 무기가 붙을 위치
KSequencer* sequencer = dynamic_cast<KSequencer*>(rightHandSeq->GetCurrentAnimation());
if (sequencer != NULL)
{
boneSeqRightWeapon = dynamic_cast<KBoneSeqObject*> (sequencer->GetSeqObject(0));
}
KSeqAvatar* leftHandSeq = seqAvatar->getAvatarPart(ANIPART_WEAPON_LEFT); // 왼손 무기가 붙을 위치
sequencer = dynamic_cast<KSequencer*>(leftHandSeq->GetCurrentAnimation());
if (sequencer != NULL)
{
boneSeqLeftWeapon = dynamic_cast<KBoneSeqObject*> (sequencer->GetSeqObject(0));
}
if (boneSeqRightWeapon == NULL && boneSeqLeftWeapon == NULL) break;
K3DMatrix* pWeaponPosMat = NULL;
K3DMatrix* pBoneMat = NULL;
K3DMatrix tempMat;
DWORD actionTime;
starttime = _starttime;
endtime = _endtime;
int i;
for (i = 0; i < subdivision; i++)
{
actionTime = (endtime - starttime) * (i + 1) / subdivision + starttime;
// Animate master bone sequencer
seqAvatar->Process(actionTime);
seqAvatar->realizeTime();
//pBoneSeq->SetTime(actionTime); // seqAvatar->Process()가 내부적으로 child시간을 계산하므로 SetTime()하면 안 됨
// pBoneSeq / boneSeq...Weapon해당
pBoneSeq->realizeTime();
if (boneSeqRightWeapon != NULL)
{
// 오른손 무기 최종 위치 계산
boneSeqRightWeapon->realizeTime();
pWeaponPosMat = &(boneSeqRightWeapon->GetBoneCacheTM()[1]);
// [0] : hand position (parallel to elbow)
// [1] : grip position (in the handle, transformed)
// [2] : blade vector (very long)
assert(pWeaponPosMat != NULL);
pBoneMat = pBoneSeq->GetBoneMatrix(DETAIL_RIGHT_HAND);
if (pBoneMat != NULL)
{
/* K3DMatrixMultiply( &(matrix_right[i])
, pWeaponPosMat // 무기 끝 위치
, pBoneMat ); // 오른손 무기 base위치
*/ K3DMatrixMultiply(tempMat, *pBoneMat, seqAvatar->GetTransform()); // <- 이것도 어떻게 보간 안 되나??
K3DMatrixMultiply((matrix_right[i]), *pWeaponPosMat, tempMat);
}
else
{
K3DMatrixIdentity((matrix_right[i]));
}
}
else
{
K3DMatrixIdentity((matrix_right[i]));
}
if (boneSeqLeftWeapon != NULL)
{
// 왼손 무기 최종 위치 계산
boneSeqLeftWeapon->realizeTime();
pWeaponPosMat = &(boneSeqLeftWeapon->GetBoneCacheTM()[1]);
// [0] : hand position (parallel to elbow)
// [1] : grip position (in the handle, transformed)
// [2] : blade vector (very long)
assert(pWeaponPosMat != NULL);
pBoneMat = pBoneSeq->GetBoneMatrix(DETAIL_LEFT_HAND);
if (pBoneMat != NULL)
{
/* K3DMatrixMultiply( (matrix_left[i])
, *pWeaponPosMat // 무기 끝 위치
, *pBoneMat ); // 왼손 무기 base위치
*/ K3DMatrixMultiply(tempMat, *pBoneMat, seqAvatar->GetTransform());
K3DMatrixMultiply((matrix_left[i]), *pWeaponPosMat, tempMat);
}
else
{
K3DMatrixIdentity((matrix_left[i]));
}
}
else
{
K3DMatrixIdentity((matrix_left[i]));
}
}
return;
}
//break 된 경우만 처리
{
// No capture
int i;
starttime = _starttime;
endtime = _endtime;
for (i = 0; i < subdivision; i++) {
K3DMatrixIdentity((matrix_right[i]));
K3DMatrixIdentity((matrix_left[i]));
}
}
}
public:
SGameAvatarEx* avatar;
DWORD starttime, endtime; // 시작시간 < 레코딩 <=끝시간. 시작시간은 계산하지 않는다.
int subdivision; // recording될 entry 숫자
K3DMatrix* matrix_left; // matrix[subdivision], 왼손용
K3DMatrix* matrix_right; // matrix[subdivision], 오른손용
};
// 2.1.16 변신 효과 중첩시 아바타 사라지는 오류 수정
class DisguiseStack
{
public:
struct Slot
{
Slot(unsigned int _stateHandle, ENC_INT _contentID, KSeqAvatarEx* _seqAvatar, float _size, float _scale, bool _isSummon)
: stateHandle(_stateHandle)
, contentID(_contentID)
, seqAvatar(_seqAvatar)
, size(_size)
, scale(_scale)
, isSummon(_isSummon)
{
}
~Slot()
{
}
Slot& operator = (const Slot& rhs)
{
//stateHandle = rhs.stateHandle; // <-- rhs 를 대입하는 것이 아니라, rhs 의 정보를 넘겨 받는 것이므로 핸들은 그대로 둔다.(ex. 중간삭제일경우)
contentID = rhs.contentID;
seqAvatar = rhs.seqAvatar;
size = rhs.size;
scale = rhs.scale;
isSummon = rhs.isSummon;
return *this;
}
bool operator == (unsigned int _stateHandle) { return stateHandle == _stateHandle; }
ENC_INT contentID;
unsigned short stateHandle;
KSeqAvatarEx* seqAvatar;
float size;
float scale;
bool isSummon;
};
struct FindByStateHandle {
FindByStateHandle(unsigned int _stateHandle) : stateHandle(_stateHandle) {}
bool operator () (const Slot& obj) const { return obj.stateHandle == stateHandle; }
unsigned int stateHandle;
};
typedef std::deque< Slot >::iterator iterator;
typedef std::deque< Slot >::const_iterator const_iterator;
~DisguiseStack()
{
while (!mSlots.empty())
{
Slot& slot = mSlots.back();
SAFE_DELETE(slot.seqAvatar);
mSlots.pop_back();
}
}
bool empty() const
{
return mSlots.empty();
}
bool onDisguise(const Slot& slot)
{
iterator found = std::find_if(mSlots.begin(), mSlots.end(), FindByStateHandle(slot.stateHandle));
if (found == mSlots.end())
{
mSlots.push_back(slot);
return true;
}
if (found == (mSlots.end() - 1))
return false;
iterator next = found + 1;
SAFE_DELETE(next->seqAvatar);
*next = *found;
mSlots.erase(found);
mSlots.push_back(slot);
return true;
}
bool onUndisguise(Slot& slot)
{
if (mSlots.empty())
return false;
iterator found;
// 핸들이 0 이면 정상적인 스택처럼 동작한다.
if (slot.stateHandle == 0)
{
found = mSlots.end() - 1;
}
else
{
found = std::find_if(mSlots.begin(), mSlots.end(), FindByStateHandle(slot.stateHandle));
if (found == mSlots.end())
return false;
// 변신 해제를 하기 위한 슬롯 정보가
// 스택의 마지막에 있는지 검사한다.
// 즉, 변신해제후 아바타의 변경이
// 필요한지를 검사한다.
if (found->stateHandle != mSlots.back().stateHandle)
{
iterator next = found + 1;
SAFE_DELETE(next->seqAvatar);
*next = *found;
mSlots.erase(found);
return false;
}
}
slot = *found;
mSlots.pop_back();
return true;
}
private:
std::deque< Slot > mSlots;
};
SGameAvatarEx::SGameAvatarEx(ENC_INT nContentID) :m_bArrowTrail(false)
, m_bBowClass(false)
, m_nEnergy(0)
, m_nFirst(0)
, m_nIsRefreshAni(0)
, m_pThreadAvatarEx(NULL)
, m_nThreadAniClass(0)
, m_bIsThreadPending(false)
, m_bIsThreadLoading(false)
, m_pProperty(new SAvatarProperty(nContentID)) //게임 컨텐츠
, m_pStateVM(NULL)
, m_pSeqAvatar(NULL)
, m_nProcess_state(-1) //Animation 상태
, m_nAniClass(0) //기본 Ani
, m_bLockAni(false)
, m_bLockAttackAni(false)
, m_dwTime(0) //시간
, m_dwStartTime(0) //시작 시간
, m_fVisibility(0.0f)
, m_speed(DEF_SPEED)
, m_bLocal(false)
, m_bLocalCreature(false)
, m_bLocalPet(false)
, m_vCheckPos(0.0f, 0.0f, 0.0f)
, m_pSeqRideLink(NULL)
, m_bIng(false)
, m_bReservation(false) //삭제 보류 대상 인가?
, m_bVisible(true)
, m_bPrevVisible(true)
, m_bIsMovingDetour(false)
, m_bIsChasing(false)
, m_unDetourStep(0)
, m_bRefreshDetour(false)
, m_CurrState(SObjectState::ID::STATE_NONE)
, m_CurrTarget(0)
, m_nWeaponSwing_RepeatMotion(0)
, m_pUISyncData(new UI_SYNC_DATA)
, m_bIsDead(false)
, m_bUseRot(true)
, m_fTargetRoll(1.0f)
, m_fPresentRoll(1.0f)
, m_dwPrevTime(0)
, m_vNextPos(0.0f, 0.0f, 0.0f)
, m_vView(0.0f, 1.0f, 0.0f)
, m_vTempView(m_vView)
, m_nAttackIndex(0)
, m_vTerrainPickPos(0.0f, 1.0f, 0.0f)
, m_nNewCurAniType(ANI_DEFAULT01)
, m_nCurPlayType(SEQTYPE_LOOP)
, m_pBoneRecorder(NULL)
, m_bUseRightWeaponTrail(false) // 오른손 무기 궤적 사용?
, m_bUseLeftWeaponTrail(false) // 왼손 무기 궤적 사용?
, m_pWeaponTrailRight(NULL) // 오른손 무기 궤적 object
, m_pWeaponTrailLeft(NULL) // 왼손 무기 궤적 object
, m_bThreadUseRightWeaponTrail(false)
, m_bThreadUseLeftWeaponTrail(false)
, m_bActRightWeaponTrail(false)
, m_bActLeftWeaponTrail(false)
, m_pAddOnMgr(new SGameAvatarAddOnMgr)
, m_bActivateTerrainDegree(false)
, m_pTerrainDegree(NULL)
, m_bPlayOverride(false)
, m_vTerrainNormal(0.0f, 0.0f, 0.0f)
, m_bRefreshInven(false)
, m_cPrevAttackIndex(0)
, m_pDisguiseStack(new DisguiseStack) // 2.1.16 변신 효과 중첩시 아바타 사라지는 오류 수정
//, m_pDisguiseSeqAvatar( NULL )
, m_nDisguise(NONE_DISGUISE)
//, m_fDisguiseSize( 1.0f )
//, m_fDisguiseScale( 1.0f )
, m_bActRightSwordSlashForSkill(false) //스킬 용
, m_bActLeftSwordSlashForSkill(false) //스킬 용
, m_pRightSwordSlashForSkill(NULL)
, m_pLeftSwordSlashForSkill(NULL)
, m_nSwordSlashForSkillMotion(0)
, m_nStateFlag(FLAG_STATE_NONE)
, m_fHidingVisiblity(1.0f)
, m_fHidingDetectRange(0.0f)
, m_bFootsteps(false)
, m_vTargetPos(0.0f, 0.0f, 0.0f)
, m_nTraceIdx(0)
, m_SkinDiffuse(0, 0, 0, 0)
, m_bPendLoading(false)
, m_fScaleAdjustDest(1.0f)
, m_fScaleAdjustPrev(1.0f)
, m_nScaleAdjustStartTime(0)
, m_fScaleAdjust(1.0f)
, m_nFadeOutStartTime(0)
, m_hCreatureTemp(NULL) // 2010.08.12 - prodongi
, m_bIsReloadWearListFileName(false)
, m_dwCheckTime(0)
, LastWeaponSwapTime(0) // Fraun weaponb swap exploit fix 8/19/2025
{
SetEventHandleNull();
memset(m_itemClass, 0, sizeof(m_itemClass));
for (int i(0); 3 > i; i++)
{
m_fSelcube[i] = -2;
m_fDeadcube[i] = -2;
}
for (int i(3); 6 > i; i++)
{
m_fSelcube[i] = 2;
m_fDeadcube[i] = 2;
}
for (int x = 0; x < 3; x++)
{
//1아이템 코드 //2파티클 아이디 //3이펙트 아이디
m_nLeftHandWeaponCode[x] = -1;
m_nRightHandWeaponCode[x] = -1;
m_nTwoHandWeaponCode[x] = -1;
}
for (int i = 0; i < EFFECT_POS_MAX; ++i)
{
K3DMatrixIdentity(m_matEVPMatrix[i]);
K3DMatrixIdentity(m_matEVPAttachMatrix[i]);
m_pEvpSequencer[i] = NULL;
m_bEVPAttachMatrix[i] = false;
}
for (int i = 0; i < EFFECT_POS_WEAPON_MAX; ++i)
{
for (int x = 0; x < EFFECT_POS_WEAPON_EP_MAX; x++)
{
K3DMatrixIdentity(m_matWeaponEVPMatrix[i][x]);
K3DMatrixIdentity(m_matWeaponEVPAttachMatrix[i][x]);
K3DMatrixIdentity(m_matWeaponEVPParentMatrix[i][x]);
m_pWeaponEvpSequencer[i][x] = NULL;
}
m_bWeaponEVPMatrix[i] = false;
}
m_nClassID = OBJ_PLAYER;
m_pArObject = NULL; //LocalPlayer() 만 설정
m_wCurTile = 0;
m_bInWater = false;
m_pAddOnMgr->SetGameObject(this);
m_dwSkinColor = 0;
m_dwHairColor = 0;
m_nHairColorIndex = 0;
// 2010.05.19 - prodongi
m_hideEquipInfo = 0;
m_noneDisguiseScale = 1.0f; /// 2011.04.29 - prodongi
m_disguiseEnhance = 0; /// 2011.07.28 redmine #16797 - prodongi
m_syncCamRoll = false;
m_isKMoving = false;
m_kmoveType = 0;
m_kmoveDir = 0.0f;
#ifdef _DEV
_EnhanceColorReload();
#endif
}
SGameAvatarEx::~SGameAvatarEx()
{
while (m_bIsThreadLoading)
{
Sleep(100);
}
removeFromLoadingList();
Destroy();
}
ANI_LIST_EX SGameAvatarEx::GetDefaultAnimation()
{
if (IsDead() || !IsLive())
{
return ANI_DEAD01; //죽었음
}
return ANI_DEFAULT01;
}
void SGameAvatarEx::SetMotionBlend(bool bIsBlend)
{
if (!m_pSeqAvatar || !m_bIsInit) return;
_CID(SETBONEBLEND);
KMsgGET_SETBONEBLEND msg;
msg.bUseBlend = bIsBlend;
Perform(id_SETBONEBLEND, msg);
}
unsigned int __stdcall SGameAvatarEx::avatar_loader(void* pArg)
{
while (!s_bStopThread)
{
SGameAvatarEx* pAvatar = NULL;
{
s_AvatarLoadingLock.Lock();
if (s_lstThreadLoadingAvatar.empty())
{
s_AvatarLoadingLock.UnLock();
#ifdef _DEBUG
Sleep(100);
#else
Sleep(50);
#endif
continue;
}
pAvatar = s_lstThreadLoadingAvatar.front();
s_lstThreadLoadingAvatar.pop_front();
pAvatar->StartThreadLoading();
s_AvatarLoadingLock.UnLock();
}
pAvatar->doLoading();
}
s_bStopThread = false;
return 0;
}
void SGameAvatarEx::BeginAvatarLoadingThread()
{
unsigned dwThreadID;
HANDLE hThread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, SGameAvatarEx::avatar_loader, NULL, 0, &dwThreadID));
CloseHandle(hThread);
}
void SGameAvatarEx::EndAvatarLoadingThread()
{
_oprint("**THREAD INFO : SGameAvatarEx::EndAvatarLoadingThread\n");
s_bStopThread = true;
while (s_bStopThread) Sleep(1);
}
void SGameAvatarEx::removeFromLoadingList()
{
THREAD_SYNCRONIZE(s_AvatarLoadingLock);
if (!m_bIsThreadPending) return;
std::list< SGameAvatarEx* >::iterator it;
for (it = s_lstThreadLoadingAvatar.begin(); it != s_lstThreadLoadingAvatar.end(); ++it)
{
if (*it == this)
{
s_lstThreadLoadingAvatar.erase(it);
return;
}
}
}
void SGameAvatarEx::addToLoadingList()
{
THREAD_SYNCRONIZE(s_AvatarLoadingLock);
#ifdef _DEBUG
std::list< SGameAvatarEx* >::iterator it;
for (it = s_lstThreadLoadingAvatar.begin(); it != s_lstThreadLoadingAvatar.end(); ++it)
{
if (*it == this)
{
assert(0);
return;
}
}
#endif
m_bIsThreadPending = true;
s_lstThreadLoadingAvatar.push_back(this);
}
void SGameAvatarEx::PendLoading()
{
if (m_bIsThreadPending) return;
if (m_bPendLoading) return;
addToLoadingList();
}
bool SGameAvatarEx::doLoading()
{
struct _FlagRemover
{
_FlagRemover(volatile bool* volatile f) : pFlag(f) {}
~_FlagRemover() { *pFlag = false; }
volatile bool* volatile pFlag;
};
struct _TrueRemover
{
_TrueRemover(volatile bool* volatile f) : pFlag(f) {}
~_TrueRemover() { *pFlag = true; }
volatile bool* volatile pFlag;
};
volatile _FlagRemover _remover0(&m_bIsThreadLoading);
volatile _FlagRemover _remover1(&m_bIsThreadPending);
const char* pFileName = GetCobFileName();
if (!pFileName)
{
return false;
}
std::string strName = pFileName;
if (strstr(strName.c_str(), ".cob") == NULL)
strName += ".cob";
m_strFileName = strName;
vec_cobset* coblist = COBManager::GetManager()->Load(strName.c_str());
if (coblist == NULL)
{
return false;
}
KSeqAvatarEx* pSeqAvatar = NULL;
unsigned char nObjType = GetInnObjType();
if (m_nFirst == 0)
{
if (nObjType != TS_ENTER::GAME_PLAYER &&
nObjType != TS_ENTER::GAME_NPC)
{
pSeqAvatar = LoadCob(coblist);
if (pSeqAvatar == NULL)
return false;
}
else
{
if (nObjType == TS_ENTER::GAME_PLAYER ||
nObjType == TS_ENTER::GAME_NPC ||
nObjType == TS_ENTER::GAME_MOB ||
nObjType == TS_ENTER::GAME_SUMMON ||
nObjType == TS_ENTER::GAME_PET) // sonador 10.2.1 팻 시스템 구현
{
iterator_cobset it = coblist->begin();
if (coblist->end() != it)
{
COBSET* pCob = *it;
LoadEvent(pCob);
//큐브 Load
for (int i(0); 6 > i; i++)
{
m_fSelcube[i] = pCob->fSelCube[i];
m_fDeadcube[i] = pCob->fDeadCube[i];
}
for (int i(0); i < 3; ++i)
{
if (m_fSelcube[i] > m_fSelcube[i + 3]) ::swap(m_fSelcube[i], m_fSelcube[i + 3]);
if (m_fDeadcube[i] > m_fDeadcube[i + 3]) ::swap(m_fDeadcube[i], m_fDeadcube[i + 3]);
}
m_fOriginalSelCubeHeight = m_fSelcube[5];
}
}
}
}
//TS_ENTER::GAME_PLAYER, TS_ENTER::GAME_NPC <- 이외 타입들은 WearList가 없으므로 밑으로 들어가면 안된다
if (!m_vWearList.empty())
{
if (nObjType == TS_ENTER::GAME_PLAYER)
{
if (IsRamadanPrayRoom())
{
MakeRamadanWearItemList();
LoadingCore(pSeqAvatar, nObjType, coblist, m_vWearList_ramadan);
}
else
LoadingCore(pSeqAvatar, nObjType, coblist, m_vWearList);
}
else
{
LoadingCore(pSeqAvatar, nObjType, coblist, m_vWearList);
}
m_vWearList.clear();
}
else
{
//WearList가 없고 npc라면 cob리스트에서 읽어 들이자
if (nObjType == TS_ENTER::GAME_NPC && pSeqAvatar == NULL)
{
pSeqAvatar = LoadCob(coblist);
if (pSeqAvatar == NULL)
return false;
}
else if (nObjType == TS_ENTER::GAME_PLAYER)
{
if (IsRamadanPrayRoom())
{
MakeRamadanWearItemList();
LoadingCore(pSeqAvatar, nObjType, coblist, m_vWearList_ramadan);
}
else
LoadingCore(pSeqAvatar, nObjType, coblist, m_vWearListForRefresh);
}
}
RefreshTextureGroup(coblist);
/// 2011.07.28 redmine #16797 - prodongi
if (m_nDisguise == STAT_DISGUISE)
{
if (GetInnObjType() == TS_ENTER::GAME_SUMMON && m_disguiseEnhance)
{
_RefreshTextureGroup(1, coblist);
EnableMTE(true);
}
}
if (m_nFirst == 0)
{
Activate();
InterlockedIncrement((volatile LONG*)&m_nFirst);
}
volatile _TrueRemover _trueremover(&m_bIsInit);
return true;
}
void SGameAvatarEx::LoadingCore(class KSeqAvatarEx* pSeqAvatar, int nObjType, vec_cobset* pCobList, std::vector< WEAR_DATA >& wearList)
{
if (wearList.size() == 0 || pCobList == NULL)
return;
SAFE_DELETE(pSeqAvatar);
pSeqAvatar = new KSeqAvatarEx;
pSeqAvatar->Initialize();
pSeqAvatar->ClearAnimation();
if (nObjType == TS_ENTER::GAME_PLAYER)
{
if (m_bIsReloadWearListFileName)
{
ReloadWearListFileName(wearList);
SetReloadWearListFileName(false);
}
//TODO : COB 데이타 적용 해야 함.
iterator_cobset it = pCobList->begin();
if (pCobList->end() != it)
{
COBSET* pCob = *it;
//이펙트 Pos List
std::string strEffPosName;
int index = 0;
for (unsigned int i(0); pCob->m_EffPosList.size() > i; i++)
{
index = pCob->m_EffPosList[i].dwIndex;
strEffPosName = pCob->m_EffPosList[i].strName;
pSeqAvatar->AddEffectPos(ANIPART_BIPED, index, strEffPosName.c_str());
}
}
}
//얼굴, 헤어 재로딩
if (m_pProperty)
{
// 2010.04.22 - prodongi
doLoadingHair(pSeqAvatar);
std::string strFace = GetDefaultItemDB().GetFileName(GetRace(), GetSex(), GetFace());
std::string strDeco;
getDecoTexName(strDeco);
pSeqAvatar->AddMesh(ANIPART_BIPED, MPART_FACE, strFace.c_str(), strDeco);
}
RefreshItemWearEx(pSeqAvatar, wearList);
pSeqAvatar->SetSkinDiffuse(m_SkinDiffuse);
LoadUseAnimation(pSeqAvatar);
SAFE_DELETE(m_pThreadAvatarEx); //쓰레드 끝나고 바로 들어 왔을 경우
m_pThreadAvatarEx = pSeqAvatar;
InterlockedIncrement((volatile LONG*)&m_nIsRefreshAni);
}
KSeqAvatarEx* SGameAvatarEx::LoadCob(vec_cobset* pCobList)
{
KSeqAvatarEx* pSeqAvatar = LoadCOBSet(pCobList);
if (!pSeqAvatar)
{
return NULL;
}
//모션 블랜딩 넣는다.
if (GetDefaultAnimation() != ANI_DEAD01)
{
if (!IsMoving())
{
if (m_nNewCurAniType == ANI_RUN) m_nNewCurAniType = ANI_DEFAULT01;
else if (m_nNewCurAniType == ANI_M_RUN_HIGH) m_nNewCurAniType = ANI_M_DEFAULT01_HIGH;
else if (m_nNewCurAniType == ANI_M_RUN_LOW) m_nNewCurAniType = ANI_M_DEFAULT01_LOW;
else if (m_nNewCurAniType == ANI_M_RUN_QILIN) m_nNewCurAniType = ANI_M_DEFAULT01_QILIN; // sonador #2.1.6
else if (m_nNewCurAniType == ANI_M_RUN_WHITE) m_nNewCurAniType = ANI_M_DEFAULT01_WHITE; // #2.1.14
else if (m_nNewCurAniType == ANI_M_RUN_UNICORN)m_nNewCurAniType = ANI_M_DEFAULT01_UNICORN; // #2.1.14
else if (m_nNewCurAniType == ANI_M_RUN_BEAKHO) m_nNewCurAniType = ANI_M_DEFAULT01_BEAKHO; /// 2011.02.08 - prodongi
}
if (IsLoopMotion(m_nNewCurAniType))
ThreadNPlayAnimation(pSeqAvatar, m_nNewCurAniType, m_nCurPlayType);
else
ThreadNPlayAnimation(pSeqAvatar, m_nNewCurAniType, SEQTYPE_NORMAL);
}
else
{
ThreadNPlayAnimation(pSeqAvatar, GetDefaultAnimation());
SetEventHandleNull();
}
pSeqAvatar->SetDeform(ANIPART_BIPED);
pSeqAvatar->SetAttach(ANIPART_BIPED);
unsigned char nObjType = GetInnObjType();
if (nObjType == TS_ENTER::GAME_PLAYER ||
nObjType == TS_ENTER::GAME_NPC ||
nObjType == TS_ENTER::GAME_MOB ||
nObjType == TS_ENTER::GAME_SUMMON ||
nObjType == TS_ENTER::GAME_PET)
{
//TODO : COB 데이타 적용 해야 함.
iterator_cobset it = pCobList->begin();
if (pCobList->end() != it)
{
COBSET* pCob = *it;
//이펙트 Pos List
std::string strEffPosName;
int index = 0;
for (unsigned int i(0); pCob->m_EffPosList.size() > i; i++)
{
index = pCob->m_EffPosList[i].dwIndex;
strEffPosName = pCob->m_EffPosList[i].strName;
pSeqAvatar->AddEffectPos(ANIPART_BIPED, index, strEffPosName.c_str());
}
//큐브 Load
for (int i(0); 6 > i; i++)
{
m_fSelcube[i] = pCob->fSelCube[i];
m_fDeadcube[i] = pCob->fDeadCube[i];
}
for (int i(0); i < 3; ++i)
{
if (m_fSelcube[i] > m_fSelcube[i + 3]) ::swap(m_fSelcube[i], m_fSelcube[i + 3]);
if (m_fDeadcube[i] > m_fDeadcube[i + 3]) ::swap(m_fDeadcube[i], m_fDeadcube[i + 3]);
}
m_fOriginalSelCubeHeight = m_fSelcube[5];
}
RefreshEffectPos(pSeqAvatar);
m_pSeqAvatar = pSeqAvatar;
//NPC Wear가 없는 것이 생기면, 아래 호출 되야 함
// if( GetInnObjType() == TS_ENTER::GAME_NPC )
// RefreshSkinColorized();
}
return pSeqAvatar;
}
void SGameAvatarEx::_RefreshTextureGroup(int texture_group_index, vec_cobset* pCobSet)
{
if (pCobSet == NULL || m_pSeqAvatar == NULL || pCobSet->empty() || texture_group_index == -1)
return;
_CID(CHANGE_MESH_TEXTURE);
KMsgCHANGE_MESH_TEXTURE msg;
iterator_cobset itCobSet = pCobSet->begin();
for (; itCobSet != pCobSet->end(); ++itCobSet)
{
for (int nMPart = 0; nMPart < MPART_MAX; ++nMPart)
{
std::vector< TEXTURE_GROUP_LIST* >::iterator itTextureGroup = (*itCobSet)->m_TextureGroupList[nMPart].begin();
for (; itTextureGroup != (*itCobSet)->m_TextureGroupList[nMPart].end(); ++itTextureGroup)
{
std::vector< TEXTURE_GROUP_LIST::Seq_list* >::iterator itSeqList = (*itTextureGroup)->vSeqList.begin();
for (; itSeqList != (*itTextureGroup)->vSeqList.end(); ++itSeqList)
{
msg.szMeshName = (*itSeqList)->strSeqName.c_str();
std::vector< std::string >::iterator itStr = (*itSeqList)->vTextureIndex[texture_group_index].begin();
while (itStr != (*itSeqList)->vTextureIndex[texture_group_index].end())
{
msg.vTextureList.push_back((*itStr).c_str());
++itStr;
}
if (msg.vTextureList.empty() == false)
{
m_pSeqAvatar->Perform((*itCobSet)->nAniPart, id_CHANGE_MESH_TEXTURE, msg);
msg.vTextureList.clear();
}
}
}
}
}
}
void SGameAvatarEx::refreshWinkByOption()
{
if (m_pSeqAvatar) refreshWink(m_pSeqAvatar);
}
void SGameAvatarEx::refreshWink(KSeqAvatarEx* pSeqAvatar)
{
if (GetInnObjType() != TS_ENTER::GAME_PLAYER)
return;
if (pSeqAvatar == NULL) return;
}
void SGameAvatarEx::SetLastWeaponSwapTime(AR_TIME NewTime) // Fraun weapon swap exploit fix 8/19/2025
{
LastWeaponSwapTime = NewTime;
}
void SGameAvatarEx::MakeRamadanWearItemList()
{
m_vWearList_ramadan.clear();
// 라마단 복장 아이템 코드
int itemCode[ItemBase::MAX_ITEM_SPARE_WEAR] =
{
0, 0,
RAMADAN_ITEM_ARMOR,
RAMADAN_ITEM_HAT,
RAMADAN_ITEM_GLOVE,
RAMADAN_ITEM_BOOTS,
};
int itemWearType[ItemBase::MAX_ITEM_SPARE_WEAR] =
{
0, 0,
ItemBase::WEAR_DECO_ARMOR,
ItemBase::WEAR_DECO_HELM,
ItemBase::WEAR_DECO_GLOVE,
ItemBase::WEAR_DECO_BOOTS,
};
ClearThreadLoadWear(); //쌓여 있는 것을 지운다.
int nRace = GetRace(); // 종족
int nSex = GetSex(); // 성별
for (int x = 0; x < ItemBase::MAX_ITEM_SPARE_WEAR; x++)
{
SGameAvatarEx::WEAR_DATA weardata;
// 종족, 성별, 아이템 코드로 해당 아이템 파일 이름을 얻는다
if (itemCode[x] != 0)
{
weardata.strFileName = GetItemDB().GetFileName(nRace, nSex, itemCode[x], 0); // GetDefaultItemDB()
weardata.strFileName += ".nx3";
}
else
weardata.strFileName = "_NoItem_"; // 아이템 코드가 없으면 "_NoItem_" 으로 파일 이름 설정
weardata.nItemClass = GetItemDB().GetClassID(itemCode[x]);
weardata.nItemCode = itemCode[x];
weardata.nItemLevel = 1;
weardata.nItemEnhanceLevel = 0;
weardata.nWearType = x;
m_vWearList_ramadan.push_back(weardata); // 쓰레드로 메쉬 로딩할 리스트에 내용 추가
}
}
bool SGameAvatarEx::IsThreadLoading()
{
if (m_bIsThreadLoading || IsThreadPendLoading())
return true;
return false;
}
bool SGameAvatarEx::IsLoadComplete()
{
if (IsThreadLoading())
return false;
return m_bIsInit;
}
//#define _NO_AVATAR_THREAD_
bool SGameAvatarEx::Initialize(class K3DRenderDeviceDX* pDevice)
{
if (IsLocalPlayer())
m_vNextPos = GetCurPosWithChangeDir();
//int nSizeCnt = sizeof( ani_test )/sizeof(int);
//for( int i=0; nSizeCnt>i; i++ )
//{
// for( int n(0); ANICLS_MAX>n; n++ )
// {
// const char * pAni = GetMotionSetDB().GetAni( GetInnObjType(), ani_test[i], GetRace(), GetSex(), n );
// std::string strAniKey;
// CStringUtil::GetStrKey( pAni, '_', strAniKey );
// _oprint( "ANI_NAME : %s\n", strAniKey.c_str() );
// }
//}
return true;
}
void SGameAvatarEx::DeleteEvent(KSVEC_KEVENT_RES& svEventList)
{
_KEY_EVENT_RES* pData;
bool res;
res = svEventList.get_first_value(pData);
while (res)
{
if (pData != NULL)
{
delete pData;
}
res = svEventList.get_next_value(pData);
}
svEventList.clear();
//KSVEC_KEVENT_RES::iterator it = svEventList.begin();
//while ( it != svEventList.end() )
//{
// delete (*it);
// ++it;
//}
//svEventList.clear();
}
void SGameAvatarEx::Destroy()
{
SAFE_DELETE(m_pProperty);
//캐스팅 Effect 삭제~
if (!m_vCastEffect.empty())
{
for (unsigned int i(0); m_vCastEffect.size() > i; i++)
DelEffect(m_vCastEffect[i]);
m_vCastEffect.clear();
}
SAFE_DELETE(m_pThreadAvatarEx);
SAFE_DELETE(m_pSeqAvatar);
SAFE_DELETE(m_pStateVM);
SAFE_DELETE(m_pDisguiseStack); // 2.1.16 변신 효과 중첩시 아바타 사라지는 오류 수정
// SAFE_DELETE( m_pDisguiseSeqAvatar );
SetEventHandleNull();
DeleteEvent(m_svEventHandle00_effectList);
DeleteEvent(m_svEventHandle00_soundList);
DeleteEvent(m_svEventHandle00_motion_effect);
DeleteEvent(m_svEventHandle01_List);
DeleteEvent(m_svEventHandle02_List);
DeleteEvent(m_svEventHandle03_List);
DeleteEvent(m_svEventHandle04_List);
DeleteEvent(m_svEventHandle05_List);
DeleteEvent(m_svEventHandle06_List);
for (unsigned int i(0); m_vAttackEventList.size() > i; i++)
{
delete m_vAttackEventList[i];
}
m_vAttackEventList.erase(m_vAttackEventList.begin(), m_vAttackEventList.end());
for (unsigned int i(0); m_vSkillEventList.size() > i; i++)
{
delete m_vSkillEventList[i];
}
m_vSkillEventList.erase(m_vSkillEventList.begin(), m_vSkillEventList.end());
for (unsigned int i(0); m_vCastSkillList.size() > i; i++) //스킬 Cast 연출
{
delete m_vCastSkillList[i];
}
m_vCastSkillList.erase(m_vCastSkillList.begin(), m_vCastSkillList.end());
for (unsigned int i(0); m_vFireSkillList.size() > i; i++) //스킬 Fire 연출
{
delete m_vFireSkillList[i];
}
m_vFireSkillList.erase(m_vFireSkillList.begin(), m_vFireSkillList.end());
clearAllState();
SAFE_DELETE(m_pUISyncData);
SAFE_DELETE(m_pBoneRecorder);
SAFE_DELETE(m_pWeaponTrailRight);
SAFE_DELETE(m_pWeaponTrailLeft);
m_bUseRightWeaponTrail = false;
m_bUseLeftWeaponTrail = false;
//SAFE_DELETE(m_pWeaponPowerupRight);
//SAFE_DELETE(m_pWeaponPowerupLeft);
//m_nUpdatePowerupRight=UPDATE_NONE;
//m_nUpdatePowerupLeft=UPDATE_NONE;
//m_bUpdatePowerupSwitch=false;
SAFE_DELETE(m_pAddOnMgr);
SAFE_DELETE(m_pTerrainDegree);
//스킬 용
SAFE_DELETE(m_pRightSwordSlashForSkill);
SAFE_DELETE(m_pLeftSwordSlashForSkill);
std::vector<class SGameWork*>::iterator itWorkList = m_vWorkList.begin();
while (itWorkList != m_vWorkList.end())
{
(*itWorkList)->SetOwner(NULL);
++itWorkList;
}
}
bool SGameAvatarEx::Activate()
{
m_bIsActivated = true;
SetWeaponEnhanceFx(m_nTwoHandWeaponCode, m_bIsActivated);
SetWeaponEnhanceFx(m_nRightHandWeaponCode, m_bIsActivated);
SetWeaponEnhanceFx(m_nLeftHandWeaponCode, m_bIsActivated);
return m_bIsActivated;
}
bool SGameAvatarEx::Deactivate()
{
m_bIsActivated = false;
SetWeaponEnhanceFx(m_nTwoHandWeaponCode, m_bIsActivated);
SetWeaponEnhanceFx(m_nRightHandWeaponCode, m_bIsActivated);
SetWeaponEnhanceFx(m_nLeftHandWeaponCode, m_bIsActivated);
return true;
}
void SGameAvatarEx::ActivateFxSwordSlash()
{
if (m_pBoneRecorder == NULL)
{
m_pBoneRecorder = new BoneRecorder(this, WEAPON_SLASH_RECORD_SUBDIVISION); // 무기 궤적용 포지션 저장 obj
m_bUseRightWeaponTrail = false; // 오른손 무기 궤적 사용?
m_bUseLeftWeaponTrail = false; // 왼손 무기 궤적 사용?
}
if (m_pWeaponTrailRight == NULL)
m_pWeaponTrailRight = new SGameFxSwordSlash(true); // 오른손 무기 궤적 object
if (m_pWeaponTrailLeft == NULL)
m_pWeaponTrailLeft = new SGameFxSwordSlash(false); // 왼손 무기 궤적 object
}
//LeaveMsg가 오면 초기화 해줘야 할것들
void SGameAvatarEx::LeaveData()
{
UnArmed(m_nLeftHandWeaponCode);
UnArmed(m_nRightHandWeaponCode);
UnArmed(m_nTwoHandWeaponCode);
for (int x = 0; x < EFFECT_POS_WEAPON_MAX; ++x)
ResetWeaponEVPMatrix(x);
SetRiderCreatureInfo();
clearAllState();
if (m_pStateVM)
{
m_pStateVM->ClearInfo();
}
}
void SGameAvatarEx::ReInitialize()
{
m_nProcess_state = -1;
m_nAniClass = 0;
m_bLockAni = false;
m_bLockAttackAni = false;
m_dwTime = 0;
m_dwStartTime = 0;
m_fVisibility = 0.0f;
m_speed = DEF_SPEED;
m_vCheckPos = K3DVector(0.0f, 0.0f, 0.0f);
m_bIng = false;
m_bReservation = false;
m_bVisible = true;
m_bPrevVisible = true;
m_bIsMovingDetour = false;
m_bIsChasing = false;
m_unDetourStep = 0;
m_bRefreshDetour = false;
m_CurrState = SObjectState::ID::STATE_NONE;
m_CurrTarget = 0;
m_nWeaponSwing_RepeatMotion = 0;
m_bIsDead = false;
m_nAttackIndex = 0;
m_bPlayOverride = false;
m_bRefreshInven = false;
m_cPrevAttackIndex = 0;
m_nSwordSlashForSkillMotion = 0;
m_nStateFlag = FLAG_STATE_NONE;
m_fHidingVisiblity = 1.0f;
m_fHidingDetectRange = 0.0f;
m_vTargetPos = K3DVector(0.0f, 0.0f, 0.0f);
m_nTraceIdx = 0;
m_SkinDiffuse = KColor(0, 0, 0, 0);
m_nNewCurAniType = ANI_DEFAULT01;
m_nCurPlayType = SEQTYPE_LOOP;
}
bool SGameAvatarEx::IsInit()
{
//로딩이 끝났다면 m_bIsInit == true
return m_bIsInit;
}
void SGameAvatarEx::SetShadowRenderFlag(BOOL bShadowRenderFlag)
{
if (bShadowRenderFlag)
m_xRenderFlag.On(AV_SHADOW);
else
m_xRenderFlag.Off(AV_SHADOW);
}
void SGameAvatarEx::SetVisibility(float fVisibility)
{
if (m_nStateFlag & FLAG_STATE_HIDING)
{
return;
}
if (m_pSeqAvatar) m_pSeqAvatar->SetVisibility(fVisibility);
m_fVisibility = fVisibility;
}
void SGameAvatarEx::SetHidingVisiblity(float fVisibility)
{
if (m_fHidingVisiblity != fVisibility)
{
if (m_pSeqAvatar) m_pSeqAvatar->SetVisibility(fVisibility);
m_fHidingVisiblity = fVisibility;
// '옵션 - 그림자 - 단순히' 로 적용하면 이 함수가 호출된다. Hiding인 경우 CircleShadow를 생성하지 않도록 막는다. bintitle. 2011.11.08
//if( (GetVisibility() <= 0.0f) || (GetHidingVisiblity() <= 0.0f) )
if (m_fHidingVisiblity <= 0.0f)
{
// Avatar를 숨기는 경우, CircleShadow도 숨겨야 한다.
if (m_pAddOnMgr->IsActivateAddOn(SGameAvatarAddOnMgr::SGAME_CIRCLE_SHADOW_FX))
{
DeActivateCircleShadow();
}
}
else
{
// '옵션 - 그림자 - 단순히' 의 경우 CircleShadow를 추가. bintitle. 2011.11.08
if (GetGameOption().GetLowShadow())
ActivateCircleShadow();
}
}
}
void SGameAvatarEx::SetVisible(bool bVisible)
{
m_bVisible = bVisible;
if (GetInnObjType() == TS_ENTER::GAME_PLAYER)
{
bool bNewVisible = (m_xRenderFlag.IsOn(AV_BASIC) && m_bVisible);
if (m_bPrevVisible != bNewVisible)
{
SetWeaponEnhanceFx(m_nTwoHandWeaponCode, bNewVisible);
SetWeaponEnhanceFx(m_nRightHandWeaponCode, bNewVisible);
SetWeaponEnhanceFx(m_nLeftHandWeaponCode, bNewVisible);
m_bPrevVisible = bNewVisible;
}
}
}
void SGameAvatarEx::_checkPetrify()
{
if (m_nStateFlag & FLAG_STATE_PETRIFY)
{
KMsgSET_FIXTEXTURE msgFixTexture;
msgFixTexture.bUseFix = true;
msgFixTexture.pTexture = _getTexture("petrify00.dds");
SetFixTexture(&msgFixTexture);
}
else
{
KMsgSET_FIXTEXTURE msgFixTexture;
msgFixTexture.bUseFix = false;
SetFixTexture(&msgFixTexture);
}
/* bool bFind = false;
int nSize = (int)m_vStateList.size();
for( int i(0); nSize>i; i++ )
{
SMSG_STATE * pState = m_vStateList[i];
if( pState->state_code == 6012 )//석화 처리
{
if( pState->state_level )
{
bFind = true;
KMsgSET_FIXTEXTURE msgFixTexture;
msgFixTexture.bUseFix = true;
msgFixTexture.pTexture = _getTexture( "petrify00.dds" );
SetFixTexture( &msgFixTexture );
}
}
}
if( !bFind )
{
KMsgSET_FIXTEXTURE msgFixTexture;
msgFixTexture.bUseFix = false;
SetFixTexture( &msgFixTexture );
}*/
}
void SGameAvatarEx::_renderThread()
{
if (GetInnObjType() == TS_ENTER::GAME_MOB || GetInnObjType() == TS_ENTER::GAME_SUMMON || GetInnObjType() == TS_ENTER::GAME_PET)
{
if (!IsThreadLoading() && m_bIsActivated && !m_pAddOnMgr->IsActivateAddOn(SGameAvatarAddOnMgr::SGAME_AVATAR_FX))
{
ModelEffectResourceGame* pModelEffectRes = NULL;
if (GetInnObjType() == TS_ENTER::GAME_SUMMON)
{
SetMotionBlend(true);
_SUMMON_INFO_FILE* pSummon = GetCreatureDB().GetCreatureData(GetInnContentID());
if (pSummon) pModelEffectRes = GetModelEffectResourceDB().GetModelEffectResource(pSummon->model_id);
}
else if (GetInnObjType() == TS_ENTER::GAME_MOB)
{
_MONSTER_INFO_FILE* pMonster = GetMonsterDB().GetMonsterData(GetInnContentID());
if (pMonster) pModelEffectRes = GetModelEffectResourceDB().GetModelEffectResource(pMonster->monster_group);
}
else if (GetInnObjType() == TS_ENTER::GAME_PET)
{
pModelEffectRes = GetModelEffectResourceDB().GetModelEffectResource(GetPetDB().Find(GetInnContentID()).getMotionFileID());
}
if (pModelEffectRes)
{
std::string strEffectName = GetResourceDB().GetEffectResourceName(pModelEffectRes->effect_file_ID);
if (!strEffectName.empty())
{
SGameAvatarFx* pAvatarFx = (SGameAvatarFx*)m_pAddOnMgr->GetAddOn(SGameAvatarAddOnMgr::SGAME_AVATAR_FX);
if (pAvatarFx == NULL)
{
pAvatarFx = new SGameAvatarFx;
pAvatarFx->SetModelEffectRes(pModelEffectRes);
m_pAddOnMgr->AddAddOn(pAvatarFx);
}
}
}
CheckStateSkill();
}
}
else
{
if (!IsThreadLoading() && m_nIsRefreshAni && m_pThreadAvatarEx)
{
m_nAniClass = m_nThreadAniClass;
m_bUseRightWeaponTrail = m_bThreadUseRightWeaponTrail;
m_bUseLeftWeaponTrail = m_bThreadUseLeftWeaponTrail;
m_bActLeftWeaponTrail = false; //초기화
m_bActRightWeaponTrail = false;
SetVisibleWeaponTrail(false);
//쓰레드 로딩 적용
RefreshAni();
//강화 이펙트 로딩
if (m_pSeqAvatar)
{
for (int x = 0; x < EFFECT_POS_WEAPON_MAX; ++x)
{
if (m_WeaponEnhanceFx[x].weardatainfo)
LoadEnhanceEffect(m_pSeqAvatar, &m_WeaponEnhanceFx[x], x);
}
}
// sonador 7.0.16 Mantis 0002790: [모션] 아바타가 활을 착용하고 오르니토를 탔을 때 모션 문제
//if( IsMountMode() )
// HideWeapon( FALSE );
CheckStateSkill();
//초기화
InterlockedDecrement((volatile LONG*)&m_nIsRefreshAni);
// 무기 파워업 FX 업데이트 스위치 ON
//m_bUpdatePowerupSwitch=true;
//NOTE : _renderEffectLoading()전에 하면 VertexBuffer가 제대로 세팅되지 않는다!
// -> renderEtc()로 이동
}
}
if (IsStateRide())
AvatarRotationByCreature();
}
void SGameAvatarEx::_renderAvatar(unsigned long uRenderBitVector, class KViewportObject** ppViewportList, int nViewportCount)
{
if (m_pSeqAvatar)
{
// for(int i = 0; i < nViewportCount; ++i)
{
if (nViewportCount >= 1 && ppViewportList[0] && ppViewportList[0]->GetAttributes() & KViewportObject::VIEWPORT_GAME) {
m_pSeqAvatar->SetTransform(*GetTransform());
m_pSeqAvatar->Render(ppViewportList[0]);
}
if (nViewportCount >= 3 && ppViewportList[2] && ppViewportList[2]->GetAttributes() & KViewportObject::VIEWPORT_WATER) {
m_pSeqAvatar->SetTransform(*GetTransform());
m_pSeqAvatar->Render(ppViewportList[2]);
}
if (nViewportCount >= 2 && ppViewportList[1] && ppViewportList[1]->GetAttributes() & KViewportObject::VIEWPORT_SHADOW)
{
if (m_xRenderFlag.IsOn(AV_SHADOW))
{
DWORD renderFlag = MAKELONG(KRenderObject::RENDEREFX_SHADOW, SHADOW_DY_CAST);
m_pSeqAvatar->Render(ppViewportList[1], renderFlag); //등록
}
}
}
}
}
void SGameAvatarEx::_renderEffectLoading()
{
if (!IsThreadLoading())
{
for (int x = 0; x < EFFECT_POS_MAX; ++x)
{
if (m_bEVPAttachMatrix[x])
{
if (x == EFFECT_POS_TOP || x == EFFECT_POS_MIDDLE) //위치 만 사용
{
K3DMatrixIdentity(m_matEVPAttachMatrix[x]);
m_matEVPAttachMatrix[x]._41 = m_pEvpSequencer[x]->GetAttachTransform()->_41;
m_matEVPAttachMatrix[x]._42 = m_pEvpSequencer[x]->GetAttachTransform()->_42;
m_matEVPAttachMatrix[x]._43 = m_pEvpSequencer[x]->GetAttachTransform()->_43;
}
else
m_matEVPAttachMatrix[x] = *m_pEvpSequencer[x]->GetAttachTransform();
}
}
for (int x = 0; x < EFFECT_POS_WEAPON_MAX; ++x)
{
if (m_bWeaponEVPMatrix[x] && m_WeaponEnhanceFx[x].weardatainfo)
{
for (int i = 0; i < EFFECT_POS_WEAPON_EP_MAX; ++i)
{
m_matWeaponEVPAttachMatrix[x][i] = *m_pWeaponEvpSequencer[x][i]->GetAttachTransform();
m_matWeaponEVPParentMatrix[x][i] = *m_pWeaponEvpSequencer[x][i]->GetParentTransform();
}
}
//로딩 안된것이 있는 지 검사
else if (m_WeaponEnhanceFx[x].weardatainfo)
{
LoadEnhanceEffect(m_pSeqAvatar, &m_WeaponEnhanceFx[x], x);
}
}
}
}
void SGameAvatarEx::SetVisibleWeaponTrail(bool bVisible)
{
if (m_bUseRightWeaponTrail && m_pWeaponTrailRight != NULL) {
m_pWeaponTrailRight->runTrail(bVisible);
}
if (m_bUseLeftWeaponTrail && m_pWeaponTrailLeft != NULL) {
m_pWeaponTrailLeft->runTrail(bVisible);
}
}
void SGameAvatarEx::_renderEtc(unsigned long uRenderBitVector, class KViewportObject** ppViewportList, int nViewportCount)
{
#ifdef _WEAPON_FX_
//-- 검광 렌더링
// if ( IsLocalPlayer() )
if (GetInnObjType() == TS_ENTER::GAME_PLAYER)
{ // 현재 player자신것만 렌더링!!!!!!!!!!!
// 오른손 무기 검광
if (m_bActRightWeaponTrail && m_bUseRightWeaponTrail && m_pWeaponTrailRight != NULL && m_pWeaponTrailRight->IsRunTrail()) {
//if (IsAttacking()) {
// // 검광 on
// m_pWeaponTrailRight->runTrail(true);
//} else {
// // 검광 off (이미 있는 검광은 부드럽게 사라짐)
// m_pWeaponTrailRight->runTrail(false);
//}
K3DMatrix* ArrowMatrix = m_pBoneRecorder->matrix_right;
if (m_bBowClass)
{
ArrowMatrix->SetPosVector(m_vArrowPos);
//ArrowMatrix = &m_ArrowMatrix;
//*m_pBoneRecorder->matrix_left = m_ArrowMatrix;
if (m_bArrowTrail)
{
m_pWeaponTrailRight->addTrails(WEAPON_SLASH_RECORD_ARROW_SUBDIVISION
, m_pBoneRecorder->starttime, m_pBoneRecorder->endtime
, ArrowMatrix, m_bBowClass, m_fTargetRoll
);
m_pWeaponTrailRight->Render(ppViewportList[0]);
}
}
else
{
// 검광 노드 좌표 업데이트
m_pWeaponTrailRight->addTrails(WEAPON_SLASH_RECORD_SUBDIVISION // 애니메이션 프레임간 검광 분할 수. 숫자가 크면 폴리곤이 많아져서 곡선이 부드러워짐
, m_pBoneRecorder->starttime, m_pBoneRecorder->endtime // 분할 시작시간 / 끝시간
//, m_pBoneRecorder->matrix_right // recording된 좌표/방향 매트릭스
, ArrowMatrix
);
m_pWeaponTrailRight->Render(ppViewportList[0]);
}
}
// 왼손 무기 검광
if (m_bActLeftWeaponTrail && m_bUseLeftWeaponTrail && m_pWeaponTrailLeft != NULL && m_pWeaponTrailLeft->IsRunTrail()) {
//if (IsAttacking()) {
// // 검광 on
// m_pWeaponTrailLeft->runTrail(true);
//} else {
// // 검광 off (이미 있는 검광은 부드럽게 사라짐)
// m_pWeaponTrailLeft->runTrail(false);
//}
K3DMatrix* ArrowMatrix = m_pBoneRecorder->matrix_left;
if (m_bBowClass)
{
ArrowMatrix->SetPosVector(m_vArrowPos);
//ArrowMatrix = &m_ArrowMatrix;
//*m_pBoneRecorder->matrix_left = m_ArrowMatrix;
if (m_bArrowTrail)
{
m_pWeaponTrailLeft->addTrails(WEAPON_SLASH_RECORD_ARROW_SUBDIVISION
, m_pBoneRecorder->starttime, m_pBoneRecorder->endtime
, ArrowMatrix
, m_bBowClass
, m_fTargetRoll
);
m_pWeaponTrailLeft->Render(ppViewportList[0]);
}
}
else
{
// 검광 노드 좌표 업데이트
m_pWeaponTrailLeft->addTrails(WEAPON_SLASH_RECORD_SUBDIVISION, m_pBoneRecorder->starttime, m_pBoneRecorder->endtime, m_pBoneRecorder->matrix_left);
m_pWeaponTrailLeft->Render(ppViewportList[0]);
}
}
if (m_bActRightSwordSlashForSkill && m_pRightSwordSlashForSkill)
{
if (m_pRightSwordSlashForSkill->IsRunTrail())
{
m_pRightSwordSlashForSkill->addTrails(WEAPON_SLASH_RECORD_SUBDIVISION
, m_pBoneRecorder->starttime
, m_pBoneRecorder->endtime
, m_pBoneRecorder->matrix_right);
}
m_pRightSwordSlashForSkill->Render(ppViewportList[0]);
}
if (m_bActLeftSwordSlashForSkill && m_pLeftSwordSlashForSkill)
{
if (m_pLeftSwordSlashForSkill->IsRunTrail())
{
m_pLeftSwordSlashForSkill->addTrails(WEAPON_SLASH_RECORD_SUBDIVISION
, m_pBoneRecorder->starttime
, m_pBoneRecorder->endtime
, m_pBoneRecorder->matrix_left);
}
m_pLeftSwordSlashForSkill->Render(ppViewportList[0]);
}
}
// //-- 무기 강화 이펙트 렌더링
// if (m_pWeaponPowerupRight!=NULL || m_pWeaponPowerupLeft!=NULL) {
// // 필요하면 mesh를 다시 build
// processWeaponPowerupMeshRebuild();
//
// try {
// // Bone의 final좌표를 가져와서 또 bone이랑 blending한다 (뭔소린지 모르겠지만 이렇게 하니까 동작한다 -_-)
// KSeqAvatarEx *seqAvatar=GetSeqForm();
// if (seqAvatar==NULL) throw 0;
//
// KSeqAvatar *bipedSeq=seqAvatar->getAvatarPart(ANIPART_BIPED); // biped animation part
// if (bipedSeq==NULL) throw 0;
//
// //KBoneSeqObject* pBoneSeq=bipedSeq->getBoneSequencer(); // biped bone
// //if (pBoneSeq==NULL) throw 0;
//
// if (m_pWeaponPowerupRight!=NULL) { // && m_nUpdatePowerupRight==UPDATE_NONE) { <- update안 할때만 렌더링... 필요 없음
// KBoneSeqObject* boneSeqRightWeapon=NULL; // 무기의 animation bone
// KSeqAvatar *rightHandSeq=seqAvatar->getAvatarPart(ANIPART_WEAPON_RIGHT); // 오른손 무기가 붙을 위치
// KSequencer *sequencer=dynamic_cast<KSequencer*>(rightHandSeq->GetCurrentAnimation());
// if (sequencer!=NULL) {
// boneSeqRightWeapon=dynamic_cast<KBoneSeqObject*> (sequencer->GetSeqObject(0));
// }
//
// if (boneSeqRightWeapon!=NULL) {
// // SMorphedMesh::SetBlendMode(K3DMaterial::MBM_ALPHATEX_EDGEENHANCE_BLEND), SetWeight(NULL)용
// m_pWeaponPowerupRight->SetParentTransform(rightHandSeq->GetParentTransform(), rightHandSeq->GetAttachTransform());
//
///* // TEST for K3DMaterial::MBM_ALPHATEX_EDGEENHANCE, but not working
// K3DMatrix *pWeaponPosMat, *pBoneMat;
// K3DMatrix tempMat, resultMat;
// pWeaponPosMat=&(boneSeqRightWeapon->GetBoneCacheTM()[1]);
// pBoneMat=pBoneSeq->GetBoneMatrix(DETAIL_RIGHT_HAND);
// K3DMatrixMultiply( &tempMat, pBoneMat, &(seqAvatar->GetTransform()));
// K3DMatrixMultiply( &resultMat, pWeaponPosMat, &tempMat);
//
// m_pWeaponPowerupRight->SetParentTransform(NULL);
// m_pWeaponPowerupRight->SetTransform(resultMat);
//*/
//
// m_pWeaponPowerupRight->Render(ppViewportList[0]);
// }
// }
//
// if (m_pWeaponPowerupLeft!=NULL) { // && m_nUpdatePowerupLeft==UPDATE_NONE) {
// KBoneSeqObject* boneSeqLeftWeapon=NULL;
// KSeqAvatar *leftHandSeq=seqAvatar->getAvatarPart(ANIPART_WEAPON_LEFT); // 왼손 무기가 붙을 위치
// KSequencer *sequencer=dynamic_cast<KSequencer*>(leftHandSeq->GetCurrentAnimation());
// if (sequencer!=NULL) {
// boneSeqLeftWeapon=dynamic_cast<KBoneSeqObject*> (sequencer->GetSeqObject(0));
// }
// if (boneSeqLeftWeapon!=NULL) {
// m_pWeaponPowerupLeft->SetParentTransform(leftHandSeq->GetParentTransform(), leftHandSeq->GetAttachTransform());
// m_pWeaponPowerupLeft->Render(ppViewportList[0]);
// }
// }
//
//
// } catch (int) {
// // empty
// }
// }
#endif
m_pAddOnMgr->Render(ppViewportList, nViewportCount);
if (m_sCubeRender)
{
if (IsLive())
sel_normal_cube = K3DBoundRotCube(m_fSelcube[0], m_fSelcube[3], m_fSelcube[1], m_fSelcube[4], m_fSelcube[2], m_fSelcube[5]);
else
sel_normal_cube = K3DBoundRotCube(m_fDeadcube[0], m_fDeadcube[3], m_fDeadcube[1], m_fDeadcube[4], m_fDeadcube[2], m_fDeadcube[5]);
sel_normal_cube.SetTransform(*GetTransform());
sel_normal_cube.Render(ppViewportList[0]);
}
// if( m_pSeqAvatar ) m_pSeqAvatar->GetBoundCube()->Render( viewport );
}
bool SGameAvatarEx::Render(unsigned long uRenderBitVector, class KViewportObject** ppViewportList, int nViewportCount)
{
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 거대화 처리
/// 2011.04.20 하위 클래스에서도 쓰기 위해서 함수로 뺐습니다. - prodongi
float scale;
K3DMatrix mat;
beginScaling(scale, mat);
/*
std::vector<SStateSlot*> PositiveList = GetPositiveStateList();
m_fScaleAdjustDest = 1.0f;
for (size_t i=0; i<PositiveList.size(); i++)
{
StateInfoEx* info = GetTenacityDB().GetTenacityData(PositiveList[i]->GetStateCode());
if (info->fValue[6] == 128) m_fScaleAdjustDest = info->fValue[7];
if (info->fValue[9] == 128) m_fScaleAdjustDest = info->fValue[10];
}
float fScale = 1.0f;
DWORD nowTime = GetSafeTickCount();
if (m_fScaleAdjustPrev == m_fScaleAdjustDest)
{
fScale = m_fScaleAdjustDest;
}
else
{
if (m_nScaleAdjustStartTime == 0) m_nScaleAdjustStartTime = nowTime;
float ratio = (nowTime - m_nScaleAdjustStartTime) / 1000.0f;
fScale = m_fScaleAdjustPrev * (1-ratio) + m_fScaleAdjustDest * ratio;
if (ratio > 1.0f)
{
m_nScaleAdjustStartTime = 0;
fScale = m_fScaleAdjustDest;
m_fScaleAdjustPrev = m_fScaleAdjustDest;
}
}
K3DMatrix mat = *GetTransform();
SetScalePure(fScale);
m_fSelcube[5] = m_fOriginalSelCubeHeight * fScale;
*/
// 거대화 관련 코드 종료
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Traitement en fondu
// AziaMafia LoadMap
if (m_nFadeOutStartTime != 0)
{
/// 2011.04.20 - prodongi
DWORD nowTime = GetSafeTickCount();
int nTime = nowTime - m_nFadeOutStartTime;
float fAlpha = 1.0f - (((float)nTime) / ((float)m_nFadeOutDuration));
fAlpha = max(fAlpha, 0.0f);
fAlpha = min(fAlpha, 1.0f);
SetVisibility(fAlpha);
if (nTime > m_nFadeOutDuration)
{
m_nFadeOutStartTime = 0;
SetReservation(false);
Deactivate();
}
}
// 페이드아웃 관련 코드 종료
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
_renderThread();
if (!m_bVisible || !m_bIsActivated || !m_bIsInit || !m_xRenderFlag.IsOn(AV_BASIC))
{
SetTransformPure(mat);
return false;
}
if (IsPendLoading()) { SetTransformPure(mat); return false; }
_renderEffectLoading(); // sonador #2.3.1.10
_renderAvatar(uRenderBitVector, ppViewportList, nViewportCount);
_renderEtc(uRenderBitVector, ppViewportList, nViewportCount);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 거대화 관련 코드로 인한 변경점 리셋
/// 2011.04.20 하위 클래스에서도 쓰기 위해서 함수로 뺐습니다. - prodongi
endScaling(scale, mat);
/*
SetTransformPure(mat);
m_fScaleAdjust = fScale;
*/
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
return true;
}
bool SGameAvatarEx::renderSelect(unsigned long uRenderBitVector, class KViewportObject** ppViewportList, int nViewportCount)
{
if (!m_pSeqAvatar)
return false;
float scale;
K3DMatrix mat;
beginScaling(scale, mat);
if (nViewportCount >= 1 && ppViewportList[0] && ppViewportList[0]->GetAttributes() & KViewportObject::VIEWPORT_GAME)
{
m_pSeqAvatar->SetTransform(*GetTransform());
m_pSeqAvatar->Render(ppViewportList[0], KRenderObject::RENDEREFX_SELECT);
}
endScaling(scale, mat);
return true;
}
void SGameAvatarEx::RefreshSkinColorized()
{
SetSkinColorized(m_dwSkinColor, K3DTexture::COLORIZED_DEF, m_dwHairColor);
}
void SGameAvatarEx::SetHairColorIndex(int nIndex)
{
m_nHairColorIndex = nIndex;
}
void SGameAvatarEx::SetHairColorRGB(unsigned int hairColor)
{
m_dwHairColor = hairColor;
m_dwHairColor |= 0xff000000; //서버에 알파 없음
}
void SGameAvatarEx::SetSkinColorized(const DWORD& color, const int& nMode, const DWORD& hairColor)
{
// Actual character render in game
m_dwSkinColor = color;
m_dwSkinColor |= 0xff000000; //서버에 알파 없음
SetHairColorRGB(hairColor);
if (m_pSeqAvatar)
{
{
_CID(SET_COLORIZE);
KMsgSET_COLORIZE msg;
msg.color[0] = 0;
msg.color[1] = m_dwSkinColor; //2번째 것만 사용
msg.color[2] = 0;
msg.color[3] = 0;
if (nMode == 0)
msg.nMode = K3DTexture::COLORIZED_DEF;
else if (nMode == 1)
msg.nMode = K3DTexture::COLORIZED_KEEP_ALPHA;
else if (nMode == 2)
msg.nMode = K3DTexture::COLORIZED_USEALPHA;
// 2010.05.18 아래 코드에 Deco Mesh적용 부분이 빠져 있어서 새로운 함수를 생성했습니다. - prodongi
KSeqAvatar* pAvatarPart = m_pSeqAvatar->getAvatarPart(ANIPART_BIPED);
if (pAvatarPart)
{
std::set<int> ignoreMeshList;
ignoreMeshList.insert(MPART_HAIR);
pAvatarPart->PerformWithIgnoreMesh(id_SET_COLORIZE, msg, &ignoreMeshList);
ignoreMeshList.clear();
}
}
//m_pSeqAvatar->Perform( ANIPART_BIPED, id_SET_COLORIZE, msg );
//얼굴 Mesh는 텍스쳐 알파로 인한 Blend를 적용 시키지 않는다.
_CID(SET_USE_TEXALPHA);
KMsgSET_USE_TEXALPHA use_texalpha_msg;
use_texalpha_msg.bIsUseTexAlpha = false;
// sonador 4.1.2 아바타 머리카락 알바 버그 재수정(ALPHABLENDTWOPASS)
_CID(SET_BLENDMODE);
KMsgSET_BLENDMODE set_blend_mode;
set_blend_mode.blendMode = K3DMaterial::MBM_ALPHABLENDTWOPASS;
m_pSeqAvatar->Perform(ANIPART_BIPED, MPART_FACE, id_SET_USE_TEXALPHA, use_texalpha_msg);
//m_pSeqAvatar->Perform( ANIPART_HAIR, MPART_HAIR, id_SET_BLENDMODE, set_blend_mode );
m_pSeqAvatar->Perform(ANIPART_BIPED, MPART_HAIR, id_SET_BLENDMODE, set_blend_mode);
m_pSeqAvatar->Perform(ANIPART_MANTLE, MPART_MANTLE, id_SET_BLENDMODE, set_blend_mode); // sonador 4.1.3 망토 알파 버그 수정
_oprint("[SetSkinColorized] color: %d; nMode: %d; hairColor: %d; m_nHairColorIndex: %d; m_dwHairColor: %d\n", color, nMode, hairColor, m_nHairColorIndex, m_dwHairColor);
if (m_nHairColorIndex == 0)
{
_CID(SET_COLORIZE);
KMsgSET_COLORIZE msg;
msg.color[0] = 0;
msg.color[1] = m_dwHairColor; // Only use the second one
msg.color[2] = 0;
msg.color[3] = 0;
// 아바타 머리색 변경
// 2010-2-8 : hunee
msg.nMode = K3DTexture::COLORIZED_GRAY;
//msg.nMode = K3DTexture::COLORIZED_USEALPHA;
m_pSeqAvatar->Perform(ANIPART_BIPED, MPART_HAIR, id_SET_COLORIZE, msg);
}
// 2010.05.25 - prodongi
else if (1 == m_nHairColorIndex || 2 == m_nHairColorIndex)
{
setMaintainHairColorNewToOld(GetHair(), m_nHairColorIndex, GetRace(), GetSex(), m_pSeqAvatar);
}
}
//refreshWink( m_pSeqAvatar );
}
void* SGameAvatarEx::Perform(KID id, KArg& msg)
{
if (!m_pSeqAvatar || !m_bIsInit) return (void*)0;
return m_pSeqAvatar->Perform(id, msg);
return (void*)0;
}
void* SGameAvatarEx::Perform(int nAniIndex, KID id, KArg& msg)
{
if (!m_pSeqAvatar || !m_bIsInit) return (void*)0;
return m_pSeqAvatar->Perform(nAniIndex, id, msg);
return (void*)0;
}
void* SGameAvatarEx::Perform(int nAniIndex, int nMeshIndex, KID id, KArg& msg)
{
if (!m_pSeqAvatar || !m_bIsInit) return (void*)0;
return m_pSeqAvatar->Perform(nAniIndex, nMeshIndex, id, msg);
return (void*)0;
}
//Animation 관련
void SGameAvatarEx::SetAttackAniLock(bool bLock)
{
m_bLockAttackAni = bLock;
}
void SGameAvatarEx::SetAniLock(bool bLock)
{
m_bLockAni = bLock;
//#ifndef NDEBUG
// if( m_bLocal )
// {
// if( m_bLockAni )
// _oprint( "AniLock - Lock\n" );
// else
// _oprint( "AniLock - UnLock\n" );
// }
//#endif
}
void SGameAvatarEx::FindEventList(const char* pAni, _KEY_EVENT_RES*& pCurEventHandle, KSVEC_KEVENT_RES& svEventList)
{
pCurEventHandle = NULL;
//체크할 필요는 없을듯 by metarrgear
// if( !m_bIsActivated || !m_bIsInit ) return;
_KEY_EVENT_RES* pFind = NULL;
if (svEventList.lookup(pAni, pFind))
{
pCurEventHandle = pFind;
pCurEventHandle->SetInit();
}
//_KEY_EVENT_RES temp;
//temp.SetName( pAni );
//int idx = svEventList.search_index( &temp );
//if( idx != -1 )
//{
// pCurEventHandle = svEventList[idx];
// pCurEventHandle->SetInit();
//}
}
const char* SGameAvatarEx::GetAniKey(int nObjType, int nAniIndex, bool bOnlyGetAniKey)
{
m_strAniKey = "";
if (nObjType == TS_ENTER::GAME_PLAYER || nObjType == TS_ENTER::GAME_MOB || nObjType == TS_ENTER::GAME_SUMMON || nObjType == TS_ENTER::GAME_PET)
{
const char* pAni = NULL;
if (nObjType == TS_ENTER::GAME_PLAYER)
pAni = GetMotionSetDB().GetAni(nObjType, nAniIndex, GetRace(), GetSex(), m_nAniClass);
else if (nObjType == TS_ENTER::GAME_MOB)
{
_MONSTER_INFO_FILE* pMonster = GetMonsterDB().GetMonsterData(GetInnContentID());
if (pMonster)
pAni = GetMonsterMotionSetDB().GetAni(pMonster->motion_file_id, nAniIndex);
else
{
_oprint("GetAni Key Fail - Mob : %d\n", GetInnContentID());
// assert( 0 && "GetAni Key Fail GetInnContentID() 이상한듯" );
}
}
else if (nObjType == TS_ENTER::GAME_SUMMON)
{
_SUMMON_INFO_FILE* pSummon = GetCreatureDB().GetCreatureData(GetInnContentID());
if (pSummon)
{
pAni = GetMonsterMotionSetDB().GetAni(pSummon->motion_file_id, nAniIndex);
}
else
{
_oprint("GetAni Key Fail - Summon : %d\n", GetInnContentID());
// assert( 0 && "GetAni Key Fail GetInnContentID() 이상한듯" );
}
}
else if (nObjType == TS_ENTER::GAME_PET)
{
SPetInfoEx Pet = GetPetDB().Find(GetInnContentID());
pAni = GetMonsterMotionSetDB().GetAni(Pet.getMotionFileID(), nAniIndex);
}
if (!bOnlyGetAniKey)
SetEventHandleNull();
if (pAni)
{
//이벤트 핸들 설정
if (!bOnlyGetAniKey)
{
FindEventList(pAni, m_pCurEventHandle00_effect, m_svEventHandle00_effectList);
FindEventList(pAni, m_pCurEventHandle00_sound, m_svEventHandle00_soundList);
FindEventList(pAni, m_pCurEventHandle00_motion_effect, m_svEventHandle00_motion_effect);
FindEventList(pAni, m_pCurEventHandle01, m_svEventHandle01_List);
FindEventList(pAni, m_pCurEventHandle02, m_svEventHandle02_List);
FindEventList(pAni, m_pCurEventHandle03, m_svEventHandle03_List);
FindEventList(pAni, m_pCurEventHandle04, m_svEventHandle04_List);
FindEventList(pAni, m_pCurEventHandle05, m_svEventHandle05_List);
FindEventList(pAni, m_pCurEventHandle06, m_svEventHandle06_List);
// FindMotionAddOnFx();
}
CStringUtil::GetStrKey(pAni, '_', m_strAniKey);
// _oprint( "ANI_NAME : %s\n", m_strAniKey.c_str() );
}
}
else if (nObjType == TS_ENTER::GAME_NPC)
{
//Todo
}
return m_strAniKey.c_str();
}
float SGameAvatarEx::Attack(AR_HANDLE target, K3DVector tpos, DWORD dwAttackRate, int nAniIndex)
{
m_nNewCurAniType = nAniIndex;
if (!m_pSeqAvatar || !m_bIsInit) return false;
int nBoneCount = 0;
DWORD dwMinTime, dwMaxTime;
dwMinTime = 0;
dwMaxTime = 0;
//공격 스피드 구하자.
std::string strAniKey = GetAniKey(GetInnObjType(), nAniIndex);
m_pSeqAvatar->GetFrameInfo(ANIPART_BIPED, strAniKey.c_str(), nBoneCount, dwMinTime, dwMaxTime);
float fAttack = GetAttackSpeed(dwAttackRate);
//기본 배율
float fRate = GetAniPlayRate(fAttack, dwMaxTime, false);
//_oprint( "SGameAvatarEx : total[%d], fAttack[%f], fRate[%f]\n", dwAttackRate, fAttack, fRate );
fRate = 4.8f * fRate;
//_oprint( "Attack Speed: %d, %d, %f\n", dwAttackRate, dwMaxTime, 4.8f / fRate );
_playAnimation(m_pSeqAvatar, strAniKey.c_str(), SEQTYPE_NORMAL, fRate);
return fRate;
}
float SGameAvatarEx::GetAttackSpeed(DWORD attack_speed)
{
float fAttack = attack_speed;
int nMotionSpeed = -1;
if (GetInnObjType() == TS_ENTER::GAME_MOB)
nMotionSpeed = GetMonsterDB().GetMotionSpeed(GetInnContentID());
else if (GetInnObjType() == TS_ENTER::GAME_SUMMON)
nMotionSpeed = GetCreatureDB().GetMotionSpeed(GetInnContentID());
if (nMotionSpeed == MOTION_SPEED_0) // 0:느림 = 공격5 : 대기5
{
fAttack = attack_speed - attack_speed * 0.5f;
}
else if (nMotionSpeed == MOTION_SPEED_1)// 1:보통 = 공격6 : 대기4
{
fAttack = attack_speed - attack_speed * 0.4f;
}
else if (nMotionSpeed == MOTION_SPEED_2)// 2:빠름 = 공격7 : 대기3
{
fAttack = attack_speed - attack_speed * 0.3f;
}
else if (nMotionSpeed == MOTION_SPEED_3)// 3:일반 = 공격10 : 대기0
{
fAttack = attack_speed;
}
return fAttack;
}
bool SGameAvatarEx::_damage()
{
if (!m_pSeqAvatar) return false;
// _oprint( "Damage()\n" );
//마운트 상태이거나 마운트 모드가 아니라면
if (!IsMount() && !IsMountMode())
{
if (m_pStateVM)
m_pStateVM->SetMode(SObjectStateMachine::MODE_ATTACK);
}
return false;
}
bool SGameAvatarEx::_playAnimation(KSeqAvatarEx* pSeqAvatarEx, const char* pAniKey, int nAniType, float fPlayRate)
{
if (pSeqAvatarEx)
{
pSeqAvatarEx->Initialize();
pSeqAvatarEx->PlayAnimation(ANIPART_BIPED, m_dwTime, pAniKey, nAniType, fPlayRate);
pSeqAvatarEx->PlayAnimation(ANIPART_HAIR, m_dwTime, pAniKey, nAniType, fPlayRate);
//pSeqAvatarEx->PlayAnimation( ANIPART_EARRING , m_dwTime, pAniKey, nAniType, fPlayRate );
pSeqAvatarEx->PlayAnimation(ANIPART_NECKLACE, m_dwTime, pAniKey, nAniType, fPlayRate);
pSeqAvatarEx->PlayAnimation(ANIPART_SHORTSKIRT, m_dwTime, pAniKey, nAniType, fPlayRate);
//m_pSeqAvatar->PlayAnimation( ANIPART_LONGSKIRT , m_dwTime, pAniKey, nAniType, fPlayRate );
pSeqAvatarEx->PlayAnimation(ANIPART_MIDSKIRT, m_dwTime, pAniKey, nAniType, fPlayRate);
pSeqAvatarEx->PlayAnimation(ANIPART_FABRIC, m_dwTime, pAniKey, nAniType, fPlayRate);
pSeqAvatarEx->PlayAnimation(ANIPART_MANTLE, m_dwTime, pAniKey, nAniType, fPlayRate);
//무기(왼,오른손)
pSeqAvatarEx->PlayAnimation(ANIPART_WEAPON_LEFT, m_dwTime, pAniKey, nAniType, fPlayRate);
pSeqAvatarEx->PlayAnimation(ANIPART_WEAPON_RIGHT, m_dwTime, pAniKey, nAniType, fPlayRate);
pSeqAvatarEx->ReSet(); //Ani 재사용시 필요.
pSeqAvatarEx->SetAttachBone();
m_bIsTryPlayAni = false;
return true;
}
m_bIsTryPlayAni = true;
return false;
}
void SGameAvatarEx::ThreadNPlayAnimation(KSeqAvatarEx* pSeqAvatarEx, int nType, int nAniType /*= SEQTYPE_NORMAL*/, float fPlayRate/* = 4.8f */)
{
m_nNewCurAniType = nType;
m_nCurPlayType = nAniType;
m_fCurPlayRate = fPlayRate;
if (GetInnObjType() == TS_ENTER::GAME_PLAYER ||
GetInnObjType() == TS_ENTER::GAME_MOB ||
GetInnObjType() == TS_ENTER::GAME_SUMMON ||
GetInnObjType() == TS_ENTER::GAME_PET)
{
std::string strAniKey = GetAniKey(GetInnObjType(), nType);
_playAnimation(pSeqAvatarEx, strAniKey.c_str(), nAniType, fPlayRate);
}
else if (GetInnObjType() == TS_ENTER::GAME_NPC)
{
std::string strAniKey = "una_default01";
_playAnimation(pSeqAvatarEx, strAniKey.c_str(), nAniType, fPlayRate);
}
}
void SGameAvatarEx::NPlayAnimation(int nType, int nAniType, float fPlayRate)
{
m_nNewCurAniType = nType;
m_nCurPlayType = nAniType;
m_fCurPlayRate = fPlayRate;
if (!m_pSeqAvatar) return;
if (GetInnObjType() == TS_ENTER::GAME_PLAYER ||
GetInnObjType() == TS_ENTER::GAME_MOB ||
GetInnObjType() == TS_ENTER::GAME_SUMMON ||
GetInnObjType() == TS_ENTER::GAME_PET)
{
std::string strAniKey = GetAniKey(GetInnObjType(), nType);
_playAnimation(m_pSeqAvatar, strAniKey.c_str(), nAniType, fPlayRate);
}
else if (GetInnObjType() == TS_ENTER::GAME_NPC)
{
std::string strAniKey = "una_default01";
_playAnimation(m_pSeqAvatar, strAniKey.c_str(), nAniType, fPlayRate);
}
}
void SGameAvatarEx::NPlayOverride(int nType, float fPlayRate)
{
if (GetInnObjType() == TS_ENTER::GAME_PLAYER ||
GetInnObjType() == TS_ENTER::GAME_MOB ||
GetInnObjType() == TS_ENTER::GAME_SUMMON ||
GetInnObjType() == TS_ENTER::GAME_PET)
{
std::string strAniKey = GetAniKey(GetInnObjType(), nType);
//이펙트 관련된 것도 Override 되도록 수정 해야 한다.
if (m_pSeqAvatar && m_bIsInit)
{
m_pSeqAvatar->PlayOverride(ANIPART_BIPED, m_dwTime, strAniKey.c_str(), fPlayRate);
m_pSeqAvatar->PlayOverride(ANIPART_HAIR, m_dwTime, strAniKey.c_str(), fPlayRate);
// m_pSeqAvatar->PlayOverride( ANIPART_EARRING , m_dwTime, strAniKey.c_str(), fPlayRate );
m_pSeqAvatar->PlayOverride(ANIPART_NECKLACE, m_dwTime, strAniKey.c_str(), fPlayRate);
m_pSeqAvatar->PlayOverride(ANIPART_SHORTSKIRT, m_dwTime, strAniKey.c_str(), fPlayRate);
// m_pSeqAvatar->PlayOverride( ANIPART_LONGSKIRT , m_dwTime, strAniKey.c_str(), fPlayRate );
m_pSeqAvatar->PlayOverride(ANIPART_MIDSKIRT, m_dwTime, strAniKey.c_str(), fPlayRate);
m_pSeqAvatar->PlayOverride(ANIPART_FABRIC, m_dwTime, strAniKey.c_str(), fPlayRate);
m_pSeqAvatar->PlayOverride(ANIPART_MANTLE, m_dwTime, strAniKey.c_str(), fPlayRate);
//무기(왼,오른손)
m_pSeqAvatar->PlayOverride(ANIPART_WEAPON_LEFT, m_dwTime, strAniKey.c_str(), fPlayRate);
m_pSeqAvatar->PlayOverride(ANIPART_WEAPON_RIGHT, m_dwTime, strAniKey.c_str(), fPlayRate);
//m_pSeqAvatar->ReSet(); //Ani 재사용시 필요.
m_pSeqAvatar->SetAttachBone();
m_bPlayOverride = true;
}
}
}
//void SGameAvatarEx::PlayAnimation( int nType , int nAniType, float fPlayRate )
//{
// if( IsAniLock() )
// return;
//
// m_nCurAniType = nType;
// m_nCurPlayType = nAniType;
// m_fCurPlayRate = fPlayRate;
// // fPlayRate = .5f;
//
// //if( IsLocalPlayer() )
// // _oprint( "PlayAnimation : %d\n", nType );
//
// //if( GetAnimationType() == ANI_DEAD )
// //{
// //}
//
// //위에서 설정 할 수 있게 바꿔야 한다.
// std::string strAniKey = pAniClassEx[m_nAniClass];
// strAniKey += pAniEx[nType];
//
// //
// //_oprint( "PlayAnimation : %s\n", strAniKey.c_str() );
//
// ////동작 되는지 알 수 없다.
// //if( nType == NANI_ATTACK01 || nType == NANI_ATTACK02 )
// //{
// // if( m_pSeqAvatar ) m_pSeqAvatar->SetItemRenderFlag( ANIPART_BIPED, true );
// //}
// //else
// //{
// // if( m_pSeqAvatar ) m_pSeqAvatar->SetItemRenderFlag( ANIPART_BIPED, false );
// //}
//
// _playAnimation( strAniKey.c_str(), nAniType, fPlayRate );
//}
//Play Animation 후에 유효하다.
void SGameAvatarEx::GetCurSeqEvent(EVENT_SET& event_set)
{
event_set.pCurEvent00_effect = m_pCurEventHandle00_effect;
event_set.pCurEvent00_sound = m_pCurEventHandle00_sound;
event_set.pCurEvent00_motion_effect = m_pCurEventHandle00_motion_effect;
event_set.pCurEvent01 = m_pCurEventHandle01;
event_set.pCurEvent02 = m_pCurEventHandle02;
event_set.pCurEvent03 = m_pCurEventHandle03;
event_set.pCurEvent04 = m_pCurEventHandle04;
event_set.pCurEvent05 = m_pCurEventHandle05;
event_set.pCurEvent06 = m_pCurEventHandle06;
m_pCurEventHandle00_effect = NULL;
m_pCurEventHandle00_sound = NULL;
m_pCurEventHandle00_motion_effect = NULL;
m_pCurEventHandle01 = NULL;
m_pCurEventHandle02 = NULL;
m_pCurEventHandle03 = NULL;
m_pCurEventHandle04 = NULL;
m_pCurEventHandle05 = NULL;
m_pCurEventHandle06 = NULL;
}
//void SGameAvatarEx::PlayOverride( int nType ,float fPlayRate )
//{
//// std::string strAniKey = pAniClassEx[m_nAniClass];
//// strAniKey += pAniEx[nType];
////
//// //이펙트 관련된 것도 Override 되도록 수정 해야 한다.
//// if( m_pSeqAvatar )
//// {
//// m_pSeqAvatar->PlayOverride( ANIPART_BIPED , m_dwTime, strAniKey.c_str(), fPlayRate );
//// m_pSeqAvatar->PlayOverride( ANIPART_HAIR , m_dwTime, strAniKey.c_str(), fPlayRate );
//// m_pSeqAvatar->PlayOverride( ANIPART_EARRING , m_dwTime, strAniKey.c_str(), fPlayRate );
//// m_pSeqAvatar->PlayOverride( ANIPART_NECKLACE , m_dwTime, strAniKey.c_str(), fPlayRate );
//// m_pSeqAvatar->PlayOverride( ANIPART_SHORTSKIRT, m_dwTime, strAniKey.c_str(), fPlayRate );
////// m_pSeqAvatar->PlayOverride( ANIPART_LONGSKIRT , m_dwTime, strAniKey.c_str(), fPlayRate );
//// m_pSeqAvatar->PlayOverride( ANIPART_MIDSKIRT , m_dwTime, strAniKey.c_str(), fPlayRate );
//// m_pSeqAvatar->PlayOverride( ANIPART_FABRIC , m_dwTime, strAniKey.c_str(), fPlayRate );
//// m_pSeqAvatar->PlayOverride( ANIPART_MANTLE , m_dwTime, strAniKey.c_str(), fPlayRate );
//// //무기(왼,오른손)
//// m_pSeqAvatar->PlayOverride( ANIPART_WEAPON_LEFT , m_dwTime, strAniKey.c_str(), fPlayRate );
//// m_pSeqAvatar->PlayOverride( ANIPART_WEAPON_RIGHT, m_dwTime, strAniKey.c_str(), fPlayRate );
////
//// //m_pSeqAvatar->ReSet(); //Ani 재사용시 필요.
//// m_pSeqAvatar->SetAttachBone();
//// }
//}
//RefreshItem 한 다음에 부른다.
void SGameAvatarEx::AttachAnimation(KSeqAvatarEx* pAvatarEx)
{
if (pAvatarEx)
{
pAvatarEx->SetAttachBone();
}
}
int SGameAvatarEx::GetItemClass()
{
if (GetObjType() == TS_ENTER::GAME_MOB)
{
_MONSTER_INFO_FILE* pMob = GetMonsterDB().GetMonsterData(GetContentID());
if (pMob)
return pMob->weapon_type;
}
else if (GetObjType() == TS_ENTER::GAME_SUMMON)
{
_SUMMON_INFO_FILE* pSummon = GetCreatureDB().GetCreatureData(GetContentID());
if (pSummon)
return pSummon->weapon_type;
}
return 1;
}
int SGameAvatarEx::GetMaterial() //재질
{
if (GetInnObjType() == TS_ENTER::GAME_MOB)
{
_MONSTER_INFO_FILE* pMob = GetMonsterDB().GetMonsterData(GetInnContentID());
if (pMob)
return pMob->nMaterial;
}
else if (GetInnObjType() == TS_ENTER::GAME_SUMMON)
{
_SUMMON_INFO_FILE* pSummon = GetCreatureDB().GetCreatureData(GetInnContentID());
if (pSummon)
return pSummon->nMaterial;
}
return 1;
}
int SGameAvatarEx::GetMovingType()
{
//2족 소형 0
//2족 중형 1
//2족 대형 2
//2족 초대형 3
//4족 소형 4
//4족 중형 5
//4족 대형 6
//4족 초대형 7
//다족 30
//미끌 31
//외발 32
//부유 33
//비행 34
//기타 99
switch (GetInnObjType())
{
case TS_ENTER::GAME_MOB: return GetMonsterDB().GetWalkType(GetInnContentID());
case TS_ENTER::GAME_SUMMON: return GetCreatureDB().GetWalkType(GetInnContentID());
case TS_ENTER::GAME_PET: return GetPetDB().Find(GetInnContentID()).getWalkType();
}
return 1;
}
void SGameAvatarEx::RefreshAni()
{
SAFE_DELETE(m_pSeqAvatar);
m_pSeqAvatar = m_pThreadAvatarEx;
m_pThreadAvatarEx = NULL;
if (IsLocalPlayer())
m_bRefreshInven = true;
if (!m_pSeqAvatar)
{
assert(0);
return;
}
SetMotionBlend(true);
//애니 메이션 클래스 변경해야 하고, 거의 다 고쳐야 한다.
if (GetCurrAnimationID() == -1)
NPlayAnimation(ANI_DEFAULT01, m_nCurPlayType);
else
{
if (!IsMoving())
{
if (m_nNewCurAniType == ANI_RUN || m_nNewCurAniType == ANI_IDLE) m_nNewCurAniType = ANI_DEFAULT01;
else if (m_nNewCurAniType == ANI_M_RUN_HIGH) m_nNewCurAniType = ANI_M_DEFAULT01_HIGH;
else if (m_nNewCurAniType == ANI_M_RUN_LOW) m_nNewCurAniType = ANI_M_DEFAULT01_LOW;
else if (m_nNewCurAniType == ANI_M_RUN_QILIN) m_nNewCurAniType = ANI_M_DEFAULT01_QILIN; // sonador #2.1.6
else if (m_nNewCurAniType == ANI_M_RUN_WHITE) m_nNewCurAniType = ANI_M_DEFAULT01_WHITE; // #2.1.14
else if (m_nNewCurAniType == ANI_M_RUN_UNICORN) m_nNewCurAniType = ANI_M_DEFAULT01_UNICORN; // #2.1.14
else if (m_nNewCurAniType == ANI_M_RUN_BEAKHO) m_nNewCurAniType = ANI_M_DEFAULT01_BEAKHO; /// 2011.02.08 - prodongi
}
if (IsLoopMotion(m_nNewCurAniType))
NPlayAnimation(m_nNewCurAniType, m_nCurPlayType);
else
NPlayAnimation(m_nNewCurAniType, SEQTYPE_NORMAL);
if (GetCurrAnimationID() == ANI_DEAD01)
{
SetEventHandleNull();
}
}
m_pSeqAvatar->SetDeform(ANIPART_BIPED);
m_pSeqAvatar->SetAttach(ANIPART_BIPED);
if (m_bIsInit)
RefreshEffectPos(m_pSeqAvatar);
//칼라 색 변경
if (GetInnObjType() == TS_ENTER::GAME_PLAYER ||
GetInnObjType() == TS_ENTER::GAME_NPC)
{
RefreshSkinColorized();
}
// 2010.05.11 - prodongi
g_pCurrentGameSystem->updateCurTarget(GetArID());
}
void SGameAvatarEx::AddMorphMesh(class KMsgSET_MORPHMESH* pMsg)
{
m_pSeqAvatar->AddMorphMesh(ANIPART_WEAPON_RIGHT, pMsg);
m_pSeqAvatar->AddMorphMesh(ANIPART_WEAPON_LEFT, pMsg);
}
void SGameAvatarEx::SetFixTexture(class KMsgSET_FIXTEXTURE* pMsg)
{
if (!IsThreadLoading() && m_bIsActivated && m_pSeqAvatar)
{
m_pSeqAvatar->SetFixTexture(ANIPART_BIPED, pMsg);
m_pSeqAvatar->SetFixTexture(ANIPART_HAIR, pMsg);
m_pSeqAvatar->SetFixTexture(ANIPART_NECKLACE, pMsg);
m_pSeqAvatar->SetFixTexture(ANIPART_EARRING, pMsg);
m_pSeqAvatar->SetFixTexture(ANIPART_MANTLE, pMsg);
m_pSeqAvatar->SetFixTexture(ANIPART_FABRIC, pMsg);
m_pSeqAvatar->SetFixTexture(ANIPART_LONGSKIRT, pMsg);
m_pSeqAvatar->SetFixTexture(ANIPART_MIDSKIRT, pMsg);
m_pSeqAvatar->SetFixTexture(ANIPART_SHORTSKIRT, pMsg);
m_pSeqAvatar->SetFixTexture(ANIPART_WEAPON_LEFT, pMsg);
m_pSeqAvatar->SetFixTexture(ANIPART_WEAPON_RIGHT, pMsg);
}
}
void SGameAvatarEx::RefreshEffectPos(KSeqAvatarEx* pSeqAvatarEx)
{
for (int x(0); x < EFFECT_POS_MAX; ++x)
{
m_bEVPAttachMatrix[x] = false;
m_pEvpSequencer[x] = NULL;
}
if (pSeqAvatarEx == NULL) return;
//이펙트 포스 설정
pSeqAvatarEx->SetAttachEffectPos(ANIPART_BIPED);
_CID(REQ_EVPOINT);
KMsgREQ_EVPOINT effect_pos_msg;
pSeqAvatarEx->Perform(ANIPART_BIPED, id_REQ_EVPOINT, effect_pos_msg);
for (int i(0); i < effect_pos_msg.GetPointCount(); ++i)
{
KEventPointSeq* pEv = effect_pos_msg.GetPoint(i);
if (!pEv) continue;
const char* pName = pEv->GetName();
for (int x(0); x < EFFECT_POS_MAX; ++x)
{
if (strlen(pName) && _stricmp(pName, pEP_Name[x]) == 0)
{
K3DMatrixIdentity(m_matEVPMatrix[x]);
//이펙트쪽 방향 문제때문에 이벤트 포인트에 위치만 가져온다
K3DMatrix matEvPoint = pEv->GetPoint();
m_matEVPMatrix[x]._41 = matEvPoint._41;
m_matEVPMatrix[x]._42 = matEvPoint._42;
m_matEVPMatrix[x]._43 = matEvPoint._43;
if (pEv->GetAttachTransform())
{
m_bEVPAttachMatrix[x] = true;
m_pEvpSequencer[x] = pEv;
K3DMatrixIdentity(m_matEVPAttachMatrix[x]);
if (x == EFFECT_POS_TOP)
{
m_matEVPAttachMatrix[x]._41 = m_pEvpSequencer[x]->GetAttachTransform()->_41;
m_matEVPAttachMatrix[x]._42 = m_pEvpSequencer[x]->GetAttachTransform()->_42;
m_matEVPAttachMatrix[x]._43 = m_pEvpSequencer[x]->GetAttachTransform()->_43;
}
else
m_matEVPAttachMatrix[x] = *m_pEvpSequencer[x]->GetAttachTransform();
}
break;
}
}
}
//몬스터 본 이펙트 추가
if (GetInnObjType() == TS_ENTER::GAME_MOB)
{
pSeqAvatarEx->SetTransform(*GetTransform());
ModelEffectResourceGame* pModelEffectRes = NULL;
_MONSTER_INFO_FILE* pMonster = GetMonsterDB().GetMonsterData(GetInnContentID());
if (pMonster) pModelEffectRes = GetModelEffectResourceDB().GetModelEffectResource(pMonster->monster_group);
if (pModelEffectRes)
{
for (int i(0); MAX_BONE_EFFECT > i; i++)
{
if (pModelEffectRes->bUseEffect[i])
{
const char* pBoneName = pModelEffectRes->bone_name[i];
const char* pBoneEffect = GetResourceDB().GetEffectResourceName(pModelEffectRes->bone_effect[i]);
//_oprint( "AddBoneEffect : Bone[%s] BoneEffect[%s]\n", pBoneName, pBoneEffect );
pSeqAvatarEx->AddBoneEffect(ANIPART_BIPED, i, pBoneName, pBoneEffect);
}
}
}
}
//크리쳐 본 이펙트 추가
//2009-03-26 : hunee
else if (GetInnObjType() == TS_ENTER::GAME_SUMMON)
{
pSeqAvatarEx->SetTransform(*GetTransform());
ModelEffectResourceGame* pModelEffectRes = NULL;
_SUMMON_INFO_FILE* pSummon = GetCreatureDB().GetCreatureData(GetInnContentID());
if (pSummon) pModelEffectRes = GetModelEffectResourceDB().GetModelEffectResource(pSummon->model_id);
if (pModelEffectRes)
{
for (int i(0); MAX_BONE_EFFECT > i; i++)
{
if (pModelEffectRes->bUseEffect[i])
{
const char* pBoneName = pModelEffectRes->bone_name[i];
const char* pBoneEffect = GetResourceDB().GetEffectResourceName(pModelEffectRes->bone_effect[i]);
//_oprint( "AddBoneEffect : Bone[%s] BoneEffect[%s]\n", pBoneName, pBoneEffect );
pSeqAvatarEx->AddBoneEffect(ANIPART_BIPED, i, pBoneName, pBoneEffect);
}
}
}
}
}
const K3DVector& SGameAvatarEx::GetViewVector()
{
return m_vTempView;
}
//방향 설정
void SGameAvatarEx::SetViewVector(const K3DVector& tpos)
{
m_fTargetRoll = atan2(tpos.y - GetPosition()->y, tpos.x - GetPosition()->x);
m_dwPrevTime = m_dwTime;
m_bUseRot = true;
}
/*
//방향
void SGameAvatarEx::SetViewVector( const K3DVector &tpos )
{
// _oprint(" SetViewVector Tpos : %7.4f, %7.4f, %7.4f\n", tpos.x, tpos.y, tpos.z);
K3DVector Cur, view, Out;
Cur = GetCurPos();
view = K3DVector( tpos.x, tpos.y, 0 ) - Cur;
K3DVectorNomalize(&Out, &view);
float fVevLen = K3DVectorGetLength( K3DVector(Cur.x,Cur.y,0.f), K3DVector( tpos.x,tpos.y,0 ) );
float fLen = Magnitude( Out );
if( fLen > 0.f && fVevLen > 0.5f )
{
m_vView = Out; //뷰벡터 설정
//방향 설정
K3DMatrix mat;
K3DMatrixIdentity(mat);
mat._11 = -Out.y;
mat._21 = -Out.x;
mat._31 = 0;
mat._12 = Out.x;
mat._22 = -Out.y;
mat._32 = 0;
mat._41 = Cur.x;
mat._42 = Cur.y;
mat._43 = GetHeight( Cur.x, Cur.y,m_wCurTile );
SetTransform(mat);
}
//else {
// m_vView;
// //방향 설정
// K3DMatrix mat;
// K3DMatrixIdentity(mat);
// mat._41 = Cur.x;
// mat._42 = Cur.y;
// mat._43 = GetHeight( Cur.x, Cur.y,m_wCurTile );
// SetTransform(mat);
// {
// _oprint(" SetViewVector Out : %7.4f, %7.4f, %7.4f\n", Out.x, Out.y, Out.z);
// }
//}
}*/
void SGameAvatarEx::ClipTest(struct K3DVector* pFrustum)
{
if (!m_bIsInit) return;
if (m_pSeqAvatar)
{
if (IsStateRide())
AvatarClipTestByCreature(pFrustum);
else
m_pSeqAvatar->ClipTest(pFrustum);
if (!m_pSeqAvatar->GetIsClip())
m_xRenderFlag.On(AV_BASIC);
else
m_xRenderFlag.Off(AV_BASIC);
if (GetInnObjType() == TS_ENTER::GAME_PLAYER)
{
bool bNewVisible = (m_xRenderFlag.IsOn(AV_BASIC) && m_bVisible);
if (m_bPrevVisible != bNewVisible)
{
SetWeaponEnhanceFx(m_nTwoHandWeaponCode, bNewVisible);
SetWeaponEnhanceFx(m_nRightHandWeaponCode, bNewVisible);
SetWeaponEnhanceFx(m_nLeftHandWeaponCode, bNewVisible);
m_bPrevVisible = bNewVisible;
}
}
}
}
//Picking
bool SGameAvatarEx::CheckCollision(const K3DVector& nv, const K3DVector& fv)
{
if (!IsLoadComplete()) return false;
if (!IsActivated()) return false;
if (IsLive())
{
K3DBoundRotCube cube(m_fSelcube[0], m_fSelcube[3], m_fSelcube[1], m_fSelcube[4], m_fSelcube[2], m_fSelcube[5]);
cube.SetTransform(*GetTransform());
return cube.CheckCollision(nv, fv);
}
else
{
K3DBoundRotCube cube(m_fDeadcube[0], m_fDeadcube[3], m_fDeadcube[1], m_fDeadcube[4], m_fDeadcube[2], m_fDeadcube[5]);
cube.SetTransform(*GetTransform());
return cube.CheckCollision(nv, fv);
}
assert(0);
//Load 안되면, 클릭안돼~
return false;
}
bool SGameAvatarEx::RelaxedCheckCollision(const K3DVector& nv, const K3DVector& fv, K3DVALUE r)
{
if (!IsActivated()) return false;
if (IsLive())
{
K3DBoundRotCube cube(m_fSelcube[0] - r, m_fSelcube[3] + r, m_fSelcube[1] - r, m_fSelcube[4] + r, m_fSelcube[2] - r, m_fSelcube[5] + r);
cube.SetTransform(*GetTransform());
return cube.CheckCollision(nv, fv);
}
else
{
K3DBoundRotCube cube(m_fDeadcube[0] - r, m_fDeadcube[3] + r, m_fDeadcube[1] - r, m_fDeadcube[4] + r, m_fDeadcube[2] - r, m_fDeadcube[5] + r);
cube.SetTransform(*GetTransform());
return cube.CheckCollision(nv, fv);
}
assert(0);
//Load 안되면, 클릭안돼~
return false;
}
void SGameAvatarEx::SetStat(struct SMSG_STAT_INFO* pStat)
{
if (GetArID() == pStat->handle && pStat->type == 0)
{
if (m_pProperty)
m_pProperty->ProcMsgAtStatic(pStat);
}
}
bool SGameAvatarEx::IsRender()
{
if (!m_bVisible || !m_bIsActivated || !m_bIsInit || !m_xRenderFlag.IsOn(AV_BASIC))
return true;
if (m_nStateFlag & FLAG_STATE_HIDING)
{
if (m_fHidingVisiblity < HIDING_VISIBILITY_RATE)
return false;
}
if (IsPendLoading())
return false;
return true;
// return m_xRenderFlag.IsOn( AV_BASIC );
}
void SGameAvatarEx::SetHP(int nHP, bool IsEnter)
{
if (IsEnter) //공격 받은 후~
{
if (m_pProperty)
m_pProperty->HP = nHP;
//if( GetHP() <= 0 )
if (nHP <= 0)
{
m_bIsDead = true; //시체 엔터된 경우
NPlayAnimation(ANI_DEAD01, SEQTYPE_LASTPAGE);
SetAnimationPos(SEQPOS_END);
SetEventHandleNull();
if (m_pStateVM) m_pStateVM->Dead();
}
return;
}
else
{
if (m_pProperty)
m_pProperty->HP = nHP;
//살아난 것임.
if (IsDead() && nHP > 0)
{
m_bIsDead = false;
Default();
}
}
}
void SGameAvatarEx::SetMaxHP(int nMaxHP)
{
if (m_pProperty) m_pProperty->MaxHP = nMaxHP;
}
void SGameAvatarEx::SetMP(int nMP)
{
if (m_pProperty) m_pProperty->MP = nMP;
}
void SGameAvatarEx::SetMaxMP(int nMaxMP)
{
if (m_pProperty) m_pProperty->MaxMP = nMaxMP;
}
void SGameAvatarEx::AddExp(__int64 nExp)
{
if (m_pProperty) m_pProperty->AddExp(nExp);
}
void SGameAvatarEx::AddJP(__int64 nJp)
{
if (m_pProperty) m_pProperty->AddJP(nJp);
}
void SGameAvatarEx::SetRace(int nRace)
{
if (m_pProperty) m_pProperty->Race = nRace;
}
int SGameAvatarEx::GetRace()
{
if (m_pProperty)
return m_pProperty->Race;
return GCLAN_NOTHING;
}
int SGameAvatarEx::GetFace()
{
if (m_pProperty)
return m_pProperty->FaceID;
return 0;
}
int SGameAvatarEx::GetHair()
{
if (m_pProperty)
return m_pProperty->HairID;
return 0;
}
int SGameAvatarEx::GetLevel()
{
if (m_pProperty)
return m_pProperty->Level;
assert(0);
return 0;
}
int SGameAvatarEx::SetLevel(int nLevel)
{
if (!m_pProperty) return false;
return m_pProperty->SetLevel(nLevel);
}
int SGameAvatarEx::GetJobLevel()
{
if (m_pProperty)
return m_pProperty->JobLevel;
assert(0);
return 0;
}
int SGameAvatarEx::SetJobLevel(int nJobLevel)
{
if (!m_pProperty) return false;
return m_pProperty->SetJobLevel(nJobLevel);
}
/// 2011.07.11 - prodongi
void SGameAvatarEx::SetJobID(int id)
{
if (m_pProperty)
m_pProperty->SetJobID(id);
}
bool SGameAvatarEx::IsMasterClass(int id)
{
if (id % 100 >= 20) // 2011.7.13 - marine 마스터 클래스 아이디만 x20~x24
return true;
else
return false;
}
void SGameAvatarEx::SetStatus(unsigned status)
{
if (m_pProperty)
{
m_pProperty->Status = status;
}
}
int SGameAvatarEx::GetStatus()
{
if (m_pProperty)
return m_pProperty->Status;
return 0;
}
void SGameAvatarEx::SetObjType(unsigned char ObjType)
{
if (m_pProperty)
m_pProperty->ObjType = ObjType;
}
unsigned char SGameAvatarEx::GetObjType()
{
if (m_pProperty)
return m_pProperty->ObjType;
assert(0);
return -1;
}
ENC_INT SGameAvatarEx::GetContentID()
{
if (m_pProperty)
return m_pProperty->ContentID();
assert(0);
return -1;
}
int SGameAvatarEx::GetJobID()
{
if (m_pProperty)
return m_pProperty->JobID;
assert(0);
return -1;
}
bool SGameAvatarEx::IsLocalPlayer()
{
return m_bLocal;
}
bool SGameAvatarEx::IsLocalCreature()
{
return m_bLocalCreature;
}
bool SGameAvatarEx::IsLocalPet()
{
return m_bLocalPet;
}
int SGameAvatarEx::GetPercentEXP()
{
if (m_pProperty)
return m_pProperty->PercentEXP;
assert(0);
return -1;
}
int SGameAvatarEx::GetHP()
{
if (m_pProperty)
return m_pProperty->HP;
assert(0);
return -1;
}
int SGameAvatarEx::GetMP()
{
if (m_pProperty)
return m_pProperty->MP;
assert(0);
return -1;
}
int SGameAvatarEx::GetMaxHP()
{
if (m_pProperty)
return m_pProperty->MaxHP;
assert(0);
return -1;
}
int SGameAvatarEx::GetMaxMP()
{
if (m_pProperty)
return m_pProperty->MaxMP;
assert(0);
return -1;
}
__int64 SGameAvatarEx::GetEXP()
{
if (m_pProperty)
return m_pProperty->EXP;
assert(0);
return -1;
}
/// 2011.04.29 int->__int64 - prodongi
__int64 SGameAvatarEx::GetJP()
{
if (m_pProperty)
return m_pProperty->JP;
assert(0);
return -1;
}
const char* SGameAvatarEx::GetName()
{
if (m_pProperty)
return m_pProperty->Name;
assert(0);
return "UnLoad Avatar";
}
void SGameAvatarEx::SetName(const char* szName)
{
if (m_pProperty)
return m_pProperty->Name = szName;
assert(0);
}
bool SGameAvatarEx::IsLive()
{
if (m_pProperty)
return m_pProperty->IsLive();
assert(0);
return false;
}
AR_UNIT SGameAvatarEx::GetAttackRange()
{
if (m_pProperty)
return m_pProperty->AttackRange;
assert(0);
return 1;
}
float SGameAvatarEx::GetDBAttackRange()
{
if (m_pProperty)
return m_pProperty->DBAttackRange;
assert(0);
return 1.f;
}
void SGameAvatarEx::ProcMsgAtStatic(struct SGameMessage* pMsg)
{
//살아난 것임.
//if( pMsg->nType == MSG_REGEN_HPMP )
//{
// SMSG_REGEN_HPMP* pRegenHpMp = static_cast<SMSG_REGEN_HPMP*>(pMsg);
// if( GetHP() <= 0 && pRegenHpMp->hp > 0 )
// {
// Default();
// }
//}
if (m_pProperty) m_pProperty->ProcMsgAtStatic(pMsg);
if (pMsg->nType == MSG_STATE)
{ //상태 이상 리스트 추가/삭제
SMSG_STATE* pStateMsg = static_cast<SMSG_STATE*>(pMsg);
StateInfoEx* pStateInfo = GetTenacityDB().GetTenacityData(pStateMsg->state_code);
if (pStateInfo)
{
//104, 114 변이 유형
switch (pStateInfo->effect_type)
{
case STATE_TYPE::STATE_MUTATION_A: //몬스터 전용
{
if (pStateMsg->state_level) //변이
{
if ((int)pStateInfo->fValue[0] > 0)
{
AddDisguiseID(pStateInfo->id);
Disguise(pStateMsg->state_handle, bits_scramble< int, 3 >((int)pStateInfo->fValue[0])); // 2.1.16 변신 효과 중첩시 아바타 사라지는 오류 수정
}
}
else if (pStateMsg->state_level == 0) //해제
{
DeleteDisguiseID(pStateInfo->id);
UnDisguise(pStateMsg->state_handle);
}
}
break;
case STATE_TYPE::STATE_MUTATION_B: //소환수 전용
{
if (pStateMsg->state_level) //변이
{
if (pStateMsg->state_value > 0)
{
AddDisguiseID(pStateInfo->id);
/// 2011.07.28 redmine #16797 - prodongi
Disguise(pStateMsg->state_handle, pStateMsg->state_value, true, pStateMsg->state_level); // 2.1.16 변신 효과 중첩시 아바타 사라지는 오류 수정
/// 2011.04.29 변신전의 크기를 기준으로 해야 된다 - prodongi
/*
if( m_nDisguise == STAT_DISGUISE )
SetScale( GetScale() * ( pStateInfo->fValue[8] + pStateInfo->fValue[9] * pStateMsg->state_level ));
*/
if (m_nDisguise == STAT_DISGUISE)
{
/// 2012.08.10 변신 전의 크기를 적용하면 쿨타임이 짧은 경우에 중복 적용될 수가 있어서, 기본에서 적용 시킨다. - prodongi
//SetScale( getNoneDisguiseScale() * ( pStateInfo->fValue[8] + pStateInfo->fValue[9] * pStateMsg->state_level ));
SetScale(getNoneDisguiseScale() * (pStateInfo->fValue[8] + pStateInfo->fValue[9]));
}
}
}
else if (pStateMsg->state_level == 0) //해제
{
DeleteDisguiseID(pStateInfo->id);
UnDisguise(pStateMsg->state_handle);
}
}
break;
case STATE_TYPE::STATE_RESURRECTION:
{
if (pStateMsg->state_level)
AddStateFlag(FLAG_STATE_RESURRECTION);
else if (pStateMsg->state_level == 0)
RemoveStateFlag(FLAG_STATE_RESURRECTION);
}
break;
/* AziaMafia Fix MEZZ
case STATE_TYPE::EF_MEZZ:
{
if (pStateMsg->state_level)
AddStateFlag(FLAG_STATE_SLEEP);
else if (pStateMsg->state_level == 0)
RemoveStateFlag(FLAG_STATE_SLEEP);
}
break;
*/
case STATE_TYPE::STATE_DETECT_HIDING:
{
if (pStateMsg->state_level)
{
StateInfoEx* pStateInfo = GetTenacityDB().GetTenacityData(pStateMsg->state_code);
if (pStateInfo) SetHidingDetectRange(pStateInfo->fValue[0] * (float)DEFAULT_UNIT_SIZE);
AddStateFlag(FLAG_STATE_DETECT_HIDING);
}
else if (pStateMsg->state_level == 0)
{
SetHidingDetectRange(0.0f);
RemoveStateFlag(FLAG_STATE_DETECT_HIDING);
}
}
break;
}
}
switch (pStateMsg->state_code) //석화 처리
{
case STATE_CODE::PETRIFY:
case STATE_CODE::STONECURSE_MORTAL:
{
if (pStateMsg->state_level)
{
KMsgSET_FIXTEXTURE msgFixTexture;
msgFixTexture.bUseFix = true;
msgFixTexture.pTexture = _getTexture("petrify00.dds");
SetFixTexture(&msgFixTexture);
AddStateFlag(FLAG_STATE_PETRIFY);
}
else if (pStateMsg->state_level == 0)
{
KMsgSET_FIXTEXTURE msgFixTexture;
msgFixTexture.bUseFix = false;
SetFixTexture(&msgFixTexture);
RemoveStateFlag(FLAG_STATE_PETRIFY);
}
}
break;
case STATE_CODE::HIDING:
case STATE_CODE::TRACE_OF_FUGITIVE:
{
if (pStateMsg->state_level)
{
if (IsLocalPlayer()) SetHidingVisiblity(HIDING_VISIBILITY_RATE);
else SetHidingVisiblity(0.0f);
AddStateFlag(FLAG_STATE_HIDING);
RemoveAllStateEffect();
}
else if (pStateMsg->state_level == 0)
{
SetHidingVisiblity(1.0f);
RemoveStateFlag(FLAG_STATE_HIDING);
RefreshAllStateEffect();
}
}
break;
//gmpbigsun( 20131107 ) : lockmoving by state
case SLEEP:
case NIGHTMARE:
case SCELLE:
case ANOMALY_SLEEP:
case MONSTER_SLEEP:
pStateMsg->state_level == 0 ? RemoveStateFlag(FLAG_STATE_SLEEP) : AddStateFlag(FLAG_STATE_SLEEP);
break;
case STUN:
case ILLUSION:
case FALL_FROM_SUMMON:
case CARELESSNESS:
case DEMONIC_STUN:
case ANOMALY_STUN:
case ANOMALY_ILLUSION:
case MONSTER_STUN:
pStateMsg->state_level == 0 ? RemoveStateFlag(FLAG_STATE_STUN) : AddStateFlag(FLAG_STATE_STUN);
break;
case HOLD:
case FROZEN_SNARE:
case EARTH_RESTRICTION:
case EARTH_TREMOR:
case ANOMALY_HOLD:
pStateMsg->state_level == 0 ? RemoveStateFlag(FLAG_STATE_HOLD) : AddStateFlag(FLAG_STATE_HOLD);
break;
case FEAR:
case DRAGONIC_FEAR:
case ANOMALY_FEAR:
pStateMsg->state_level == 0 ? RemoveStateFlag(FLAG_STATE_FEAR) : AddStateFlag(FLAG_STATE_FEAR);
break;
case FROZEN:
case ANOMALY_FROZEN:
case TOTAL_FROZEN:
pStateMsg->state_level == 0 ? RemoveStateFlag(FLAG_STATE_FROZEN) : AddStateFlag(FLAG_STATE_FROZEN);
break;
}
UpdateState(pStateMsg);
return;
}
}
const char* SGameAvatarEx::GetEffectPosName(std::string& strName)
{
CStringUtil::GetEventStrKey(strName.c_str(), '.', m_strTemp);
return m_strTemp.c_str();
return "";
}
const char* SGameAvatarEx::GetCobFileName()
{
if (GetInnObjType() == TS_ENTER::GAME_MOB)
return GetMonsterDB().GetCobFileName(GetInnContentID());
else if (GetInnObjType() == TS_ENTER::GAME_SUMMON)
{
return GetCreatureDB().GetCobFileName(GetInnContentID());
}
else if (GetInnObjType() == TS_ENTER::GAME_NPC)
{
// NpcResourceBase * pNPC = GetNpcResourceDB().GetNpcInfo( GetInnContentID() );
// if( pNPC )
{
std::string str = SStringDB::GetCobFileName(GetInnRace(), GetInnSex());
if (str.empty())
return GetNpcResourceDB().GetCobFileName(GetInnContentID());
else
return SStringDB::GetCobFileName(GetInnRace(), GetInnSex());
}
// else
// return GetNpcResourceDB().GetCobFileName( GetInnContentID() );
}
else if (GetInnObjType() == TS_ENTER::GAME_PLAYER)
return SStringDB::GetCobFileName(GetInnRace(), GetInnSex());
else if (GetInnObjType() == TS_ENTER::GAME_PET) // sonador 10.2.1 팻 시스템 구현
return GetPetDB().Find(GetInnContentID()).getModelFileName();
assert(0 && "Avatar 의 Type이 비정상적임");
return " ";
}
KSeqAvatarEx* SGameAvatarEx::LoadCOBSet(vec_cobset* pSet)
{
if (!pSet) return NULL;
KSeqAvatarEx* pSeqAvatar = new KSeqAvatarEx;
pSeqAvatar->Initialize();
pSeqAvatar->ClearAnimation();
iterator_cobset it = pSet->begin();
if (pSet->end() != it)
{
COBSET* pCob = *it;
LoadEvent(pCob);
}
if (GetInnObjType() == TS_ENTER::PLAYER)
LoadPlayerCOBSet(pSet, pSeqAvatar);
else if (GetInnObjType() == TS_ENTER::GAME_NPC)
LoadNpcCOBSet(pSet, pSeqAvatar);
else
LoadMonsterCOBSet(pSet, pSeqAvatar);
return pSeqAvatar;
}
void SGameAvatarEx::LoadPlayerCOBSet(vec_cobset* pSet, KSeqAvatarEx* pSeqAvatar)
{
iterator_cobset it = pSet->begin();
for (it = pSet->begin(); pSet->end() != it; it++)
{
COBSET* pCob = *it;
//TODO : 손보자
for (unsigned int j(0); pCob->m_AniList.size() > j; j++)
{
if (strstr(pCob->m_AniList[j].c_str(), "una_") &&
(strstr(pCob->m_AniList[j].c_str(), "default") ||
strstr(pCob->m_AniList[j].c_str(), "walk") ||
strstr(pCob->m_AniList[j].c_str(), "run")))
pSeqAvatar->AddAnimation(pCob->nAniPart, pCob->m_AniList[j].c_str(), true);
}
for (unsigned int j(0); pCob->m_HairList.size() > j; j++)
{
if (m_pProperty)
{
//std::string strHair = GetDefaultItemDB().GetFileName( GetRace(), GetSex(), GetHair() );
//pSeqAvatar->AddMesh( ANIPART_HAIR, MPART_HAIR, strHair.c_str() );
std::string strHair = GetDefaultItemDB().GetFileName(GetRace(), GetSex(), GetHair());
int nGroup = GetDefaultItemDB().GetDecoHairGroupID(GetHair());
std::string strDeco = GetDefaultTextureResourceDB().GetTextureName(nGroup, GetRace(), GetSex());
pSeqAvatar->AddMesh(ANIPART_BIPED, MPART_HAIR, strHair.c_str(), strDeco);
}
else
AddCommonMesh(pSeqAvatar, pCob, MPART_HAIR);
}
AddCommonMesh(pSeqAvatar, pCob, MPART_HELM);
AddCommonMesh(pSeqAvatar, pCob, MPART_MANTLE);
for (unsigned int j(0); pCob->m_FaceList.size() > j; j++)
{
if (m_pProperty)
{
std::string strFace = GetDefaultItemDB().GetFileName(GetRace(), GetSex(), GetFace());
// 2010.06.18 - prodongi
/*
// 2010.04.22 - prodongi
//std::string strDeco = GetDefaultTextureResourceDB().GetDecoTextureName();
std::string strDeco = getDecoTextureName();
*/
std::string strDeco;
getDecoTexName(strDeco);
pSeqAvatar->AddMesh(ANIPART_BIPED, MPART_FACE, strFace.c_str(), strDeco);
}
else
AddCommonMesh(pSeqAvatar, pCob, MPART_FACE);
}
AddCommonMesh(pSeqAvatar, pCob, MPART_BODY);
AddCommonMesh(pSeqAvatar, pCob, MPART_HAND);
AddCommonMesh(pSeqAvatar, pCob, MPART_FOOT);
AddCommonMesh(pSeqAvatar, pCob, MPART_L_WEAPON);
AddCommonMesh(pSeqAvatar, pCob, MPART_R_WEAPON);
}
}
void SGameAvatarEx::LoadMonsterCOBSet(vec_cobset* pSet, KSeqAvatarEx* pSeqAvatar)
{
iterator_cobset it = pSet->begin();
for (it = pSet->begin(); pSet->end() != it; it++)
{
COBSET* pCob = *it;
for (unsigned int j(0); pCob->m_AniList.size() > j; j++)
{
//스쳐 지나가는 몹일수도 있으니 디폴트 모션과 뛰는 모션만 바로 로딩
if (strstr(pCob->m_AniList[j].c_str(), "default") ||
strstr(pCob->m_AniList[j].c_str(), "run"))
{
pSeqAvatar->AddAnimation(pCob->nAniPart, pCob->m_AniList[j].c_str(), true);
}
else
pSeqAvatar->AddAnimation(pCob->nAniPart, pCob->m_AniList[j].c_str(), false);
}
AddMesh(pSeqAvatar, pCob, MPART_HAIR);
AddMesh(pSeqAvatar, pCob, MPART_HELM);
AddMesh(pSeqAvatar, pCob, MPART_MANTLE);
AddMesh(pSeqAvatar, pCob, MPART_FACE);
AddMesh(pSeqAvatar, pCob, MPART_BODY);
AddMesh(pSeqAvatar, pCob, MPART_S_SKIRT);
AddMesh(pSeqAvatar, pCob, MPART_S_SKIRT);
AddMesh(pSeqAvatar, pCob, MPART_S_SKIRT);
AddMesh(pSeqAvatar, pCob, MPART_FABRIC);
AddMesh(pSeqAvatar, pCob, MPART_HAND);
AddMesh(pSeqAvatar, pCob, MPART_FOOT);
AddMesh(pSeqAvatar, pCob, MPART_L_WEAPON);
AddMesh(pSeqAvatar, pCob, MPART_R_WEAPON);
AddMesh(pSeqAvatar, pCob, MPART_S_SKIRT);
}
}
void SGameAvatarEx::LoadNpcCOBSet(vec_cobset* pSet, KSeqAvatarEx* pSeqAvatar)
{
int nRace = 0;
NpcResourceBase* pNPC = GetNpcResourceDB().GetNpcInfo(GetInnContentID());
if (pNPC)
nRace = pNPC->race_id;
iterator_cobset it = pSet->begin();
for (it = pSet->begin(); pSet->end() != it; it++)
{
COBSET* pCob = *it;
for (unsigned int j(0); pCob->m_AniList.size() > j; j++)
{
if (strstr(pCob->m_AniList[j].c_str(), "default") || strstr(pCob->m_AniList[j].c_str(), "run"))
pSeqAvatar->AddAnimation(pCob->nAniPart, pCob->m_AniList[j].c_str(), true);
else
pSeqAvatar->AddAnimation(pCob->nAniPart, pCob->m_AniList[j].c_str(), false);
}
if (nRace == 99)
{
for (unsigned int j(0); pCob->m_HairList.size() > j; j++)
{
if (m_pProperty)
{
//std::string strHair = GetDefaultItemDB().GetFileName( GetRace(), GetSex(), GetHair() );
//pSeqAvatar->AddMesh( ANIPART_BIPED, MPART_HAIR, strHair.c_str() );
std::string strHair = GetDefaultItemDB().GetFileName(GetRace(), GetSex(), GetHair());
int nGroup = GetDefaultItemDB().GetDecoHairGroupID(GetHair());
std::string strDeco = GetDefaultTextureResourceDB().GetTextureName(nGroup, GetRace(), GetSex());
pSeqAvatar->AddMesh(ANIPART_BIPED, MPART_HAIR, strHair.c_str(), strDeco);
}
else
AddMesh(pSeqAvatar, pCob, MPART_HAIR);
}
AddMesh(pSeqAvatar, pCob, MPART_HELM);
AddMesh(pSeqAvatar, pCob, MPART_MANTLE);
for (unsigned int j(0); pCob->m_FaceList.size() > j; j++)
{
if (m_pProperty)
{
std::string strFace = GetDefaultItemDB().GetFileName(GetRace(), GetSex(), GetFace());
pSeqAvatar->AddMesh(ANIPART_BIPED, MPART_FACE, strFace.c_str());
}
else
AddMesh(pSeqAvatar, pCob, MPART_FACE);
}
AddMesh(pSeqAvatar, pCob, MPART_BODY);
AddMesh(pSeqAvatar, pCob, MPART_S_SKIRT);
AddMesh(pSeqAvatar, pCob, MPART_M_SKIRT);
AddMesh(pSeqAvatar, pCob, MPART_L_SKIRT);
AddMesh(pSeqAvatar, pCob, MPART_FABRIC);
AddMesh(pSeqAvatar, pCob, MPART_HAND);
AddMesh(pSeqAvatar, pCob, MPART_FOOT);
AddMesh(pSeqAvatar, pCob, MPART_L_WEAPON);
AddMesh(pSeqAvatar, pCob, MPART_R_WEAPON);
}
else
{
for (unsigned int j(0); pCob->m_HairList.size() > j; j++)
{
if (m_pProperty)
{
//std::string strHair = GetDefaultItemDB().GetFileName( GetRace(), GetSex(), GetHair() );
//pSeqAvatar->AddMesh( ANIPART_HAIR, MPART_HAIR, strHair.c_str() );
std::string strHair = GetDefaultItemDB().GetFileName(GetRace(), GetSex(), GetHair());
int nGroup = GetDefaultItemDB().GetDecoHairGroupID(GetHair());
std::string strDeco = GetDefaultTextureResourceDB().GetTextureName(nGroup, GetRace(), GetSex());
pSeqAvatar->AddMesh(ANIPART_BIPED, MPART_HAIR, strHair.c_str(), strDeco);
break;
}
else
AddCommonMesh(pSeqAvatar, pCob, MPART_HAIR, true);
}
AddCommonMesh(pSeqAvatar, pCob, MPART_HELM, true);
AddCommonMesh(pSeqAvatar, pCob, MPART_MANTLE, true);
for (unsigned int j(0); pCob->m_FaceList.size() > j; j++)
{
if (m_pProperty)
{
std::string strFace = GetDefaultItemDB().GetFileName(GetRace(), GetSex(), GetFace());
pSeqAvatar->AddMesh(ANIPART_BIPED, MPART_FACE, strFace.c_str());
break;
}
else
AddCommonMesh(pSeqAvatar, pCob, MPART_FACE, true);
}
AddCommonMesh(pSeqAvatar, pCob, MPART_BODY, true);
AddMesh(pSeqAvatar, pCob, MPART_S_SKIRT);
AddMesh(pSeqAvatar, pCob, MPART_M_SKIRT);
AddMesh(pSeqAvatar, pCob, MPART_L_SKIRT);
AddMesh(pSeqAvatar, pCob, MPART_FABRIC);
AddCommonMesh(pSeqAvatar, pCob, MPART_HAND, true);
AddCommonMesh(pSeqAvatar, pCob, MPART_FOOT, true);
AddCommonMesh(pSeqAvatar, pCob, MPART_L_WEAPON, true);
AddCommonMesh(pSeqAvatar, pCob, MPART_R_WEAPON, true);
}
}
}
void SGameAvatarEx::AddMesh(KSeqAvatarEx* pSeqAvatar, COBSET* pCob, int nMeshPart)
{
std::vector< std::string >* pMeshList = pCob->GetPartNameList(nMeshPart);
if (!pMeshList) return;
std::vector< std::string >::iterator iter = pMeshList->begin();
for (; iter != pMeshList->end(); ++iter)
pSeqAvatar->AddMesh(pCob->nAniPart, nMeshPart, (*iter).c_str());
}
void SGameAvatarEx::AddCommonMesh(KSeqAvatarEx* pSeqAvatar, COBSET* pCob, int nMeshPart, bool bIsNpc)
{
std::vector< std::string >* pMeshList = pCob->GetPartNameList(nMeshPart);
if (!pMeshList) return;
std::vector< std::string >::iterator iter = pMeshList->begin();
for (; iter != pMeshList->end(); ++iter)
{
if (strstr((*iter).c_str(), "common"))
{
pSeqAvatar->AddMesh(pCob->nAniPart, nMeshPart, (*iter).c_str());
if (bIsNpc) break;
}
}
}
void SGameAvatarEx::LoadUseAnimation(KSeqAvatarEx* pSeqAvatarEx)
{
if (!pSeqAvatarEx) return;
DWORD dwStartTime = GetSafeTickCount();
bool bIsNpc = false;
if (GetInnObjType() == TS_ENTER::NPC) bIsNpc = true;
// _oprint( "애니메이션 Loading Start\n" );
/// 2010.11.30 - prodongi
std::vector< int >* pAniList = GetMotionSetDB().GetAniClass(GetRace(), GetSex(), m_nThreadAniClass);
if (pAniList)
{
pSeqAvatarEx->ClearAnimation();
//타겟 창 Animation은 항상 갖고 있는다.
{
//const char * pSex[] = { "n", "f", "m", };
//const char * pRace[] = { "non", "mob", "npc", "ga", "de", "as", "af", "gi", "am", };
if (GetRace() >= GCLAN_NOTHING && GetRace() < GCLAN_MAX &&
GetSex() >= SEX_NONE && GetSex() < SEX_MAX)
{
std::string strAniName, strAniFullName;
strAniName = pRace[GetRace()];
strAniName += pSex[GetSex()];
strAniName += "_una_default01";
for (int i(0); ANIPART_MAX > i; i++)
{
strAniFullName = strAniName;
strAniFullName += pPartExt[i];
pSeqAvatarEx->AddAnimation(i, strAniFullName.c_str(), true);
}
}
}
// _oprint( "애니메이션 Loading 01 [ %d ]\n", GetSafeTickCount()-dwStartTime );
dwStartTime = GetSafeTickCount();
int nCnt = 0;
/// 2010.11.30 - prodongi
std::vector< int >::iterator it = pAniList->begin();
for (; it != pAniList->end(); it++)
{
/// 2010.11.30 - prodongi
const char* pAni = GetCharacterMotionEventDB().getFileName(*it);
if (strlen(pAni) < 2) continue;
//COB Biped Name
std::string strAniName, strAniFullName;
CStringUtil::GetEventStrKey(pAni, '_', strAniName);
//_oprint( "무기 체인지 [%d] : %s\n", nCnt++, pAni );
bool bNowLoad = false;
if (strAniName.length() > 0)
{
if (bIsNpc)
{
if (strstr(strAniName.c_str(), "default")) //|| strstr( strAniName.c_str(), "run" ) ) //나중에 이동 가능 NPC가 추가 된다면 이동/이동불가능 여부 체크후 로딩 판단
{
if (strstr(strAniName.c_str(), "ride"))
{
continue;
}
bNowLoad = true;
}
}
else
{
if (strstr(strAniName.c_str(), "default") ||
strstr(strAniName.c_str(), "run"))
/* strstr( strAniName.c_str(), "attack" )
strstr( strAniName.c_str(), "cast" )
strstr( strAniName.c_str(), "damage" )*/
{
if (strstr(strAniName.c_str(), "ride") == 0)
{
bNowLoad = true;
}
}
}
for (int i(0); ANIPART_MAX > i; i++)
{
strAniFullName = strAniName;
strAniFullName += pPartExt[i];
// _oprint( "무기 체인지 : %s\n", strAniFullName.c_str() );
pSeqAvatarEx->AddAnimation(i, strAniFullName.c_str(), bNowLoad);
}
}
}
// _oprint( "애니메이션 Loading 02 [ %d ]\n", GetSafeTickCount()-dwStartTime );
}
// _oprint( "애니메이션 Loading End\n" );
}
void SGameAvatarEx::SetMotionEventHandle(const char* pAni, struct _CHARACTER_MOTION* pMotionInfo, std::vector< Key_EVENT_NEW >& eventlist, KSVEC_KEVENT_RES& svHandleList)
{
_KEY_EVENT_RES* keyEvent = new _KEY_EVENT_RES;
keyEvent->SetKeyCount((int)eventlist.size(), (160 * pMotionInfo->nFrame_Length) / 4.8f);
keyEvent->SetKey(0, &eventlist[0], (int)eventlist.size());
keyEvent->SetName(pAni);
_KEY_EVENT_RES* pFind = NULL;
if (svHandleList.lookup(pAni, pFind))
{
assert(0);
}
else
{
svHandleList.add(pAni, keyEvent);
}
}
void SGameAvatarEx::AddEvent(std::vector< Key_EVENT_NEW >& eventlist, int nEventID, int nTiming)
{
if (nTiming <= 0) return;
Key_EVENT_NEW key;
key.bUse = false;
key.time = (160 * nTiming) / 4.8f;
key.nHandleID = nEventID;
eventlist.push_back(key);
}
void SGameAvatarEx::LoadEvent(COBSET* pCob)
{
//NPC는 데이타 없음.
if (GetInnObjType() == TS_ENTER::GAME_NPC) return;
if (!pCob) return;
if (pCob->nAniPart == ANIPART_BIPED)
{
for (unsigned int i(0); pCob->m_AniList.size() > i; i++)
{
//뒤에 부분만 잘른다.
std::string strAni;
#if defined( _DEBUG )
std::string strAniKey, strKey;
CStringUtil::GetEventStrKey(pCob->m_AniList[i].c_str(), '_', strKey);
CStringUtil::GetStrKey(pCob->m_AniList[i].c_str(), '_', strAniKey);
#endif
CStringUtil::GetEventStrKey(pCob->m_AniList[i].c_str(), '.', strAni);
SetEventData(strAni.c_str());
}
if (GetInnObjType() == TS_ENTER::GAME_MOB)
{
int nAniSize = (int)pCob->m_AniList.size();
bool bUseDBDeadMotion = true;
for (int i(0); i < nAniSize; ++i)
{
if (strstr(pCob->m_AniList[i].c_str(), "una_") && strstr(pCob->m_AniList[i].c_str(), "dead"))
{
bUseDBDeadMotion = false; //Cob에 Dead 모션이 포함돼 있다면 패스
break;
}
}
if (bUseDBDeadMotion) //Cob에 Dead 모션이 없다면
{
_MONSTER_INFO_FILE* pMonster = GetMonsterDB().GetMonsterData(GetInnContentID());
if (pMonster) //DB에서 모션을 찾았다면
{
const char* pDeadAni01 = GetMonsterMotionSetDB().GetAni(pMonster->motion_file_id, ANI_DEAD01);
const char* pDeadAni02 = GetMonsterMotionSetDB().GetAni(pMonster->motion_file_id, ANI_DEAD02);
if (pDeadAni01) SetEventData(pDeadAni01);
if (pDeadAni02) SetEventData(pDeadAni02);
}
}
}
}
}
void SGameAvatarEx::SetEventData(const char* szAniName)
{
_CHARACTER_MOTION* pMotionEvent = GetCharacterMotionEventDB().GetAniEvent(szAniName);
if (pMotionEvent)
{
std::vector< Key_EVENT_NEW > eventlist00_effect;
std::vector< Key_EVENT_NEW > eventlist00_sound;
std::vector< Key_EVENT_NEW > eventlist00_motioin_effect;
std::vector< Key_EVENT_NEW > eventlist01;
std::vector< Key_EVENT_NEW > eventlist02;
std::vector< Key_EVENT_NEW > eventlist03;
std::vector< Key_EVENT_NEW > eventlist04;
std::vector< Key_EVENT_NEW > eventlist05;
std::vector< Key_EVENT_NEW > eventlist06;
//Main 이벤트는 예외로 이벤트 핸들을 안 쓰고, 화일을 직접 사용.
if (pMotionEvent->graphic_effect_file_ID > 0 || pMotionEvent->nGraphic_effect_speed_type == 2)
{ //시작 하자 마자 무조건 출력
Key_EVENT_NEW key;
key.bUse = false;
key.time = 0;
key.nHandleID = 0;
key.nEffPos = pMotionEvent->nGraphic_effect_position;
key.strEffect = GetResourceDB().GetEffectResourceName(pMotionEvent->graphic_effect_file_ID);
key.nSpeedType = pMotionEvent->nGraphic_effect_speed_type;
key.followflag = pMotionEvent->graphic_effect_follow;
eventlist00_effect.push_back(key);
}
//Main 이벤트는 예외로 이벤트 핸들을 안 쓰고, 화일을 직접 사용.
if (pMotionEvent->nSound_timing > 0)
{
Key_EVENT_NEW key;
key.bUse = false;
key.time = (160 * pMotionEvent->nSound_timing) / 4.8f;
key.nHandleID = 0;
key.nSoundVolume = pMotionEvent->nSound_volumn;
key.nSound_play_probability = pMotionEvent->nSound_play_probability;
key.strSound = GetResourceDB().GetSoundResourceName(pMotionEvent->sound_file_ID);
key.followflag = 0;
key.SoundOption[0] = pMotionEvent->sound_reverb_apply == 0 ? false : true;
key.SoundOption[1] = pMotionEvent->sound_filter_apply == 0 ? false : true;
key.SoundOption[2] = pMotionEvent->sound_stereo_apply == 0 ? false : true;
eventlist00_sound.push_back(key);
}
//모션 특정 프레임에 출력될 이펙트
if (pMotionEvent->fx_id != 0)
{
Key_EVENT_NEW key;
key.bUse = false;
key.time = (160 * pMotionEvent->fx_timing) / 4.8f;
key.nHandleID = 0;
key.nSoundVolume = 100;
key.nSound_play_probability = 100;
key.strSound = "";
key.nFXsetID = pMotionEvent->fx_id;
key.nEffPos = pMotionEvent->fx_position;
key.fPlayRate = (float)pMotionEvent->fx_play_speed * 4.8f;
key.followflag = 0;
eventlist00_motioin_effect.push_back(key);
}
AddEvent(eventlist01, pMotionEvent->nEvent01_id, pMotionEvent->nEvent01_timing);
AddEvent(eventlist02, pMotionEvent->nEvent02_id, pMotionEvent->nEvent02_timing);
AddEvent(eventlist03, pMotionEvent->nEvent03_id, pMotionEvent->nEvent03_timing);
AddEvent(eventlist04, pMotionEvent->nEvent04_id, pMotionEvent->nEvent04_timing);
AddEvent(eventlist05, pMotionEvent->nEvent05_id, pMotionEvent->nEvent05_timing);
AddEvent(eventlist06, pMotionEvent->nEvent06_id, pMotionEvent->nEvent06_timing);
if (!eventlist00_effect.empty()) SetMotionEventHandle(szAniName, pMotionEvent, eventlist00_effect, m_svEventHandle00_effectList);
if (!eventlist00_sound.empty()) SetMotionEventHandle(szAniName, pMotionEvent, eventlist00_sound, m_svEventHandle00_soundList);
if (!eventlist00_motioin_effect.empty()) SetMotionEventHandle(szAniName, pMotionEvent, eventlist00_motioin_effect, m_svEventHandle00_motion_effect);
if (!eventlist01.empty()) SetMotionEventHandle(szAniName, pMotionEvent, eventlist01, m_svEventHandle01_List);
if (!eventlist02.empty()) SetMotionEventHandle(szAniName, pMotionEvent, eventlist02, m_svEventHandle02_List);
if (!eventlist03.empty()) SetMotionEventHandle(szAniName, pMotionEvent, eventlist03, m_svEventHandle03_List);
if (!eventlist04.empty()) SetMotionEventHandle(szAniName, pMotionEvent, eventlist04, m_svEventHandle04_List);
if (!eventlist05.empty()) SetMotionEventHandle(szAniName, pMotionEvent, eventlist05, m_svEventHandle05_List);
if (!eventlist06.empty()) SetMotionEventHandle(szAniName, pMotionEvent, eventlist06, m_svEventHandle06_List);
eventlist00_effect.clear();
eventlist00_sound.clear();
eventlist00_motioin_effect.clear();
eventlist01.clear();
eventlist02.clear();
eventlist03.clear();
eventlist04.clear();
eventlist05.clear();
eventlist06.clear();
}
}
void SGameAvatarEx::AllWorkEnd()
{
std::vector< SGameWork* >::iterator it;
//일반
if (!m_vWorkList.empty())
{
it = m_vWorkList.begin();
(*it)->SetEnd(TRUE);
}
//공격 이벤트
if (!m_vAttackEventList.empty())
{
it = m_vAttackEventList.begin();
(*it)->SetEnd(TRUE);
}
//스킬 이벤트
if (!m_vSkillEventList.empty())
{
it = m_vSkillEventList.begin();
(*it)->SetEnd(TRUE);
}
}
void SGameAvatarEx::_processEvent(_KEY_EVENT_RES* pEventHandle, DWORD dwAniTime)
{
// TODO: Check this later; Performance tweak
Key_EVENT_NEW* pKey1 = NULL;
Key_EVENT_NEW* pKey2 = NULL;
pEventHandle->GetData(dwAniTime, pKey1, pKey2);
if (pKey1 && pKey1->bUse == false)
{
pKey1->bUse = true; //사용.
_MOTION_EVENT_HANDER* pEventHandler = GetMotionEventHanderDB().GetScript(pKey1->nHandleID);
if (pEventHandler == NULL) return;
std::string strScript;
if (m_bFootsteps && m_sMoveSound)
{
switch (pKey1->nHandleID)
{
// case SMotionEventHanderDB::EV_HIT : break;//힛팅
// case SMotionEventHanderDB::EV_SHOOT : break;//슈팅
case SMotionEventHanderDB::EV_WALK:
XStringUtil::Format(strScript, "%s( %u )", pEventHandler->szScript, GetArID());
break;//스텝_걷기
case SMotionEventHanderDB::EV_RUN:
XStringUtil::Format(strScript, "%s( %u )", pEventHandler->szScript, GetArID());
break;//스텝_뛰기
case SMotionEventHanderDB::EV_MWALK:
XStringUtil::Format(strScript, "%s( %u )", pEventHandler->szScript, GetArID());
break;//몬스터스텝_걷기
case SMotionEventHanderDB::EV_MRUN:
XStringUtil::Format(strScript, "%s( %u )", pEventHandler->szScript, GetArID());
break;//몬스터스텝_뛰기
}
}
if (strScript.empty())
{
switch (pKey1->nHandleID)
{
case SMotionEventHanderDB::EV_DEAD: XStringUtil::Format(strScript, "%s( %u )", pEventHandler->szScript, GetArID()); break;//캐릭터사망시 땅에부딛힘
case SMotionEventHanderDB::EV_SWING: XStringUtil::Format(strScript, "%s( %u )", pEventHandler->szScript, GetArID()); break;//무기휘두름(사운드)
case SMotionEventHanderDB::EV_WEAPON_HIT: XStringUtil::Format(strScript, "%s( %u )", pEventHandler->szScript, GetArID()); break;//무기히트(피격처리)
case SMotionEventHanderDB::EV_SCREAM: XStringUtil::Format(strScript, "%s( %u )", pEventHandler->szScript, GetArID()); break;//맞을때비명(랜덤처리)
}
}
if (strScript.length())
{
LUA()->RunString(strScript.c_str());
// _oprint( "스크립트 출력 : %s\n", pEventHandler->szScript );
}
}
}
void SGameAvatarEx::_processDef()
{
for (unsigned int i(0); m_vAttackEventList.size() > i; i++)
m_vAttackEventList[i]->Process(m_dwTime);
for (unsigned int i(0); m_vWorkList.size() > i; i++)
m_vWorkList[i]->Process(m_dwTime);
for (unsigned int i(0); m_vSkillEventList.size() > i; i++)
m_vSkillEventList[i]->Process(m_dwTime);
//공격 이벤트 지우기~
if (!m_vAttackEventList.empty())
CheckWorkDel(m_vAttackEventList);
//스킬 이벤트 지우기~
//Work
if (!m_vSkillEventList.empty())
CheckWorkDel(m_vSkillEventList);
//Work
if (!m_vWorkList.empty())
CheckWorkDel(m_vWorkList);
if (!IsStateRide())
{
AvatarRotationProcess(m_dwTime);
K3DVector pos;
/// local에 따라서 나눈 이유는 항상 getMyPos()를 써도 되는지 확실하지 않기 때문이다.
if (IsLocalPlayer() || IsLocalCreature())
{
if (isKMoving())
pos = getMyPos();
else
pos = GetCurPosWithChangeDir();
}
else
{
pos = GetCurPosWithChangeDir();
}
if (m_vCheckPos.x != pos.x || m_vCheckPos.y != pos.y)
{
GetHeight(pos.x, pos.y, pos.z, m_wCurTile);
PlayerInsideWaterExistence(pos, m_bInWater);
m_vCheckPos = pos;
}
SetPosition(m_vCheckPos);
}
//Ani 처리
if (m_pSeqAvatar && m_bIsInit)
{
m_nProcess_state = m_pSeqAvatar->Process(m_dwTime);
//아바타 감추었을때, 위치는 갱신 한다.
if (m_pSeqAvatar && !m_xRenderFlag.IsOn(AV_BASIC))
{
m_pSeqAvatar->SetTransform(*GetTransform());
}
//마지막 꺼에서, 재 초기화
if (m_nProcess_state == KSeqAvatar::SEQINFO_LOOPWRAP)
{
SetEventHandleInit();
}
}
DWORD dwAniTime = GetAniTime();
if (m_pCurEventHandle00_effect)
{
Key_EVENT_NEW* pKey1 = NULL;
Key_EVENT_NEW* pKey2 = NULL;
m_pCurEventHandle00_effect->GetData(dwAniTime, pKey1, pKey2);
if (pKey1 && pKey1->bUse == false)
{
FindMotionAddOnFx();
if (pKey1->nSpeedType == 0)
{
pKey1->bUse = true; //사용.
//방향성 다시 잡아야 함.
AddEffect(&FX_DATA_EX(pKey1->strEffect.c_str(), pKey1->followflag, GetArID(), GetArID(), GetArID(), pKey1->nEffPos, false, 0, m_fCurPlayRate));
}
else if (pKey1->nSpeedType == 2)
{
pKey1->bUse = true; //사용.
//방향성 다시 잡아야 함.
if (!pKey1->strEffect.empty())
AddEffect(&FX_DATA_EX(pKey1->strEffect.c_str(), pKey1->followflag, GetArID(), GetArID(), GetArID(), pKey1->nEffPos, false, 0, m_fCurPlayRate));
ActivateFxSwordSlashForSkill();
}
}
}
if (m_pCurEventHandle00_sound)
{
Key_EVENT_NEW* pKey1 = NULL;
Key_EVENT_NEW* pKey2 = NULL;
m_pCurEventHandle00_sound->GetData(dwAniTime, pKey1, pKey2);
if (pKey1 && pKey1->bUse == false)
{
pKey1->bUse = true; //사용.
if (pKey1->nSound_play_probability != 100)
{
int nRatio = rand() % 100;
if (nRatio < pKey1->nSound_play_probability)
StartSound(this, pKey1->strSound.c_str(), *GetPosition(), true, pKey1->nSoundVolume, false, pKey1->SoundOption);
}
else
{
StartSound(this, pKey1->strSound.c_str(), *GetPosition(), true, pKey1->nSoundVolume, false, pKey1->SoundOption);
}
}
}
if (m_pCurEventHandle00_motion_effect)
{
Key_EVENT_NEW* pKey1 = NULL;
Key_EVENT_NEW* pKey2 = NULL;
m_pCurEventHandle00_motion_effect->GetData(dwAniTime, pKey1, pKey2);
if (pKey1 && pKey1->bUse == false)
{
pKey1->bUse = true; //사용.
FX_DATA fxdata;
fxdata.nFX_ID = pKey1->nFXsetID;
fxdata.nEffPos = pKey1->nEffPos;
fxdata.owner = GetArID();
fxdata.attack = GetArID();
fxdata.target = GetArID();
fxdata.fPlayRate = pKey1->fPlayRate;
fxdata.nPlayID = 0;//한번
fxdata.nMode = 0;//기본
fxdata.bDir = false;
AddEffect(&fxdata);
}
}
if (m_pCurEventHandle01) _processEvent(m_pCurEventHandle01, dwAniTime);
if (m_pCurEventHandle02) _processEvent(m_pCurEventHandle02, dwAniTime);
if (m_pCurEventHandle03) _processEvent(m_pCurEventHandle03, dwAniTime);
if (m_pCurEventHandle04) _processEvent(m_pCurEventHandle04, dwAniTime);
if (m_pCurEventHandle05) _processEvent(m_pCurEventHandle05, dwAniTime);
if (m_pCurEventHandle06) _processEvent(m_pCurEventHandle06, dwAniTime);
//Sound
// if( m_pCurSoundKeyEx )
// {
//
// Key_EVENT_EX * pKey1 = NULL;
// Key_EVENT_EX * pKey2 = NULL;
//
// m_pCurSoundKeyEx->GetData( dwAniTime, pKey1, pKey2 );
//
// if( pKey1 && pKey1->bUse == false )
// {
// pKey1->bUse = true; //사용.
//
// K3DVector pos = *K3DMatrixGetPosVector( *GetTransform() );
//
// //if( IsLocalPlayer() )
// //_oprint( "Ani Time : %d\n %s\n", dwAniTime, pKey1->strScriptFunc.c_str() );
//
// std::string strExec;
// //strTmp = pKey1->strScriptFunc.c_str();
// //str_replace( strTmp, "%d", "%u" );
//
// XStringUtil::Format( strExec, pKey1->strScriptFunc.c_str(), 0, GetArID(), GetArID() );
//
// LUA()->RunString( strExec.c_str() );
// }
// }
//Effect
// if( m_pCurEventKeyEx )
// {
//
// Key_EVENT_EX * pKey1 = NULL;
// Key_EVENT_EX * pKey2 = NULL;
//
// m_pCurEventKeyEx->GetData( dwAniTime, pKey1, pKey2 );
//
// if( pKey1 && pKey1->bUse == false )
// {
// pKey1->bUse = true; //사용.
// std::string strExec;
// //strTmp = pKey1->strScriptFunc.c_str();
// //str_replace( strTmp, "%d", "%u" );
//
// XStringUtil::Format( strExec, pKey1->strScriptFunc.c_str(), GetArID(), GetArID(), m_fCurPlayRate/4.8f );
//
// LUA()->RunString( strExec.c_str() );
// }
// }
m_pAddOnMgr->Process(m_dwTime);
}
int SGameAvatarEx::CheckWorkDel(std::vector< SGameWork* >& worklist)
{
int nDelCnt = 0;
std::vector< SGameWork* >::iterator it = worklist.begin();
while (it != worklist.end())
{
// (*it)->Process( m_dwTime );
if ((*it)->IsEnd())
{
delete (*it);
it = worklist.erase(it);
nDelCnt++;
}
else
it++;
}
return nDelCnt;
}
//////////////////////////////////////////////////////////////////////////
//프로세스
void SGameAvatarEx::AvatarRotationProcess(DWORD time)
{
float roll, prevroll;
roll = fmod(m_fTargetRoll, 3.1415926f * 2);
prevroll = fmod(m_fPresentRoll, 3.1415926f * 2);
const float unitval = 3.1415926f / 12 * (time - m_dwPrevTime) / 66.f;
if (fabs(roll - prevroll) > fabs(roll - prevroll - 3.1415926f * 2))
prevroll += 3.1415926f * 2;
else if (fabs(roll - prevroll) > fabs(roll - prevroll + 3.1415926f * 2))
prevroll -= 3.1415926f * 2;
float minval = min(fabs(roll - prevroll), min(fabs(roll - prevroll + 3.1415926f * 2), fabs(roll - prevroll - 3.1415926f * 2)));
if ((roll > prevroll) && (minval > unitval))
m_fPresentRoll += unitval;
else if (roll > prevroll)
m_fPresentRoll = m_fTargetRoll;
if ((roll < prevroll) && (minval > unitval))
m_fPresentRoll -= unitval;
else if (roll < prevroll)
m_fPresentRoll = m_fTargetRoll;
if (m_bActivateTerrainDegree)
{
if (m_pTerrainDegree->CheckPrevAngle() || m_bUseRot || m_syncCamRoll)
{
m_pTerrainDegree->CalcCurrentAngle(time);
K3DMatrix matWorld, matZ;
m_vView = K3DVector(0.0f, 1.0f, 0.0f);
K3DMatrixRotationZ(matZ, m_fPresentRoll + 3.1415926f / 2);
K3DVectorTransform(m_vView, m_vView, matZ);
K3DMatrixRotationYawPitchRoll(matWorld, (m_pTerrainDegree->GetCurrentAngleX() - 3.1415926f / 2),
(m_pTerrainDegree->GetCurrentAngleY() - 3.1415926f / 2),
m_fPresentRoll + 3.1415926f / 2);
matWorld._41 = GetTransform()->_41;
matWorld._42 = GetTransform()->_42;
matWorld._43 = GetTransform()->_43;
SetTransform(matWorld);
if (sMathUtil::isEqual(m_fPresentRoll, m_fTargetRoll))
{
m_bUseRot = false;
m_syncCamRoll = false;
}
}
K3DVector vPos;
if (IsLocalPlayer() || IsLocalCreature()) vPos = getMyPos();
else vPos = GetCurPosWithChangeDir();
if (m_vCheckPos.x != vPos.x || m_vCheckPos.y != vPos.y)
{
K3DVector v1, v2, v3;
GetTerrainTriangle(vPos.x, vPos.y, v1, v2, v3);
v1 = v2 - v1;
v2 = v3 - v2;
m_vTerrainNormal = CrossProduct(v2, v1);
Normalize(m_vTerrainNormal);
K3DMatrix matZ;
K3DVector vView = K3DVector(0.0f, 1.0f, 0.0f);
K3DMatrixRotationZ(matZ, m_fTargetRoll + 3.1415926f / 2);
K3DVectorTransform(vView, vView, matZ);
// K3DVector vCross = CrossProduct(m_vTerrainNormal, -vView);
// if( fabsf(vCross.z) < 0.4f )
m_pTerrainDegree->CalcTerrainDegree(m_vTerrainNormal, time);
// else
// m_pTerrainDegree->Reset( time );
}
}
else
{
if (m_bUseRot || m_syncCamRoll)
{
K3DMatrix zRollMat;
K3DMatrixIdentity(zRollMat);
K3DMatrixRotationZ(zRollMat, m_fPresentRoll + 3.1415926f / 2);
m_vView = K3DVector(0.0f, 1.0f, 0.0f);
K3DVectorTransform(m_vView, m_vView, zRollMat);
zRollMat._41 = GetTransform()->_41;
zRollMat._42 = GetTransform()->_42;
zRollMat._43 = GetTransform()->_43;
SetTransform(zRollMat);
if (sMathUtil::isEqual(m_fPresentRoll, m_fTargetRoll))
{
m_bUseRot = false;
m_syncCamRoll = false;
}
}
}
m_vTempView = -m_vView;
}
bool SGameAvatarEx::Process(DWORD time, unsigned long uProcessBitVector)
{
if (!m_vWearList_Thread.empty() && !IsThreadLoading())
{
m_vWearListForRefresh.clear();
//쓰레드 로딩 데이타
for (unsigned int i(0); m_vWearList_Thread.size() > i; ++i)
{
m_vWearList.push_back(m_vWearList_Thread[i]);
m_vWearListForRefresh.push_back(m_vWearList_Thread[i]);
}
m_vWearList_Thread.clear();
//쓰레드 로딩
PendLoading();
}
// 2010.04.22 - prodongi
else
procHairThreadData();
//Load 검사?
if (!m_bIsActivated || !m_bIsInit) return false;
//시간 처리
DWORD dwLastTime = m_dwTime;
m_dwTime = time;
// 검광 record
// if (IsLocalPlayer()) {
if (GetInnObjType() == TS_ENTER::GAME_PLAYER)
{
bool bCheck = false;
while (true)
{
if (m_pWeaponTrailRight)
bCheck = m_pWeaponTrailRight->IsRunTrail();
if (bCheck) break;
if (m_pWeaponTrailLeft)
bCheck = m_pWeaponTrailLeft->IsRunTrail();
break;
}
if (bCheck && m_pBoneRecorder)
m_pBoneRecorder->record(dwLastTime + 1, time);
if (m_bActRightSwordSlashForSkill || m_bActLeftSwordSlashForSkill)
{
if (m_nSwordSlashForSkillMotion != GetCurrAnimationID())
{
if (m_pRightSwordSlashForSkill)
m_pRightSwordSlashForSkill->runTrail(false);
if (m_pLeftSwordSlashForSkill)
m_pLeftSwordSlashForSkill->runTrail(false);
m_nSwordSlashForSkillMotion = GetCurrAnimationID();
}
bool bRight = false;
if (m_pRightSwordSlashForSkill)
bRight = m_pRightSwordSlashForSkill->IsRunTrail();
bool bLeft = false;
if (m_pLeftSwordSlashForSkill)
bLeft = m_pLeftSwordSlashForSkill->IsRunTrail();
if (bRight || bLeft)
{
if (!bCheck && m_pBoneRecorder)
m_pBoneRecorder->record(dwLastTime + 1, time);
}
else
{
DeActivateFxSwordSlashForSkill();
}
}
}
_processDef();
if (!isKMoving() && !IsMoving())
{
if (GetCurrAnimationID() == ANI_RUN ||
GetCurrAnimationID() == ANI_WALK)
{
Default();
}
else if (CurrentlyAnimationIsMRun() || CurrentlyAnimationIsMWalk()) // sonador #2.1.6
{
if (GetInnObjType() == TS_ENTER::GAME_PLAYER && IsMountMode())
{
if (!m_bLocal) Default();
}
}
//스킬 사용 중이 아니면.
if (!IsUsingSkill() && !IsPlaying())
{
if (CurrentlyAnimationIsAttack() && GetObjType() != TS_ENTER::GAME_PLAYER)
Default();
}
if (CurrentlyAnimationIsDamage() && !IsPlaying())
Default();
}
StateProcess(time);
return true;
}
void SGameAvatarEx::StateProcess(DWORD dwTime)
{
if (m_dwTime < m_dwCheckTime + 1000) return;
m_dwCheckTime = m_dwTime;
int bLocalUpdate = FALSE;
SGameLocalPlayer* localPlayer = dynamicCast<SGameLocalPlayer*>(g_pCurrentGameSystem->GetLocalPlayer());
SStateSlot* pState(NULL);
//iterator_state_slot PositiveIt = m_vecPositiveList.begin();
//iterator_state_slot NegativeIt = m_vecNegativeList.begin();
if (m_vecPositiveList.empty() && m_vecNegativeList.empty() && m_vecCashStateList.empty() && m_vecMarkStateList.empty())
return;
for (int i = 0; i < m_vecCashStateList.size(); i++)
{
m_vecCashStateList[i]->Process(dwTime);
}
/// 2011.01.14 - prodongi
for (int i = 0; i < m_vecMarkStateList.size(); i++)
{
pState = m_vecMarkStateList[i];
pState->Process(dwTime);
if (IsLocalPlayer())
{
if (dwTime > pState->GetBeginTime() + pState->GetMaxTime()) bLocalUpdate = TRUE;
}
}
for (int i = 0; i < m_vecPositiveList.size(); i++)
{
pState = m_vecPositiveList[i];
if (!pState->IsToggleSkill())
{
pState->Process(dwTime);
if (IsLocalPlayer())
{
if (dwTime > pState->GetBeginTime() + pState->GetMaxTime()) bLocalUpdate = TRUE;
}
}
}
for (int i = 0; i < m_vecNegativeList.size(); i++)
{
pState = m_vecNegativeList[i];
if (!pState->IsToggleSkill())
{
pState->Process(dwTime);
if (IsLocalPlayer())
{
if (dwTime > pState->GetBeginTime() + pState->GetMaxTime()) bLocalUpdate = TRUE;
}
}
}
/*while(true)
{
if( PositiveIt == m_vecPositiveList.end() && NegativeIt == m_vecNegativeList.end() )
break;
if( PositiveIt != m_vecPositiveList.end() )
{
pState = (*PositiveIt);
if( !pState->IsToggleSkill() )
{
pState->Process(dwTime);
if (IsLocalPlayer() && (dwTime > pState->GetBeginTime()+pState->GetMaxTime() )) bLocalUpdate = TRUE;
}
++PositiveIt;
}
if( NegativeIt != m_vecNegativeList.end() )
{
pState = (*NegativeIt);
if( !pState->IsToggleSkill() )
{
pState->Process(dwTime);
if (IsLocalPlayer() && (dwTime > pState->GetBeginTime()+pState->GetMaxTime() )) bLocalUpdate = TRUE;
}
++NegativeIt;
}
}*/
if (IsLocalPlayer())
{
if ((bLocalUpdate && ((dwTime - localPlayer->m_dwUpdateTime) > 1000)))
{
int cur = GetArTime();
localPlayer->m_dwUpdateTime = dwTime;
TS_CS_UPDATE msg;
msg.handle = GetArID();
msg.ar_time = cur;
time_t nowtime;
time(&nowtime);
msg.rtc = nowtime;
SendMsg(&msg);
}
SendGameInterfaceMsg(&(SIMSG_UI_STATE_UPDATE(SIMSG_TOGGLE_UIWINDOW::UIWINDOW_STATE_H_EFFECT, m_arObject.handle)));
}
if (g_pCurrentGameSystem->IsTarget(m_arObject.handle)) SendGameInterfaceMsg(&(SIMSG_UI_STATE_UPDATE(SIMSG_TOGGLE_UIWINDOW::UIWINDOW_TARGET_STATE, m_arObject.handle)));
if (g_pCurrentGameSystem->IsPartyMember(m_arObject.handle)) SendGameInterfaceMsg(&(SIMSG_UI_STATE_UPDATE(SIMSG_TOGGLE_UIWINDOW::UIWINDOW_PARTY_STATE, m_arObject.handle)));
}
bool SGameAvatarEx::IsMoving()
{
if (m_pArObject)
{
return m_pArObject->GetMyPos().IsMoving();
}
else
{
return GetArObject().mv.IsMoving();
}
assert(0);
return false;
}
K3DVector& SGameAvatarEx::GetNextPos()
{
return m_vNextPos;
}
K3DVector SGameAvatarEx::GetCurPosWithChangeDir()
{
K3DVector Cur;
if (m_pArObject) //Local Player 임
{
Cur = K3DVector(m_pArObject->GetMyPos().x, m_pArObject->GetMyPos().y, 0.f);
if (m_pArObject->GetMyPos().HasDirectionChanged())
{
const ArPosition& cursteppos = m_pArObject->GetMyPos().GetDirection();
m_vNextPos = K3DVector(cursteppos.x, cursteppos.y, 0.f);
SetViewVector(m_vNextPos);
}
}
else
{
Cur = K3DVector(GetArObject().mv.x, GetArObject().mv.y, 0.f);
if (GetArObject().mv.HasDirectionChanged())
{
const ArPosition& cursteppos = GetArObject().mv.GetDirection();
m_vNextPos = K3DVector(cursteppos.x, cursteppos.y, 0.f);
SetViewVector(m_vNextPos);
}
}
return Cur;
}
unsigned char SGameAvatarEx::getSpeed()
{
if (m_pArObject)
{
return m_pArObject->GetMyPos().GetSpeed();
}
else
{
return GetArObject().mv.GetSpeed();
}
}
unsigned char SGameAvatarEx::getMovingSpeed()
{
if (IsMoving())
{
return getSpeed();
}
return 0;
}
K3DVector SGameAvatarEx::getMyPos()
{
/// 우선 GetCurPosWithChangeDir를 리턴하고 getMyPos()를 없애야 겠음
return GetCurPosWithChangeDir();
/*
/// m_vNextPos가 플레이어의 방향을 구할 때 쓰이기 때문에 추가함.(미니맵 등의)
if( m_pArObject ) //Local Player 임
{
if( m_pArObject->GetMyPos().HasDirectionChanged() )
{
const ArPosition& cursteppos = m_pArObject->GetMyPos().GetDirection();
m_vNextPos = K3DVector( cursteppos.x, cursteppos.y, 0.f );
}
return K3DVector( m_pArObject->GetMyPos().x, m_pArObject->GetMyPos().y, 0.f );
}
else
{
if( GetArObject().mv.HasDirectionChanged() )
{
const ArPosition& cursteppos = GetArObject().mv.GetDirection();
m_vNextPos = K3DVector( cursteppos.x, cursteppos.y, 0.f );
}
return K3DVector( GetArObject().mv.x, GetArObject().mv.y, 0.f );
}
*/
}
bool SGameAvatarEx::IsPlaying()
{
if (!m_bIsActivated || !m_bIsInit) return false; //참 - -;;
if (m_pSeqAvatar)
return m_pSeqAvatar->IsPlaying();
return false;
}
void SGameAvatarEx::SetSex(int nSex)
{
if (m_pProperty) m_pProperty->Sex = nSex;
}
int SGameAvatarEx::GetSex()
{
return m_pProperty->Sex;
}
void SGameAvatarEx::SetFaceID(int nFaceID)
{
if (m_pProperty) m_pProperty->FaceID = nFaceID;
}
void SGameAvatarEx::SetHairID(int nHairID)
{
if (m_pProperty) m_pProperty->HairID = nHairID;
}
int SGameAvatarEx::GetCurrAnimationID()
{
return m_nNewCurAniType;
}
//int SGameAvatarEx::GetAnimationType()
//{
// return m_nCurAniType;
//}
DWORD SGameAvatarEx::GetAniTime()
{
if (m_pSeqAvatar && m_bIsInit)
return m_pSeqAvatar->GetAniTime();
return 0;
}
void SGameAvatarEx::SetAnimationPos(int nPosFlag)
{
if (!m_bIsActivated || !m_bIsInit) return;
if (m_pSeqAvatar) m_pSeqAvatar->SetAnimationPos(nPosFlag);
}
void SGameAvatarEx::SetRenderFlag(int nRenderIndex)
{
if (m_xRenderFlag.IsOn(nRenderIndex))
m_xRenderFlag.Off(nRenderIndex);
else
m_xRenderFlag.On(nRenderIndex);
}
KSeqAvatarEx* SGameAvatarEx::GetSeqForm()
{
return m_pSeqAvatar;
}
void SGameAvatarEx::DestroySeqAvatar()
{
m_bIsActivated = false;
SAFE_DELETE(m_pSeqAvatar);
}
void SGameAvatarEx::SetEventHandleInit()
{
if (m_pCurEventHandle00_effect) m_pCurEventHandle00_effect->SetInit();
if (m_pCurEventHandle00_sound) m_pCurEventHandle00_sound->SetInit();
if (m_pCurEventHandle00_motion_effect) m_pCurEventHandle00_motion_effect->SetInit();
if (m_pCurEventHandle01) m_pCurEventHandle01->SetInit();
if (m_pCurEventHandle02) m_pCurEventHandle02->SetInit();
if (m_pCurEventHandle03) m_pCurEventHandle03->SetInit();
if (m_pCurEventHandle04) m_pCurEventHandle04->SetInit();
if (m_pCurEventHandle05) m_pCurEventHandle05->SetInit();
if (m_pCurEventHandle06) m_pCurEventHandle06->SetInit();
}
void SGameAvatarEx::SetEventHandleNull()
{
m_pCurEventHandle00_effect = NULL;
m_pCurEventHandle00_sound = NULL;
m_pCurEventHandle00_motion_effect = NULL;
m_pCurEventHandle01 = NULL;
m_pCurEventHandle02 = NULL;
m_pCurEventHandle03 = NULL;
m_pCurEventHandle04 = NULL;
m_pCurEventHandle05 = NULL;
m_pCurEventHandle06 = NULL;
}
void SGameAvatarEx::OnAttack(const SStateInfo& info) //일반 공격
{
SetAniLock(false);
int nAttackAni = ANI_ATTACK01;
if (GetInnObjType() == TS_ENTER::GAME_PLAYER)
{
if (!info.vAttackInfoList.empty() && (info.vAttackInfoList[0].flag & TS_ATTACK_EVENT::FLAG_CRITICAL))
{
if (info.attack_flag & TS_ATTACK_EVENT::ATTACK_FLAG_DOUBLE_ATTACK)
{
if (m_nAttackIndex == 0) nAttackAni = ANI_DOUBLE_ATTACK01;
else if (m_nAttackIndex == 1) nAttackAni = ANI_DOUBLE_ATTACK02;
else if (m_nAttackIndex == 2) nAttackAni = ANI_DOUBLE_ATTACK03;
}
else
{
if (m_nAttackIndex == 0) nAttackAni = ANI_CRITICAL_ATTACK01;
else if (m_nAttackIndex == 1) nAttackAni = ANI_CRITICAL_ATTACK02;
else if (m_nAttackIndex == 2) nAttackAni = ANI_CRITICAL_ATTACK03;
}
++m_nAttackIndex;
if (m_nAttackIndex > 2)
m_nAttackIndex = 0;
}
else
{
m_nAttackIndex = 0;
int nAttackIndex = rand() % 3;
while (nAttackIndex == m_cPrevAttackIndex)
{
nAttackIndex = rand() % 3;
}
m_cPrevAttackIndex = nAttackIndex;
if (info.attack_flag & TS_ATTACK_EVENT::ATTACK_FLAG_DOUBLE_ATTACK)
{
if (nAttackIndex == 0) nAttackAni = ANI_DOUBLE_ATTACK01;
else if (nAttackIndex == 1) nAttackAni = ANI_DOUBLE_ATTACK02;
else if (nAttackIndex == 2) nAttackAni = ANI_DOUBLE_ATTACK03;
}
else
{
if (nAttackIndex == 0) nAttackAni = ANI_ATTACK01;
else if (nAttackIndex == 1) nAttackAni = ANI_ATTACK02;
else if (nAttackIndex == 2) nAttackAni = ANI_ATTACK03;
}
}
}
float fAttackPlayRate = Attack(info.hTarget, info.vTargetPos, info.dwSpeed, nAttackAni);
SetAttackAniLock(true);
//타겟 핸들, 현재 이벤트 키, 이벤트 전체 길이, 현재 시간, 공격 스피드
SWorkAttackEx* pAttackEx = new SWorkAttackEx(this, info.hTarget, fAttackPlayRate);
pAttackEx->SetEventHandle(m_dwTime, info.dwSpeed,
m_pCurEventHandle00_effect,
m_pCurEventHandle00_sound,
m_pCurEventHandle00_motion_effect,
m_pCurEventHandle01,
m_pCurEventHandle02,
m_pCurEventHandle03,
m_pCurEventHandle04,
m_pCurEventHandle05,
m_pCurEventHandle06);
pAttackEx->SetDamegeInfo(&info);
m_vAttackEventList.push_back(pAttackEx);
//공격 이펙트는 나올 필요가 없다.
SetEventHandleNull();
}
void SGameAvatarEx::OnAttackBow(const SStateInfo& info)//활 공격
{
}
bool SGameAvatarEx::IsUsingSkill() //스킬 사용 중 인가?
{
if (!m_vCastSkillList.empty())
return true;
if (!m_vFireSkillList.empty())
return true;
return false;
}
bool SGameAvatarEx::IsAttacking() //공격 중인가
{
if (!m_vAttackEventList.empty())
return true;
return false;
}
bool SGameAvatarEx::IsAttackingByBow()
{
std::vector< class SGameWork* >::iterator iter = m_vCastSkillList.begin();
for (; iter != m_vCastSkillList.end(); ++iter)
{
if ((*iter)->GetWorkType() != SGameWork::WORK_AIMINGBOW)
return false;
}
iter = m_vFireSkillList.begin();
for (; iter != m_vFireSkillList.end(); ++iter)
{
if ((*iter)->GetWorkType() != SGameWork::WORK_SHOOTINGBOW)
return false;
}
return true;
}
//스킬을 사용 하기 전에 설정 한다.
//애니 메이션 관리 기능 추가..
void SGameAvatarEx::StartUseSkill(int nSkillID)
{
_SKILL_FX* pSkillFX = GetSkillStageDB().GetSkillStageData(nSkillID);
//어떤 모션을 사용한다. 다른 일반 모션은 사용을 금지 한다.
//PlayAnimation을 직접 사용 금하고, Animation 관리 한다.
}
void SGameAvatarEx::EndUseSkill(int nSkillID)
{
}
void SGameAvatarEx::ActivateForceSphere()
{
m_pAddOnMgr->RemoveAddOn(SGameAvatarAddOnMgr::SGAME_FORCE_SPHERE_FX);
SGameForceSphereFX* pForceSphereFx = new SGameForceSphereFX;
// pForceSphereFx->SetSphereHeight( GetRace(), GetSex() );
switch (GetInnObjType())
{
case TS_ENTER::GAME_PLAYER:
{
if (GetSex() == SEX_MALE) pForceSphereFx->SetSphereHeight(12.0f);
else pForceSphereFx->SetSphereHeight(10.0f);
}
break;
case TS_ENTER::GAME_MOB:
{
_MONSTER_INFO_FILE* pMonster = GetMonsterDB().GetMonsterData(GetInnContentID());
if (pMonster)
{
pForceSphereFx->SetSphereHeight(pMonster->target_fx_size);
pForceSphereFx->SetSphereDistance(pMonster->target_fx_size);
}
}
break;
case TS_ENTER::GAME_SUMMON:
{
_SUMMON_INFO_FILE* pSummon = GetCreatureDB().GetCreatureData(GetInnContentID());
if (pSummon)
{
pForceSphereFx->SetSphereHeight(pSummon->target_fx_size);
pForceSphereFx->SetSphereDistance(pSummon->target_fx_size);
}
}
break;
case TS_ENTER::GAME_PET: // sonador 10.2.1 팻 시스템 구현
{
SPetInfoEx PetInfo = GetPetDB().Find(GetInnContentID());
pForceSphereFx->SetSphereHeight(PetInfo.getTargetFxSize());
pForceSphereFx->SetSphereDistance(PetInfo.getTargetFxSize());
}
break;
}
m_pAddOnMgr->AddAddOn(pForceSphereFx);
}
void SGameAvatarEx::ActivateCircleShadow()
{
m_pAddOnMgr->RemoveAddOn(SGameAvatarAddOnMgr::SGAME_CIRCLE_SHADOW_FX);
SGameCircleShadowFX* pCircleShadowFX = new SGameCircleShadowFX;
m_pAddOnMgr->AddAddOn(pCircleShadowFX);
}
void SGameAvatarEx::DeActivateCircleShadow()
{
m_pAddOnMgr->RemoveAddOn(SGameAvatarAddOnMgr::SGAME_CIRCLE_SHADOW_FX);
}
void SGameAvatarEx::OnMsgForceSphere(int nForceSphereSize)
{
SGameForceSphereFX* pForceSphereFx = (SGameForceSphereFX*)m_pAddOnMgr->GetAddOn(SGameAvatarAddOnMgr::SGAME_FORCE_SPHERE_FX);
if (!pForceSphereFx) return;
int nSize = pForceSphereFx->GetForceSphereSize();
if (nSize == 0)
{
for (int x = 0; x < nForceSphereSize; x++)
pForceSphereFx->AddForceSphere();
}
else if (nForceSphereSize > nSize)
{
nSize = nForceSphereSize - nSize;
for (int x = 0; x < nSize; x++)
pForceSphereFx->AddForceSphere();
}
else
{
nSize = nSize - nForceSphereSize;
for (int x = 0; x < nSize; x++)
pForceSphereFx->UseForceSphere();
}
m_nEnergy = nForceSphereSize;
}
//기공 추가~
void SGameAvatarEx::AddForceSphere()
{
SGameForceSphereFX* pForceSphereFx = (SGameForceSphereFX*)m_pAddOnMgr->GetAddOn(SGameAvatarAddOnMgr::SGAME_FORCE_SPHERE_FX);
if (!pForceSphereFx) return;
pForceSphereFx->AddForceSphere();
}
//기공 사용
void SGameAvatarEx::UseForceSphere()
{
SGameForceSphereFX* pForceSphereFx = (SGameForceSphereFX*)m_pAddOnMgr->GetAddOn(SGameAvatarAddOnMgr::SGAME_FORCE_SPHERE_FX);
if (!pForceSphereFx) return;
pForceSphereFx->UseForceSphere();
}
void SGameAvatarEx::EvolutionSummon(SMSG_SUMMON_EVOLUTION* pMsg)
{
if (m_pProperty == NULL) return;
m_pProperty->ContentID() = pMsg->code;
m_pProperty->Name = pMsg->name;
m_bIsInit = false;
DestroySeqAvatar();
m_pAddOnMgr->RemoveAddOn(SGameAvatarAddOnMgr::SGAME_AVATAR_FX);
Initialize(NULL);
Activate();
}
void SGameAvatarEx::SetRiderCreatureInfo(RiderCreatureInfo* pInfo)
{
if (pInfo)
{
m_RiderCreatureInfo.m_hRider = pInfo->m_hRider;
m_RiderCreatureInfo.m_nRidePos = pInfo->m_nRidePos;
m_RiderCreatureInfo.m_nRideType = pInfo->m_nRideType;
m_RiderCreatureInfo.m_bIsTransportCreature = pInfo->m_bIsTransportCreature;
}
else
{
m_RiderCreatureInfo.Reset();
}
}
class KEventPointSeq* SGameAvatarEx::GetSaddleEffectPos()
{
if (m_pSeqRideLink) return m_pSeqRideLink;
_CID(REQ_EVPOINT);
KMsgREQ_EVPOINT effect_pos_msg;
Perform(ANIPART_BIPED, id_REQ_EVPOINT, effect_pos_msg);
KEventPointSeq* pEv = NULL;
for (int i(0); effect_pos_msg.GetPointCount() > i; i++)
{
pEv = effect_pos_msg.GetPoint(i);
const char* pName = pEv->GetName();
if (strlen(pName) && _stricmp(pName, "ep_ride01_main") == 0)
return m_pSeqRideLink = pEv;
}
// assert( false && "ep_ride01_main 이펙트 포스를 찾을수 없습니다." );
m_pSeqRideLink = NULL;
return m_pSeqRideLink;
}
void SGameAvatarEx::ResetWeaponEVPMatrix(int nAnyPart)
{
m_WeaponEnhanceFx[nAnyPart].weardatainfo = false;
m_bWeaponEVPMatrix[nAnyPart] = false;
m_pWeaponEvpSequencer[nAnyPart][EFFECT_POS_WEAPON_EP_START] = NULL;
m_pWeaponEvpSequencer[nAnyPart][EFFECT_POS_WEAPON_EP_END] = NULL;
}
void SGameAvatarEx::SetWeaponInfo(KSeqAvatarEx* pAvatarEx, WEAR_DATA& WearData, const char* pEventFileName)
{
const _OPT_DATA& optData = GetGameOption().GetOptData(); // 게임 옵션 가져오기. mantis 3855이슈 관련 수정. kappamind, 2010.01.11
if (WearData.nItemCode == 0)
{
if (WearData.nWearType == ItemBase::WEAR_LEFTHAND)
{
UnArmed(m_nLeftHandWeaponCode);
ResetWeaponEVPMatrix(EFFECT_POS_LEFT_WEAPON);
}
else if (WearData.nWearType == ItemBase::WEAR_RIGHTHAND)
{
UnArmed(m_nTwoHandWeaponCode);
UnArmed(m_nRightHandWeaponCode);
ResetWeaponEVPMatrix(EFFECT_POS_RIGHT_WEAPON);
ResetWeaponEVPMatrix(EFFECT_POS_TWOHAND_WEAPON);
}
return;
}
bool bAttachEnhanceFX = true;
if (WearData.nWearType == ItemBase::WEAR_LEFTHAND)
{
UnArmed(m_nLeftHandWeaponCode);
ResetWeaponEVPMatrix(EFFECT_POS_LEFT_WEAPON);
if (((WearData.nItemClass != ItemBase::CLASS_SHIELD) && bAttachEnhanceFX)) // 치장 무기가 있고 원래의 무기를 표시안하는 경우에는 강화 효과를 아예 로드 안한다.
{
m_WeaponEnhanceFx[EFFECT_POS_LEFT_WEAPON].weardata = WearData;
m_WeaponEnhanceFx[EFFECT_POS_LEFT_WEAPON].weardatainfo = true;
if (pEventFileName)
m_WeaponEnhanceFx[EFFECT_POS_LEFT_WEAPON].strEventFileName = pEventFileName;
}
}
else if (WearData.nWearType == ItemBase::WEAR_RIGHTHAND)
{
UnArmed(m_nTwoHandWeaponCode);
UnArmed(m_nRightHandWeaponCode);
ResetWeaponEVPMatrix(EFFECT_POS_RIGHT_WEAPON);
ResetWeaponEVPMatrix(EFFECT_POS_TWOHAND_WEAPON);
if (WearData.nItemClass == ItemBase::CLASS_TWOHAND_AXE || WearData.nItemClass == ItemBase::CLASS_TWOHAND_MACE ||
WearData.nItemClass == ItemBase::CLASS_TWOHAND_SPEAR || WearData.nItemClass == ItemBase::CLASS_TWOHAND_STAFF ||
WearData.nItemClass == ItemBase::CLASS_TWOHAND_SWORD)
{
if (bAttachEnhanceFX) // 치장 무기가 있고 원래의 무기를 표시안하는 경우에는 강화 효과를 아예 로드 안한다.
{
m_WeaponEnhanceFx[EFFECT_POS_TWOHAND_WEAPON].weardata = WearData;
m_WeaponEnhanceFx[EFFECT_POS_TWOHAND_WEAPON].weardatainfo = true;
if (pEventFileName)
m_WeaponEnhanceFx[EFFECT_POS_TWOHAND_WEAPON].strEventFileName = pEventFileName;
}
}
else if (WearData.nItemClass == ItemBase::CLASS_LIGHT_BOW || WearData.nItemClass == ItemBase::CLASS_HEAVY_BOW)
{
UnArmed(m_nLeftHandWeaponCode);
ResetWeaponEVPMatrix(EFFECT_POS_LEFT_WEAPON);
m_WeaponEnhanceFx[EFFECT_POS_LEFT_WEAPON].weardata = WearData;
m_WeaponEnhanceFx[EFFECT_POS_LEFT_WEAPON].weardatainfo = true;
if (pEventFileName)
m_WeaponEnhanceFx[EFFECT_POS_LEFT_WEAPON].strEventFileName = pEventFileName;
}
else
{
if (bAttachEnhanceFX) // 치장 무기가 있고 원래의 무기를 표시안하는 경우에는 강화 효과를 아예 로드 안한다.
{
m_WeaponEnhanceFx[EFFECT_POS_RIGHT_WEAPON].weardata = WearData;
m_WeaponEnhanceFx[EFFECT_POS_RIGHT_WEAPON].weardatainfo = true;
if (pEventFileName)
m_WeaponEnhanceFx[EFFECT_POS_RIGHT_WEAPON].strEventFileName = pEventFileName;
}
}
}
}
void SGameAvatarEx::LoadEnhanceEffect(KSeqAvatarEx* pAvatarEx, WEAPON_ENHANCE_EFFECT* pWeaponEnFx, int nEffectPart)
{
if (nEffectPart == EFFECT_POS_LEFT_WEAPON)
{
UnArmed(m_nLeftHandWeaponCode);
Armed(pAvatarEx, m_nLeftHandWeaponCode, ANIPART_WEAPON_LEFT, EFFECT_POS_W_LEFT, pWeaponEnFx, nEffectPart);
}
else if (nEffectPart == EFFECT_POS_RIGHT_WEAPON)
{
UnArmed(m_nRightHandWeaponCode);
UnArmed(m_nTwoHandWeaponCode);
Armed(pAvatarEx, m_nRightHandWeaponCode, ANIPART_WEAPON_RIGHT, EFFECT_POS_W_RIGHT, pWeaponEnFx, nEffectPart);
}
else if (nEffectPart == EFFECT_POS_TWOHAND_WEAPON)
{
UnArmed(m_nRightHandWeaponCode);
UnArmed(m_nTwoHandWeaponCode);
Armed(pAvatarEx, m_nTwoHandWeaponCode, ANIPART_WEAPON_RIGHT, EFFECT_POS_W_TWOHAND, pWeaponEnFx, nEffectPart);
}
else
assert(false && "LoadEnhanceEffect");
}
void SetWeaponColorized(int nIndex, KSeqAvatarEx* pAvatarEx, unsigned int dwColor)
{
//DWORD dwColor = 0xFF000000;
//dwColor = ( DWORD ) b | ( DWORD ) g << 8 | ( DWORD ) r << 16;
// dwColor = ( DWORD ) rand()%255 | ( DWORD ) rand()%255 << 8 | ( DWORD ) rand()%255 << 16;
_CID(SET_COLORIZE);
_CID(SET_USE_TEXALPHA);
KMsgSET_COLORIZE msg;
msg.color[0] = dwColor;
msg.color[1] = 0;
msg.color[2] = 0;
msg.color[3] = 0;
msg.nMode = K3DTexture::COLORIZED_USEALPHA;
if (pAvatarEx)
pAvatarEx->Perform(nIndex, id_SET_COLORIZE, msg);
}
namespace
{
static char* s_szVariationPatterns[] =
{
"_r",
"_b",
NULL
};
std::string RemoveVariationPrefix(const std::string& strFileName)
{
std::string strReturn = strFileName;
std::string strPrefixExt;
for (int i = 0; s_szVariationPatterns[i] != NULL; ++i)
{
strPrefixExt = std::string(s_szVariationPatterns[i]) + ".nx3";
int nPos = strReturn.find(strPrefixExt);
if (nPos != strReturn.npos)
{
strReturn.replace(strReturn.begin() + nPos, strReturn.end(), ".nx3");
break;
}
}
return strReturn;
}
} // namespace //2011.03.30 - servantes 주석추가
void SGameAvatarEx::Armed(KSeqAvatarEx* pAvatarEx, int* nItemCode, int nAnyPart, int nEffectPos, WEAPON_ENHANCE_EFFECT* pWeaponEnFx, int nWeaponEffectPos)
{
WEAR_DATA* pWearData = &pWeaponEnFx->weardata;
bool bRefreshWpEffectPos = false;
if (pAvatarEx)
{
pAvatarEx->AddEffectPos(nAnyPart, nEffectPos, pWeaponEnFx->strEventFileName.c_str());
bRefreshWpEffectPos = RefreshWeaponEffectPos(pAvatarEx, nWeaponEffectPos);
if (!bRefreshWpEffectPos)
{
ResetWeaponEVPMatrix(nWeaponEffectPos);
pWeaponEnFx->weardatainfo = false;
}
}
int nEnhanceLevel = GetEnhanceCheatLevel();
if (nEnhanceLevel == 0)
nEnhanceLevel = pWearData->nItemEnhanceLevel;
if (((nEnhanceLevel <= 0) && (pWearData->cElementalEffect == 0)) || !GetGameOption().IsEnhanceRende())
{
if (pWearData->nItemCode != nItemCode[0])
UnArmed(nItemCode);
return;
}
if (pWearData->nItemCode != nItemCode[0])
{
UnArmed(nItemCode);
int wt_width = GetWeaponLength(pWearData->nItemCode);
int wt_length = 50 + nEnhanceLevel * 10;;
unsigned int* pcolor = g_pEnhanceColor[0];
if (nEnhanceLevel > 0 && nEnhanceLevel <= 25) pcolor = g_pEnhanceColor[nEnhanceLevel]; // 강화도에 따른 색상
<<<<<<< HEAD
bool bBowClass = (pWearData->nItemClass == ItemBase::CLASS_LIGHT_BOW) || (pWearData->nItemClass == ItemBase::CLASS_HEAVY_BOW) || (pWearData->nItemClass == ItemBase::CLASS_CROSSBOW); //Double Crossbow
=======
// AziaMafia Double Crossbow
//bool bBowClass = (pWearData->nItemClass == ItemBase::CLASS_LIGHT_BOW) || (pWearData->nItemClass == ItemBase::CLASS_HEAVY_BOW);
//bool bBowClass = (pWearData->nItemClass == ItemBase::CLASS_LIGHT_BOW) || (pWearData->nItemClass == ItemBase::CLASS_HEAVY_BOW) || (pWearData->nItemClass == ItemBase::CLASS_CROSSBOW );
// From ZONE source; dual crossbows
bool bBowClass = (pWearData->nItemClass == ItemBase::CLASS_LIGHT_BOW) || (pWearData->nItemClass == ItemBase::CLASS_HEAVY_BOW) || (pWearData->nItemClass == ItemBase::CLASS_CROSSBOW);
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
m_bBowClass = bBowClass;
if (bBowClass)
{
wt_width = 1;
wt_length = 10;
}
if (nAnyPart == ANIPART_WEAPON_RIGHT || nAnyPart == ANIPART_WEAPON_LEFT)
{
//-------------------------------
//검기
if (wt_length > 1)
{
SGameFxSwordSlash* pFxSword = NULL;
if (nAnyPart == ANIPART_WEAPON_RIGHT && m_pWeaponTrailRight)
{
pFxSword = m_pWeaponTrailRight;
m_bActRightWeaponTrail = true;
}
else if (nAnyPart == ANIPART_WEAPON_LEFT && m_pWeaponTrailLeft)
{
pFxSword = m_pWeaponTrailLeft;
m_bActLeftWeaponTrail = true;
}
if (pFxSword)
{
KColor Scolor0(pcolor[0]);
KColor Scolor1(pcolor[1]);
KColor Ecolor0(pcolor[2]);
KColor Ecolor1(pcolor[3]);
pFxSword->setTrailWidth(wt_width);
pFxSword->setTrailNodeCount(wt_length);
pFxSword->setTrailNodeColor(0, 0, Scolor0.color);
pFxSword->setTrailNodeColor(0, 1, Scolor1.color);
pFxSword->setTrailNodeColor(1, 0, Ecolor0.color);
pFxSword->setTrailNodeColor(1, 1, Ecolor1.color);
if (nEnhanceLevel > 0)
{
pFxSword->setTrailTexture("wfxsforce_lv03.dds");
//pFxSword->setTrailTexture( GetResourceDB().GetTextureResourceName( pEnhanceFx->wt_texture_ID ) );
}
}
}
// 2010.09.28 아래에 선언된 내용을 이쪽으로 옮김 - prodongi
bool bLeftWeapon = (nAnyPart == ANIPART_WEAPON_LEFT);
bool bRightWeapon = (nAnyPart == ANIPART_WEAPON_RIGHT);
std::string strColorNx3;
std::string strAttrNx3;
// 2010.09.24 데코 아이템이 무기 대신 출력되는 경우에 데코 이펙트를 출력하게 해준다 - prodongi
//std::string strColorFile = RemoveVariationPrefix( pWearData->strFileName.c_str() );
//std::string strAttrFile = RemoveVariationPrefix( pWearData->strFileName.c_str() );
bool isDecoEffect = false;
if (pWearData->bWithDecoItem && !pWearData->bAttachDecoItem)
{
//if( GetGameOption().GetAvatarDeco() != 0 ) // 2010.10.11. 게임플레이옵션에서 "꾸미기보이기" 제거.
//{
if (bRightWeapon || (bLeftWeapon && bBowClass))
{
if (isHideEquipInfo(ItemBase::DECO_HIDE_EQUIP_WEAPON))
isDecoEffect = true;
}
else if (bLeftWeapon)
{
if (isHideEquipInfo(ItemBase::DECO_HIDE_EQUIP_SHIELD))
isDecoEffect = true;
}
// else는 뭘 해야 되나??
else
{
}
//}
}
std::string strColorFile, strAttrFile;
//if (pWearData->bWithDecoItem && !pWearData->bAttachDecoItem)
if (isDecoEffect)
{
strColorFile = RemoveVariationPrefix(pWearData->strDecoFileName.c_str());
strAttrFile = RemoveVariationPrefix(pWearData->strDecoFileName.c_str());
}
else
{
strColorFile = RemoveVariationPrefix(pWearData->strFileName.c_str());
strAttrFile = RemoveVariationPrefix(pWearData->strFileName.c_str());
}
std::string strColorTemp;
std::string strAttrTemp;
strColorNx3 = "rcwfx_";
strAttrNx3 = "rcwfx_";
// 2010.09.28 선언 위치 변경 - prodongi
/*
bool bLeftWeapon = (nAnyPart == ANIPART_WEAPON_LEFT );
bool bRightWeapon = (nAnyPart == ANIPART_WEAPON_RIGHT );
bool bBowClass = (pWearData->nItemClass == ItemBase::CLASS_LIGHT_BOW) ||
(pWearData->nItemClass == ItemBase::CLASS_HEAVY_BOW) ||
(pWearData->nItemClass == ItemBase::CLASS_CROSSBOW );
*/
//if ( pEnhanceFx )
{
if (bRightWeapon || (bLeftWeapon && bBowClass))
{
//레벨 별
if (nEnhanceLevel >= 5 && nEnhanceLevel < 10)
strColorTemp = "_lv05_color.";
else if (nEnhanceLevel >= 10 && nEnhanceLevel < 15)
strColorTemp = "_lv10_color.";
else
strColorTemp = "_lv15_color.";
}
else if (bLeftWeapon)
{
if (nEnhanceLevel >= 5 && nEnhanceLevel < 10)
strColorTemp = "_L_lv05_color.";
else if (nEnhanceLevel >= 10 && nEnhanceLevel < 15)
strColorTemp = "_L_lv10_color.";
else
strColorTemp = "_L_lv15_color.";
}
}
if (bRightWeapon || (bLeftWeapon && bBowClass))
{
switch (pWearData->cElementalEffect)
{
case 1: strAttrTemp = "_fire."; break; ///Weapon Mystic Jewel //thanks to ink
case 2: strAttrTemp = "_water."; break; ///Weapon Mystic Jewel //thanks to ink
case 3: strAttrTemp = "_wind."; break; ///Weapon Mystic Jewel //thanks to ink
case 4: strAttrTemp = "_earth."; break; ///Weapon Mystic Jewel //thanks to ink
case 5: strAttrTemp = "_light."; break;
case 6: strAttrTemp = "_dark."; break;
case 7: strAttrTemp = "_fire2."; break;
case 8: strAttrTemp = "_water2."; break;
case 9: strAttrTemp = "_wind2."; break;
case 10: strAttrTemp = "_earth2."; break;
case 11: strAttrTemp = "_light2."; break;
case 12: strAttrTemp = "_dark2."; break;
}
}
else if (bLeftWeapon)
{
switch (pWearData->cElementalEffect)
{
case 1: strAttrTemp = "_L_fire."; break;
case 2: strAttrTemp = "_L_water."; break;
case 3: strAttrTemp = "_L_wind."; break;
case 4: strAttrTemp = "_L_earth."; break;
case 5: strAttrTemp = "_L_light."; break;
case 6: strAttrTemp = "_L_dark."; break;
case 7: strAttrTemp = "_L_fire2."; break;
case 8: strAttrTemp = "_L_water2."; break;
case 9: strAttrTemp = "_L_wind2."; break;
case 10: strAttrTemp = "_L_earth2."; break;
case 11: strAttrTemp = "_L_light2."; break;
case 12: strAttrTemp = "_L_dark2."; break;
}
}
// 2011.07.26 - servantes : 가독성 있는 코드로 수정
// if( strColorFile.length() > 5 ) strColorFile.replace( strColorFile.size() - 4, 1, strColorTemp.c_str() );
// if( strAttrFile.length() > 5 ) strAttrFile.replace ( strAttrFile.size() - 4 , 1, strAttrTemp.c_str() );
if (strColorFile.length() > 5)
{
if (strColorTemp.length() > 5)
strColorFile.replace(strColorFile.size() - 4, 1, strColorTemp.c_str());
}
if (strAttrFile.length() > 5)
{
if (strAttrTemp.length() > 5)
strAttrFile.replace(strAttrFile.size() - 4, 1, strAttrTemp.c_str());
}
strColorNx3 += strColorFile;
strAttrNx3 += strAttrFile;
//무기 강화 이펙트 화일 붙이자!!!
if (nAnyPart == ANIPART_WEAPON_RIGHT)
{
AddAttachItemPart(ANIPART_WEAPON_RIGHT, ATTACH_HAND_RIGHT_WEAPON01, strColorNx3.c_str());
AddAttachItemPart(ANIPART_WEAPON_RIGHT, ATTACH_HAND_RIGHT_WEAPON02, strAttrNx3.c_str());
//if ( pEnhanceFx )
SetWeaponColorized(ANIPART_WEAPON_RIGHT, pAvatarEx, pcolor[3]);
RefreshDeform();
}
else if (nAnyPart == ANIPART_WEAPON_LEFT)
{
AddAttachItemPart(ANIPART_WEAPON_LEFT, ATTACH_HAND_LEFT_WEAPON01, strColorNx3.c_str());
AddAttachItemPart(ANIPART_WEAPON_LEFT, ATTACH_HAND_LEFT_WEAPON02, strAttrNx3.c_str());
//if ( pEnhanceFx )
SetWeaponColorized(ANIPART_WEAPON_LEFT, pAvatarEx, pcolor[3]);
RefreshDeform();
}
}
if (bRefreshWpEffectPos)
{
// nItemCode[1] = AddWeaponEnhanceEffect( nWeaponEffectPos, pEnhanceFx, pWearData->nItemClass );
}
if (nItemCode[1] == -1) return;
nItemCode[0] = pWearData->nItemCode;
}
}
void SGameAvatarEx::UnArmed(int* nItemCode)
{
if (nItemCode[1] != -1)
RemoveEnhanceEffect(nItemCode[1]);
if (nItemCode[2] != -1)
EndLoopFx(nItemCode[2]);
nItemCode[0] = -1;
nItemCode[1] = -1;
nItemCode[2] = -1;
}
int SGameAvatarEx::AddWeaponEnhanceEffect(int nWeaponEffectPos, EnhanceFX* pEnhanceFx, int nItemClass)
{
if (m_bWeaponEVPMatrix[nWeaponEffectPos])
return AddEnhanceEffect(this, nWeaponEffectPos, pEnhanceFx, nItemClass);
_oprint("무기 이벤트 포인트를 찾을수 없습니다.\n");
// assert( false && "무기 이벤트 포인트를 찾을수 없습니다." );
return -1;
}
void SGameAvatarEx::HideWeapon(BOOL bHide)
{
if (!m_pSeqAvatar || !m_bIsInit) return;
// sonador 7.0.16 Mantis 0002790: [모션] 아바타가 활을 착용하고 오르니토를 탔을 때 모션 문제
bool bShowWeapon = bHide; // sonador wrong naming
if (bShowWeapon && IsMountMode()) return;
//장착된 무기 숨기기
m_pSeqAvatar->SetMeshRenderFlag(ANIPART_WEAPON_LEFT, MPART_L_WEAPON, bHide);
m_pSeqAvatar->SetMeshRenderFlag(ANIPART_WEAPON_RIGHT, MPART_R_WEAPON, bHide);
//장착된 치자용 무기 숨기기
m_pSeqAvatar->SetDecoMeshRenderFlag(ANIPART_WEAPON_LEFT, MDECOPART_L_WEAPON, bHide);
m_pSeqAvatar->SetDecoMeshRenderFlag(ANIPART_WEAPON_RIGHT, MDECOPART_R_WEAPON, bHide);
//장착된 아이템 숨기기
m_pSeqAvatar->SetItemRenderFlag(ANIPART_BIPED, ATTACH_HAND_LEFT, bHide);
m_pSeqAvatar->SetItemRenderFlag(ANIPART_BIPED, ATTACH_HAND_RIGHT, bHide);
m_pSeqAvatar->SetItemRenderFlag(ANIPART_BIPED, ATTACH_HAND_ARM2L, bHide);
m_pSeqAvatar->SetItemRenderFlag(ANIPART_BIPED, ATTACH_HAND_ARM2R, bHide);
m_pSeqAvatar->SetItemRenderFlag(ANIPART_BIPED, ATTACH_HAND_ARM2L_DECO, bHide);
m_pSeqAvatar->SetItemRenderFlag(ANIPART_BIPED, ATTACH_HAND_ARM2R_DECO, bHide);
m_pSeqAvatar->SetItemRenderFlag(ANIPART_WEAPON_RIGHT, ATTACH_HAND_RIGHT_WEAPON01, bHide); // sonador 7.0.16 Mantis 0002790: [모션] 아바타가 활을 착용하고 오르니토를 탔을 때 모션 문제
m_pSeqAvatar->SetItemRenderFlag(ANIPART_WEAPON_RIGHT, ATTACH_HAND_RIGHT_WEAPON02, bHide); //
m_pSeqAvatar->SetItemRenderFlag(ANIPART_WEAPON_LEFT, ATTACH_HAND_LEFT_WEAPON01, bHide); //
m_pSeqAvatar->SetItemRenderFlag(ANIPART_WEAPON_LEFT, ATTACH_HAND_LEFT_WEAPON02, bHide); //
if (bHide)
{
bool bAniLock = GetAniLock();
SetAniLock(false);
AttachAnimation(m_pSeqAvatar);
m_pSeqAvatar->SetAttach(ANIPART_BIPED);
SetAniLock(bAniLock);
}
SetWeaponEnhanceFx(m_nTwoHandWeaponCode, bHide);
SetWeaponEnhanceFx(m_nRightHandWeaponCode, bHide);
SetWeaponEnhanceFx(m_nLeftHandWeaponCode, bHide);
}
void SGameAvatarEx::RefreshDeform()
{
if (!m_pSeqAvatar || !m_bIsInit) return;
bool bAniLock = GetAniLock();
SetAniLock(false);
AttachAnimation(m_pSeqAvatar);
for (int nAniPart = 0; nAniPart < ANIPART_MAX; ++nAniPart)
{
m_pSeqAvatar->SetDeform(nAniPart);
m_pSeqAvatar->SetAttach(nAniPart);
}
SetAniLock(bAniLock);
}
void SGameAvatarEx::SetWeaponEnhanceFx(int* nItemCode, bool bHide)
{
if (nItemCode[1] != -1)
{
SetRenderEnhanceFx(nItemCode[1], bHide);
}
}
bool SGameAvatarEx::IsMovingDetour()
{
size_t numDetourPoints = m_vDetourPath.size();
// if(numDetourPoints < 2) return false;
// if(numDetourPoints > m_unDetourStep + 1) return true;
if (numDetourPoints == 0)
{
EraseDetour();
return false;
}
K3DVertex curpos = *GetPosition();
if ((int)curpos.x == m_vDetourPath[numDetourPoints - 1].x && (int)curpos.y == m_vDetourPath[numDetourPoints - 1].y)
{
return false;
}
else
{
return true;
}
}
bool SGameAvatarEx::IsChasing()
{
return m_bIsChasing;
}
bool SGameAvatarEx::MoveDetour(K3DVertex& vtMovePos)
{
size_t numDetourPoints = m_vDetourPath.size();
// if(numDetourPoints < m_unDetourStep + 2) return false;
if (numDetourPoints <= m_unDetourStep) return false;
bool bRefreshDetour = m_bRefreshDetour;
m_bRefreshDetour = false;
K3DVertex curpos;
curpos = *GetPosition();
if (bRefreshDetour || ((int)curpos.x == m_vDetourPath[m_unDetourStep].x && (int)curpos.y == m_vDetourPath[m_unDetourStep].y))
{
if (numDetourPoints > m_unDetourStep + 1)
{
vtMovePos.x = m_vDetourPath[m_unDetourStep + 1].x;
vtMovePos.y = m_vDetourPath[m_unDetourStep + 1].y;
vtMovePos.z = 0.0f;
++m_unDetourStep;
return true;
}
}
return false;
}
bool SGameAvatarEx::CollisionToLine(const K3DVector& vStart, const K3DVector& vEnd)
{
return m_pMsgHandler->CollisionToLine(vStart, vEnd);
}
void SGameAvatarEx::FindDetour(const K3DVertex& vEnd, bool bRestraint, bool bChase)
{
EraseDetour();
K3DVertex vStart = *GetPosition();
m_pMsgHandler->FindDetour(vStart, vEnd, m_vDetourPath, bRestraint, bChase, (GetObjType() == TS_ENTER::PLAYER));
m_bIsChasing = bChase;
m_unDetourStep = 0;
m_bRefreshDetour = true;
}
void SGameAvatarEx::EraseDetour()
{
m_vDetourPath.erase(m_vDetourPath.begin(), m_vDetourPath.end());
m_bRefreshDetour = false;
m_unDetourStep = 0;
}
size_t SGameAvatarEx::GetDetourSize()
{
if (m_vDetourPath.empty())
return 0;
return m_vDetourPath.size();
}
bool SGameAvatarEx::GetDetourPoint(size_t index, int& x, int& y)
{
size_t numDetourPoints = m_vDetourPath.size();
if (numDetourPoints <= index) return false;
x = m_vDetourPath[index].x;
y = m_vDetourPath[index].y;
return true;
}
ArPosition* SGameAvatarEx::GetAllDetourPoint()
{
int numDetourPoints = (int)m_vDetourPath.size();
if (numDetourPoints <= 1) return NULL;
ArPosition* pArPosition = new ArPosition[numDetourPoints];
for (int x = 1; x < numDetourPoints; x++)
{
pArPosition[x - 1].x = m_vDetourPath[x].x;
pArPosition[x - 1].y = m_vDetourPath[x].y;
}
m_vReqPoint.push_back(pArPosition);
return pArPosition;
}
void SGameAvatarEx::DeleteReqPoint()
{
for (size_t i(0); m_vReqPoint.size() > i; ++i)
{
SAFE_DELETE_ARRAY(m_vReqPoint[i]);
}
m_vReqPoint.clear();
}
int SGameAvatarEx::GetAllDetourPointSize()
{
int numDetourPoints = (int)m_vDetourPath.size();
if (numDetourPoints <= 1) return 0;
return numDetourPoints - 1;
}
size_t SGameAvatarEx::GetDetourStep()
{
return m_unDetourStep;
}
bool SGameAvatarEx::CheckAllState()
{
if (IsCasting() || IsAttack() || IsMount() || IsMountMode() || IsMoving() || GetStatus() & TS_ENTER::PlayerInfo::FLAG_SITDOWN)
return false;
return true;
}
void SGameAvatarEx::SetUISyncData(UI_SYNC_INFO::TARGET_INFO& target_info)
{
if (target_info.nTarget_hp != -1)
{
m_pUISyncData->nLast_hp = target_info.nTarget_hp;
}
else
{
if (m_pUISyncData->nLast_hp == -1)
m_pUISyncData->nLast_hp = GetHP();
}
if (target_info.nTarget_mp != -1)
{
m_pUISyncData->nLast_mp = target_info.nTarget_mp;
}
else
{
if (m_pUISyncData->nLast_mp == -1)
m_pUISyncData->nLast_mp = GetMP();
}
++m_pUISyncData->nMessageCnt;
}
void SGameAvatarEx::AddUISyncData(UI_SYNC_INFO& uisyncinfo)
{
if (uisyncinfo.nMode == SIMSG_UI_TARGET_STAT::USE_DEF ||
uisyncinfo.nMode == SIMSG_UI_TARGET_STAT::USE_HPMP ||
uisyncinfo.nMode == SIMSG_UI_TARGET_STAT::USE_STATE_DMG)
SetUISyncData(uisyncinfo.CasterInfo);
m_pUISyncData->vinfo_list.push_back(uisyncinfo);
std::vector< UI_SYNC_INFO::TARGET_INFO >::iterator iter = uisyncinfo.vTargetInfo.begin();
for (; iter != uisyncinfo.vTargetInfo.end(); )
{
SGameAvatarEx* pTarget = (SGameAvatarEx*)GetGameObject((*iter).hTarget);
if (pTarget)
{
pTarget->SetUISyncData((*iter));
++iter;
}
else
iter = uisyncinfo.vTargetInfo.erase(iter);
}
}
UI_SYNC_DATA* SGameAvatarEx::GetUISyncData()
{
return m_pUISyncData;
}
void SGameAvatarEx::Dead()
{
if (GetCurrAnimationID() != ANI_DEAD01)
{
EnterDeadAnimation();
}
if (GetObjType() == TS_ENTER::GAME_MOB)
{
ItemDrop();
}
//죽으면, 초기화
m_dwStartTime = 0;
//죽으면, 기본 상태
if (m_pStateVM)
{
m_pStateVM->SetMode(SObjectStateMachine::MODE_NORMAL);
m_pStateVM->Dead();
}
m_bIsDead = true;
}
void SGameAvatarEx::SetTerrainPickPos(K3DVector* vPick)
{
m_vTerrainPickPos = *vPick;
}
K3DVector* SGameAvatarEx::GetTerrainPickPos()
{
return &m_vTerrainPickPos;
}
const K3DMatrix* SGameAvatarEx::GetEventPointMatrix(int nEffectPos)
{
if (nEffectPos < EFFECT_POS_MAX && nEffectPos > -1)
return &m_matEVPMatrix[nEffectPos];
return NULL;
}
const K3DMatrix* SGameAvatarEx::GetEventPointAttachMatrix(int nEffectPos)
{
if (nEffectPos < EFFECT_POS_MAX && nEffectPos > -1)
return &m_matEVPAttachMatrix[nEffectPos];
return NULL;
}
int SGameAvatarEx::GetWeaponLength(int itemCode)
{
int wt_width = 10;
int cls = GetItemDB().GetClassID(itemCode) - ItemBase::CLASS_ONEHAND_SWORD;
if (cls >= 9) cls--;
int rank = GetItemDB().GetItemRank(itemCode);
if (cls >= 0 && cls <= 11 && rank >= 1 && rank <= 7)
{
wt_width = g_pWeaponLength[cls][rank];
}
return wt_width;
}
const K3DMatrix* SGameAvatarEx::GetWeaponEventPointMatrix(int nWeaponEffectPos, int nEventPointPos)
{
return &m_matWeaponEVPMatrix[nWeaponEffectPos][nEventPointPos];
}
const K3DMatrix* SGameAvatarEx::GetWeaponEventPointAttachMatrix(int nWeaponEffectPos, int nEventPointPos)
{
return &m_matWeaponEVPAttachMatrix[nWeaponEffectPos][nEventPointPos];
}
const K3DMatrix* SGameAvatarEx::GetWeaponEventPointParentMatrix(int nWeaponEffectPos, int nEventPointPos)
{
return &m_matWeaponEVPParentMatrix[nWeaponEffectPos][nEventPointPos];
}
bool SGameAvatarEx::GetWeaponEventPoint(int nWeaponEffectPos)
{
return m_bWeaponEVPMatrix[nWeaponEffectPos];
}
void SGameAvatarEx::GetCurrentAnimationInfo(int& nBoneCnt, DWORD& dwMinTime, DWORD& dwMaxTime, DWORD& dwCurAniTime)
{
if (m_pSeqAvatar && m_bIsInit)
{
std::string strAniKeyName = GetAniKey(GetInnObjType(), GetCurrAnimationID(), true);
m_pSeqAvatar->GetFrameInfo(ANIPART_BIPED, strAniKeyName.c_str(), nBoneCnt, dwMinTime, dwMaxTime);
dwCurAniTime = m_pSeqAvatar->GetAniTime();
}
}
bool SGameAvatarEx::RefreshWeaponEffectPos(KSeqAvatarEx* pSeqAvatarEx, int nWeaponEffectPos)
{
//무기 이펙트 포스 설정
pSeqAvatarEx->SetAttachEffectPos(ANIPART_WEAPON_LEFT);
pSeqAvatarEx->SetAttachEffectPos(ANIPART_WEAPON_RIGHT);
_CID(REQ_EVPOINT);
KMsgREQ_EVPOINT w_effect_pos_msg;
pSeqAvatarEx->Perform(ANIPART_WEAPON_LEFT, id_REQ_EVPOINT, w_effect_pos_msg);
pSeqAvatarEx->Perform(ANIPART_WEAPON_RIGHT, id_REQ_EVPOINT, w_effect_pos_msg);
m_bWeaponEVPMatrix[nWeaponEffectPos] = false;
m_pWeaponEvpSequencer[nWeaponEffectPos][EFFECT_POS_WEAPON_EP_START] = NULL;
m_pWeaponEvpSequencer[nWeaponEffectPos][EFFECT_POS_WEAPON_EP_END] = NULL;
if (w_effect_pos_msg.GetPointCount() <= 0) return false;
KEventPointSeq* pEv = NULL;
KEventPointSeq* pEv1 = NULL;
KEventPointSeq* pEv2 = NULL;
for (int pos_cnt = 0; w_effect_pos_msg.GetPointCount() > pos_cnt; ++pos_cnt)
{
pEv = w_effect_pos_msg.GetPoint(pos_cnt);
const char* pName = pEv->GetName();
if (strlen(pName) && _stricmp(pName, pWeaponEpName[nWeaponEffectPos][EFFECT_POS_WEAPON_EP_START]) == 0)
pEv1 = pEv;
if (strlen(pName) && _stricmp(pName, pWeaponEpName[nWeaponEffectPos][EFFECT_POS_WEAPON_EP_END]) == 0)
pEv2 = pEv;
if (pEv1 && pEv2)
{
m_matWeaponEVPMatrix[nWeaponEffectPos][EFFECT_POS_WEAPON_EP_START] = pEv1->GetPoint();
m_matWeaponEVPMatrix[nWeaponEffectPos][EFFECT_POS_WEAPON_EP_END] = pEv2->GetPoint();
if (pEv1->GetAttachTransform() && pEv2->GetAttachTransform())
{
m_bWeaponEVPMatrix[nWeaponEffectPos] = true;
m_pWeaponEvpSequencer[nWeaponEffectPos][EFFECT_POS_WEAPON_EP_START] = pEv1;
m_pWeaponEvpSequencer[nWeaponEffectPos][EFFECT_POS_WEAPON_EP_END] = pEv2;
for (int epcnt = 0; epcnt < EFFECT_POS_WEAPON_EP_MAX; ++epcnt)
{
K3DMatrixIdentity(m_matWeaponEVPAttachMatrix[nWeaponEffectPos][epcnt]);
K3DMatrixIdentity(m_matWeaponEVPParentMatrix[nWeaponEffectPos][epcnt]);
}
m_matWeaponEVPAttachMatrix[nWeaponEffectPos][EFFECT_POS_WEAPON_EP_START] = *pEv1->GetAttachTransform();
m_matWeaponEVPAttachMatrix[nWeaponEffectPos][EFFECT_POS_WEAPON_EP_END] = *pEv2->GetAttachTransform();
m_matWeaponEVPParentMatrix[nWeaponEffectPos][EFFECT_POS_WEAPON_EP_START] = *pEv1->GetParentTransform();
m_matWeaponEVPParentMatrix[nWeaponEffectPos][EFFECT_POS_WEAPON_EP_END] = *pEv2->GetParentTransform();
}
break;
}
}
return m_bWeaponEVPMatrix[nWeaponEffectPos];
}
//-------------------------------------
// Weapon powerup fx
//-------------------------------------
//void SGameAvatarEx::updateWeaponPowerupMesh(int partNo, bool forceUpdateNow) // 나중에 폴리곤 rebuild하도록 flag
//{
// if (forceUpdateNow) {
// // 현재 FX를 다시 세팅한다. (꽁수?)
// setWeaponPowerupFx(partNo, this->getWeaponPowerupFx(partNo), false);
// return;
// }
//
// switch (partNo) {
// case MPART_R_WEAPON: // 오른손 무기
// if (m_pWeaponPowerupRight!=NULL) m_nUpdatePowerupRight=UPDATE_REBUILD;
// break;
//
// case MPART_L_WEAPON:
// if (m_pWeaponPowerupLeft!=NULL) m_nUpdatePowerupLeft=UPDATE_REBUILD;
// break;
// }
//}
//void SGameAvatarEx::clearWeaponPowerupMesh(int partNo) // 나중에 폴리곤 delete하도록 flag세움
//{
// switch (partNo) {
// case MPART_R_WEAPON: // 오른손 무기
// if (m_pWeaponPowerupRight!=NULL) m_nUpdatePowerupRight=UPDATE_DELETE;
// break;
//
// case MPART_L_WEAPON:
// if (m_pWeaponPowerupLeft!=NULL) m_nUpdatePowerupLeft=UPDATE_DELETE;
// break;
// }
//}
//void SGameAvatarEx::setWeaponPowerupFx(int partNo, SGameFxWeaponPowerup *newFX, bool deleteOldFx)
//{
// if (partNo==MPART_R_WEAPON) { // 오른손 FX
// if (deleteOldFx) SAFE_DELETE(m_pWeaponPowerupRight);
// m_pWeaponPowerupRight=newFX;
// if (newFX!=NULL && m_nUpdatePowerupRight==UPDATE_NONE) {
// if (!rebuildWeaponPowerupMesh(partNo)) { // 즉시 업데이트에 실패하면
// m_nUpdatePowerupRight=UPDATE_REBUILD; // 나중에 업데이트
// }
// }
// } else if (partNo==MPART_L_WEAPON) { // 왼손 FX
// if (deleteOldFx) SAFE_DELETE(m_pWeaponPowerupLeft);
// m_pWeaponPowerupLeft=newFX;
// if (newFX!=NULL && m_nUpdatePowerupLeft==UPDATE_NONE) {
// if (!rebuildWeaponPowerupMesh(partNo)) { // 즉시 업데이트에 실패하면
// m_nUpdatePowerupLeft=UPDATE_REBUILD; // 나중에 업데이트
// }
// }
// }
//}
//SGameFxWeaponPowerup * SGameAvatarEx::getWeaponPowerupFx(int partNo)
//{
// if (partNo==MPART_R_WEAPON) { // 오른손 FX
// return m_pWeaponPowerupRight;
// } else if (partNo==MPART_L_WEAPON) { // 왼손 FX
// return m_pWeaponPowerupLeft;
// }
// return NULL;
//}
//bool SGameAvatarEx::rebuildWeaponPowerupMesh(int partNo) // partNo : MPART_R_WEAPON or MPART_L_WEAPON
//{
// int aniPart;
// SGameFxWeaponPowerup *powerupFx;
//
// if (partNo==MPART_R_WEAPON) {
// // 오른손 FX
// aniPart=ANIPART_WEAPON_RIGHT;
// powerupFx=m_pWeaponPowerupRight;
// } else if (partNo==MPART_L_WEAPON) {
// // 왼손 FX
// aniPart=ANIPART_WEAPON_LEFT;
// powerupFx=m_pWeaponPowerupLeft;
// } else {
// assert(0);
// return false;
// }
//
// //내부에 칼 애니메이션이 있으므로, Primitive 딴 복사로는 문제가 생김.
// if (m_pSeqAvatar!=NULL && powerupFx!=NULL)
// {
// KSequencer *seq=dynamic_cast<KSequencer*>(m_pSeqAvatar->GetMesh(aniPart, partNo)); // ANIPART_WEAPON_RIGHT, MPART_R_WEAPON
// if (seq!=NULL)
// {
// KMeshSeqObject *meshseq=dynamic_cast<KMeshSeqObject*>(seq->GetSeqObject(0));
// if (meshseq!=NULL)
// {
// KMeshPrimitive *pr=meshseq->getMeshPrimitive(0);
// if (pr!=NULL)
// {
// if (pr->GetVertexBuffer()!=NULL && pr->GetIndexBuffer()!=NULL)
// {
// // Weapon mesh primitive loaded
// powerupFx->close();
// powerupFx->init(pr); // do initialize
//
// return true;
// }
// }
// }
// }
// }
//
// return false;
//}
//void SGameAvatarEx::deleteWeaponPowerupMesh(int partNo) // 폴리곤 삭제
//{
// assert(partNo==MPART_R_WEAPON || partNo==MPART_L_WEAPON);
// if (partNo==MPART_R_WEAPON) {
// m_pWeaponPowerupRight->close();
// } else if (partNo==MPART_L_WEAPON) {
// m_pWeaponPowerupLeft->close();
// }
//}
//void SGameAvatarEx::processWeaponPowerupMeshRebuild()
//{
////!!TEST : Localplayer일 경우에만 처리
////if ( IsLocalPlayer() )
//
// if (m_bUpdatePowerupSwitch) { // 무기 강화 이펙트 초기화 (weapon mesh가 update되었음)
// bool br, bl; // 좌우 모두 제대로 처리 되었나?
// br=bl=false;
//
// if (m_pWeaponPowerupRight!=NULL && m_nUpdatePowerupRight!=UPDATE_NONE) { // 오른손용
// if (m_nUpdatePowerupRight==UPDATE_DELETE) {
// // polygon delete
// deleteWeaponPowerupMesh(MPART_R_WEAPON);
// m_nUpdatePowerupRight=UPDATE_NONE;
// br=true;
// } else if (rebuildWeaponPowerupMesh(MPART_R_WEAPON)) {
// m_nUpdatePowerupRight=UPDATE_NONE;
// br=true;
// } else if (m_pSeqAvatar->GetMesh(ANIPART_WEAPON_RIGHT, MPART_R_WEAPON)==NULL) {
// // 오른손 무기 mesh가 존재하지 않으면
// // update플래그 소멸
// deleteWeaponPowerupMesh(MPART_R_WEAPON);
// m_nUpdatePowerupRight=UPDATE_NONE;
// br=true;
// }
// // else br=false;
// } else br=true;
//
// if (m_pWeaponPowerupLeft!=NULL && m_nUpdatePowerupLeft!=UPDATE_NONE) { // 왼손용
// if (m_nUpdatePowerupLeft==UPDATE_DELETE) {
// // polygon delete
// deleteWeaponPowerupMesh(MPART_L_WEAPON);
// m_nUpdatePowerupLeft=UPDATE_NONE;
// bl=true;
// } else if (rebuildWeaponPowerupMesh(MPART_L_WEAPON)) {
// m_nUpdatePowerupLeft=UPDATE_NONE;
// bl=true;
// } else if (m_pSeqAvatar->GetMesh(ANIPART_WEAPON_LEFT, MPART_L_WEAPON)==NULL) {
// // 오른손 무기 mesh가 존재하지 않으면
// // update플래그 소멸
// deleteWeaponPowerupMesh(MPART_L_WEAPON);
// m_nUpdatePowerupLeft=UPDATE_NONE;
// bl=true;
// }
// // else bl=false;
// } else bl=true;
//
// if (br && bl) {
// m_bUpdatePowerupSwitch=false;
// }
// }
//}
//-------------------------------------
// Terrain degree
//-------------------------------------
void SGameAvatarEx::ActivateTerrainDegree()
{
m_bActivateTerrainDegree = true;
if (m_pTerrainDegree) return;
m_pTerrainDegree = new SGameAvatarTerrainDegree;
}
void SGameAvatarEx::DeActivateTerrainDegree()
{
m_bActivateTerrainDegree = false;
SAFE_DELETE(m_pTerrainDegree);
}
float SGameAvatarEx::GetCurAngleX()
{
return m_bActivateTerrainDegree ? m_pTerrainDegree->GetCurrentAngleX() : 0.0f;
}
float SGameAvatarEx::GetCurAngleY()
{
return m_bActivateTerrainDegree ? m_pTerrainDegree->GetCurrentAngleY() : 0.0f;
}
void SGameAvatarEx::StandingDegree()
{
if (!m_bActivateTerrainDegree) return;
K3DVector vPos = GetCurPosWithChangeDir();
K3DVector v1, v2, v3;
GetTerrainTriangle(vPos.x, vPos.y, v1, v2, v3);
v1 = v2 - v1;
v2 = v3 - v2;
m_vTerrainNormal = CrossProduct(v2, v1);
Normalize(m_vTerrainNormal);
K3DMatrix matZ;
K3DVector vView = K3DVector(0.0f, 1.0f, 0.0f);
K3DMatrixRotationZ(matZ, m_fTargetRoll + 3.1415926f / 2);
K3DVectorTransform(vView, vView, matZ);
// K3DVector vCross = CrossProduct(m_vTerrainNormal, -vView);
// if( fabsf(vCross.z) < 0.4f )
m_pTerrainDegree->CalcTerrainDegree(m_vTerrainNormal, m_dwTime);
// else
// m_pTerrainDegree->Reset( m_dwTime );
}
void SGameAvatarEx::StandingDegreeForMount()
{
if (!m_bActivateTerrainDegree) return;
m_pTerrainDegree->Reset(m_dwTime);
}
void SGameAvatarEx::FindNewEvent()
{
int nObjType = GetInnObjType();
if (nObjType == TS_ENTER::GAME_PLAYER || nObjType == TS_ENTER::GAME_MOB || nObjType == TS_ENTER::GAME_SUMMON || nObjType == TS_ENTER::GAME_PET) // sonador 10.2.1 팻 시스템 구현
{
const char* pAni = NULL;
if (nObjType == TS_ENTER::GAME_PLAYER)
pAni = GetMotionSetDB().GetAni(nObjType, m_nNewCurAniType, GetRace(), GetSex(), m_nAniClass);
else if (nObjType == TS_ENTER::GAME_MOB)
{
_MONSTER_INFO_FILE* pMonster = GetMonsterDB().GetMonsterData(GetInnContentID());
if (pMonster)
pAni = GetMonsterMotionSetDB().GetAni(pMonster->motion_file_id, m_nNewCurAniType);
}
else if (nObjType == TS_ENTER::GAME_SUMMON)
{
_SUMMON_INFO_FILE* pSummon = GetCreatureDB().GetCreatureData(GetInnContentID());
if (pSummon)
{
pAni = GetMonsterMotionSetDB().GetAni(pSummon->motion_file_id, m_nNewCurAniType);
}
}
else if (nObjType == TS_ENTER::GAME_PET) // sonador 10.2.1 팻 시스템 구현
{
SPetInfoEx PetInfo = GetPetDB().Find(GetInnContentID());
pAni = GetMonsterMotionSetDB().GetAni(PetInfo.getMotionFileID(), m_nNewCurAniType);
}
SetEventHandleNull();
//이벤트 핸들 설정
FindEventList(pAni, m_pCurEventHandle00_effect, m_svEventHandle00_effectList);
FindEventList(pAni, m_pCurEventHandle00_sound, m_svEventHandle00_soundList);
FindEventList(pAni, m_pCurEventHandle00_motion_effect, m_svEventHandle00_motion_effect);
FindEventList(pAni, m_pCurEventHandle01, m_svEventHandle01_List);
FindEventList(pAni, m_pCurEventHandle02, m_svEventHandle02_List);
FindEventList(pAni, m_pCurEventHandle03, m_svEventHandle03_List);
FindEventList(pAni, m_pCurEventHandle04, m_svEventHandle04_List);
FindEventList(pAni, m_pCurEventHandle05, m_svEventHandle05_List);
FindEventList(pAni, m_pCurEventHandle06, m_svEventHandle06_List);
FindMotionAddOnFx();
}
}
void SGameAvatarEx::FindMotionAddOnFx()
{
if (!m_pCurEventHandle00_effect) return;
Key_EVENT_NEW* pKey1 = NULL;
Key_EVENT_NEW* pKey2 = NULL;
m_pCurEventHandle00_effect->GetData(GetAniTime(), pKey1, pKey2);
if (!pKey1 || pKey1->bUse == false) return;
if (pKey1->nSpeedType == 1)
{
pKey1->bUse = true;
SGameAvatarMotionFx* pAvatarMotionFx = (SGameAvatarMotionFx*)m_pAddOnMgr->GetAddOn(SGameAvatarAddOnMgr::SGAME_AVATAR_MOTION_FX);
if (pAvatarMotionFx)
{
pAvatarMotionFx->SetMotioinFxInfo(m_dwTime, pKey1->strEffect.c_str(), pKey1->nEffPos, m_nNewCurAniType);
pAvatarMotionFx->ChangeNewMotionFx();
pAvatarMotionFx->SetRenderFlag(true);
}
else
{
pAvatarMotionFx = new SGameAvatarMotionFx;
pAvatarMotionFx->SetMotioinFxInfo(m_dwTime, pKey1->strEffect.c_str(), pKey1->nEffPos, m_nNewCurAniType);
m_pAddOnMgr->AddAddOn(pAvatarMotionFx);
}
}
else
{
SGameAvatarMotionFx* pAvatarMotionFx = (SGameAvatarMotionFx*)m_pAddOnMgr->GetAddOn(SGameAvatarAddOnMgr::SGAME_AVATAR_MOTION_FX);
if (pAvatarMotionFx) pAvatarMotionFx->SetRenderFlag(false);
}
}
void SGameAvatarEx::FindMotionAddOnFx(Key_EVENT_NEW* pKey1)
{
if (!pKey1) return;
if (pKey1->nSpeedType == 1)
{
SGameAvatarMotionFx* pAvatarMotionFx = (SGameAvatarMotionFx*)m_pAddOnMgr->GetAddOn(SGameAvatarAddOnMgr::SGAME_AVATAR_MOTION_FX);
if (pAvatarMotionFx)
{
pAvatarMotionFx->SetMotioinFxInfo(m_dwTime, pKey1->strEffect.c_str(), pKey1->nEffPos, m_nNewCurAniType);
pAvatarMotionFx->ChangeNewMotionFx();
pAvatarMotionFx->SetRenderFlag(true);
}
else
{
pAvatarMotionFx = new SGameAvatarMotionFx;
pAvatarMotionFx->SetMotioinFxInfo(m_dwTime, pKey1->strEffect.c_str(), pKey1->nEffPos, m_nNewCurAniType);
m_pAddOnMgr->AddAddOn(pAvatarMotionFx);
}
}
else
{
SGameAvatarMotionFx* pAvatarMotionFx = (SGameAvatarMotionFx*)m_pAddOnMgr->GetAddOn(SGameAvatarAddOnMgr::SGAME_AVATAR_MOTION_FX);
if (pAvatarMotionFx) pAvatarMotionFx->SetRenderFlag(false);
}
}
bool SGameAvatarEx::CurrentlyAnimationIsMount()
{
switch (GetCurrAnimationID())
{
case ANI_M_MOUNT_HIGH:
case ANI_M_MOUNT_LOW:
case ANI_M_MOUNT01_WHITE:
case ANI_M_MOUNT01_UNICORN:
return true;
}
return false;
}
bool SGameAvatarEx::CurrentlyAnimationIsUnMount()
{
switch (GetCurrAnimationID())
{
case ANI_M_UNMOUNT_HIGH:
case ANI_M_UNMOUNT_LOW:
case ANI_M_FALL:
case ANI_M_UNMOUNT01_WHITE:
case ANI_M_UNMOUNT01_UNICORN:
return true;
}
return false;
}
// sonador #2.1.6
bool SGameAvatarEx::CurrentlyAnimationIsMDef()
{
switch (GetCurrAnimationID())
{
case ANI_M_DEFAULT01_HIGH:
case ANI_M_DEFAULT01_LOW:
case ANI_M_DEFAULT01_QILIN:
case ANI_M_DEFAULT01_WHITE: // #2.1.14
case ANI_M_DEFAULT01_UNICORN: // #2.1.14
case ANI_M_DEFAULT01_BEAKHO: /// 2011.02.08 - prodongi
return true;
}
return false;
}
bool SGameAvatarEx::CurrentlyAnimationIsMWalk()
{
switch (GetCurrAnimationID())
{
case ANI_M_WALK:
case ANI_M_WALK_QILIN:
case ANI_M_WALK_WHITE: // #2.1.14
case ANI_M_WALK_UNICORN: // #2.1.14
case ANI_M_WALK_BEAKHO: /// 2011.02.08 - prodongi
return true;
}
return false;
}
bool SGameAvatarEx::CurrentlyAnimationIsMRun()
{
switch (GetCurrAnimationID())
{
case ANI_M_RUN_HIGH: return true;
case ANI_M_RUN_LOW: return true;
case ANI_M_RUN_QILIN: return true; // sonador #2.1.6
case ANI_M_RUN_WHITE: return true; // #2.1.14
case ANI_M_RUN_UNICORN: return true; // #2.1.14
case ANI_M_RUN_BEAKHO: return true; /// 2011.02.08 - prodongi
}
return false;
}
bool SGameAvatarEx::CurrentlyAnimationIsAttack()
{
switch (GetCurrAnimationID())
{
case ANI_ATTACK01: return true;
case ANI_ATTACK02: return true;
case ANI_ATTACK03: return true;
case ANI_CRITICAL_ATTACK01: return true;
case ANI_CRITICAL_ATTACK02: return true;
case ANI_CRITICAL_ATTACK03: return true;
case ANI_DOUBLE_ATTACK01: return true;
case ANI_DOUBLE_ATTACK02: return true;
case ANI_DOUBLE_ATTACK03: return true;
}
return false;
}
bool SGameAvatarEx::CurrentlyAnimationIsDamage()
{
switch (GetCurrAnimationID())
{
case ANI_DAMAGE01: return true;
case ANI_DAMAGE02: return true;
case ANI_M_DAMAGE01: return true;
case ANI_M_DAMAGE02: return true;
}
return false;
}
void SGameAvatarEx::InputFreezing()
{
if (m_pStateVM)
m_pStateVM->InputFreezing();
}
void SGameAvatarEx::InputThawing()
{
if (m_pStateVM)
m_pStateVM->InputThawing();
}
void SGameAvatarEx::ClearPendingNextState()
{
if (m_pStateVM)
m_pStateVM->ClearPendingNextState();
}
bool SGameAvatarEx::IsLoopMotion(int nAniType)
{
switch (nAniType)
{
case ANI_DEFAULT01: return true;
case ANI_DEFAULT02: return true;
case ANI_IDLE: return true;
case ANI_WALK: return true;
case ANI_RUN: return true;
case ANI_M_IDLE: return true;
case ANI_M_WALK: return true;
case ANI_M_DEFAULT01_HIGH: return true;
case ANI_M_RUN_HIGH: return true;
case ANI_M_DEFAULT01_LOW: return true;
case ANI_M_RUN_LOW: return true;
case ANI_M_DEFAULT01_QILIN: return true; // sonador #2.1.6
case ANI_M_WALK_QILIN: return true;
case ANI_M_RUN_QILIN: return true;
case ANI_M_DEFAULT01_WHITE: return true; // #2.1.14
case ANI_M_WALK_WHITE: return true; //
case ANI_M_RUN_WHITE: return true; //
case ANI_M_DEFAULT01_UNICORN: return true; // #2.1.14
case ANI_M_WALK_UNICORN: return true; //
case ANI_M_RUN_UNICORN: return true; //
/// 2011.02.08 - prodongi
case ANI_M_DEFAULT01_BEAKHO:
case ANI_M_WALK_BEAKHO:
case ANI_M_RUN_BEAKHO: return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////
//AvatarEx 내부 사용 용
void SGameAvatarEx::SetInnSex(int nSex)
{
if (m_pProperty) m_pProperty->InnSex = nSex;
}
void SGameAvatarEx::SetInnRace(int nRace)
{
if (m_pProperty) m_pProperty->InnRace = nRace;
}
void SGameAvatarEx::SetInnFaceID(int nFaceID)
{
if (m_pProperty) m_pProperty->InnFaceID = nFaceID;
}
void SGameAvatarEx::SetInnHairID(int nHairID)
{
if (m_pProperty) m_pProperty->InnHairID = nHairID;
}
void SGameAvatarEx::SetInnObjType(unsigned char ObjType)
{
if (m_pProperty) m_pProperty->InnObjType = ObjType;
}
int SGameAvatarEx::GetInnSex()
{
if (m_pProperty) return m_pProperty->InnSex;
return 0;
}
int SGameAvatarEx::GetInnRace()
{
if (m_pProperty) return m_pProperty->InnRace;
return 0;
}
int SGameAvatarEx::GetInnFace()
{
if (m_pProperty) return m_pProperty->InnFaceID;
return 0;
}
int SGameAvatarEx::GetInnHair()
{
if (m_pProperty) return m_pProperty->InnHairID;
return 0;
}
unsigned char SGameAvatarEx::GetInnObjType()
{
if (m_pProperty)
return m_pProperty->InnObjType;
return -1;
}
ENC_INT SGameAvatarEx::GetInnContentID()
{
if (m_pProperty) return m_pProperty->InnContentID();
return -1;
}
//////////////////////////////////////////////////////////////////////////
//변장
void SGameAvatarEx::UpdateDisguiseState()
{
iterator_state_slot PositiveIt = m_vecPositiveList.begin();
iterator_state_slot NegativeIt = m_vecNegativeList.begin();
SStateSlot* pState(NULL);
StateInfoEx* pStateInfo(NULL);
while (true)
{
//이로운 지속효과와 해로운 지속효과를 모두 순환하였으니 break;
if (PositiveIt == m_vecPositiveList.end() && NegativeIt == m_vecNegativeList.end())
break;
if (PositiveIt != m_vecPositiveList.end())
{
if (m_vecPositiveList.end() == PositiveIt + 1)
SetDisguise(*PositiveIt, true);
else
SetDisguise(*PositiveIt);
++PositiveIt;
}
if (NegativeIt != m_vecNegativeList.end())
{
if (m_vecNegativeList.end() == NegativeIt + 1)
SetDisguise(*NegativeIt, true);
else
SetDisguise(*NegativeIt);
++NegativeIt;
}
}
}
void SGameAvatarEx::SetDisguise(SStateSlot* pState, bool bLastDisguese /*= false*/)
{
if (!pState) return;
StateInfoEx* pStateInfo = GetTenacityDB().GetTenacityData(pState->GetStateCode());
bool bComplete = false; // 변신이 끝난후 쓰레드가 돌았는지 체크 (변신 완료후 쓰레드를 거쳐야 다음 변신적용가능)
if (pStateInfo)
{
switch (pStateInfo->effect_type)
{
case STATE_TYPE::STATE_MUTATION_A: //몬스터 전용
{
if (pState->GetStateLevel()) //변이
{
if ((int)pStateInfo->fValue[0] > 0)
{
AddDisguiseID(pStateInfo->id);
while (bComplete == false)
{
bComplete = Disguise(pState->GetStateHandle(), bits_scramble< int, 3 >((int)pStateInfo->fValue[0])); // 2.1.16 변신 효과 중첩시 아바타 사라지는 오류 수정
}
if (bLastDisguese)
m_nDisguise = STAT_DISGUISE;
}
}
else if (pState->GetStateLevel() == 0) //해제
{
DeleteDisguiseID(pStateInfo->id);
UnDisguise(pState->GetStateHandle());
}
}
break;
case STATE_TYPE::STATE_MUTATION_B: //소환수 전용
{
if (pState->GetStateLevel()) //변이
{
if (pState->GetStateValue() > 0)
{
AddDisguiseID(pStateInfo->id);
Disguise(pState->GetStateHandle(), pState->GetStateValue(), true, pState->GetStateLevel());
/*
while (bComplete == false)
{
bComplete = Disguise(pState->GetStateHandle(), pState->GetStateValue(), true , pState->GetStateLevel() ); // 2.1.16 변신 효과 중첩시 아바타 사라지는 오류 수정
}
if (bLastDisguese)
m_nDisguise = STAT_DISGUISE;
*/
if (m_nDisguise == STAT_DISGUISE)
{
//SetScale( getNoneDisguiseScale() * ( pStateInfo->fValue[8] + pStateInfo->fValue[9] * pState->GetStateLevel() ));
SetScale(getNoneDisguiseScale() * (pStateInfo->fValue[8] + pStateInfo->fValue[9]));
}
}
}
else if (pState->GetStateLevel() == 0) //해제
{
DeleteDisguiseID(pStateInfo->id);
UnDisguise(pState->GetStateHandle());
}
}
break;
default:
m_nDisguise = STAT_DISGUISE;
break;
}
}
}
void SGameAvatarEx::CheckDisguise()
{
if (m_nDisguise == PROG_DISGUISE)
{
UpdateDisguiseState();
}
else if (m_nDisguise == REMO_DISGUISE)
{
// 2.1.16 변신 효과 중첩시 아바타 사라지는 오류 수정
unsigned int handle = m_UndisguiseStateHandleQueue.front();
m_UndisguiseStateHandleQueue.pop_front();
UnDisguise(handle);
}
}
// 2.1.16 변신 효과 중첩시 아바타 사라지는 오류 수정
/// 2011.07.28 redmine #16797 - prodongi
bool SGameAvatarEx::Disguise(unsigned int stateHandle, ENC_INT nContentID, bool bIsSummon, int disguiseEnhance)
{
/// 2011.07.28 redmine #16797 ¼­¹ö¿¡¼­ SMSG_STATE¸¦ ¹Þ´Â °Í°ú µ¥ÀÌŸ ·Îµù ¼ø¼­°¡ ¾È ¸Â¾Æ¼­ ÀÌ·¸°Ô ÇÔ - prodongi
if (disguiseEnhance > 1)
m_disguiseEnhance = 1;
else
m_disguiseEnhance = 0;
/// 2011.06.20 servantes : 9078 : Å©¸®Ã³ º¯½Å ÈÄ ¾ß¼ö º¯½Å ½ºÅ³ »ç¿ë ½Ã ¹®Á¦
ENC_INT _tempContentID = 0;
if (IsThreadLoading() || !m_bIsActivated || !m_pSeqAvatar)
{
m_nDisguise = PROG_DISGUISE; //º¯Àå Áß »óÅ·Î
return false;
}
else
{
if (m_nDisguise == STAT_DISGUISE) //ÀÌ¹Ì º¯Àå ÁßÀ̶ó¸é
{
// 2011.06.20 - servantes
_tempContentID = GetInnContentID();
if (GetInnContentID() == nContentID)
return true;
else
_tempContentID = nContentID;
//KSeqAvatarEx* pSeqAvatar = m_pSeqAvatar;
//m_pSeqAvatar = m_pDisguiseSeqAvatar;
//SetScale( m_fDisguiseScale );
//SAFE_DELETE( pSeqAvatar );
}
// 2011.06.20 - servantes
else // 2011.06.20 - servantes
{
_tempContentID = nContentID;
}
}
// 2011.06.20 - servantes
if (!m_pDisguiseStack->onDisguise(DisguiseStack::Slot(stateHandle, _tempContentID, m_pSeqAvatar, GetSize(), GetScale(), bIsSummon)))
return true;
Deactivate();
//m_pDisguiseSeqAvatar = m_pSeqAvatar;
//m_fDisguiseSize = GetSize();
//m_fDisguiseScale = GetScale();
/// 2011.04.29 - prodongi
float oldScale = GetScale();
m_pSeqAvatar = NULL;
m_nFirst = 0;
// 2011.06.20 - servantes
m_pProperty->SetInnContentID(_tempContentID);
if (!bIsSummon)
{
SetInnObjType(TS_ENTER::GAME_MOB);
}
else
{
SetInnObjType(TS_ENTER::GAME_SUMMON);
}
SetInnSex(0);
SetInnRace(0);
SetInnFaceID(0);
SetInnHairID(0);
InfoRemoveForDisguise();
switch (GetInnObjType())
{
case TS_ENTER::GAME_PLAYER:
{
SetScale(1.0f);
}
break;
case TS_ENTER::GAME_NPC:
{
SetScale(1.0f);
}
break;
case TS_ENTER::GAME_MOB:
{
// 2011.06.20 - servantes
_MONSTER_INFO_FILE* pMonsterInfo = GetMonsterDB().GetMonsterData(_tempContentID);
if (pMonsterInfo)
{
/* if( m_strBackupName.empty() )
{
m_strBackupName = GetName();
SetName( GetStringDB().GetString( pMonsterInfo->name_id ) );
}*/
SetScale(pMonsterInfo->scale);
if (GetObjType() == TS_ENTER::GAME_PLAYER)
SetRunNWalkAniSpeed(pMonsterInfo);
}
else
SetScale(1.0f);
}
break;
case TS_ENTER::GAME_SUMMON:
{
// 2011.06.20 - servantes
_SUMMON_INFO_FILE* pSummon = GetCreatureDB().GetCreatureData(_tempContentID);
if (pSummon)
{
/* if( m_strBackupName.empty() )
{
m_strBackupName = GetName();
SetName( GetStringDB().GetString( pSummon->name_id ) );
}*/
SetScale(pSummon->scale);
if (GetObjType() == TS_ENTER::GAME_PLAYER)
SetRunNWalkAniSpeed(pSummon);
}
else
SetScale(1.0f);
}
break;
}
RefreshEffectPos(NULL);
addToLoadingList();
/// 2011.04.29 º¯½Å ÀüÀÇ Å©±â¸¦ ÀúÀåÇØ ³õ´Â´Ù - prodongi
if (m_nDisguise == NONE_DISGUISE)
{
m_noneDisguiseScale = oldScale;
}
m_nDisguise = STAT_DISGUISE; //º¯Àå »óÅÂ
doLoading();
return true;
}
// 2.1.16 변신 효과 중첩시 아바타 사라지는 오류 수정
void SGameAvatarEx::UnDisguise(unsigned int stateHandle)
{
/// 2011.07.28 redmine #16797 - prodongi
m_disguiseEnhance = 0;
if (IsThreadLoading() || !m_bIsActivated || !m_pSeqAvatar)
{
m_nDisguise = REMO_DISGUISE; //변장 해제 중 상태로
m_UndisguiseStateHandleQueue.push_back(stateHandle);
return;
}
/* if( m_strBackupName.empty() == false )
{
SetName( m_strBackupName.c_str() );
m_strBackupName.clear();
}*/
if (m_pDisguiseStack->empty())
{
m_nDisguise = NONE_DISGUISE;
return;
}
DisguiseStack::Slot disguiseSlot(stateHandle, 0, 0, 0, 0, 0);
if (!m_pDisguiseStack->onUndisguise(disguiseSlot))
return;
SAFE_DELETE(m_pSeqAvatar);
m_pSeqAvatar = disguiseSlot.seqAvatar;
if (!m_DisguiseList.empty())
{
m_pProperty->SetInnContentID(disguiseSlot.contentID);
if (!disguiseSlot.isSummon)
{
SetInnObjType(TS_ENTER::GAME_MOB);
}
else
{
SetInnObjType(TS_ENTER::GAME_SUMMON);
}
SetInnSex(0);
SetInnRace(0);
SetInnFaceID(0);
SetInnHairID(0);
InfoRemoveForDisguise();
SetScale(disguiseSlot.scale);
switch (GetInnObjType())
{
case TS_ENTER::GAME_MOB:
{
_MONSTER_INFO_FILE* pMonsterInfo = GetMonsterDB().GetMonsterData(disguiseSlot.contentID);
if (pMonsterInfo && GetObjType() == TS_ENTER::GAME_PLAYER)
SetRunNWalkAniSpeed(pMonsterInfo);
}
break;
case TS_ENTER::GAME_SUMMON:
{
_SUMMON_INFO_FILE* pSummon = GetCreatureDB().GetCreatureData(disguiseSlot.contentID);
if (pSummon && GetObjType() == TS_ENTER::GAME_PLAYER)
SetRunNWalkAniSpeed(pSummon);
}
break;
}
//이벤트 다시 로드
const char* pFileName = GetCobFileName();
if (pFileName)
{
std::string strName = pFileName;
if (strstr(strName.c_str(), ".cob") == NULL)
strName += ".cob";
m_strFileName = strName;
vec_cobset* coblist = COBManager::GetManager()->Load(strName.c_str());
if (coblist)
{
RefreshTextureGroup(coblist);
iterator_cobset it = coblist->begin();
if (coblist->end() != it)
{
COBSET* pCob = *it;
LoadEvent(pCob);
//큐브 Load
for (int i(0); 6 > i; i++)
{
m_fSelcube[i] = pCob->fSelCube[i];
m_fDeadcube[i] = pCob->fDeadCube[i];
}
for (int i(0); i < 3; ++i)
{
if (m_fSelcube[i] > m_fSelcube[i + 3]) ::swap(m_fSelcube[i], m_fSelcube[i + 3]);
if (m_fDeadcube[i] > m_fDeadcube[i + 3]) ::swap(m_fDeadcube[i], m_fDeadcube[i + 3]);
}
}
}
}
RefreshEffectPos(m_pSeqAvatar);
//변장 해제 될때 이펙트
AddEffect(GetArID(), GetArID(), GetArID(), 4079, EFFECT_POS_BOTTOM);
return;
}
Activate();
SetScale(disguiseSlot.scale);
//기존 정보로 셋팅
m_pProperty->SetInnContentID(GetContentID());
SetInnObjType(GetObjType());
SetInnSex(GetSex());
SetInnRace(GetRace());
SetInnFaceID(GetFace());
SetInnHairID(GetHair());
InfoRemoveForDisguise();
//이벤트 다시 로드
const char* pFileName = GetCobFileName();
if (pFileName)
{
std::string strName = pFileName;
if (strstr(strName.c_str(), ".cob") == NULL)
strName += ".cob";
m_strFileName = strName;
vec_cobset* coblist = COBManager::GetManager()->Load(strName.c_str());
if (coblist)
{
iterator_cobset it = coblist->begin();
if (coblist->end() != it)
{
COBSET* pCob = *it;
LoadEvent(pCob);
//큐브 Load
for (int i(0); 6 > i; i++)
{
m_fSelcube[i] = pCob->fSelCube[i];
m_fDeadcube[i] = pCob->fDeadCube[i];
}
for (int i(0); i < 3; ++i)
{
if (m_fSelcube[i] > m_fSelcube[i + 3]) ::swap(m_fSelcube[i], m_fSelcube[i + 3]);
if (m_fDeadcube[i] > m_fDeadcube[i + 3]) ::swap(m_fDeadcube[i], m_fDeadcube[i + 3]);
}
}
}
}
//이펙트 포스 다시 얻어오기
RefreshEffectPos(m_pSeqAvatar);
NPlayAnimation(m_nNewCurAniType, m_nCurPlayType);
SetVisibility(m_fVisibility);
//변장 해제 될때 이펙트
AddEffect(GetArID(), GetArID(), GetArID(), 4079, EFFECT_POS_BOTTOM);
m_nDisguise = NONE_DISGUISE; //원 상태
}
bool SGameAvatarEx::IsLastDisguise()
{
if (m_DisguiseList.empty())
return true;
return false;
}
void SGameAvatarEx::AddDisguiseID(int nDisguiseId)
{
std::list<int>::iterator it;
for (it = m_DisguiseList.begin(); it != m_DisguiseList.end(); ++it)
{
if (*it == nDisguiseId)
return; // 이미 추가 되어있는 id
}
m_DisguiseList.push_back(nDisguiseId);
}
void SGameAvatarEx::DeleteDisguiseID(int nDisguiseId)
{
std::list<int>::iterator it;
for (it = m_DisguiseList.begin(); it != m_DisguiseList.end(); ++it)
{
if (*it == nDisguiseId)
{
it = m_DisguiseList.erase(it);
return;
}
}
}
//변장을 위한 정보 삭제
void SGameAvatarEx::InfoRemoveForDisguise()
{
SetEventHandleInit();
SetEventHandleNull();
DeleteEvent(m_svEventHandle00_effectList);
DeleteEvent(m_svEventHandle00_soundList);
DeleteEvent(m_svEventHandle00_motion_effect);
DeleteEvent(m_svEventHandle01_List);
DeleteEvent(m_svEventHandle02_List);
DeleteEvent(m_svEventHandle03_List);
DeleteEvent(m_svEventHandle04_List);
DeleteEvent(m_svEventHandle05_List);
DeleteEvent(m_svEventHandle06_List);
if (m_pAddOnMgr)
{
m_pAddOnMgr->RemoveAddOn(SGameAvatarAddOnMgr::SGAME_AVATAR_FX);
m_pAddOnMgr->RemoveAddOn(SGameAvatarAddOnMgr::SGAME_AVATAR_MOTION_FX);
}
SGameCircleShadowFX* pCirclrShadowFx = (SGameCircleShadowFX*)m_pAddOnMgr->GetAddOn(SGameAvatarAddOnMgr::SGAME_CIRCLE_SHADOW_FX);
if (pCirclrShadowFx) pCirclrShadowFx->Refresh();
m_bUseRot = true;
}
bool SGameAvatarEx::SetFrame(int nFrame)
{
KSeqAvatarEx* pSeqAvatar = GetSeqForm();
if (!pSeqAvatar) return false;
KSeqAvatar* pBipedSeq = pSeqAvatar->getAvatarPart(ANIPART_BIPED);
if (!pBipedSeq) return false;
KBoneSeqObject* pBoneSeq = pBipedSeq->getBoneSequencer();
if (!pBipedSeq) return false;
KBoneSeqObject* pBoneSeqRightWeapon = NULL;
KBoneSeqObject* pBoneSeqLeftWeapon = NULL;
KSeqAvatar* pRightHandSeq = pSeqAvatar->getAvatarPart(ANIPART_WEAPON_RIGHT);
KSequencer* pSequencer = dynamic_cast<KSequencer*>(pRightHandSeq->GetCurrentAnimation());
if (pSequencer != NULL)
{
pBoneSeqRightWeapon = dynamic_cast<KBoneSeqObject*> (pSequencer->GetSeqObject(0));
}
KSeqAvatar* pLeftHandSeq = pSeqAvatar->getAvatarPart(ANIPART_WEAPON_LEFT);
pSequencer = dynamic_cast<KSequencer*>(pLeftHandSeq->GetCurrentAnimation());
if (pSequencer != NULL)
{
pBoneSeqLeftWeapon = dynamic_cast<KBoneSeqObject*> (pSequencer->GetSeqObject(0));
}
if (!pBoneSeqRightWeapon || !pBoneSeqLeftWeapon) return false;
DWORD dwTime = nFrame * 160;
pSeqAvatar->SetAniTime(dwTime);
pSeqAvatar->realizeTime();
pBoneSeq->realizeTime();
pRightHandSeq->realizeTime();
pLeftHandSeq->realizeTime();
pBoneSeqRightWeapon->realizeTime();
pBoneSeqLeftWeapon->realizeTime();
_renderEffectLoading();
return true;
}
bool SGameAvatarEx::SetFxSwordSlashDBData(SGameFxSwordSlash* pFxSwordSlash, int nItemCode, int nEnhanceLevel)
{
if (pFxSwordSlash == NULL) return false;
int wt_width = GetWeaponLength(nItemCode);
int wt_length = 50 + nEnhanceLevel * 10; // 강화도에 따라 trail이 길어진다
unsigned int* pcolor = g_pEnhanceColor[0];
if (nEnhanceLevel > 0 && nEnhanceLevel <= 25) pcolor = g_pEnhanceColor[nEnhanceLevel]; // 강화도에 따른 색상
if (wt_length > 1)
{
KColor Scolor0(pcolor[0]);
KColor Scolor1(pcolor[1]);
KColor Ecolor0(pcolor[2]);
KColor Ecolor1(pcolor[3]);
pFxSwordSlash->setTrailWidth(wt_width);
pFxSwordSlash->setTrailNodeCount(wt_length);
pFxSwordSlash->setTrailNodeColor(0, 0, Scolor0.color);
pFxSwordSlash->setTrailNodeColor(0, 1, Scolor1.color);
pFxSwordSlash->setTrailNodeColor(1, 0, Ecolor0.color);
pFxSwordSlash->setTrailNodeColor(1, 1, Ecolor1.color);
pFxSwordSlash->setTrailTexture("wfxsforce_lv03.dds");
return true;
}
return false;
}
void SGameAvatarEx::ActivateFxSwordSlashForSkill()
{/*
if(GetInnObjType() != TS_ENTER::GAME_PLAYER) return;
m_nSwordSlashForSkillMotion = GetCurrAnimationID();
ItemBase::ItemCode nRightHandCode = GetItemCode(ItemBase::WEAR_WEAPON);
if(m_bActRightWeaponTrail == false && m_bActRightSwordSlashForSkill == false)
{
SGameFxSwordSlash* pFxSwordSlash = new SGameFxSwordSlash(true);
if(SetFxSwordSlashDBData(pFxSwordSlash, nRightHandCode, 15))
{
m_pRightSwordSlashForSkill = pFxSwordSlash;
m_pRightSwordSlashForSkill->runTrail(true);
m_bActRightSwordSlashForSkill = true;
}
else
{
SAFE_DELETE(pFxSwordSlash);
}
}
ItemBase::ItemCode nLeftHandCode = GetItemCode(ItemBase::WEAR_SHIELD);
if(m_bActLeftWeaponTrail == false && m_bActLeftSwordSlashForSkill == false)
{
SGameFxSwordSlash* pFxSwordSlash = new SGameFxSwordSlash(false);
if(SetFxSwordSlashDBData(pFxSwordSlash, nLeftHandCode, 15))
{
m_pLeftSwordSlashForSkill = pFxSwordSlash;
m_pLeftSwordSlashForSkill->runTrail(true);
m_bActLeftSwordSlashForSkill = true;
}
else
{
SAFE_DELETE(pFxSwordSlash);
}
}
*/
}
void SGameAvatarEx::DeActivateFxSwordSlashForSkill()
{
m_bActRightSwordSlashForSkill = false;
m_bActLeftSwordSlashForSkill = false;
SAFE_DELETE(m_pRightSwordSlashForSkill);
SAFE_DELETE(m_pLeftSwordSlashForSkill);
m_nSwordSlashForSkillMotion = 0;
}
void SGameAvatarEx::CheckStateSkill()
{
_checkPetrify();
CheckDisguise();
if (m_nStateFlag & FLAG_STATE_HIDING)
{
if (m_pSeqAvatar)
m_pSeqAvatar->SetVisibility(m_fHidingVisiblity);
}
}
void SGameAvatarEx::UpdateState(SMSG_STATE* pMsg)
{
if (pMsg->state_level)
{
AddState(pMsg);
}
else if (pMsg->state_level == 0)
{
DeleteState(pMsg);
}
else
{
assert(0 && "상태 이상 데이타 이상!!!");
}
}
struct FuncSortEndTime
{
bool operator() (const SStateSlot* pr1, const SStateSlot* pr2) const
{
return pr1->GetEndTime() < pr2->GetEndTime();
}
};
void SGameAvatarEx::AddState(SMSG_STATE* pMsg)
{
int nPos(NULL);
SStateSlot* pOldState(GetOldStateInfo(pMsg, nPos));
SStateSlot* pOldCashState(GetOldCashStateInfo(pMsg, nPos));
if (pOldState) //이미 있는 것이니 레벨과 데이터만 갱신
{
StateInfoEx* s_data(GetTenacityDB().GetTenacityData(pMsg->state_code));
if (!s_data)
return;
pOldState->SetStateLevel(pMsg->state_level);
pOldState->SetStateTime(pMsg->start_time, pMsg->end_time);
pOldState->SetToggleType(pMsg->isToggle);
pOldState->SetStateValue(pMsg->state_value);
SIMSG_UI_STATE_LIST_UPDATE MSG(pMsg->handle, SIMSG_UI_STATE_LIST_UPDATE::STATE_CHANGE, s_data->is_harmful, nPos, pOldState);
SendGameInterfaceMsg(&MSG);
if (!pMsg->isToggle && IsLocalPlayer())
{
/// 2012.02.01 중첩 불가이고, 새로 걸리는 버프 일 때만 - prodongi
if (1 > s_data->reiteration_count)
{
if (pMsg->isNewState)
OutputAddStateSystemMsg(pMsg);
}
}
//-----------------------------------------------------------------------
//gmpbigsun(20131120): Sort
if (pOldState->IsHarmful())
std::sort(m_vecNegativeList.begin(), m_vecNegativeList.end(), FuncSortEndTime());
else
std::sort(m_vecPositiveList.begin(), m_vecPositiveList.end(), FuncSortEndTime());
SIMSG_UI_STATE_LIST_UPDATE MSG2(pMsg->handle, SIMSG_UI_STATE_LIST_UPDATE::STATE_REFRESH, false, 0, NULL);
SendGameInterfaceMsg(&MSG2);
//-----------------------------------------------------------------------
}
else if (pOldCashState)
{
StateInfoEx* s_data(GetTenacityDB().GetTenacityData(pMsg->state_code));
if (!s_data)
return;
pOldCashState->SetStateLevel(pMsg->state_level);
pOldCashState->SetStateTime(pMsg->start_time, pMsg->end_time);
pOldCashState->SetToggleType(pMsg->isToggle);
pOldCashState->SetStateValue(pMsg->state_value);
if (isMarkState(pMsg->state_code))
{
SIMSG_UI_STATE_LIST_UPDATE MSG(pMsg->handle, SIMSG_UI_STATE_LIST_UPDATE::STATE_UPDATE_MARK, s_data->is_harmful, nPos, pOldCashState);
SendGameInterfaceMsg(&MSG);
std::sort(m_vecMarkStateList.begin(), m_vecMarkStateList.end(), FuncSortEndTime());
SIMSG_UI_STATE_LIST_UPDATE MSG2(pMsg->handle, SIMSG_UI_STATE_LIST_UPDATE::STATE_REFRESH, false, 0, NULL);
SendGameInterfaceMsg(&MSG2);
}
else if (IsCashState(pMsg->state_code))
{
SIMSG_UI_STATE_LIST_UPDATE MSG(pMsg->handle, SIMSG_UI_STATE_LIST_UPDATE::STATE_CHANGE_CASH, s_data->is_harmful, nPos, pOldCashState);
SendGameInterfaceMsg(&MSG);
std::sort(m_vecCashStateList.begin(), m_vecCashStateList.end(), FuncSortEndTime());
SIMSG_UI_STATE_LIST_UPDATE MSG2(pMsg->handle, SIMSG_UI_STATE_LIST_UPDATE::STATE_REFRESH, false, 0, NULL);
SendGameInterfaceMsg(&MSG2);
}
else
__noop;
/// 2012.02.01 중첩 불가이고, 새로 걸리는 버프 일 때만 - prodongi
if (1 > s_data->reiteration_count)
{
if (pMsg->isNewState)
OutputAddStateSystemMsg(pMsg);
}
}
else
{
int nIndex(0);
SStateSlot* pSlot = AddStateInfo(pMsg, nIndex);
if (!pSlot) return;
/// 2011.01.14 - prodongi
if (isMarkState(pMsg->state_code))
{
SIMSG_UI_STATE_LIST_UPDATE MSG(pMsg->handle, SIMSG_UI_STATE_LIST_UPDATE::STATE_UPDATE_MARK, false, 0, NULL);
SendGameInterfaceMsg(&MSG);
}
else if (IsCashState(pMsg->state_code))
{
SIMSG_UI_STATE_LIST_UPDATE MSG(pMsg->handle, SIMSG_UI_STATE_LIST_UPDATE::STATE_ADD_CASH, pSlot->IsHarmful(), nIndex, pSlot);
SendGameInterfaceMsg(&MSG);
}
else
{
SIMSG_UI_STATE_LIST_UPDATE MSG(pMsg->handle, SIMSG_UI_STATE_LIST_UPDATE::STATE_ADD, pSlot->IsHarmful(), nIndex, pSlot);
SendGameInterfaceMsg(&MSG);
}
if (IsLocalPlayer())
OutputAddStateSystemMsg(pMsg);
}
}
void SGameAvatarEx::DeleteState(SMSG_STATE* pMsg)
{
StateInfoEx* s_data = GetTenacityDB().GetTenacityData(pMsg->state_code);
if (!s_data) return;
int nPos(0);
SStateSlot* pState = GetOldStateInfo(pMsg, nPos);
if (!pState) pState = GetOldCashStateInfo(pMsg, nPos);
if (!pState) return;
int nStateLv(pState->GetStateLevel());
int nIndex = DeleteStateInfo(pMsg->handle, pMsg->state_handle, pMsg->state_code);
if (nIndex != -1)
{
/// 2011.01.14 - prodongi
if (isMarkState(pMsg->state_code))
{
SIMSG_UI_STATE_LIST_UPDATE MSG(pMsg->handle, SIMSG_UI_STATE_LIST_UPDATE::STATE_UPDATE_MARK, false, 0, NULL);
SendGameInterfaceMsg(&MSG);
}
else if (IsCashState(pMsg->state_code))
{
SIMSG_UI_STATE_LIST_UPDATE MSG(pMsg->handle, SIMSG_UI_STATE_LIST_UPDATE::STATE_DELETE_CASH, s_data->is_harmful, nIndex, NULL);
SendGameInterfaceMsg(&MSG);
}
else
{
SIMSG_UI_STATE_LIST_UPDATE MSG(pMsg->handle, SIMSG_UI_STATE_LIST_UPDATE::STATE_DELETE, s_data->is_harmful, nIndex, NULL);
SendGameInterfaceMsg(&MSG);
}
if (IsLocalPlayer())
OutputDeleteStateSystemMsg(pMsg, nStateLv);
}
}
void SGameAvatarEx::OutputAddStateSystemMsg(SMSG_STATE* pMsg)
{
// _performance_print( "%d - %d - %d - %d - %d [ %d %d ]\n", pMsg->handle, pMsg->state_handle, pMsg->state_code, pMsg->state_level, pMsg->data_owner, pMsg->end_time, pMsg->start_time );
std::string strTextMsg;
StateInfoEx* pStateInfo = GetTenacityDB().GetTenacityData(pMsg->state_code);
std::string strStateNAme(GetStringDB().GetString(GetTenacityDB().GetNameID(pMsg->state_code)));
if (pStateInfo && !pStateInfo->is_harmful) //이로운 스킬
{
strTextMsg = SR(SYS_MSG_USE_BUFF, "#@skill_name@#", strStateNAme.c_str(), "#@skill_level@#", pMsg->state_level);
// AziaMafia Fix String 96
strTextMsg = SR(SYS_MSG_USE_BUFF, "#@s@#", strStateNAme.c_str());
}
else
{
strTextMsg = SR(SYS_MSG_GET_DEBUFF, "#@skill_name@#", strStateNAme.c_str(), "#@skill_level@#", pMsg->state_level);
// AziaMafia Fix String 96
strTextMsg = SR(SYS_MSG_GET_DEBUFF, "#@s@#", strStateNAme.c_str());
}
if (!strTextMsg.empty()) m_pMsgHandler->AddChatMessage(strTextMsg.c_str());
}
void SGameAvatarEx::OutputDeleteStateSystemMsg(SMSG_STATE* pMsg, int nLv)
{
std::string strTextMsg = SStringDB::ParseString(GetStringDB().GetString(SYS_MSG_DISABLE_BUFF),
"#@skill_name@#", GetStringDB().GetString(GetTenacityDB().GetNameID(pMsg->state_code)),
"#@skill_level@#", SStringDB::ToString(nLv).c_str());
// AziaMafia Fix String 96
strTextMsg = SStringDB::ParseString(GetStringDB().GetString(SYS_MSG_DISABLE_BUFF),
"#@s@#", GetStringDB().GetString(GetTenacityDB().GetNameID(pMsg->state_code)));
if (!strTextMsg.empty()) m_pMsgHandler->AddChatMessage(strTextMsg.c_str());
}
SStateSlot* SGameAvatarEx::GetOldStateInfo(SMSG_STATE* pMsg, int& nOutPos)
{
iterator_state_slot PositiveIt = m_vecPositiveList.begin();
iterator_state_slot NegativeIt = m_vecNegativeList.begin();
int nPos(0);
while (true)
{
//이로운 지속효과와 해로운 지속효과를 모두 순환하였으니 break;
if (PositiveIt == m_vecPositiveList.end() && NegativeIt == m_vecNegativeList.end())
break;
//이로운 지속효과
if (PositiveIt != m_vecPositiveList.end())
{
if (IsEqualState(*PositiveIt, pMsg))
{
nOutPos = nPos;
return *PositiveIt;
}
++PositiveIt;
}
//해로운 지속효과
if (NegativeIt != m_vecNegativeList.end())
{
if (IsEqualState(*NegativeIt, pMsg))
{
nOutPos = nPos;
return *NegativeIt;
}
++NegativeIt;
}
++nPos;
}
return NULL;
}
SStateSlot* SGameAvatarEx::GetOldCashStateInfo(SMSG_STATE* pMsg, int& nOutPos)
{
/// 2012.08.08 m_vecMarkStateList도 캐쉬 아이템에 해당 되기 때문에 같이 검사함 - prodongi
SStateSlot* stat = GetStateInfo(m_vecCashStateList, pMsg, nOutPos);
if (stat)
return stat;
stat = GetStateInfo(m_vecMarkStateList, pMsg, nOutPos);
if (stat)
return stat;
return NULL;
}
SStateSlot* SGameAvatarEx::GetStateInfo(vec_state_slot const& stateList, SMSG_STATE* pMsg, int& nOutPos)
{
vec_state_slot::const_iterator it = stateList.begin();
int nPos(0);
while (it != stateList.end())
{
if (IsEqualState(*it, pMsg))
{
nOutPos = nPos;
return *it;
}
++it;
++nPos;
}
return NULL;
}
StateInfoEx* SGameAvatarEx::GetStateDBInfo(STATE_TYPE nType)
{
/// 2011.01.14 - prodongi
StateInfoEx* pStateInfo = NULL;
pStateInfo = GetStateDBInfo(m_vecPositiveList, nType);
if (pStateInfo) return pStateInfo;
pStateInfo = GetStateDBInfo(m_vecNegativeList, nType);
if (pStateInfo) return pStateInfo;
pStateInfo = GetStateDBInfo(m_vecCashStateList, nType);
if (pStateInfo) return pStateInfo;
pStateInfo = GetStateDBInfo(m_vecMarkStateList, nType);
if (pStateInfo) return pStateInfo;
return NULL;
}
/// 2011.01.14 - prodongi
StateInfoEx* SGameAvatarEx::GetStateDBInfo(vec_state_slot const& stateList, STATE_TYPE nType)
{
vec_state_slot::const_iterator iter = stateList.begin();
for (; iter != stateList.end(); ++iter)
{
StateInfoEx* pStateInfo = GetTenacityDB().GetTenacityData((*iter)->GetStateCode());
if (pStateInfo == NULL) continue;
if (pStateInfo->effect_type == nType) return pStateInfo;
}
return NULL;
}
bool SGameAvatarEx::IsEqualState(SStateSlot* pInfo, SMSG_STATE* pMsg)
{
if (!pInfo || !pMsg) return false;
return IsEqualState(pInfo, pMsg->handle, pMsg->state_handle, pMsg->state_code);
}
bool SGameAvatarEx::IsEqualState(SStateSlot* pInfo, AR_HANDLE hTarget, AR_HANDLE hState, unsigned int state_code)
{
if (!pInfo) return false;
if (pInfo->GetTargetHandle() == hTarget &&
pInfo->GetStateHandle() == hState &&
pInfo->GetStateCode() == state_code)
{
return true;
}
return false;
}
SStateSlot* SGameAvatarEx::AddStateInfo(SMSG_STATE* pMsg, int& nIndex)
{
SStateSlot* pState = new SStateSlot;
pState->SetTargetHandle(pMsg->handle);
pState->SetStateHandle(pMsg->state_handle);
pState->SetStateCode(pMsg->state_code);
pState->SetStateLevel(pMsg->state_level);
pState->SetStateValue(pMsg->state_value);
pState->SetToggleType(pMsg->isToggle);
pState->SetStateTime(pMsg->start_time, pMsg->end_time);
StateInfoEx* s_data = GetTenacityDB().GetTenacityData(pMsg->state_code);
if (s_data)
{
vec_state_slot* pvStateList = NULL;
/// 2011.01.14 - prodongi
if (isMarkState(pMsg->state_code))
{
pvStateList = &m_vecMarkStateList;
}
else if (IsCashState(pMsg->state_code))
{
pvStateList = &m_vecCashStateList;
}
else
{
pState->SetStateHarmful(s_data->is_harmful);
if (s_data->is_harmful)
pvStateList = &m_vecNegativeList;
else
pvStateList = &m_vecPositiveList;
}
pvStateList->push_back(pState);
//gmpbigsun(20131119) : 종료시간기준 sort
std::sort(pvStateList->begin(), pvStateList->end(), FuncSortEndTime());
}
else
{
SAFE_DELETE(pState);
}
return pState;
}
int SGameAvatarEx::DeleteStateInfo(AR_HANDLE hTarget, AR_HANDLE hState, unsigned int state_code)
{
/// 2011.01.14 - prodongi
if (isMarkState(state_code))
{
int nIndexpos(0);
iterator_state_slot it = m_vecMarkStateList.begin();
while (it != m_vecMarkStateList.end())
{
SStateSlot* pSlot = *it;
if (pSlot->GetStateCode() == state_code)
{
SAFE_DELETE(pSlot);
m_vecMarkStateList.erase(it);
return nIndexpos;
}
++it;
++nIndexpos;
}
return -1;
}
if (IsCashState(state_code))
{
int nIndexpos(0);
iterator_state_slot it = m_vecCashStateList.begin();
while (it != m_vecCashStateList.end())
{
SStateSlot* pSlot = *it;
if (pSlot->GetStateCode() == state_code)
{
SAFE_DELETE(pSlot);
m_vecCashStateList.erase(it);
return nIndexpos;
}
++it;
++nIndexpos;
}
return -1;
}
iterator_state_slot NegativeIt = m_vecNegativeList.begin();
iterator_state_slot PositiveIt = m_vecPositiveList.begin();
int nPos(0);
while (true)
{
//이로운 지속효과와 해로운 지속효과를 모두 순환하였으니 break;
if (PositiveIt == m_vecPositiveList.end() && NegativeIt == m_vecNegativeList.end())
break;
//이로운 지속효과
if (PositiveIt != m_vecPositiveList.end())
{
if (IsEqualState(*PositiveIt, hTarget, hState, state_code))
{
SAFE_DELETE((*PositiveIt));
PositiveIt = m_vecPositiveList.erase(PositiveIt);
return nPos;
}
else ++PositiveIt;
}
//해로운 지속효과
if (NegativeIt != m_vecNegativeList.end())
{
if (IsEqualState(*NegativeIt, hTarget, hState, state_code))
{
SAFE_DELETE((*NegativeIt));
NegativeIt = m_vecNegativeList.erase(NegativeIt);
return nPos;
}
else ++NegativeIt;
}
++nPos;
}
return -1;
}
bool SGameAvatarEx::IsCashState(unsigned int state_code)
{
for (int i(0); i < c_nMaxCashState; ++i)
{
if (c_nCashStateId[i] == state_code)
return true;
}
return false;
}
/// 2011.01.14 - prodongi
bool SGameAvatarEx::isMarkState(unsigned int state_code) const
{
if (9004 == state_code || /// 시크루트 프리패스
9005 == state_code || /// 라펠즈 pc방
9006 == state_code) /// 라펠즈 더블 plus pc방
return true;
return false;
}
void SGameAvatarEx::GetAllStateList(vec_state_slot& rStateList, bool bAddCashState)
{
rStateList.clear();
int nSize = 0;
if (bAddCashState)
{
nSize = (int)m_vecCashStateList.size();
for (int i(0); i < nSize; ++i)
rStateList.push_back(m_vecCashStateList[i]);
/// 2011.01.14 - prodongi
nSize = (int)m_vecMarkStateList.size();
for (int i(0); i < nSize; ++i)
rStateList.push_back(m_vecMarkStateList[i]);
}
nSize = (int)m_vecPositiveList.size();
for (int i(0); i < nSize; ++i)
rStateList.push_back(m_vecPositiveList[i]);
nSize = (int)m_vecNegativeList.size();
for (int i(0); i < nSize; ++i)
rStateList.push_back(m_vecNegativeList[i]);
}
bool SGameAvatarEx::HaveState(bool bAddCashState)
{
if (HavePositiveState() || HaveNegativeState())
return true;
if (bAddCashState && HaveCashState())
return true;
return false;
}
void SGameAvatarEx::clearAllState()
{
for (unsigned int i(0); m_vecPositiveList.size() > i; i++) //현재 상태 이상 리스트
{
SAFE_DELETE(m_vecPositiveList[i]);
}
for (unsigned int i(0); m_vecNegativeList.size() > i; i++) //현재 상태 이상 리스트
{
SAFE_DELETE(m_vecNegativeList[i]);
}
for (unsigned int i(0); m_vecCashStateList.size() > i; i++) //현재 상태 이상 리스트
{
SAFE_DELETE(m_vecCashStateList[i]);
}
/// 2011.01.14 - prodongi
for (unsigned int i(0); m_vecMarkStateList.size() > i; i++) //현재 상태 이상 리스트
{
SAFE_DELETE(m_vecMarkStateList[i]);
}
m_vecPositiveList.clear();
m_vecNegativeList.clear();
m_vecCashStateList.clear();
/// 2011.01.14 - prodongi
m_vecMarkStateList.clear();
}
bool SGameAvatarEx::CurrentlyAnimationIsLoopWrap()
{
return m_nProcess_state == KSeqAvatar::SEQINFO_LOOPWRAP ? true : false;
}
void SGameAvatarEx::UnMountFallUnSummon()
{
if (m_pStateVM == NULL) return;
if (m_pStateVM->GetMode() == SObjectStateMachine::MODE_MOUNT)
{
m_pStateVM->SetMode(SObjectStateMachine::MODE_NORMAL);
m_pStateVM->StopCurrentState();
}
}
void SGameAvatarEx::SetSkinDiffuse(KColor& diffuse)
{
m_SkinDiffuse.r = diffuse.r;
m_SkinDiffuse.g = diffuse.g;
m_SkinDiffuse.b = diffuse.b;
m_SkinDiffuse.a = diffuse.a / 255;
if (m_pSeqAvatar) m_pSeqAvatar->SetSkinDiffuse(m_SkinDiffuse);
}
void SGameAvatarEx::RefreshItemWear()
{
ClearThreadLoadWear();
for (unsigned int i(0); m_vWearListForRefresh.size() > i; ++i)
{
//m_vWearList_Thread.push_back( m_vWearListForRefresh[i] );
AddThreadItemWear(m_vWearListForRefresh[i]);
}
m_vWearListForRefresh.clear();
}
void SGameAvatarEx::RefreshAllStateEffect()
{
vec_state_slot vecStateList;
GetAllStateList(vecStateList, false);
SGameOption& gameoption = GetGameOption();
SMSG_STATE state;
SStateSlot* pStateSlot = NULL;
iterator_state_slot iter = vecStateList.begin();
for (; iter != vecStateList.end(); ++iter)
{
pStateSlot = (*iter);
if (pStateSlot == NULL) continue;
state.handle = pStateSlot->GetTargetHandle();
state.state_handle = pStateSlot->GetStateHandle();
state.state_code = pStateSlot->GetStateCode();
state.state_level = pStateSlot->GetStateLevel();
state.end_time = pStateSlot->GetEndTime();
if (state.end_time == (AR_TIME)(-1))
{ //토글형 스킬 임
state.isToggle = true;
}
DelStateEffect(&state);
bool bAdd = false;
if (IsLocalPlayer() || IsLocalCreature() || gameoption.IsStatePlayerEftRend())
bAdd = true;
else if (gameoption.IsStatePartyEftRend())
{
if (GetObjType() == TS_ENTER::GAME_SUMMON)
{
if (IsPartyRaidMemeber(GetMaster()))
bAdd = true;
}
else
{
if (IsPartyRaidMemeber(GetArID()))
bAdd = true;
}
}
else
{
if (gameoption.IsStateEnemyEftRend())
bAdd = true;
}
if (GetStatus() & TS_ENTER::CreatureInfo::FLAG_INVISIBLE ||
GetStateFlag() & SGameAvatarEx::FLAG_STATE_HIDING)
{
bAdd = false; //Invisible모드이거나 은신모드일경우 이펙트를 보여주지 않는다
}
if (bAdd) AddStateEffect(&state);
}
}
void SGameAvatarEx::RemoveAllStateEffect()
{
vec_state_slot vecStateList;
GetAllStateList(vecStateList, false);
SMSG_STATE state;
SStateSlot* pStateSlot = NULL;
iterator_state_slot iter = vecStateList.begin();
for (; iter != vecStateList.end(); ++iter)
{
pStateSlot = (*iter);
if (pStateSlot == NULL) continue;
state.handle = pStateSlot->GetTargetHandle();
state.state_handle = pStateSlot->GetStateHandle();
state.state_code = pStateSlot->GetStateCode();
state.state_level = pStateSlot->GetStateLevel();
state.end_time = pStateSlot->GetEndTime();
DelStateEffect(&state);
}
}
// 죽을때 모션이 두개이기 때문에 모션 선택하는 부분을 따로 함수로 뺐다.
void SGameAvatarEx::EnterDeadAnimation()
{
NPlayAnimation(ANI_DEAD01, SEQTYPE_NORMAL);
}
// 가상함수로 만들어서 AvatarEx의 하위클래스들에 맞게 바꿔야 함..
int SGameAvatarEx::GetAnimationLength(int ani_id)
{
return -1;
}
bool SGameAvatarEx::ExistAnimation(int ani_id)
{
return true;
}
#ifndef _EQUATION
bool SGameAvatarEx::IsInDeathMatch()
{
int x = GetPosition()->x;
int y = GetPosition()->y;
if (
(x >= 193536 && x <= 201600
&& y >= 104832 && y <= 112896)
|| (x >= 201600 && x <= 209664
&& y >= 104832 && y <= 112896)
|| (x >= 193536 && x <= 201600
&& y >= 96768 && y <= 104832)
|| (x >= 201600 && x <= 209664
&& y >= 96768 && y <= 104832)
|| (x >= 193536 && x <= 201600
&& y >= 88704 && y <= 96768)
|| (x >= 201600 && x <= 209664
&& y >= 88704 && y <= 96768)
|| (x >= 193536 && x <= 201600
&& y >= 80640 && y <= 88704)
|| (x >= 201600 && x <= 209664
&& y >= 80640 && y <= 88704)
) // 데스매치
{
return true;
}
return false;
}
#else
bool SGameAvatarEx::IsInDeathMatch()
{
return GetCurrentLocation() == PLAYER_IN_DEATHMATCH;
}
#endif
bool SGameAvatarEx::IsInBearroad()
{
int x = GetPosition()->x;
int y = GetPosition()->y;
if (x >= 84435 && x <= 94471
&& y >= 4320 && y <= 12343)// 베어로드 안쪽임.
{
return true;
}
return false;
}
bool SGameAvatarEx::IsInBearroadLobby()
{
int x = GetPosition()->x;
int y = GetPosition()->y;
if (x >= 81831 && x <= 85288
&& y >= 636 && y <= 4295)// 베어로드 대기실
{
return true;
}
return false;
}
void SGameAvatarEx::setHairThreadData(SMSG_HAIR_INFO* msg)
{
m_hairThreadData.m_isRecv = true;
m_hairThreadData.m_hairId = msg->nHairID;
m_hairThreadData.m_hairColorIndex = msg->nHairColorIndex;
m_hairThreadData.m_hairColorRgb = msg->nHairColorRGB;
}
void SGameAvatarEx::procHairThreadData()
{
if (IsThreadLoading()) return;
if (m_bPendLoading) return;
if (!m_hairThreadData.m_isRecv) return;
if (!m_pSeqAvatar) return;
m_hairThreadData.m_isRecv = false;
SetHairID(m_hairThreadData.m_hairId);
SetHairColorIndex(m_hairThreadData.m_hairColorIndex);
SetHairColorRGB(m_hairThreadData.m_hairColorRgb);
// 2010.06.10 머리 장식/투구가 있는지 체크, 헤어가 보일 경우는 제외 - prodongi
KSeqAvatar* avatarPart = m_pSeqAvatar->getAvatarPart(ANIPART_BIPED);
if (avatarPart->isDecoMeshCheck() && avatarPart->isRenderDecoMesh(MDECOPART_HELM) && 1 == avatarPart->IsExistDecoMesh(MDECOPART_HELM) && !avatarPart->isRenderMesh(MPART_HAIR))
return;
// 2010.07.26 헬멧을 장착하고 있어도 헤어가 보일 경우는 제외- prodongi
if (avatarPart->isMeshCheck() && avatarPart->isRenderMesh(MPART_HELM) && 1 == avatarPart->IsExistMesh(MPART_HELM) && !avatarPart->isRenderMesh(MPART_HAIR))
return;
doLoadingHair(m_pSeqAvatar);
RefreshSkinColorized();
m_pSeqAvatar->SetDeform(ANIPART_BIPED);
m_pSeqAvatar->SetAttach(ANIPART_BIPED);
if (IsLocalPlayer())
m_bRefreshInven = true;
g_pCurrentGameSystem->updateCurTarget(GetArID());
}
void SGameAvatarEx::doLoadingHair(KSeqAvatarEx* avatar)
{
std::string modelName = GetDefaultItemDB().GetFileName(GetRace(), GetSex(), GetHair());
int nGroup = GetDefaultItemDB().GetDecoHairGroupID(GetHair());
std::string texName = GetDefaultTextureResourceDB().GetTextureName(nGroup, m_nHairColorIndex, GetRace(), GetSex());
avatar->AddMesh(ANIPART_BIPED, MPART_HAIR, modelName.c_str(), texName);
}
// 2010.06.18 - prodongi
void SGameAvatarEx::getDecoTexName(std::string& texName)
{
int nGroup = GetDefaultItemDB().GetDecoFaceGroupID(GetFace());
texName = GetDefaultTextureResourceDB().GetTextureName(nGroup, getDecoIndex(), GetRace(), GetSex());
}
// MTE
void SGameAvatarEx::EnableMTE(bool bEnable, const char* szFileName)
{
if (TS_ENTER::GAME_MOB != GetInnObjType() && TS_ENTER::GAME_SUMMON != GetInnObjType())
return;
_CID(SET_MTETEX);
std::string strMteTexName;
KMsgSET_MTETEX kMsg;
kMsg.pTexture = NULL;
if (NULL != szFileName)
strMteTexName = szFileName;
else
{
std::string strCobName = GetCobFileName();
if (strCobName.find(".cob") == std::string::npos)
strCobName += ".cob";
vec_cobset* coblist = COBManager::GetManager()->Load(strCobName.c_str());
if (coblist)
{
if (coblist->empty())
return;
COBSET* pCob = (*coblist)[0];
strMteTexName = pCob->m_strCameraCollisionFile;
}
}
//텍스쳐 정보가 유효한경우만 적용
if (true == strMteTexName.empty() || strMteTexName.find('.') == std::string::npos)
{
return;
}
else
{
if (bEnable)
{
NX3LoadPack loadpack;
loadpack.Init();
kMsg.pTexture = KTextureManager::GetManager()->GetTexture(strMteTexName.c_str(), &loadpack);
}
else
kMsg.pTexture = NULL;
}
if (m_pSeqAvatar)
m_pSeqAvatar->Perform(id_SET_MTETEX, kMsg);
}
/// 2011.04.20 거대화 처리 시작 - prodongi
void SGameAvatarEx::beginScaling(float& scale, K3DMatrix& oldTM)
{
std::vector<SStateSlot*> PositiveList = GetPositiveStateList();
/// 2012.08.10 가장 큰 스케일 값이 적용되도록 한다 - prodongi
m_fScaleAdjustDest = -1.0f;
for (size_t i = 0; i < PositiveList.size(); i++)
{
bool bflag = false;
StateInfoEx* info = GetTenacityDB().GetTenacityData(PositiveList[i]->GetStateCode());
if (GetStatus() & TS_ENTER::PlayerInfo::FLAG_SELL_BOOTH || GetStatus() & TS_ENTER::PlayerInfo::FLAG_BUY_BOOTH)
bflag = true;
if (info->fValue[6] == 128 && !bflag)
{
float fScaleLev = (float)info->fValue[7] + ((float)info->fValue[8] * (float)PositiveList[i]->GetStateLevel());
m_fScaleAdjustDest = ::max(m_fScaleAdjustDest, fScaleLev);
if (m_fScaleAdjustDest <= 0.0f)
m_fScaleAdjustDest = 1.0f;
//m_fScaleAdjustDest = ::max(m_fScaleAdjustDest, (float)info->fValue[7]);
}
if (info->fValue[9] == 128)
m_fScaleAdjustDest = ::max(m_fScaleAdjustDest, (float)info->fValue[10]);
}
if (-1.0f >= m_fScaleAdjustDest)
m_fScaleAdjustDest = 1.0f;
scale = 1.0f;
DWORD nowTime = GetSafeTickCount();
if (m_fScaleAdjustPrev == m_fScaleAdjustDest)
{
scale = m_fScaleAdjustDest;
}
else
{
if (m_nScaleAdjustStartTime == 0) m_nScaleAdjustStartTime = nowTime;
float ratio = (nowTime - m_nScaleAdjustStartTime) / 1000.0f;
scale = m_fScaleAdjustPrev * (1 - ratio) + m_fScaleAdjustDest * ratio;
if (ratio > 1.0f)
{
m_nScaleAdjustStartTime = 0;
scale = m_fScaleAdjustDest;
m_fScaleAdjustPrev = m_fScaleAdjustDest;
}
}
oldTM = *GetTransform();
SetScalePure(scale);
m_fSelcube[5] = m_fOriginalSelCubeHeight * scale;
}
/// 2011.04.20 거대화 처리 종료 - prodongi
void SGameAvatarEx::endScaling(float scale, K3DMatrix const& oldTM)
{
SetTransformPure(oldTM);
m_fScaleAdjust = scale;
}
/// 2011.04.21 - prodongi
void SGameAvatarEx::setCameraRoll(float angle)
{
if (sMathUtil::isEqual(m_fPresentRoll, angle))
return;
m_fPresentRoll = angle;
m_fTargetRoll = angle;
m_dwPrevTime = m_dwTime;
m_syncCamRoll = true;
m_kmoveDir = angle;
}
//-----------------------------------------------------------------------------------------------------------------
// 의상 파일 이름을 재 로딩한다.
//-----------------------------------------------------------------------------------------------------------------
void SGameAvatarEx::ReloadWearListFileName(std::vector<WEAR_DATA>& wearList)
{
int nSex(GetSex());
int nRace(GetRace());
for (UINT nCount = 0; nCount < wearList.size(); nCount++)
{
WEAR_DATA* pWearData(&wearList[nCount]);
if (NULL == pWearData)
continue;
int nitemCode(pWearData->nItemCode);
if (nitemCode < 10000) // 기본 Mesh
{
if (nitemCode != 0)
pWearData->strFileName = GetDefaultItemDB().GetFileName(nRace, nSex, nitemCode);
else
pWearData->strFileName = "_NoItem_";
}
else
{
if (pWearData->nAppearanceItemCode)
pWearData->strFileName = GetItemDB().GetFileName(nRace, nSex, pWearData->nAppearanceItemCode, pWearData->nItemLevel);
else
pWearData->strFileName = GetItemDB().GetFileName(nRace, nSex, pWearData->nItemCode, pWearData->nItemLevel);
pWearData->strFileName += ".nx3";
}
if (pWearData->bWithDecoItem)
{
if (pWearData->nAppearanceItemCode)
pWearData->strDecoFileName = GetItemDB().GetFileName(nRace, nSex, pWearData->nAppearanceItemCode, pWearData->nItemLevel);
else
pWearData->strDecoFileName = GetItemDB().GetFileName(nRace, nSex, pWearData->nDecoItemCode, pWearData->nItemLevel);
pWearData->strDecoFileName += ".nx3";
}
}
}