Files
Leviathan/Server/GameServer/Game/Struct/StructMonster.h
T
2026-06-01 12:46:52 +02:00

379 lines
13 KiB
C++

#pragma once
#include <vector>
#include <mmo/ArObject.h>
#include <geometry/X2DPolygon.h>
#include <toolkit/XPropertySet.h>
#include "StructCreature.h"
#include "GameRule.h"
#include "GameContent.h"
struct _DAMAGE_TAG
{
_DAMAGE_TAG( AR_TIME n, AR_HANDLE _uid, int d ) : nTime( n ), uid( _uid ), nDamage( d )
{
}
AR_HANDLE uid;
AR_TIME nTime;
int nDamage;
};
struct _HATE_TAG
{
_HATE_TAG( AR_TIME n, AR_HANDLE _uid, __int64 h ) : nTime( n ), uid( _uid ), nHate( h ), bIsActive( true ), nBadAttackCount( 0 ), nLastMaxHate( 0 )
{
}
AR_HANDLE uid;
AR_TIME nTime;
__int64 nHate;
bool bIsActive;
int nBadAttackCount;
int nLastMaxHate;
};
struct _HATE_MODIFIER_TAG
{
_HATE_MODIFIER_TAG( AR_HANDLE _uid, int _hate ) : uid ( _uid ), nHate( _hate )
{
}
AR_HANDLE uid;
int nHate;
};
struct StructMonster : StructCreature, XPropertySet
{
struct MonsterDeleteHandler
{
// 타이머(m_nLifeTime)에 의해 삭제되는 몬스터의 경우와 실제로 사냥 당해서 사망하는 경우 모두 호출 됨(몬스터 데이터 삭제 시)
virtual void onMonsterDelete( struct StructMonster * pMonster ) = 0;
};
// 경험치 분배시 모든 공격자를 가상의 파티로 인식한다. 솔로 플레이어는 1인 파티가 된다.
struct VIRTUAL_PARTY
{
VIRTUAL_PARTY( int id, int d, int lv ) : nPartyID( id ), nDamage( d ), nLevel( lv )
{
hPlayer = 0;
fContribute = 0.0f;
bTamer = false;
}
VIRTUAL_PARTY( AR_HANDLE h, int d, int lv ) : hPlayer( h ), nDamage( d ), nLevel( lv )
{
nPartyID = 0;
fContribute = 0.0f;
bTamer = false;
}
// bool operator <( const VIRTUAL_PARTY & rh ) const
// {
// return nDamage > rh.nDamage;
// }
int nPartyID;
AR_HANDLE hPlayer;
int nDamage;
float fContribute;
bool bTamer;
int nLevel;
static bool greaterByDamage( const VIRTUAL_PARTY & lh, const VIRTUAL_PARTY & rh )
{
return lh.nDamage > rh.nDamage;
}
static bool greaterByContribute( const VIRTUAL_PARTY & lh, const VIRTUAL_PARTY & rh )
{
return lh.fContribute > rh.fContribute;
}
};
enum MONSTER_GENERATE_CODE
{
BY_NONE = 0,
BY_RESPAWN,
BY_SCRIPT,
BY_SHOVELING,
};
enum MONSTER_STATUS
{
STATUS_NORMAL = 0,
STATUS_TRACKING,
STATUS_FIND_ATTACK_POS,
STATUS_ATTACK,
STATUS_DEAD,
STATUS_RUNAWAY,
};
enum
{
ITEM_DROP_LENGTH = 18, // How far from the mob the item will drop
};
virtual const char* getClassName() { return "StructMonster"; }
static void BindProperty();
static StructMonster* AllocMonster( unsigned idx, unsigned char difficulty = 0 );
static void FreeMonster( StructMonster* p );
AR_HANDLE GetHandle() const { return m_hHandle; }
virtual const char* GetName() const;
virtual int GetNameID() const; //AziaMafia get_monster_info
virtual int GetCreatureGroup() const;
void SetGenerateCode( int code ) { m_nGenerateCode = code; }
void SetDeleteHandler( MonsterDeleteHandler * pHandler ) { m_pDeleteHandler = pHandler; }
const MonsterDeleteHandler * GetDeleteHandler() const { return m_pDeleteHandler; }
// 지정 시간 이후에 몬스터가 없어지도록 함, -1을 인자로 넘기면 지정되어 있던 타이머가 초기화 됨
void SetLifeTime( const AR_TIME nLifeTime ) { m_nLifeTime = ( nLifeTime != INFINITE_TIME ) ? GetArTime() + nLifeTime : 0; }
const bool IsLifeTimeOver() const { return m_nLifeTime && m_nLifeTime <= GetArTime(); }
void SetReturnPosition( AR_UNIT x, AR_UNIT y ) { m_RespawnX = x; m_RespawnY = y; }
const ArPosition GetReturnPosition() { return ArPosition( m_RespawnX, m_RespawnY ); }
bool SetMonsterInfo( unsigned idx );
bool IsMonster() const { return true; }
bool IsEnvironmentMonster() const;
virtual bool IsBattleMode() const { return ( GetStatus() == STATUS_TRACKING || GetStatus() == STATUS_ATTACK || GetStatus() == STATUS_FIND_ATTACK_POS ); }
bool IsBossMonster() const;
int GetMonsterType() const { return m_pContentInfo->monster_type; }
bool IsDungeonConnector() const;
bool IsAgent() const;
bool IsAutoTrap() const;
bool IsRunaway() const;
bool IsDungeonCore() const;
AR_UNIT GetChaseRange() const;
int GetDungeonId() const { return m_nDungeonId; }
bool IsDungeonRaidMonster() const { return m_bIsDungeonRaidMonster; }
bool IsOriginalDungeonSiegerGuardian() const { return m_bIsDungeonSiegerGuardian; }
bool IsOriginalDungeonOwnerGuardian() const { return m_bIsDungeonOwnerGuardian; }
void SetDungeonOwnerGuardian() { m_bIsDungeonOwnerGuardian = true; }
void SetDungeonSiegerGuardian() { m_bIsDungeonSiegerGuardian = true; }
void ResetDungeonOwnerGuardian() { m_bIsDungeonOwnerGuardian = false; }
void ResetDungeonSiegerGuardian() { m_bIsDungeonSiegerGuardian = false; }
void SetDungeonRaidMonster() { m_bIsDungeonRaidMonster = true; }
void SetDungeonId( int dungeon_id ) { m_nDungeonId = dungeon_id; }
// 헌터홀릭 던전 내 몬스터 처리 관련
int GetInstanceRespawnID() const { return m_nInstanceRespawnID; }
void SetInstanceRespawnID( const int nInstanceRespawnID ) { m_nInstanceRespawnID = nInstanceRespawnID; }
AR_UNIT GetFirstAttackRange() const;
bool IsEnemy( StructCreature* pTarget, bool bIncludeHiding = false );
bool IsAlly( StructCreature* pTarget );
bool IsFirstAttacker() const;
bool IsGroupRevenger() const;
bool IsGroupFirstAttacker() const;
bool IsCastRevenger() const;
bool IsBattleRevenger() const;
int GetMonsterGroup() const;
bool IsTameable() const;
ItemBase::ItemCode GetTameItemCode() const;
int GetTameCode() const;
const c_fixed10 & GetTamePercetage() const;
float GetTameExpAdjust() const;
bool IsMonsterCreatureTame() const;
int GetMonsterCreatureTameCode() const;
int GetMonsterCreatureTameGroupCode() const;
int GetMonsterCreatureTameItemCode() const;
virtual float GetScale() const;
virtual float GetSize() const;
MONSTER_STATUS GetStatus() const;
void SetStatus( MONSTER_STATUS status );
void SetNeedToFindEnemy( bool bNeedToFindEnemy = true ) { m_bNeedToFindEnemy = bNeedToFindEnemy; }
virtual bool StartAttack( AR_HANDLE target, bool bNeedFastReaction );
virtual int onDamage( StructCreature * pFrom, Elemental::Type elementalType, DamageType damageType, int nDamage, bool bCritical );
int GetMonsterId();
virtual const CreatureStat & GetBaseStat() const;
virtual int GetLevel() const;
virtual unsigned char GetRace() const;
int GetHate( AR_HANDLE handle );
int AddHate( AR_HANDLE handle, int pt, bool bBroadcast = true, bool bProcRoamingMonster = true );
int RemoveHate( AR_HANDLE handle, int pt );
AR_HANDLE GetEnemyUID();
AR_HANDLE GetMaxDamageDealer() const;
virtual void OnUpdate();
AR_HANDLE GetTamer() const;
void SetTamer( AR_HANDLE handle, StructSkill* pTamingSkill );
StructSkill* GetTamingSkill() const { return m_pTamingSkill; }
int GetTamingSkillLevel() const { return m_nTamingSkillLevel; }
bool IsTamingSuccessed() const { return m_bTamedSuccess; }
void SetWandering( bool IsWandering ) { m_bIsWandering = IsWandering; }
virtual bool IsAttackable();
virtual bool IsMovable();
virtual bool IsKnockbackable();
virtual bool IsSkillCastable();
virtual bool IsMagicCastable();
// Decide whether to continue or stop attack processing when calling a script in AI_processAttack
void SetContinueAttack( bool bContinue ) { m_bContinueAttack = bContinue; }
bool IsNeedToContinueAttack() { return m_bContinueAttack; }
const MonsterBase * GetMonsterBase() { return m_pContentInfo; }
void SetRespawnByScript() { m_bRespawnByScript = true; }
#ifndef _USE_NEW_ROAMING_ONLY
void SetWayPointInfo( const struct GameContent::WAY_POINT_INFO* pWayPointInfo )
{
m_pWayPointInfo = pWayPointInfo;
}
#endif
void SetRoamer( struct StructRoamer * pRoamer ) { m_pRoamer = pRoamer; }
struct StructRoamer * GetRoamer() { return m_pRoamer; }
void SetSkillTargetPosition( const ArPosition & pos ) { m_posSkillTarget = pos; }
ArPosition GetSkillTargetPosition() const { return m_posSkillTarget; }
void comeBackHome( bool bInvincible ); // 응? -_-
protected:
StructMonster( AR_HANDLE handle, unsigned idx, unsigned char difficulty = 0 );
virtual ~StructMonster();
// ArScheduler 에서 StructMonster 를 지우기 위해 존재함.
// alloc/free 메커니즘에 관한 확실한 이해 전에는 수정 말것!
virtual bool ProcDelete();
// { Monster AI
virtual void onProcess( int nThreadIdx );
virtual void regenHPMP( AR_TIME t );
bool CheckTriggerCondition( const MonsterBase::MONSTER_TRIGGER & trigger, const int nTriggerIndex );
bool ResetTriggerCondition();
void AI_processAttack( AR_TIME t );
void AI_processAttack( StructCreature * pEnemy, AR_TIME t );
void processWalk( AR_TIME t );
void processMove( AR_TIME t );
void processDead( AR_TIME t );
void processFirstAttack( AR_TIME t );
bool findAttackablePosition( const ArPosition & myPosition, ArPosition & enemyPosition, AR_UNIT distance, AR_UNIT gap );
void findNextEnemy();
bool getMovePosition( ArPosition & pos );
ArPosition getNonDuplicateAttackPos( StructCreature * pEnemy );
_HATE_TAG * getHateTag( AR_HANDLE handle, AR_TIME t = 0 );
_HATE_TAG * addHate( AR_HANDLE handle, int nHate );
bool removeFromHateList( AR_HANDLE handle );
void clearHateList();
void updateHate();
_DAMAGE_TAG * getDamageTag( AR_HANDLE handle, AR_TIME t = 0 );
_DAMAGE_TAG * addDamage( AR_HANDLE handle, int nDamage );
bool removeFromDamageList( AR_HANDLE handle );
void procDropChaos( StructCreature * pKiller, std::vector< VIRTUAL_PARTY > & vPartyContribute, float fDropRatePenalty, float fPCBangDropRateBonus );
void procDropGold( const ArPosition & pos, StructCreature * pKiller, struct takePriority* pPriority, std::vector< VIRTUAL_PARTY > & vPartyContribute, float fDropRatePenalty, float fPCBangDropRateBonus );
void procDropItem( const ArPosition & pos, StructCreature * pKiller, struct takePriority* pPriority, std::vector< VIRTUAL_PARTY > & vPartyContribute, float fDropRatePenalty, float fPCBangDropRateBonus );
const bool selectDropItems( std::vector< int > & vItemID, std::vector< __int64 > & vItemCount );
void dropItemGroup( const ArPosition & pos, StructCreature * pKiller, struct takePriority* pPriority, std::vector< VIRTUAL_PARTY > & vPartyContribute, int nDropGroupID, const __int64 & count, int level, int nFlagIndex );
void dropItem( const ArPosition & pos, StructCreature * pKiller, struct takePriority* pPriority, std::vector< VIRTUAL_PARTY > & vPartyContribute, ItemBase::ItemCode code, const __int64 & count, int level, bool bIsEventItem, int nFlagIndex );
void calcPartyContribute( StructCreature * pKiller, std::vector< VIRTUAL_PARTY > & vPartyContribute );
void procImmoralPoint( std::vector< VIRTUAL_PARTY > & vPartyContribute );
//struct StructCreature* m_pEnemy;
AR_HANDLE m_hTamer;
AR_TIME m_nTamedTime;
bool m_bTamedSuccess; // 테이밍이 성공적으로 완료 되었는지 여부
StructSkill* m_pTamingSkill; // 테이밍 시도할 때 건 스킬
int m_nTamingSkillLevel;// 테이밍 시도할 때 사용된 스킬 레벨
AR_TIME m_nLastTrackTime;
AR_TIME m_nHateCheckTime;
AR_HANDLE m_hFirstAttacker;
AR_TIME m_nFirstAttackTime;
std::vector< struct _DAMAGE_TAG > m_vDamageList;
std::vector< struct _HATE_TAG > m_vHateList;
std::vector< struct _HATE_MODIFIER_TAG > m_vHateModifierByState;
bool m_bNeedToFindEnemy;
int m_nMaxHate;
AR_TIME m_nLastHateUpdateTime;
// }
bool m_bComeBackHome;
AR_TIME m_nRegenTime;
bool m_bRespawnByScript;
// { AI용
AR_UNIT m_nLastEnemyDistance;
virtual void onDead( StructCreature *pKiller, bool decreaseEXPOnDead = true );
virtual void procQuestAndTitle( const ArPosition & pos, StructCreature *pKiller, struct takePriority* pPriority, std::vector< VIRTUAL_PARTY > & vPartyContribute, float fDropRatePenalty );
void procEXP( StructCreature *pKiller, std::vector< VIRTUAL_PARTY > & vPartyContribute );
struct MonsterBase* m_pContentInfo;
AR_HANDLE m_hHandle;
int m_nTotalDamage;
int m_nStatus;
int m_nGenerateCode;
bool m_bIsWandering;
AR_UNIT m_RespawnX, m_RespawnY;
bool m_bNeedToSetReturnPos;
MonsterDeleteHandler * m_pDeleteHandler;
AR_TIME m_nLifeTime;
int m_nDungeonId;
bool m_bIsDungeonRaidMonster;
bool m_bIsDungeonOwnerGuardian;
bool m_bIsDungeonSiegerGuardian;
int m_nInstanceRespawnID;
std::vector< int > m_vTriggerFlag;
#ifndef _USE_NEW_ROAMING_ONLY
const struct GameContent::WAY_POINT_INFO* m_pWayPointInfo;
int m_nWayPointIdx;
#endif
struct StructRoamer * m_pRoamer;
bool m_bContinueAttack;
unsigned char m_nDifficulty;
ArPosition m_posSkillTarget;
// 스탯 관련 함수 및 변수들을 아래에 정리
protected:
// --- 스탯 및 능력치 연산에 관련된 지속 효과들 적용하는 루틴 ---
virtual void applyState( StructState & state );
// --- 이하 핸들러들 ---
virtual void onBeforeCalculateStat();
virtual void onApplyAttributeAdjustment();
virtual void onCompleteCalculateStat();
};