#ifndef _CMONSTER_H_ #define _CMONSTER_H_ #include #include #include #include #include #include #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(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(this); } return NULL; } #endif