Files
Client/Server/RylServerProject/RylGameLibrary/Creature/Monster/Monster.h
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

271 lines
8.4 KiB
C++

#ifndef _CMONSTER_H_
#define _CMONSTER_H_
#include <Creature/Character/Character.h>
#include <Creature/Monster/FSM/FSM.h>
#include <Map/FieldMap/Cell.h>
#include <Skill/Spell/SpellKind.h>
#include <GameEvent/GameEventMgr.h>
#include <Community/Party/Party.h>
#include "MonsterMgr.h"
const unsigned long LongRange = 45; // 장거리 공격에 의해 쫓아가는 거리.
const unsigned long OutsideSearchRange = 10; // 영역 밖에서의 시야
const unsigned long ReturnRange = 20; // 영역
const unsigned long MoveRange = 15; // 영역 안에서의 최대 이동거리.
// 전방 참조
class CStatue;
class CMonster : public CAggresiveCreature
{
public:
enum MovingPattern { AREA = 0, FIXED, ROUTE, NONAREA };
enum _Const
{
MONSTER_SEARCH_RANGE = 8,
BOSS_SEARCH_RANGE = 15,
NAMED_SEARCH_RANGE = 15,
CHIEF_SEARCH_RANGE = 15,
MAGE_SEARCH_RANGE = 18,
ACOLYTE_SEARCH_RANGE = 18,
GUARD_SEARCH_RANGE = 15,
GOLD_INC_LEVEL_LIMIT = 20,
RUN_ANI_LIMIT_MAX = 3,
RUN_ANI_LIMIT_MIN = 1,
RATE_MOVING_AND_PLAYER = 10,
MAX_MONSTER_UID = 0xFFFF - 0x8000 - 0x4000,
MONSTER_PARTY_BIT = 0x80000000
};
struct MonsterCreateInfo; // 몬스터 정보 구조체
typedef MonsterCreateInfo *LPMonsterCreateInfo;
CMonster();
CMonster(MonsterCreateInfo& MonsterCreate, bool bAdminCmdSummon = false);
virtual ~CMonster();
// --------------------------------------------------------------------------------------------
// 초기 설정
bool InitMonster(Position& Pos, bool bDead = false);
virtual bool GetMotion(unsigned long MotionID, MotionInfo& Motion); // 몬스터 모션 정보를 얻음.
// --------------------------------------------------------------------------------------------
// 몬스터 행동 관련
bool CheckPartyTarget(); // 몬스터 파티의 타겟을 체크해서 패턴을 변경하는가?
virtual void SearchPlayer(void); // 플레이어 검색
bool IsOverlap(void); // 다른 몬스터와 겹치는가 검색
bool Process(void); // 몬스터 행동 처리 - 내부에서 UpdateBehavior호출
void UpdateBehavior(unsigned long dwTick); // 몬스터 행동 업데이트
virtual void NormalBehavior(unsigned long dwTick); // 보통 상태
virtual void AttackBehavior(unsigned long dwTick); // 공격 상태
virtual void ReturnBehavior(unsigned long dwTick); // 귀환 상태
virtual void EscapeBehavior(void); // 도망 상태
virtual void DeadBehavior(unsigned long dwTick); // 죽은 상태
// Action 관련 처리
void AttackAction();
void WalkAttackAction(float fVelocity=0.1f);
void RunAction(float fDistance, float fDstX, float fDstZ);
bool IsReturn();
inline Position CalculateCoor(void); // 이동 후의 좌표 계산
virtual const int CalculateFixLevelGap(CAggresiveCreature *pDefender);
virtual bool Attack(AtType attackType, unsigned char cDefenderNum,
CAggresiveCreature** ppDefenders, unsigned char* cDefenderJudges, unsigned short* wDefenderMPHeal);
inline virtual void Attacked(void); // 공격을 받음
bool MultiAttack(void); // 타겟을 찾아 공격 (내부에서 Attack함수를 호출)
void CancelTarget(bool bSaveThreat = false); // 타겟을 취소
virtual bool Dead(CAggresiveCreature* pOffencer); // 죽었을 때 호출되는 함수
virtual EnemyCheck::EnemyType IsEnemy(CCreature* lpTarget, unsigned char* cResult = NULL);
virtual void Respawn(unsigned long dwTick);
// --------------------------------------------------------------------------------------------
// 파티 관련
void SetPID(unsigned long dwPID) { m_dwPID = dwPID; }
unsigned long GetPID(void) { return m_dwPID; }
// --------------------------------------------------------------------------------------------
// 패킷을 만들어서 보내는 함수들
virtual LONG SendMove(unsigned short nAniNum);
// --------------------------------------------------------------------------------------------
// 기타 함수
virtual Item::CItem* SellToCharacter(CCharacter *lpCustomer, unsigned short wKindItem, TakeType takeType,
Item::CItem* lpRequestItem, unsigned long &dwPrice, unsigned short wCouponID, unsigned short &usError) { return NULL; }
bool HasSkill(void); // 스킬을 사용하는 몬스터인가?
int GetUseSkillNum(void); // 몇가지의 스킬을 가지고 있는가?
inline unsigned char GetOptionBaseNum(Item::EquipType::OptionType eType);
unsigned long GetDropRate(unsigned char nIndex);
unsigned long GetAwardItem(int nIndex) { return m_MonsterInfo.m_aryAwardItem[nIndex]; }
inline CStatue* DowncastToStatue(void);
// 몬스터 일련번호 얻기
int GetSerialNumber(void) { return ((m_dwCID - Creature::MONSTER_BIT) >> 16); }
unsigned short GetKID(void) { return static_cast<unsigned short>(m_MonsterInfo.m_dwKID); }
unsigned char GetPattern(void) { return m_MonsterInfo.m_cSkillPattern; }
int GetCurrentState(void) { return m_nCurrentState; }
short GetAttackRange(void) { return m_MonsterInfo.m_wAttackRange; }
bool IsDeadSummonMonster(void);
virtual void SetGuard(bool bGuard) { return; }
virtual unsigned short ApplyDamage(AtType attackType, CAggresiveCreature* pOffencer, unsigned char &cOffencerJudge,
unsigned char &cDefenserJudge, unsigned short& wOffencerMPHeal, unsigned short& wDefenserMPHeal, unsigned short &wError);
virtual void GuardMe(CAggresiveCreature* lpTarget, unsigned short wThreat) { return; }
virtual void AttackCmd(CAggresiveCreature* lpTarget, unsigned short wThreat) { return; }
virtual bool IsPeaceMode(void) { return false; }
virtual bool IsRideArms(void) const { return false; }
virtual unsigned char GetNation() const { return m_MonsterInfo.m_cNation; }
virtual unsigned char GetRealmPoint() { return 0; }
static void LogMonsterMoveCount(void);
Broadcast2nd::CSerializeMonsterData& GetSerializeData() { return m_SerializeMonsterData; }
protected:
// 각종 상수들
enum _Timing
{
FPS = 30
};
MonsterInfo m_MonsterInfo;
Position m_OriginalPosition; // 몬스터의 초기 위치
unsigned long m_dwLastBehaviorTick; // 마지막으로 행동한 시점의 Tick
Broadcast2nd::CSerializeMonsterData m_SerializeMonsterData;
CAggresiveCreature* m_lpTarget; // 공격할 타겟
long m_lCurrentFrame; // 현재 진행중인 Frame을 나타냄. 동작이 끝났는지를 확인하기 위해 삽입
int m_nNormalMovingDelay; // 노말 상태의 이동 타이밍 간격 (주위 플레이어 수에 따라 유동적)
int m_nLeaveMovingNum; // 남은 이동 수
int m_nMovingPattern; // 이동 패턴 (영역, 붙박이, 루트, 비영역)
int m_nCurrentState; // 현재 State
unsigned short m_wSearchRange; // 몬스터의 시야
unsigned short m_wDefaultSearchRange; // 몬스터의 기본 시야
bool m_bLongRangeAttacked; // 원거리 공격? (원거리 공격에 맞으면 시야를 넓혀 타겟을 찾음)
bool m_bScout; // 스카우터인가?
bool m_bAttacking; // 공격 중인가?
unsigned short m_wRespawnArea; // 리스폰 지점에서의 랜덤영역값
// 옵션 요소.
bool m_bAvoid; // 피할 턴인가? (피하기 옵션이 켜진 경우)
bool m_bAdminCmdSummon; // Admin 명령으로 소환한 몬스터인가?
// 파티 관련 PID
unsigned long m_dwPID; // 몬스터 파티 아이디
static LONG ms_NormalBehaviorSendCount;
static LONG ms_AttackBehaviorSendCount;
static LONG ms_ReturnBehaviorSendCount;
static LONG ms_EscapeBehaviorSendCount;
static LONG ms_DeadBehaviorSendCount;
};
struct CMonster::MonsterCreateInfo
{
Position m_Pos;
unsigned long m_dwCID;
unsigned long m_dwPID;
int m_nKID;
int m_nMovingPattern;
bool m_bScout;
unsigned short m_wRespawnArea;
MonsterCreateInfo()
: m_dwCID(0), m_nKID(0), m_dwPID(0), m_bScout(false), m_nMovingPattern(0), m_wRespawnArea(0)
{
}
};
Position CMonster::CalculateCoor(void)
{
float fVel = (true == GetEnchantInfo().GetFlag(Skill::SpellID::Slow)) ?
m_MotionInfo.m_fVelocity / 4 : m_MotionInfo.m_fVelocity;
return Position(m_CurrentPos.m_fPointX + fVel * cosf(m_MotionInfo.m_fDirection),
m_CurrentPos.m_fPointY, m_CurrentPos.m_fPointZ + fVel * sinf(m_MotionInfo.m_fDirection));
}
void CMonster::Attacked(void)
{
m_bLongRangeAttacked = true;
if (m_nCurrentState == STATE_ID_NORMAL || m_nCurrentState == STATE_ID_RETURN)
{
m_lCurrentFrame = 0;
}
m_nCurrentState = CFSM::GetInstance().StateTransition(m_nCurrentState, INPUT_ID_ATTACKED_PLAYER);
}
unsigned char CMonster::GetOptionBaseNum(Item::EquipType::OptionType eType)
{
switch (eType)
{
case Item::EquipType::STANDARD_OPTION: return m_MonsterInfo.m_cStandardBaseNum;
case Item::EquipType::OVER_OPTION: return m_MonsterInfo.m_cOverBaseNum;
}
return 0;
}
CStatue* CMonster::DowncastToStatue(void)
{
if (0 != this &&
MonsterInfo::MIN_STATUE_KID <= m_MonsterInfo.m_dwKID &&
MonsterInfo::MAX_STATUE_KID >= m_MonsterInfo.m_dwKID)
{
return reinterpret_cast<CStatue *>(this);
}
return NULL;
}
#endif