Files
Sun1602/Client/GameClient/PlayerMonster.cpp
T
2022-10-26 12:25:11 +08:00

3548 lines
75 KiB
C++

//------------------------------------------------------------------------------
// PlayerMonster.cpp
// (C) 2008 Webzen Sunstudio
//------------------------------------------------------------------------------
#include "SunClientPrecompiledHeader.h"
#include "varpacket.h"
#include "ItemInfoParser.h"
#include "Player.h"
#include "Monster.h"
#include "PlayerMonster.h"
#include "Map.h"
#include "EquipmentContainer.h"
#include "ItemManager.h"
#include "AppearanceManager.h"
#include "ObjectManager.h"
#include "ProjectileManagerEx.h"
#include "HeroActionInput.h"
#include "soundeffect.h"
#include "CommonCharacterFormula.h"
#include <SCItemSlot.h>
#include "InterfaceManager.h"
#include "StyleInfoParser.h"
#include <PlayerAttributes.h>
#include "ItemAttrCalculator.h"
#include "SkillAttrCalculator.h"
#include "SkillInfoParser.h"
#include "ChatMsg.h"
#include "ChatDialog.h"
#include "Hero.h"
#include "CharSoundInfoParser.h"
#include "WeaponSoundInfoParser.h"
#include "AppearanceResourceCode.h"
#include "ProjectileInfoParser.h"
#include "HeroHeightInfoParser.h"
#include "SetItemOptionInfoParser.h"
#include "globalfunc.h"
#include "GameFramework.h"
#include "BattleScene.h"
#include <Timer.h>
#include "ExpValueInfoParser.h"
#include <NPCAttributes.h>
#include "CharacterScene.h"
#include "uiPartyMan/uiPartyMan.h"
#include "RewardInfoList.h"
#include "SunEventInfoParser.h"
#include "GameConst_Color.h"
#include "DelayLoadManager.h"
#include "ResourceManager.h"
using namespace util;
extern DWORD g_CurTime;
//------------------------------------------------------------------------------
/**
*/
PlayerMonster::PlayerMonster( void )
{
// m_pEquipContainer = NULL;
m_eAttackSequence = eATTACK_SEQUENCE_THIRD;
SetObjectType(SSQMONSTER_OBJECT);
m_dwValkyrieShotSerial = 0;
m_iCurTile=m_iOldTile=-1;
m_dwCurTileAtt=m_dwOldTileAtt=0;
m_bValkyrieReload = FALSE;
m_bInvisible = false; // 투명
m_iValkyrieShotAnimVariation = 0;
m_bHideHelmet = FALSE;
#ifdef _NA_000000_20120420_EQUIPMENTS_VISIBLE_WING
m_bHideWing = FALSE;
#endif//_NA_000000_20120420_EQUIPMENTS_VISIBLE_WING
m_bInvincible = FALSE; // 무적
m_bCasting = FALSE;
m_iInvicibleTime =0;
m_dwKeyboardMoveTime=0;
m_fScale=1.0f;
m_wAttSpeedRatio = 100;
m_wMoveSpeedRatio = 100;
m_iJumpFlag=0;
}
//------------------------------------------------------------------------------
/**
*/
PlayerMonster::~PlayerMonster( void )
{
DestroyCharacterVariation();
}
//------------------------------------------------------------------------------
/**
*/
WzVector PlayerMonster::GetHeadBonePos()
{
return GetSpecialBonePos(StrToWzID("HEAD"));
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetKeyboardMoveTime(DWORD dwTime)
{
m_dwKeyboardMoveTime = dwTime;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::AddKeyboardMoveTime(DWORD dwDelta)
{
m_dwKeyboardMoveTime += dwDelta;
}
//------------------------------------------------------------------------------
/**
*/
DWORD PlayerMonster::GetKeyboardMoveTime()
{
return m_dwKeyboardMoveTime;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetMonsterInfo(BASE_NPCINFO *pInfo)
{
if (pInfo)
{
m_NPCInfo = *pInfo;
if(m_NPCInfo.m_wSize / 100.0f>=0.0f)
m_fScale = (float) m_NPCInfo.m_wSize / 100.0f;
SetScale(m_fScale);
// pInfo->m_byGrade 가 eNPC_SSQ_MONSTER(11) 가 아니면 MONSTER_OBJECT 으로 취급한다.
// 저주받은탑의 보스 등으로 나오는 플레이어형몬스터같은 경우를
// 타락한 사원의 플레이어형 몬스터와 구분하기 위하여 MONSTER_OBJECT 으로 세팅하여 취급한다.
if (pInfo->m_byGrade != eNPC_SSQ_MONSTER)
{
SetObjectType(MONSTER_OBJECT);
}
}
TCHAR szString[INTERFACE_STRING_LENGTH] = {0,};
g_InterfaceManager.GetInterfaceString(
pInfo->m_NCode,
szString,
MAX_MONSTERNAME_LENGTH);
#ifdef _DEV_VER
//#ifdef _SCJ_SHOW_NPC_ID
if (CGeneralGameParam::Instance()->IsShowNpcId())
{
TCHAR buffer_string[INTERFACE_STRING_LENGTH] ={0,};
StrnCopy(buffer_string, szString, INTERFACE_STRING_LENGTH-1);
Snprintf(szString, INTERFACE_STRING_LENGTH-1, _T("%s <NPCID:%ld>"),
buffer_string, pInfo->m_MonsterCode);
}
//#endif //_SCJ_SHOW_NPC_ID
#endif //#ifdef _DEV_VER
SetName( szString );
m_pNPCAttriburtes = new NPCAttributes;
m_pNPCAttriburtes->SetOwner( &m_scNPCAtt);
m_pNPCAttriburtes->SetCharInfo(pInfo,0,0,0);
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetClass(eCHAR_TYPE eType)
{
Monster::SetClass(eType);
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::Create( DWORD dwObjectKey, DWORD dwID)
{
SetObjectKey( dwObjectKey );
m_dwParentId=0;
m_dwTransFormCode=0;
m_iAlarmVoice = 0;
m_iWaitSoundDelay = 0;
m_bNoCull = TRUE;
m_eMonsterType = MONSTER_TYPE_GENERAL;
m_iMonsterGaugeShowDelay = 0;
m_iComboCount = 0;
m_iComboDelay=0;
//GetCharInfo()->m_byClassCode = (BYTE)dwID;
//GetCharInfo()->SetChangeOfClass((eCHAREX_TYPE)dwID);
m_fLandFrame=0.0f;
APPEARANCEINFO appearInfo;
ZeroMemory(&appearInfo,sizeof(appearInfo));
appearInfo.ObjectType = APPEARANCEINFO::PLAYER;
appearInfo.Job = dwID; // 일단 ID를 캐릭터 종류로 쓴다.
BOOL rt = Character::Create(dwObjectKey, dwID);
assert(rt);
CreateCharacterVariation(&appearInfo, TRUE);
InitContainer();
m_iValkyrieShotDelay = 0;
m_iValkyrieShotCount = 0;
m_iValkyrieShotRemain = 0;
m_bSpecialMoveFlag=0;
m_dwValkyrieShotSerial = 0;
m_dwOldAttackStyle = NONE_ID;
m_dwDustTime = 0;
m_iValkyrieBulletCount = 20;
m_iValkyrieShotAnimSet = 0;
m_iValkyrieShotAnimCount = 0;
m_bInvisible = FALSE;
m_dwShieldTime=0;
m_bStandUp=FALSE;
m_dwTransSkillCode=0;
InitState(STATE::IDLE,g_CurTime);
//InitAttachEffectForSetItem();
InitMeshHeight();
#ifdef _NA_008185_20150402_COSTUME_ITEM_FOR_NPC
playermonster_costume_item_ = 0;
#endif //_NA_008185_20150402_COSTUME_ITEM_FOR_NPC
return TRUE;
}
void PlayerMonster::SetPolymorph( BOOL Active )
{
if( m_IsPolymorphApperance == Active )
return;
m_IsPolymorphApperance = Active;
if( m_IsPolymorphApperance == TRUE )
{
APPEARANCEINFO appearInfo;
ZeroMemory(&appearInfo,sizeof(appearInfo));
appearInfo.ObjectType = APPEARANCEINFO::POLOMORPH;
//appearInfo.pMonsterInfo = GetMonsterInfo();
InitRender( MP_COUNT, MP_BONE, &appearInfo, 0, FALSE );
//appearInfo.Job = GetClass();
//InitRender(BP_COUNT, BP_BONE, &appearInfo, AppearanceManager::kAppearanceAttachIndex_Count, TRUE);
SetIdleState();
GlobalFunc::CreateEffectBeUpToOption( StrToWzID("KC05"), GetVisiblePos() );
}
else
{
// 파츠 초기화
APPEARANCEINFO appearInfo;
ZeroMemory(&appearInfo,sizeof(appearInfo));
appearInfo.ObjectType = APPEARANCEINFO::PLAYER;
appearInfo.Job = GetClass();
InitRender(BP_COUNT, BP_BONE, &appearInfo, AppearanceManager::kAppearanceAttachIndex_Count, FALSE);
RefreshAppearRender(TRUE);
// NpcInfo로부터 Scale을 재설정
SetMonsterInfo(GetMonsterInfo());
//SetScale(m_fScale);
SetIdleState();
GlobalFunc::CreateEffectBeUpToOption( StrToWzID("KC05"), GetVisiblePos() );
}
}
//------------------------------------------------------------------------------
/**
*/
WzVector PlayerMonster::GetTrailBonePos(int index, int start)
{
return Object::GetTrailBonePos(index,start);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetTrailEffectCode()
{
if(GameFramework::GetCurrentScene()&&GameFramework::GetCurrentScene()->GetType() == SCENE_TYPE_SSQ)
return Object::GetTrailEffectCode();
return Monster::GetTrailEffectCode();
}
//------------------------------------------------------------------------------
/**
*/
DWORD PlayerMonster::IncreaseComboCount()
{
m_iComboCount++;//콤보수 증가
DWORD dwCurStyle = GetCurrentAttackStyle();//공격스타일을 얻음
BASE_STYLEINFO *pInfo = SkillInfoParser::Instance()->GetStyleInfo((SLOTCODE)dwCurStyle);
// 펀치나 원거리 공격은 콤보없음
if(pInfo==NULL)
{
if (m_iComboCount >= 2)//기본 공격 2타
{
m_iComboCount = 0;
}
return m_iComboCount;
}
if(IsRangedNormalAttack())
{
if (m_iComboCount >= 2)//기본 공격 2타
{
m_iComboCount = 0;
}
}
else if(pInfo->m_byStyleCheck==FALSE)//스타일 없음 2타
{
if (m_iComboCount >= 2)
{
m_iComboCount = 0;
}
}
// 스타일이 있을땐 3연타~
else
{
if (m_iComboCount >= 3)
{
m_iComboCount = 0;
}
}
return m_iComboCount;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetComboDelay(int combodelay)
{
m_iComboDelay = combodelay;
}
//------------------------------------------------------------------------------
/**
*/
int PlayerMonster::GetComboDelay()
{
return m_iComboDelay;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::Destroy( void )
{
ReleaseContainer();
Monster::Destroy();
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::Render( void )
{
if( m_bObserverMode )
return TRUE;
if ( GetShow() == TRUE )
{
if (this->m_bInvincible)
{
SetColor( 154, 154, 154,100);
}
return Character::Render();
}
else
{
return TRUE;
}
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::ApplyTerrainColor(BOOL bApply)
{
if (!m_bInvincible)
{
Character::ApplyTerrainColor(bApply);
}
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::InitContainer()
{
EquipmentContainer* equipment_container = new EquipmentContainer();
equipment_container->SetOwnerKey(GetObjectKey());
SetEquipmentContainer(equipment_container);
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::ReleaseContainer()
{
EquipmentContainer* equipment_container = GetEquipmentContainer();
if (equipment_container != NULL)
{
equipment_container->Release();
delete equipment_container;
SetEquipmentContainer(NULL);
}
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::ResetMoveFlag()
{
m_iMoveFlag = 0;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::AddMoveFlag(int MoveFlag)
{
BIT_ADD(m_iMoveFlag,MoveFlag);
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::RemoveMoveFlag(int MoveFlag)
{
BIT_REMOVE(m_iMoveFlag,MoveFlag);
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::CheckMoveFlag(int MoveFlag)
{
return BIT_CHECK(m_iMoveFlag,MoveFlag);
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetMoveFlag(int MoveFlag)
{
m_iMoveFlag = MoveFlag;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::RefreshEquipData()
{
RefreshAppearRender();
}
//------------------------------------------------------------------------------
/**
*/
int PlayerMonster::GetMoveFlag()
{
return m_iMoveFlag;
}
//------------------------------------------------------------------------------
/**
*/
float PlayerMonster::ProcessAnimation(DWORD dwTick,WzEvent *pEvent,BOOL bIgnoreEvent)
{
ProcessStandAnimationDelay(dwTick);
return Monster::ProcessAnimation(dwTick,pEvent,bIgnoreEvent);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentAttackAnimation()
{
WzID animationID = StrToWzID("A001");
DWORD dwStyle = GetCurrentAttackStyle();
DWORD sequence=GetAttackSequence();
DWORD weapon =GetWeaponKind();
BASE_STYLEINFO *pInfo = SkillInfoParser::Instance()->GetStyleInfo( (SLOTCODE)dwStyle );
//safecode
if(!pInfo)
{
WRITELOG(eLOG_LEVEL_ERR, c_wOUTPUT_LOG_FILE | c_wOUTPUT_LOG_CENTER, _T("BASE_STYLEINFO *pInfo is NULL-StyleCode[%d]"), dwStyle);
assert( !"BASE_STYLEINFO *pInfo is NULL");
return animationID;
}
// 한손석궁이 아니면
if (weapon != eWEAPONTYPE_ONEHANDCROSSBOW)
{
switch(sequence)
{
case eATTACK_SEQUENCE_FIRST:
animationID = pInfo->m_wzidCodeFirst.id;
break;
case eATTACK_SEQUENCE_SECOND:
animationID = pInfo->m_wzidCodeSecond.id;
break;
case eATTACK_SEQUENCE_THIRD:
animationID = pInfo->m_wzidCodeThird.id;
break;
}
}
else
{
if (m_iValkyrieShotAnimSet)
{
switch(m_iValkyrieShotAnimCount)
{
case 0:
case 1:
case 2:
animationID = pInfo->m_wzidCodeFirst.id;
break;
default:
animationID = pInfo->m_wzidCodeSecond.id;
break;
}
}
else
{
switch(m_iValkyrieShotAnimCount)
{
case 0:
case 1:
case 2:
case 3:
case 4:
animationID = pInfo->m_wzidCodeSecond.id;
break;
default:
animationID = pInfo->m_wzidCodeFirst.id;
break;
}
}
m_iValkyrieShotAnimCount++;
if (m_iValkyrieShotAnimCount >= 8)
{
m_iValkyrieShotAnimSet = rand() % 2;
m_iValkyrieShotAnimCount = 0;
}
}
return animationID;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::RefreshPunchStyle()
{
switch(GetClass())
{
case eCHAR_BERSERKER:
m_dwAttackStyle=eSTYLE_BERSERKER_PUNCH;
break;
case eCHAR_DRAGON:
m_dwAttackStyle=eSTYLE_DRAGON_PUNCH;
break;
case eCHAR_SHADOW:
m_dwAttackStyle=eSTYLE_SHADOW_PUNCH;
break;
case eCHAR_VALKYRIE:
m_dwAttackStyle=eSTYLE_VALKYRIE_PUNCH;
break;
case eCHAR_ELEMENTALIST:
m_dwAttackStyle=eSTYLE_MAGICIAN_PUNCH;
break;
case eCHAR_MYSTIC: //_NA_004965_20120613_NEW_CHARACTER_MYSTIC
m_dwAttackStyle=eSTYLE_MYSTIC_PUNCH;
break;
case eCHAR_HELLROID: //_NA_000000_20130812_NEW_CHARACTER_HELLROID
m_dwAttackStyle=eSTYLE_HELLROID_PUNCH;
case eCHAR_WITCHBLADE: //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
m_dwAttackStyle=eSTYLE_WITCHBLADE_PUNCH;
break;
}
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetCurrentNomalAttackStyle(DWORD dwWeaponType)
{
switch(dwWeaponType)
{
case eWEAPONTYPE_TWOHANDAXE://버서커
{
m_dwAttackStyle=eSTYLE_TWOHANDAXE_NORMAL;
}
break;
case eWEAPONTYPE_TWOHANDSWORD:
{
m_dwAttackStyle=eSTYLE_TWOHANDSWORD_NORMAL;
}
break;
case eWEAPONTYPE_ONEHANDSWORD://드라곤
{
m_dwAttackStyle=eSTYLE_ONEHANDSWORD_NORMAL;
}
break;
case eWEAPONTYPE_SPEAR:
{
m_dwAttackStyle=eSTYLE_SPEAR_NORMAL;
}
break;
case eWEAPONTYPE_DAGGER://쉐도우
{
m_dwAttackStyle=eSTYLE_SHADOW_DAGGER_NORMAL;
}
break;
case eWEAPONTYPE_WHIP:
{
m_dwAttackStyle=eSTYLE_SHADOW_WHIP_NORMAL;
}
break;
case eWEAPONTYPE_ONEHANDCROSSBOW://발키리
{
m_dwAttackStyle=eSTYLE_ONEHANDCROSSBOW_NORMAL;
}
break;
case eWEAPONTYPE_ETHERWEAPON:
{
m_dwAttackStyle=eSTYLE_ETHER_NORMAL;
}
break;
case eWEAPONTYPE_STAFF://엘리
{
m_dwAttackStyle=eSTYLE_STAFF_NORMAL;
}
break;
case eWEAPONTYPE_ORB:
{
m_dwAttackStyle=eSTYLE_ORB_NORMAL;
}
break;
//_NA_004965_20120613_NEW_CHARACTER_MYSTIC
case eWEAPONTYPE_GUNTLET:
{
m_dwAttackStyle=eSTYLE_MYSTIC_GUNTLET_NORMAL;
}
break;
case eWEAPONTYPE_POLEARM:
{
m_dwAttackStyle=eSTYLE_MYSTIC_POLEARM_NORMAL;
}
break;
//_NA_000000_20130812_NEW_CHARACTER_HELLROID
case eWEAPONTYPE_HELLROID_1:
{
m_dwAttackStyle=eSTYLE_HELLROID_WEAPON1;
}
break;
//_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
case eWEAPONTYPE_ARCBLADE:
{
m_dwAttackStyle=eSTYLE_WITCHBLADE_ARCBLADE;
}
break;
case eWEAPONTYPE_PUNCH:
{
RefreshPunchStyle();
}
break;
}
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentIdleAnimation()
{
WzID animationID = 0;
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'N';
szAniCode[1] = '0';
szAniCode[2] = '0';
szAniCode[3] = '1';
szAniCode[1] = GetWeaponAnimationCode();
if (IsFainting())
{
szAniCode[0] = 'F';
szAniCode[3] = '4';
}
else
{
// 어택스탠드는 코드 끝이 3 기본은 1이다.
if (m_iAttackStandTime > 0 )
{
if (GetClass() == eCHAR_VALKYRIE)
{
// 발키리 공격시는 Idle상태가 아니다 공격모션을 취해준다.
if (m_iValkyrieShotDelay > 0)
{
return StrToWzID("A201");
}
else
{
szAniCode[3] = '3';
}
}
else
{
szAniCode[3] = '3';
}
}
else
{
if (m_dwStandAnimDelay)
{
szAniCode[3] = '1';
}
else
{
szAniCode[3] = '2';
}
}
}
animationID = StrToWzID(szAniCode);
return animationID;
}
WzID PlayerMonster::GetCurrentReviveAnimation()
{
WzID animationID = 0;
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'R';
szAniCode[1] = '0';
szAniCode[2] = '0';
szAniCode[3] = '1';
animationID = StrToWzID(szAniCode);
return animationID;
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentMoveAnimation()
{
WzID animationID = 0;
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
if (GetMoveState() == CMS_WALK)
{
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
szAniCode[3] = '6';
}
else
{
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
szAniCode[3] = '7';
}
animationID = StrToWzID(szAniCode);
return animationID;
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentBlockAnimation()
{
WzID animationID = 0;
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'M';
szAniCode[1] = '0';
szAniCode[2] = '0';
szAniCode[3] = '1';
szAniCode[1] = GetWeaponAnimationCode();
animationID = StrToWzID(szAniCode);
return animationID;
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentDeathAnimation()
{
WzID animationID = 0;
int i=0;
while(1)
{
if(i==10)
animationID = StrToWzID("D001");
int iType=rand()%3;
if(iType==0)
animationID = StrToWzID("D001");
else if(iType==1)
animationID = StrToWzID("D002");
else if(iType==2)
animationID = StrToWzID("D003");
CWzUnit* pUnit=GetBasePart()->GetWzUnit();
if(!pUnit)
return StrToWzID("D001");
WzAnimationInfo *pAnimationInfo =pUnit->GetAnimationInfo(animationID);
if(!pAnimationInfo)
{
return StrToWzID("D001");
}
if(pAnimationInfo->m_wiAction==animationID)
{
break;
}
i++;
}
return animationID;
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentDamageAnimation(BOOL bRight,BOOL bCritical)
{
WzID animationID = 0;
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'H';
szAniCode[1] = GetWeaponAnimationCode();
if (!bRight)
{
szAniCode[2] = 'R';
}
else
{
szAniCode[2] = 'L';
}
if (bCritical)
{
szAniCode[3] = '2';
}
else
{
szAniCode[3] = '1';
}
animationID = StrToWzID(szAniCode);
return animationID;
}
//------------------------------------------------------------------------------
/**
앉기 에니를 얻는다.
*/
WzID PlayerMonster::GetCurrentSitAnimation()
{
WzID animationID = 0;
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
szAniCode[3] = '4';
animationID = StrToWzID(szAniCode);
return animationID;
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentSittingAnimation()
{
WzID animationID = 0;
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
szAniCode[3] = '5';
animationID = StrToWzID(szAniCode);
return animationID;
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentStandUpAnimation()
{
WzID animationID = 0;
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '1';
szAniCode[3] = '6';
animationID = StrToWzID(szAniCode);
return animationID;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::CreateDamageEffect(BOOL bCritical,BOOL bRight,DWORD dwAttackObjId)
{
Monster::CreateDamageEffect(bCritical,bRight,dwAttackObjId);
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetOldMoveFlag(int iOldMoveFlag)
{
m_iOldMoveFlag = iOldMoveFlag;
}
//------------------------------------------------------------------------------
/**
*/
int PlayerMonster::GetOldMoveFlag()
{
return m_iOldMoveFlag;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetOldKeyboardDirection(WzVector *pVector)
{
m_vOldDirection = *pVector;
}
//------------------------------------------------------------------------------
/**
*/
WzVector PlayerMonster::GetOldKeyboardDirection()
{
return m_vOldDirection;
}
//
////------------------------------------------------------------------------------
///** 플레이어 몬스터 랜더정보
//*/
//void PlayerMonster::SetPlayerInfo(PLAYER_RENDER_INFO_EX* pPlayerInfo)
//{
// ZeroMemory(GetCharInfo(),sizeof(BASE_PLAYERINFO));
//
// GetCharInfo()->m_byClassCode = pPlayerInfo->char_class;
// GetCharInfo()->SetChangeOfClass( (eCHAREX_TYPE) pPlayerInfo->char_class);
// GetCharInfo()->m_LV = pPlayerInfo->level;
// m_dwAttackStyle = pPlayerInfo->selected_style_code;
// m_wMoveSpeedRatio = pPlayerInfo->move_speed_ratio;
// m_wAttSpeedRatio = pPlayerInfo->attack_speed_ratio;
// m_pPlayerAttriburtes->SetCharInfo( m_PlayerData.GetCharacterInfo(), 0, 0, 0 );
// SetPartVariation(PLAYER_VARIATION_HAIR,pPlayerInfo->hair_style);
// SetPartVariation(PLAYER_VARIATION_FACE,pPlayerInfo->face);
// SetHeightVariation(pPlayerInfo->height);
//
// SetStateTotalInfo(pPlayerInfo->state_total_info);
//}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::ValkyrieShot(DWORD dwAttackSerial)
{
HideAttachment(FALSE);
SetAttackStandTime(ATTACK_STAND_TIME);
m_fValkyrieShotSpeed = GetAttackSpeedModifier();
SetCurrentBlendAnimation(GetValkyrieShotAnimation(),GetShotBlendBone(),m_fValkyrieShotSpeed,0);
OpenCrossbow();
if (m_dwValkyrieShotSerial)
{
ProcessAttackResult(m_dwValkyrieShotSerial,TRUE);
m_dwValkyrieShotSerial = 0;
}
WzAnimationInfo *pAniInfo = NULL;
if (GetBasePart()->GetWzUnit() != NULL)
{
pAniInfo = GetBasePart()->GetWzUnit()->GetAnimationInfo(GetValkyrieShotAnimation());
}
m_dwValkyrieShotSerial = dwAttackSerial;
if( pAniInfo )
{
m_iValkyrieShotDelay = (int)((float)pAniInfo->m_nMaxFrame * 33.0f / m_fValkyrieShotSpeed);
}
else
{
m_iValkyrieShotDelay = 500;
}
m_iValkyrieShotDelayTime = m_iValkyrieShotDelay;
m_iValkyrieShotCount = 0;
m_iValkyrieShotRemain = 2;
m_bValkyrieReload = FALSE;
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::CanValkyrieAction()
{
// 사격 가능상태!
if( GetCurState() == STATE::KEYBOARDMOVE || GetCurState() == STATE::MOVE )
{
return TRUE;
}
return FALSE;
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::Process(DWORD dwTick)
{
g_dwCharProcessCount++;
ProcessComboDelay(dwTick);
BeforeRefreshTileAtt();
if (GetClass() == eCHAR_VALKYRIE)
{
ProcessValkyrieShot(dwTick);
}
//시간이 지나면 자동으로 꺼준다.
if(m_bInvincible&&m_iInvicibleTime)
{
m_iInvicibleTime-=dwTick;
if(m_iInvicibleTime<=0)
{
m_iInvicibleTime=0;
m_bInvincible=FALSE;
}
}
m_dwShieldTime-=dwTick;
m_dwShieldTime=max(m_dwShieldTime,0);
if ( GetCurState() == STATE::MOVE ||
(GetCurState() == STATE::KEYBOARDMOVE && GetMoveFlag() & KEYBOARDMOVE_ISMOVING) )
{
m_dwDustTime += dwTick;
}
else
{
m_dwDustTime = 0;
}
if (m_dwDustTime >= 500)
{
m_dwDustTime = 0;
}
BOOL bRet = Monster::Process(dwTick);
AfterRefreshTileAtt();
return bRet;
}
//-------------------------------------------------------------------------------------------
/**
*/
void PlayerMonster::ProcessComboDelay(DWORD dwTick)
{
if (m_iComboDelay > 0)
{
if (GetCurState() != STATE::ATTACK)
{
m_iComboDelay -= dwTick;
}
if (m_iComboDelay <= 0)
{
m_iComboDelay = 0;
m_iComboCount = 0;
SetComboCount(0);
}
}
}
//------------------------------------------------------------------------------
/**
*/
int PlayerMonster::GetComboCount()
{
return m_iComboCount;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetComboCount(int iCount)
{
m_iComboCount = iCount;
}
//------------------------------------------------------------------------------
/**
*/
int PlayerMonster::DoAction(PLAYER_ACTION *pAction)
{
SetCurrentAction(pAction);
PLAYER_ACTION idleaction;
idleaction.ActionID = ACTION_IDLE;
idleaction.IDLE.vCurPos = GetPosition();
switch(pAction->ActionID)
{
case ACTION_ATTACK:
{
Character *pTarget = (Character *)g_ObjectManager.GetObject(pAction->ATTACK.dwTargetID);
StopMove();
if (pTarget)
{
if (pAction->ATTACK.bAttackMove)
{
SetPosition(pAction->ATTACK.vCurPos);
SetAttackMovePath(pAction->ATTACK.vCurPos,pAction->ATTACK.vDestPos);
SetAttackMove(TRUE);
}
else
{
SetAttackMove(FALSE);
SetPosition(pAction->ATTACK.vCurPos);
}
SetInterpolatePosition();
SetTargetID(pTarget->GetObjectKey());
switch (GetComboCount())
{
case 0:
SetAttackSequence(eATTACK_SEQUENCE_FIRST);
break;
case 1:
SetAttackSequence(eATTACK_SEQUENCE_SECOND);
break;
case 2:
SetAttackSequence(eATTACK_SEQUENCE_THIRD);
break;
}
SetNextActionAttackSerial(pAction->ATTACK.dwAttackSerial);
SetNextState(STATE::ATTACK,g_CurTime);
SetComboCount(IncreaseComboCount());
if(GetClass()==eCHAR_BERSERKER||GetClass()==eCHAR_DRAGON)
{
if(GetAttackSequence()==eATTACK_SEQUENCE_FIRST)
{
srand(pAction->ATTACK.dwAttackSerial);
GameFunc::SetPlayerMonsterAttackStyle(this);
}
}
return 1;
}
else
{
ProcessAttackResult(pAction->ATTACK.dwAttackSerial,TRUE);
SetCurrentAction(&idleaction);
SetNextState(STATE::IDLE,g_CurTime);
return 0;
}
}
break;
// 이동~
case ACTION_MOVE:
{
StopMove();
SetNextMove(pAction->MOVE.vCurPos.wvPos,pAction->MOVE.vDestPos.wvPos,pAction->MOVE.byState,pAction->MOVE.bThrust,pAction->MOVE.vCurPos.wTile,pAction->MOVE.vDestPos.wTile);
SetPosition(pAction->MOVE.vCurPos.wvPos,pAction->MOVE.vCurPos.wTile);
SetInterpolatePosition();
SetNextState(STATE::MOVE,g_CurTime);
return 1;
}
break;
case ACTION_TRANSFORM:
{
StopMove();
GetTransformData().SetTransFormResourceCode(pAction->TRANSFORM.rcCode);
GetTransformData().SetTransFormType(pAction->TRANSFORM.transFormType);
GetTransformData().SetTransFormProcessType(pAction->TRANSFORM.transFormProcess);
GetTransformData().SetAppearanceKind(pAction->TRANSFORM.appearKind);
SetNextState(STATE::TRANSFORM,g_CurTime);
}
return 1;
case ACTION_FALLDOWN:
{
StopMove();
SetNextState(STATE::FALL_DOWN,g_CurTime);
}
return 1;
case ACTION_AIR_FALLDOWN:
{
StopMove();
SetNextState( STATE::AIR_FALL_DOWN, g_CurTime );
}
return 1;
case ACTION_KEYBOARDMOVE:
{
StopMove();
SetPosition(pAction->KEYBOARDMOVE.vKeyboardCurPos);
SetInterpolatePosition();
SetAngle(pAction->KEYBOARDMOVE.fKeyboardAngle);
SetMoveFlag(pAction->KEYBOARDMOVE.byKeyboardState);
SetNextState(STATE::KEYBOARDMOVE,g_CurTime);
return 1;
}
break;
case ACTION_SPECIAL_MOVE:
{
StopMove();
SetPosition(pAction->SPECIALMOVE.vCurPos);
SetInterpolatePosition();
SetAngle(pAction->SPECIALMOVE.fAngle,TRUE);// 특수 이동은 바로 꺽는다.
SetSpecialMoveFlag(pAction->SPECIALMOVE.bType);
SetNextState(STATE::SPECIALMOVE,g_CurTime);
return 1;
}
break;
case ACTION_KEYBOARDJUMP:
{
GameFunc::PickTerrainMesh(pAction->KEYBAORDJUMP.vDest,this->vVisibleDest);
this->vSrc = this->GetVisiblePos();
StopMove();
SetNextState(STATE::KEYBOARDJUMP,g_CurTime);
}
return 1;
case ACTION_SKILL:
{
Character *pTarget = (Character *)g_ObjectManager.GetObject(pAction->SKILL.dwTargetID);
StopMove();
if (pTarget)
{
SetCurrentAction(pAction);
SetNextActionAttackSerial(pAction->ATTACK.dwAttackSerial);
SetTargetID(pAction->SKILL.dwTargetID);
SetDirection( pTarget->GetVisiblePos() );
UseSkill(pAction->SKILL.dwSkillID);
return 1;
}
else
{
ProcessAttackResult(pAction->SKILL.dwAttackSerial,TRUE);
SetNextState(STATE::IDLE,g_CurTime);
SetCurrentAction(&idleaction);
return 0;
}
}
break;
case ACTION_TELEPORT:
{
GlobalFunc::CreateEffectBeUpToOption(StrToWzID("k470"),GetVisiblePos(),GetObjectKey());
StopMove();
WzVector vPos=pAction->TELEPORT.vDest;
SetDestWarp(vPos);//워프할 좌표를 세팅 한뒤 텔레포트 스테이트 종료시 빼자
SetPosition(vPos);
SetDirection(vPos, TRUE);
}
break;
case ACTION_KNOCKBACK:
{
StopMove();
SetNextState(STATE::DAMAGE,g_CurTime);
}
return 1;
case ACTION_KNOCKBACK2:
{
StopMove();
SetNextState(STATE::KNOCKBACK2,g_CurTime);
return 1;
}
break;
case ACTION_FIRECRACKER:
{
StopMove();
SetNextState(STATE::FIRECRACKER, g_CurTime);
return 1;
}
break;
case ACTION_TOAIR:
{
StopMove();
//TOAIR_INFO info;
//info.bGroundHit = FALSE;
//info.fDownForceLimit = pAction->TOAIR.fDownForceLimit;
//info.fGravity = pAction->TOAIR.fGravity;
//info.fHeightLimit = pAction->TOAIR.fHeightLimit;
//info.fUpperForce = pAction->TOAIR.fUpperForce;
//info.iBoundCount = 0;
//info.bForceDown= pAction->TOAIR.bForceDown;
//ToAirInfo(&info);
SetNextState(STATE::AIR,g_CurTime);
}
return 1;
case ACTION_DOWN:
{
StopMove();
SetNextState(STATE::DOWN,g_CurTime);
}
return 1;
case ACTION_GETUP:
{
StopMove();
SetNextState(STATE::GETUP,g_CurTime);
}
return 1;
case ACTION_SIT:
{
StopMove();
SetNextState(STATE::SIT,g_CurTime);
}
return 1;
case ACTION_EVENTJUMP:
{
StopMove();
SetNextState(STATE::EVENTJUMP,g_CurTime);
}
return 1;
case ACTION_STOP:
{
StopMove();
SetPosition(pAction->STOP.vCurPos);
SetNextState(STATE::IDLE,g_CurTime);
}
return 1;
case ACTION_NPCMEET:
{
SetNextState(STATE::NPC_RESPONSE_STATE, g_CurTime);
}
return 1;
case ACTION_VENDORMEET:
{
}
return 1;
case ACTION_TRIGGER_ANIMATION_CONTROL:
{
if (pAction->TRIGGERANIMATIONCONTROL.start_animation_id != 0)
{
StopMove();
SetNextState(STATE::TRIGGER_ANIMATION_CONTROL, g_CurTime);
return 1;
}
}
break;
default:
{
assert(!"Character::DoNextAction() 처리되지 않은 큐 명령");
break;
}
}
SetCurrentAction(&idleaction);
SetNextState(STATE::IDLE,g_CurTime);
return 0;
}
//------------------------------------------------------------------------------
/**
*/
int PlayerMonster::GetValkyrieShotDelay()
{
return m_iValkyrieShotDelay;
}
//------------------------------------------------------------------------------
/**
*/
DWORD PlayerMonster::GetCurrentAttackStyle()
{
return m_dwAttackStyle;
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::SetCurrentAttackStyle(DWORD dwStyle,BOOL bCheck)
{
m_dwAttackStyle = dwStyle;
return TRUE;
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::CheckAttackStyle(DWORD dwStyle)
{
BASE_STYLEINFO *pInfo = SkillInfoParser::Instance()->GetStyleInfo((SLOTCODE)dwStyle);
if(pInfo==NULL)
{
return FALSE;
}
else if(pInfo->m_iWeaponDefine==GetWeaponKind())
{
return TRUE;
}
return FALSE;
}
//------------------------------------------------------------------------------
/**
장착 하려는 무기 타입과 스타일을 검사 한다.
*/
BOOL PlayerMonster::CheckStyleForWeapon(DWORD dwWeaponType)
{
DWORD dwStyle =this->GetCurrentAttackStyle();
BASE_STYLEINFO *pInfo = SkillInfoParser::Instance()->GetStyleInfo((SLOTCODE)dwStyle);
//스타일 정보가 없다.
if(pInfo==NULL)
{
this->SetCurrentNomalAttackStyle(dwWeaponType);//스타일 없음 설정
return FALSE;
}
else if(pInfo->m_iWeaponDefine!=dwWeaponType) //무기와 스타일이 안맞다면
{
this->SetCurrentNomalAttackStyle(dwWeaponType);//스타일 없음 설정
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
/**
*/
WzVector PlayerMonster::GetWeaponBonePos(int index)
{
int boneindex = GetWeaponBone(index);
WzVector ret;
ZeroMemory(&ret,sizeof(ret));
ret = GetBonePos(boneindex);
return ret;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::ProcessValkyrieShot(DWORD dwTick)
{
const float fTrailHeight = 0.03f;
const DWORD dwShotLifeTime = 500;
const float fCrossBowShotFrame1 = m_iValkyrieShotDelayTime - ((2.8f * 33) / m_fValkyrieShotSpeed);
const float fCrossBowShotFrame2 = m_iValkyrieShotDelayTime - ((5.3f * 33) / m_fValkyrieShotSpeed);
const int VALKYRIE_SHOT_SOUND1 = 408;
const int VALKYRIE_SHOT_SOUND2 = 409;
if (m_iValkyrieShotDelay > 0)
{
m_iValkyrieShotDelay -= dwTick;
if (m_iValkyrieShotDelay < fCrossBowShotFrame1)
{
if (m_iValkyrieShotRemain >= 2)
{
g_SoundEffect.Play(VALKYRIE_SHOT_SOUND1,&GetVisiblePos());
WzVector StartPosition = GetArrowBonePos(0);
cProjectileUnit* pProjectile = new cProjectileUnit();
pProjectile->SetLifeTime( 500 );
pProjectile->SetArrowStartPosition( StartPosition );
if( Character* pTarget = (Character*)g_ObjectManager.GetObject(GetLockedTarget()) )
pProjectile->SetArrowTargetObjectKey( pTarget->GetObjectKey(), TRUE );
else
pProjectile->SetArrowTargetPosition( StartPosition + GetDirection() * 4.0f );
pProjectile->SetUnitCode( eProjectile_SRC_ARROW );
pProjectile->CreateTrail( g_ProjectileManagerEx.GetTrailTexture(), 0.03f, 0.8f, 100, 150, 255 );
pProjectile->SetHitData( GetObjectKey(), m_dwValkyrieShotSerial, 0, FALSE, 0, FALSE );
ShotCrossbow();
m_iValkyrieShotRemain--;
}
}
if (m_iValkyrieShotDelay < fCrossBowShotFrame2)
{
if (m_iValkyrieShotRemain >= 1)
{
g_SoundEffect.Play(VALKYRIE_SHOT_SOUND2,&GetVisiblePos());
WzVector StartPosition = GetWeaponKind() == eWEAPONTYPE_ONEHANDCROSSBOW ? GetArrowBonePos(1) : GetArrowBonePos(0);
cProjectileUnit* pProjectile = new cProjectileUnit();
pProjectile->SetLifeTime( 500 );
pProjectile->SetArrowStartPosition( StartPosition );
if( Character* pTarget = (Character*)g_ObjectManager.GetObject(GetLockedTarget()) )
pProjectile->SetArrowTargetObjectKey( pTarget->GetObjectKey(), TRUE );
else
pProjectile->SetArrowTargetPosition( StartPosition + GetDirection() * 4.0f );
pProjectile->SetUnitCode( eProjectile_SRC_ARROW );
pProjectile->CreateTrail( g_ProjectileManagerEx.GetTrailTexture(), 0.03f, 0.8f, 100, 150, 255 );
pProjectile->SetHitData( GetObjectKey(), m_dwValkyrieShotSerial, 0, FALSE, 0, FALSE );
ShotCrossbow();
m_iValkyrieShotRemain--;
}
}
if (m_iValkyrieShotDelay <= 0)
{
m_iValkyrieShotDelay = 0;
m_dwValkyrieShotSerial = 0;
CloseCrossbow();
// 타플레이어는 공격후 고개를 원래대로 돌린다.
if (g_pHero && g_pHero->GetObjectKey() != GetObjectKey())
{
LockOn(0);
}
}
}
}
//------------------------------------------------------------------------------
/**
*/
DWORD PlayerMonster::GetValkyrieShotSerial()
{
return m_dwValkyrieShotSerial;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::PlayDamageAnimation(BOOL bRight,BOOL bCritical)
{
// 플레이어는 이동중이거나 Idle상태일때만
// 맞는 동작을 출력
WzID damageAnimation = 0;
BOOL bAniCritcal = FALSE;
if (bCritical)
{
if (rand() % 2)
{
damageAnimation = GetCurrentDamageAnimation(bRight,TRUE);
bAniCritcal = TRUE;
}
else
{
damageAnimation = GetCurrentDamageAnimation(bRight,FALSE);
}
}
else
{
damageAnimation = GetCurrentDamageAnimation(bRight,FALSE);
}
assert(damageAnimation);
if (bAniCritcal)
{
SetCurrentBlendAnimation(damageAnimation,0,1.0f,-1,FALSE);
}
else
{
SetCurrentBlendAnimation(damageAnimation,0,1.0f,-1,TRUE);
}
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::PlayDamageSound(eWEAPONSOUNDKIND eSoundKind)
{
SOUND_INFO_CODE SoundInfoCode;
SoundInfoCode.wCharacterCode = static_cast<WORD>(GetClass());
SoundInfoCode.bWeaponType = static_cast<BYTE>(eSoundKind);
SoundInfoCode.bGenderType = static_cast<BYTE>(ResourceCode::CheckValidGender(GetClass(), GetGender()));
BASE_CharSoundInfo *pInfo = CharSoundInfoParser::Instance()->GetCharSoundInfo(SoundInfoCode.dwSoundCode);
BASE_WeaponSoundInfo *pWeaponSoundInfo = WeaponSoundInfoParser::Instance()->GetWeaponSoundInfo(eSoundKind);
assert(eSoundKind >= 0 && eSoundKind < eWEAPONSOUNDKIND_MAX);
if (eSoundKind < 0 || eSoundKind >= eWEAPONSOUNDKIND_MAX)
{
return;
}
int iDamageVoice = 0;
int iImpactSound = 0;
int iWeaponSound = 0;
if (pInfo != NULL)
{
iDamageVoice = pInfo->SoundInfo.dwMoanSound[rand() % MAX_SOUND_VARIATION];
iImpactSound = pInfo->SoundInfo.dwArmorSound[rand() % MAX_SOUND_VARIATION];
}
if (pWeaponSoundInfo)
{
iWeaponSound = pWeaponSoundInfo->m_dWeaponSound[rand() % MAX_SOUND_VARIATION];
}
if (iDamageVoice)
{
g_SoundEffect.Play(iDamageVoice,&GetPosition());
}
if (iImpactSound)
{
g_SoundEffect.Play(iImpactSound,&GetPosition());
}
if (iWeaponSound)
{
g_SoundEffect.Play(iWeaponSound,&GetPosition());
}
}
//------------------------------------------------------------------------------
/**
*/
int PlayerMonster::GetShotBlendBone()
{
switch(GetClass())
{
case eCHAR_VALKYRIE:
{
if (GetBasePart()->GetWzUnit() != NULL)
{
WzBoneInfo *pInfo = GetBasePart()->GetWzUnit()->GetBoneInfo(StrToWzID("BLND"));
if (pInfo)
{
return pInfo->m_iNode;
}
else
{
return 5;
}
}
else
{
return 5;
}
}
}
return 0;
}
//------------------------------------------------------------------------------
/**
*/
BASE_ITEMINFO* PlayerMonster::GetWeaponInfo()
{
EquipmentContainer* equipment_container = GetEquipmentContainer();
if (equipment_container == NULL)
{
return NULL;
}
// 무기에따라서 기본자세가 바뀝니다.
SCSlot & rSlot = equipment_container->GetSlot(EquipmentContainer::EQUIP_WEAPON1);
if (rSlot.GetCode() == 0)
{
return NULL;
}
else
{
BASE_ITEMINFO *pItemInfo = ItemInfoParser::Instance()->GetItemInfo(rSlot.GetCode());
if(!pItemInfo)
{
WRITELOG(eLOG_LEVEL_ERR, c_wOUTPUT_LOG_CENTER, "Invalid Weapon ID [%d]", rSlot.GetCode());
assert(pItemInfo && "장착된 무기 ID가 잘못되었습니다.");
}
return pItemInfo;
}
}
//------------------------------------------------------------------------------
/**
*/
float PlayerMonster::GetMoveSpeedModifier()
{
float fMoveSpeedModifier = m_wMoveSpeedRatio / 100.0f;
return fMoveSpeedModifier;
}
//------------------------------------------------------------------------------
/**
*/
float PlayerMonster::GetAttackSpeedModifier()
{
const float fWeaponMultiplier = 0.67f;
float fFinalMultiplier = fWeaponMultiplier * m_wAttSpeedRatio / 100.0f;
return fFinalMultiplier;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetExp(EXPTYPE exp)
{
//this->GetCharInfo()->m_i64Exp = exp;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetLevel(LEVELTYPE LV)
{
//this->GetCharInfo()->m_LV = LV;
}
//------------------------------------------------------------------------------
/**
*/
EXPTYPE PlayerMonster::GetExp()
{
return 0;
//return this->GetCharInfo()->m_i64Exp;
}
//------------------------------------------------------------------------------
/**
*/
LEVELTYPE PlayerMonster::GetLevel()
{
return 0;
//return GetCharInfo()->m_LV;
}
//------------------------------------------------------------------------------
/**
*/
EXPTYPE PlayerMonster::GetNextExp()
{
return 0;
}
//------------------------------------------------------------------------------
/**
*/
EXPTYPE PlayerMonster::GetAccumExp(LEVELTYPE LV)
{
BASE_ACCUM_EXP_INFO * pAccumExpInfo = (BASE_ACCUM_EXP_INFO *)ExpValueInfoParser::Instance()->GetAccumExpInfo(LV);
if( !pAccumExpInfo )
{
return 0;
}
return pAccumExpInfo->m_AccumExp;
}
//------------------------------------------------------------------------------
/**
*/
float PlayerMonster::GetLandFrame()
{
return m_fLandFrame;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetLandFrame(float fFrame)
{
m_fLandFrame=fFrame;
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentLeftTurnAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '1';
szAniCode[3] = '2';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentRightTurnAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '1';
szAniCode[3] = '3';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentLeftStepAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
szAniCode[3] = '9';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentRightStepAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '1';
szAniCode[3] = '0';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentBackStepAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '1';
szAniCode[3] = '1';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentSpecialRightStepAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '2';
szAniCode[3] = '0';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentSpecialFrontStepAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '1';
szAniCode[3] = '7';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentSpecialBackStepAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '1';
szAniCode[3] = '8';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentSpecialLeftStepAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'N';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '1';
szAniCode[3] = '9';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentJumpStartAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'J';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
szAniCode[3] = '1';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentJumpKeepAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'J';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
szAniCode[3] = '2';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentJumpEndAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'J';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
szAniCode[3] = '3';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentJumpLandAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'J';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
szAniCode[3] = '4';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentJumpStunAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'J';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
szAniCode[3] = '5';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentJumpStunKeepAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'J';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
szAniCode[3] = '6';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentJumpStunEndAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'J';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
szAniCode[3] = '7';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentJumpEndRunAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'J';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
szAniCode[3] = '4';
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::UpdateActiveSkillEffectAttr(SkillAttrCalculator &SkillCalc)
{
std::vector<SKILL_EFFECT*>& array = GetSkillEffectArray();
for( size_t i=0;i!=array.size();++i)
{
SKILL_EFFECT* pEffect = array[i];
if( SkillScriptInfo* pInfo = SkillInfoParser::Instance()->GetSkillInfo((SLOTCODE)pEffect->dwSkillID) )
{
if (pEffect->AbilityInfo.m_wAbilityID == pEffect->dwAbilityID)
{
eATTR_TYPE eType = pEffect->AbilityInfo.GetAttrType();
if( eType == eATTR_CUR_HP )
{
;
}
else if( eType == eATTR_CUR_MP )
{
;
}
else if( eType != eATTR_TYPE_INVALID )
{
int iAddValue =
(int)SkillCalc.AddAttr(
eType,
pEffect->AbilityInfo.m_iParam[0],
pEffect->AbilityInfo.m_iParam[1] );
}
}
}
}
}
//------------------------------------------------------------------------------
/**
// 플레이어와 같음
Todo:무기에 따라서 나가는 발사체 종류 처리
*/
DWORD PlayerMonster::CreateProjectile(Character *pTarget,int iArrowBone)
{
if( pTarget == NULL )
return 0;
DWORD dwProjectileCode = 0;
BASE_ITEMINFO* pWeaponInfo = GetWeaponInfo();
if (pWeaponInfo)
{
dwProjectileCode = pWeaponInfo->m_wMissile;
}
BASE_ProjectileInfo* pInfo = ProjectileInfoParser::Instance()->GetProjectileInfo(dwProjectileCode);
WzVector StartPosition = GetArrowBonePos(iArrowBone);
WzVector TargetPosition;
if( pTarget != NULL )
{
TargetPosition = pTarget->GetArrowTargetPos();
}
else
{
TargetPosition = StartPosition + (GetDirection() * 4.0f);
}
DWORD ProjectileKey = 0;
DWORD OwnerObjectKey = GetObjectKey();
if( pInfo )
{
cProjectileUnit* pProjectile = new cProjectileUnit();
pProjectile->SetArrowStartPosition( StartPosition );
pProjectile->SetArrowTargetObjectKey( pTarget->GetObjectKey(), TRUE );
pProjectile->SetLifeTime( 333 );
pProjectile->CreateEffect( pInfo->m_wzidFlyingEffectID.id, GetObjectKey(), pTarget->GetObjectKey() );
pProjectile->SetHitData( GetObjectKey(), GetCurrentAttackSerial(), pInfo->m_wzidHitEffectID.id, FALSE, 0, TRUE );
if( pInfo->m_bMakeTrail == TRUE )
{
pProjectile->CreateTrail( g_ProjectileManagerEx.GetTrailTexture(), 0.04f, 0.8f, 150, 200, 255 );
}
g_ProjectileManagerEx.InsertProjectile( pProjectile );
ProjectileKey = pProjectile->GetKey();
}
else if( GetWeaponKind() == eITEMTYPE_ORB )
{
WzVector temp = TargetPosition - StartPosition;
float fDistance = VectorLength(&temp);
DWORD MoveTime = max(200, (DWORD)(800.f * fDistance / GetAttackRange())); // 사정거리에 2.5초에 도달하는 속도
cProjectileUnit* pProjectile = new cProjectileUnit();
pProjectile->SetArrowStartPosition( StartPosition );
pProjectile->SetArrowTargetObjectKey( pTarget->GetObjectKey(), TRUE );
pProjectile->SetLifeTime( MoveTime );
pProjectile->CreateEffect( StrToWzID("E056"), GetObjectKey(), pTarget->GetObjectKey() );
pProjectile->SetHitData( GetObjectKey(), GetCurrentAttackSerial(), 0, FALSE, 0, TRUE );
g_ProjectileManagerEx.InsertProjectile( pProjectile );
ProjectileKey = pProjectile->GetKey();
}
else if( GetWeaponKind()== eITEMTYPE_ETHERWEAPON )
{
WzVector temp = TargetPosition - StartPosition;
float fDistance = VectorLength(&temp);
DWORD MoveTime = max(200, (DWORD)(733.0f * fDistance / GetAttackRange())); // 사정거리에 2.5초에 도달하는 속도
cProjectileUnit* pProjectile = new cProjectileUnit();
pProjectile->SetArrowStartPosition( StartPosition );
pProjectile->SetArrowTargetObjectKey( pTarget->GetObjectKey(), TRUE );
pProjectile->SetLifeTime( MoveTime );
pProjectile->CreateEffect( StrToWzID("A511"), GetObjectKey(), pTarget->GetObjectKey() );
pProjectile->SetHitData( GetObjectKey(), GetCurrentAttackSerial(), 0, FALSE, 0, TRUE );
g_ProjectileManagerEx.InsertProjectile( pProjectile );
ProjectileKey = pProjectile->GetKey();
}
else
{
cProjectileUnit* pProjectile = new cProjectileUnit();
pProjectile->SetArrowStartPosition( StartPosition );
pProjectile->SetArrowTargetObjectKey( pTarget->GetObjectKey(), TRUE );
pProjectile->SetLifeTime( 100 );
pProjectile->CreateEffect( StrToWzID("A041"), GetObjectKey(), pTarget->GetObjectKey() );
pProjectile->SetUnitCode( eProjectile_SRC_ARROW );
pProjectile->CreateTrail( g_ProjectileManagerEx.GetTrailTexture(), 0.04f, 0.8f, 150, 200, 255 );
pProjectile->SetHitData( GetObjectKey(), GetCurrentAttackSerial(), 0, FALSE, 0, TRUE );
g_ProjectileManagerEx.InsertProjectile( pProjectile );
ProjectileKey = pProjectile->GetKey();
}
return ProjectileKey;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::CreatePopupMesh(
CODETYPE SkillCode,
INT64 iNumber,
eDAMAGEPOPUP_KIND eKind,
WzColor color,
BOOL bCritical,
BOOL bDoubleDamage,
float fMultiplier /*= 1.0f*/,
int iSecondary /*= -1*/,
WzColor secondarycol /*= WzColor_RGBA(0,0,0,0)*/,
float fHeight /*= 0.0f*/,
BOOL bHero /*= FALSE*/
)
{
BOOL bBySkill = (BOOL)SkillCode;
eDMGPOP_TARGET_TYPE eTargetType = eDMGPOP_TARGET_PLAYER;
eDMGPOP_COLOR_TYPE eColorType = eDMGPOP_COLOR_GENERAL;
switch( eKind )
{
case eDAMAGEPOPUP_ENEMYHPDAMAGE:
case eDAMAGEPOPUP_ENEMYMPDAMAGE:
case eDAMAGEPOPUP_PLAYERHPDAMAGE:
case eDAMAGEPOPUP_PLAYERMPDAMAGE:
{
eColorType = eDMGPOP_COLOR_CRITICAL; // 플레이어는 무조건 붉은색으로 뜨게함.
}
break;
case eDAMAGEPOPUP_HEAL:
eColorType = eDMGPOP_COLOR_HEAL;
break;
case eDAMAGEPOPUP_EXP:
eColorType = eDMGPOP_COLOR_EXP;
break;
case eDAMAGEPOPUP_MISS:
eColorType = eDMGPOP_COLOR_MISS;
break;
case eDAMAGEPOPUP_BLOCK:
eColorType = eDMGPOP_COLOR_BLOCK;
break;
default:
break;
}
color = c_PopupColorInfo[(int)eTargetType][(int)eColorType];
Character::CreatePopupMesh(
SkillCode,
iNumber,
eKind,
color,
bCritical,
bDoubleDamage,
fMultiplier,
iSecondary,
secondarycol,
fHeight,
FALSE
);
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::OpenCrossbow()
{
if (GetWeaponKind() == eWEAPONTYPE_ONEHANDCROSSBOW)
{
SetAttachmentAnimation(0,StrToWzID("N002"),FALSE);
SetAttachmentAnimation(1,StrToWzID("N002"),FALSE);
}
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::CloseCrossbow()
{
if (GetWeaponKind() == eWEAPONTYPE_ONEHANDCROSSBOW)
{
SetAttachmentAnimation(0,StrToWzID("N001"),FALSE);
SetAttachmentAnimation(1,StrToWzID("N001"),FALSE);
}
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::ShotCrossbow()
{
if (GetWeaponKind() == eWEAPONTYPE_ONEHANDCROSSBOW)
{
SetAttachmentAnimation(0,StrToWzID("N003"),FALSE);
SetAttachmentAnimation(1,StrToWzID("N003"),FALSE);
}
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetValkyrieShotAnimation()
{
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
szAniCode[0] = 'A';
szAniCode[1] = GetWeaponAnimationCode();
szAniCode[2] = '0';
switch (GetCurState())
{
// 이동중
case STATE::MOVE:
case STATE::KEYBOARDMOVE:
{
szAniCode[3] = '3';
szAniCode[3] += m_iValkyrieShotAnimVariation;
}
break;
// 일반
default:
{
szAniCode[3] = '1';
szAniCode[3] += m_iValkyrieShotAnimVariation;
}
break;
}
return StrToWzID(szAniCode);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetValkyrieReloadAnimation()
{
return StrToWzID("A211");
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetIdleAnimation()
{
tagWZID AnimID;
if(!IsBlock())
{
AnimID.id = GetCurrentIdleAnimation();
if (AnimID.id != GetCurrentAnimation())
{
if (AnimID.code[3] == '2')
{
SetAnimation( AnimID.id, FALSE );
}
else
{
SetAnimation( AnimID.id, TRUE );
}
GetBasePart()->SetInterpolationFrame(6);
}
}
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::OnAttack(DWORD dwSkillCode)
{
Character::OnAttack(dwSkillCode);
#ifndef _PERF_DEBUG
BASE_SKILLINFO *pInfo = SkillInfoParser::Instance()->GetSkillInfo((SLOTCODE)dwSkillCode);
if(pInfo)
{
switch (pInfo->m_SkillClassCode)//스킬에 따른 이펙트 처리
{
case eSKILL_WIND_SHIELD:
{
if(m_dwShieldTime==0)
{
m_dwShieldTime=1000;
cTargetPosition Position;
Position.SetTargetVisiblePosition( GetObjectKey(), TRUE );
Position.SetOffsetPosition( 0.0f, 0.0f, 0.95f );
g_ProjectileManagerEx.CreateEffect( GetObjectKey(), StrToWzID("K370"), 3000, Position );
}
}
break;
case eSKILL_ELECTRIC_FIELD:
{
if(m_dwShieldTime==0)
{
m_dwShieldTime=1000;
cTargetPosition Position;
Position.SetTargetVisiblePosition( GetObjectKey(), TRUE );
Position.SetOffsetPosition( 0.0f, 0.0f, 0.95f );
g_ProjectileManagerEx.CreateEffect( GetObjectKey(), StrToWzID("K381"), 3000, Position );
}
}
break;
}
}
#endif
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::OnDamage(const DAMAGE_PRAM &rDamage)
{
Character::OnDamage(rDamage);
DWORD dwAdditionalEffect = rDamage.pResult->GetTargetData().GetAdditionalEffect();
SetAttackStandTime(ATTACK_STAND_TIME);
BOOL bCritical = dwAdditionalEffect & (ATTACK_ADDITIONAL_EFFECT_CRITICAL);
// 맞는 이펙트도 나온다
CreateDamageEffect(bCritical,rDamage.bRight,rDamage.dwObjKey);
if ( !(rand() % 3) )
{
PlayDamageSound(rDamage.pResult->GetWeaponSound());
}
switch (GetCurState())
{
case STATE::DEATH:
break;
default:
if ( !(dwAdditionalEffect & ATTACK_ADDITIONAL_EFFECT_DONOTPLAYANIMATION) )
{
PlayDamageAnimation(rDamage.bRight,bCritical);
}
break;
}
if(GetCurState()==STATE::SIT || GetCurState()==STATE::EMOTICON)
{
SetNextState(STATE::IDLE,g_CurTime);
}
//쉴드 표시
if (m_dwShieldTime == 0)
{
std::vector<SKILL_EFFECT*>& array = GetSkillEffectArray();
DWORD dwState=0;
for( size_t i=0;i!=array.size();++i)
{
SKILL_EFFECT* pEffect = array[i];
if( pEffect->dwAbilityID == eABILITY_MAGIC_SHIELD )
{
m_dwShieldTime = 300;
cTargetPosition Position;
Position.SetTargetVisiblePosition( GetObjectKey(), TRUE );
Position.SetOffsetPosition( 0.0f, 0.0f, 0.95f );
g_ProjectileManagerEx.CreateEffect( GetObjectKey(), StrToWzID("K361"), 3000, Position );
break;
}
}
}
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::PlayEvadeAnimation()
{
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::PlayBlockAnimation()
{
WzID blockanim = GetCurrentBlockAnimation();
assert(blockanim);
// 플레이어는 이동중이거나 Idle상태일때만
// 맞는 동작을 출력
switch(GetCurState())
{
case STATE::IDLE:
this->SetAnimation(blockanim,FALSE);
break;
}
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::AnimateUnit()
{
Character::AnimateUnit();
}
//------------------------------------------------------------------------------
/**
*/
WzVector PlayerMonster::GetArrowBonePos(int iAttachIndex)
{
// Player::GetArrowBonePos와 같다.
if (!IsAnimated())
{
AnimateUnit();
}
if (iAttachIndex >= 0 && iAttachIndex < (int)GetAttachmentCount())
{
CWzUnitDraw* pSkeleton = GetAttachment(iAttachIndex).GetUnitDraw();
if ((pSkeleton != NULL) && (pSkeleton->GetWzUnit() != NULL))
{
if( WzBoneInfo* pInfo = pSkeleton->GetWzUnit()->GetBoneInfo( StrToWzID("ARRW") ) )
{
WzVector vRet;
if ( GameFunc::GetBonePos( pSkeleton, pInfo->m_iNode, &vRet) == TRUE )
{
return vRet;
}
}
}
}
else
{
assert(iAttachIndex >= 0 && iAttachIndex < (int)GetAttachmentCount() );
}
return GetVisiblePos();
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::RenderInfo()
{
Monster::RenderInfo();
}
//------------------------------------------------------------------------------
/**
*/
float PlayerMonster::GetAttackRange( void )
{
const float PUNCH_ATTACK_RANGE = 2.0f;
// 무기에따라서 기본자세가 바뀝니다.
EquipmentContainer* equipment_container = GetEquipmentContainer();
if (equipment_container == NULL)
{
return PUNCH_ATTACK_RANGE;
}
SCSlot& rSlot = equipment_container->GetSlot(EquipmentContainer::EQUIP_WEAPON1);
//float fBonus = (float)m_pPlayerAttriburtes->GetNormalRangeBonus() / 10.0f;
if (rSlot.GetCode() == 0)
{
return PUNCH_ATTACK_RANGE;
}
else
{
BASE_ITEMINFO *pItemInfo = ItemInfoParser::Instance()->GetItemInfo(rSlot.GetCode());
if(pItemInfo)
{
return (float)(pItemInfo->m_fAttRange );
}
else
{
#ifdef _DEV_VER
TCHAR szDebugMsg[1024] = {0,};
Sprintf(szDebugMsg, _T("장착된 무기 ID가 잘못되었습니다[%d]"), rSlot.GetCode());
GlobalFunc::OutputMsg_SysMsg(szDebugMsg);
#endif
return PUNCH_ATTACK_RANGE;
}
}
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::IsRangedNormalAttack()
{
switch (GetWeaponKind())
{
case eWEAPONTYPE_ONEHANDCROSSBOW:
case eWEAPONTYPE_ETHERWEAPON:
case eWEAPONTYPE_ORB:
{
return TRUE;
}
break;
default:
{
return FALSE;
}
break;
}
}
//------------------------------------------------------------------------------
/**
*/
float PlayerMonster::GetMeshHeight()
{
float mesh_height = m_fMeshHeight;
if (GetImageClass() == eCHAR_VALKYRIE)
{
mesh_height *= 0.9f;
}
return mesh_height;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::OnFootStep(BOOL b2D /* = FALSE */)
{
if (BIT_CHECK(m_dwCurTileAtt, PTA_PLAYER_FALLDOWN_TILE))
{
return;
}
if (m_bObserverMode)
{
return;
}
const int MAX_FOOTSTEP_VARIATION = 4;
WzVector vPos = GetVisiblePos();
BOOL bMan;
switch (GetClass())
{
case eCHAR_BERSERKER:
case eCHAR_DRAGON:
case eCHAR_SHADOW:
bMan = TRUE;
break;
default:
bMan = FALSE;
break;
}
DWORD dwVariation = rand() % MAX_FOOTSTEP_VARIATION;
switch (m_dwTerrainAttribute)
{
case eTERRAIN_ATTRIBUTE_DIRT:
{
if (bMan)
{
if (b2D)
{
g_SoundEffect.PlayUI(2100 + dwVariation);
}
else
{
g_SoundEffect.Play(2100 + dwVariation, &vPos);
}
}
else
{
if (b2D)
{
g_SoundEffect.PlayUI(2000 + dwVariation);
}
else
{
g_SoundEffect.Play(2000 + dwVariation, &vPos);
}
}
}
break;
case eTERRAIN_ATTRIBUTE_STONE:
{
if (bMan)
{
if (b2D)
{
g_SoundEffect.PlayUI(2124 + dwVariation);
}
else
{
g_SoundEffect.Play(2124 + dwVariation, &vPos);
}
}
else
{
if (b2D)
{
g_SoundEffect.PlayUI(2024 + dwVariation);
}
else
{
g_SoundEffect.Play(2024 + dwVariation, &vPos);
}
}
}
break;
case eTERRAIN_ATTRIBUTE_PEBBLE:
{
if (bMan)
{
if (b2D)
{
g_SoundEffect.PlayUI(2108 + dwVariation);
}
else
{
g_SoundEffect.Play(2108 + dwVariation, &vPos);
}
}
else
{
if (b2D)
{
g_SoundEffect.PlayUI(2008 + dwVariation);
}
else
{
g_SoundEffect.Play(2008 + dwVariation, &vPos);
}
}
}
break;
case eTERRAIN_ATTRIBUTE_GRASS:
{
if (bMan)
{
if (b2D)
{
g_SoundEffect.PlayUI(2104 + dwVariation);
}
else
{
g_SoundEffect.Play(2104 + dwVariation, &vPos);
}
}
else
{
if (b2D)
{
g_SoundEffect.PlayUI(2004 + dwVariation);
}
else
{
g_SoundEffect.Play(2004 + dwVariation, &vPos);
}
}
}
break;
case eTERRAIN_ATTRIBUTE_METAL:
{
if (bMan)
{
if (b2D)
{
g_SoundEffect.PlayUI(2112 + dwVariation);
}
else
{
g_SoundEffect.Play(2112 + dwVariation, &vPos);
}
}
else
{
if (b2D)
{
g_SoundEffect.PlayUI(2012 + dwVariation);
}
else
{
g_SoundEffect.Play(2012 + dwVariation, &vPos);
}
}
}
break;
case eTERRAIN_ATTRIBUTE_WATER:
{
if (bMan)
{
if (b2D)
{
g_SoundEffect.PlayUI(2128 + dwVariation);
}
else
{
g_SoundEffect.Play(2128 + dwVariation, &vPos);
}
}
else
{
if (b2D)
{
g_SoundEffect.PlayUI(2028 + dwVariation);
}
else
{
g_SoundEffect.Play(2028 + dwVariation, &vPos);
}
}
}
break;
case eTERRAIN_ATTRIBUTE_MUD:
{
if (bMan)
{
if (b2D)
{
g_SoundEffect.PlayUI(2116 + dwVariation);
}
else
{
g_SoundEffect.Play(2116 + dwVariation, &vPos);
}
}
else
{
if (b2D)
{
g_SoundEffect.PlayUI(2016 + dwVariation);
}
else
{
g_SoundEffect.Play(2016 + dwVariation, &vPos);
}
}
}
break;
case eTERRAIN_ATTRIBUTE_WOOD:
{
if (bMan)
{
if (b2D)
{
g_SoundEffect.PlayUI(2132 + dwVariation);
}
else
{
g_SoundEffect.Play(2132 + dwVariation, &vPos);
}
}
else
{
if (b2D)
{
g_SoundEffect.PlayUI(2032 + dwVariation);
}
else
{
g_SoundEffect.Play(2032 + dwVariation, &vPos);
}
}
}
break;
case eTERRAIN_ATTRIBUTE_SNOW:
{
if (bMan)
{
if (b2D)
{
g_SoundEffect.PlayUI(2120 + dwVariation);
}
else
{
g_SoundEffect.Play(2120 + dwVariation, &vPos);
}
}
else
{
if (b2D)
{
g_SoundEffect.PlayUI(2020 + dwVariation);
}
else
{
g_SoundEffect.Play(2020 + dwVariation, &vPos);
}
}
}
break;
case eTERRAIN_ATTRIBUTE_DESERT:
{
if (bMan)
{
if (b2D)
{
g_SoundEffect.PlayUI(2136 + dwVariation);
}
else
{
g_SoundEffect.Play(2136 + dwVariation, &vPos);
}
}
else
{
if (b2D)
{
g_SoundEffect.PlayUI(2036 + dwVariation);
}
else
{
g_SoundEffect.Play(2036 + dwVariation, &vPos);
}
}
}
break;
}
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::ProcessStandAnimationDelay(DWORD dwTick)
{
if (m_dwStandAnimDelay < dwTick)
{
m_dwStandAnimDelay = 0;
}
else
{
m_dwStandAnimDelay -= dwTick;
}
}
//------------------------------------------------------------------------------
/**
*/
int PlayerMonster::GetBulletCount()
{
return m_iValkyrieBulletCount;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetBulletCount(int iCount)
{
m_iValkyrieBulletCount = iCount;
}
//------------------------------------------------------------------------------
/**
*/
int PlayerMonster::DecreaseBulletCount()
{
m_iValkyrieBulletCount--;
return m_iValkyrieBulletCount;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::ValkyrieReload( BOOL bAnimation )
{
m_iValkyrieShotAnimVariation = rand() % 2;
WzID ReloadAnimID = GetValkyrieReloadAnimation();
WzAnimationInfo *pAniInfo = NULL;
if (GetBasePart()->GetWzUnit() != NULL)
{
pAniInfo = GetBasePart()->GetWzUnit()->GetAnimationInfo(ReloadAnimID);
}
m_iValkyrieShotDelay = 300;
// 이전 공격에 대한 처리를 확실히 해준다.
// 이걸 과연 해야할지 의구심이든다 -> 꾸오
if (m_dwValkyrieShotSerial)
{
ProcessAttackResult(m_dwValkyrieShotSerial,TRUE);
m_dwValkyrieShotSerial = 0;
}
if (pAniInfo)
{
m_iValkyrieShotDelay = (int)((float)pAniInfo->m_nMaxFrame * 33.0f);
}
if( bAnimation )
{
SetCurrentBlendAnimation(ReloadAnimID,GetShotBlendBone());
}
m_bValkyrieReload = TRUE;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetAttackSpeedRatio(int iSpeed)
{
m_wAttSpeedRatio = iSpeed;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetMoveSpeedRatio(int iSpeed)
{
m_wMoveSpeedRatio = iSpeed;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::LaunchEtherWeapon()
{
if (GetWeaponKind() == eWEAPONTYPE_ETHERWEAPON)
{
SetAttachmentAnimation(0,StrToWzID("N001"),FALSE);
}
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::OnShotStart()
{
OpenCrossbow();
LaunchEtherWeapon();
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::OnShotEnd()
{
CloseCrossbow();
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::OnParalyzed()
{
// 키보드이동도멈춤
ResetMoveFlag();
Character::OnParalyzed();
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::OnShotFire(int iShotCount)
{
switch(GetWeaponKind())
{
case eWEAPONTYPE_ONEHANDCROSSBOW:
{
GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A509"),GetArrowBonePos(iShotCount),GetObjectKey());
SetAttachmentAnimation(iShotCount,StrToWzID("N001"),FALSE);
//화살타격
Character *pTarget = (Character *)GetTargetObject();
if (pTarget)
{
WzVector vDest,vTemp;
float fArrowAngleZ,fArrowAngleX;
vTemp=pTarget->GetVisiblePos();
vTemp.z+=pTarget->GetArrowTargetHeight();
vDest = vTemp-GetArrowBonePos(iShotCount);//이전 위치에서 현재 위치로 계산하자.
vTemp = vDest;
float fLength;
if (vTemp.x == 0.0f && vTemp.y == 0.0f)
{
fLength = 0.0f;
}
else
{
fLength = VectorLength(&vTemp);
}
fArrowAngleX = -atan2(vDest.z,fLength); //최종 목적지가 아닌 현재 목적지로 꺽자
fArrowAngleZ = Math_GetAngleFromVector(&vDest); //최종 목적지가 아닌 현재 목적지로 꺽자
vDest=pTarget->GetVisiblePos();
vDest.z+=pTarget->GetArrowTargetHeight();
HANDLE handle;
handle=GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A041"),vDest,GetObjectKey());//!loop 이펙트 쓰지 말것
CEffectBody *pBody = g_pEffectManager->GetEffectPtrHandle(handle);
if(pBody)
{
WzVector vRot;
vRot.x = fArrowAngleX;
vRot.y = 0.0f;
vRot.z = fArrowAngleZ;
WzVector vScale;
vScale.x = 1.0f;
vScale.y = 1.0f;
vScale.z = 1.0f;
pBody->SetResultMatrix(vDest,vRot,vScale);
}
}
}
break;
case eWEAPONTYPE_ETHERWEAPON:
{
}
break;
}
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::CanBeAttackTarget()
{
BOOL bFlag = Character::CanBeAttackTarget();
// 공격가능이라도 무적상태이면 공격불가.
if (bFlag)
{
if (IsInvincible())
{
bFlag = FALSE;
}
}
return bFlag;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetPartVariation(int iPart,int iVariation)
{
if (iPart < 0 || iPart >= PLAYER_VARIATION_MAX)
{
return;
}
//switch (iPart)
//{
//case PLAYER_VARIATION_HAIR:
// GetCharInfo()->m_byHair = iVariation;
// break;
//case PLAYER_VARIATION_FACE:
// GetCharInfo()->m_byFace = iVariation;
// break;
//}
Character::SetPartVariation(iPart, iVariation);
}
//------------------------------------------------------------------------------
/**
*/
WzID PlayerMonster::GetCurrentCamAnimation()
{
return StrToWzID("0000");
}
//------------------------------------------------------------------------------
/**
*/
int PlayerMonster::GetShotCount()
{
if (GetWeaponKind() == eITEMTYPE_ONEHANDCROSSBOW)
{
return 2;
}
else
{
return 1;
}
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::ResetJumpFlag()
{
m_iJumpFlag = 0;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::AddJumpFlag(int JumpFlag)
{
BIT_ADD(m_iJumpFlag,JumpFlag);
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::RemoveJumpFlag(int JumpFlag)
{
BIT_REMOVE(m_iJumpFlag,JumpFlag);
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::CheckJumpFlag(int JumpFlag)
{
return BIT_CHECK(m_iJumpFlag,JumpFlag);
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetJumpFlag(int JumpFlag)
{
m_iJumpFlag = JumpFlag;
}
//------------------------------------------------------------------------------
/**
*/
int PlayerMonster::GetJumpFlag()
{
return m_iJumpFlag;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::SetOldJumpFlag(int iOldJumpFlag)
{
m_iOldJumpFlag = iOldJumpFlag;
}
//------------------------------------------------------------------------------
/**
*/
int PlayerMonster::GetOldJumpFlag()
{
return m_iOldJumpFlag;
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::IsFlyFinishWeapon()
{
switch(GetWeaponKind())
{
case eWEAPONTYPE_TWOHANDSWORD:
case eWEAPONTYPE_TWOHANDAXE:
case eWEAPONTYPE_ONEHANDSWORD:
case eWEAPONTYPE_SPEAR:
case eWEAPONTYPE_ETHERWEAPON:
return TRUE;
break;
}
return FALSE;
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::IsShowRenderinfo()
{
// 이름 전부보임
if( GAMEOPTION->GetShowPlayerName() || // 이름 전부보임
( g_HeroInput.GetPickedObjectKey() == GetObjectKey() ) ) // 마우스 오버
{
return TRUE;
}
return FALSE;
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::SetPosition( const HONGPOS& Pos)
{
return SetPosition( Pos.wvPos, Pos.wTile);
}
//------------------------------------------------------------------------------
/**
*/
BOOL PlayerMonster::SetPosition( const WzVector& wvPos ,int iTileIndex)
{
WzVector vOldPos = m_pPathExplorer->GetPos();
AfterRefreshTileAtt();
BOOL rt = Character::SetPosition( wvPos, iTileIndex );
//가끔 서버로 부터 갈수 없는 곳에 세우는 버그가 있다.처음 부터 유효하지 않은 좌표가 온다면 현재 복원 안됨
if (m_dwCurTileAtt & (PTA_NO_WALK))
{
rt=FALSE;
}
if ( !GENERALPARAM->IsNet() )
{
rt=TRUE;
}
if(!rt && (m_iOldTile >= 0))
{
rt=g_pSunTerrain->PathExp_Reset( m_pPathExplorer, vOldPos);
}
AfterRefreshTileAtt();
return rt;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::BeforeRefreshTileAtt()
{
//키보드 이동 이외에 워프성 포지션 세팅
m_iOldTile=m_pPathExplorer->GetTile();
//현재 속성이 있다면 현재 속성 대입 없으면 새로 구함
m_dwOldTileAtt=m_dwCurTileAtt;
}
//------------------------------------------------------------------------------
/**
*/
void PlayerMonster::AfterRefreshTileAtt()
{
m_iCurTile=m_pPathExplorer->GetTile();
//타일이 바뀌었거나 초기화가 안되었을경우
if((m_iOldTile!=m_iCurTile)||m_iCurTile<0)
m_dwCurTileAtt=GetCurrentTileAtt(TRUE);
}
#ifdef _NA_008185_20150402_COSTUME_ITEM_FOR_NPC
void PlayerMonster::SetCostumeItemCode( SLOTCODE item_code )
{
playermonster_costume_item_ = item_code;
}
SLOTCODE PlayerMonster::GetCostumeItemCode()
{
return playermonster_costume_item_;
}
#endif//_NA_008185_20150402_COSTUME_ITEM_FOR_NPC
#ifdef _NA_008633_20160104_ADD_DECORATECOSTUME
void PlayerMonster::SetDecorateCostumeItemCode( SLOTCODE item_code )
{
playermonster_decorate_costume_item_ = item_code;
}
SLOTCODE PlayerMonster::GetDecorateCostumeItemCode()
{
return playermonster_decorate_costume_item_;
}
#endif // _NA_008633_20160104_ADD_DECORATECOSTUME