Files
Sun1602/Server/GameServer/Npcai/BattleRecord.h
T
2022-10-26 12:25:11 +08:00

299 lines
7.7 KiB
C++

#ifndef __GAMESERVER_BATTLE_RECORD_H__
#define __GAMESERVER_BATTLE_RECORD_H__
#pragma once
struct AI_TYPE_INFO;
class NPC;
class AIParamParser;
class BattleRecord;
// (CHANGES) (091216) code arrangement
// (CHANGES) (091216) move 'eBATTLE_POINT_TYPE' to 'AITypes.h'
typedef BATTLEPOINT BattlePoints[BATTLE_POINT_MAX];
//==================================================================================================
//
// BattleRecord
//
//==================================================================================================
/// 한 NPC 혹은 NPCGroup이 적으로 인식하고 있는 Character들에 대한 전투기록
class BattleRecord
{
friend class TargetManager;
public:
//----------------------------------------------------------------------------------------------
/// 개인별 전투 기록
class Node
{
public:
Node();
//~Node();
void Init();
void Update();
void SetObjectKey(DWORD objectKey);
DWORD GetObjectKey() const;
void SetBattlePoint(eBATTLE_POINT_TYPE ePointType, int iPoint);
BATTLEPOINT GetBattlePoint(eBATTLE_POINT_TYPE ePointType) const;
#ifdef _NA_0_20100819_AGGRO_RENEWAL
void SetAIPaserInfo(AI_TYPE_INFO* pAITypeInfo);
BATTLEPOINT GetCalcTotalPoint() const;
void SetTargetDistance(float TargetDistance);
float GetTargetDistance() const;
#endif
// (CHANGES) (091223) (WAVERIX) add interface
//void GetBattlePoints(BattlePoints* OUT points) const;
//DWORD GetCreateTick() const;
void PlusDamage(int iDamage);
DWORD GetTotDamage() const;
void SetPointDamage(int iDamage);
DWORD GetPointDamage() const;
BOOLEAN IsFirstAttacker() const;
private:
DWORD m_ObjectKey;
//DWORD m_CreateTick;
BOOLEAN m_bFirstAttack;
DWORD m_dwPointDamage; // 데미지 포인트 계산을 위한 데미지(포인트 계산후 초기화)
DWORD m_dwTotDamage; // 전체 데미지(소유권 계산을 위함)
// 타입별 포인트
BattlePoints m_wBattlePoint;
#ifdef _NA_0_20100819_AGGRO_RENEWAL
float m_TargetDistance; //대상과의 거리 값
AI_TYPE_INFO* m_pAITypeInfo;
#endif
};
//----------------------------------------------------------------------------------------------
public:
typedef STLX_MAP<DWORD, Node> Records;
#ifdef _NA_20100322_AGGRO_DISPLAY
typedef STLX_VECTOR<Records::iterator> AggroDisplayList;
struct compare_node_value
{
bool operator() (const Records::const_iterator& it1,
const Records::const_iterator& it2) const
{
return it1->second.GetCalcTotalPoint() > it2->second.GetCalcTotalPoint();
}
};
#endif
BattleRecord(NPC* pNPC);
~BattleRecord();
void Init();
void Update();
int GetSize() const;
BOOL Remove(DWORD object_key);
void Clear(DWORD dwExceptKey = 0);
Character* SelectBestTarget();
BOOLEAN IsFirstAttacked();
void SetFirstAttacker(BattleRecord::Node* pRecord);
#ifdef _NA_20100322_AGGRO_DISPLAY
void SetFirstVictim(BattleRecord::Node* pRecord);
#endif
template<class RecordOperator>
void ForEachRecord(RecordOperator& Opr);
template<class RecordOperator>
void ForEachRecord(const RecordOperator& Opr) const;
const Records& GetRecords() const;
const BattleRecord::Node* Get(DWORD object_key) const;
#ifdef _NA_20100322_AGGRO_DISPLAY
void SendAggroDisPlayInfo(Player* const player);
#endif
private:
Records& GetRecords();
BattleRecord::Node* Get(DWORD object_key);
BattleRecord::Node* Add(Character* pAttacker);
void UpdateTotalPoint(const BOOLEAN need_battlerecord_update = false);
void SetBattlePoint(DWORD object_key, eBATTLE_POINT_TYPE ePointType, int iPoint);
BATTLEPOINT GetBattlePoint(DWORD object_key, eBATTLE_POINT_TYPE ePointType) const;
#ifdef _NA_0_20100819_AGGRO_RENEWAL
BATTLEPOINT GetCalcTotalPoint(DWORD object_key) const;
#endif
private:
NPC* const m_pNPC;
const AI_TYPE_INFO* m_pAITypeInfo; // for caching
Records m_Records;
DWORD m_LastUpdateTick;
BOOLEAN m_bFirstAttacked; // 처음으로 공격받은 상태인가?
//
__DISABLE_COPY(BattleRecord);
};
//==================================================================================================
// Implementations
inline
BattleRecord::Node::Node() {
ZeroMemory(this, sizeof(*this));
}
//inline
//BattleRecord::Node::~Node() {
//}
inline void
BattleRecord::Node::Init() {
new (this) Node();
}
#ifdef _NA_0_20100819_AGGRO_RENEWAL
inline void
BattleRecord::Node::SetAIPaserInfo(AI_TYPE_INFO* pAITypeInfo)
{
m_pAITypeInfo = pAITypeInfo;
}
#endif
inline void
BattleRecord::Node::SetObjectKey(DWORD objectKey) {
m_ObjectKey = objectKey;
}
inline DWORD
BattleRecord::Node::GetObjectKey() const {
return m_ObjectKey;
}
inline BATTLEPOINT
BattleRecord::Node::GetBattlePoint(eBATTLE_POINT_TYPE ePointType) const {
return m_wBattlePoint[ePointType];
}
// (CHANGES) (091223) (WAVERIX) add interface
// youngmoon _NA_0_20100819_AGGRO_RENEWAL 추가된 이후 BATTLE_POINT_TOTAL 는 캐릭터별 비율 계산이 들어가므로 사용하지 않기로 한다.
//inline void
//BattleRecord::Node::GetBattlePoints(BattlePoints* OUT points) const {
// CopyMemory(points, m_wBattlePoint, sizeof(*points));
//}
//inline DWORD
//BattleRecord::Node::GetCreateTick() const {
// return m_CreateTick;
//}
inline void
BattleRecord::Node::PlusDamage(int iDamage) {
m_dwTotDamage += iDamage;
m_dwPointDamage += iDamage;
}
inline DWORD
BattleRecord::Node::GetTotDamage() const {
return m_dwTotDamage;
}
inline void
BattleRecord::Node::SetPointDamage(int iDamage) {
m_dwPointDamage = iDamage;
}
inline DWORD
BattleRecord::Node::GetPointDamage() const {
return m_dwPointDamage;
}
inline BOOLEAN
BattleRecord::Node::IsFirstAttacker() const {
return m_bFirstAttack;
}
#ifdef _NA_0_20100819_AGGRO_RENEWAL
inline void
BattleRecord::Node::SetTargetDistance(float TargetDistance){
m_TargetDistance = TargetDistance;
}
inline float
BattleRecord::Node::GetTargetDistance() const{
return m_TargetDistance;
}
#endif
//==================================================================================================
inline int
BattleRecord::GetSize() const {
return (int)m_Records.size();
}
inline BOOLEAN
BattleRecord::IsFirstAttacked() {
return m_bFirstAttacked;
}
inline BattleRecord::Records&
BattleRecord::GetRecords() {
return m_Records;
}
inline const BattleRecord::Records&
BattleRecord::GetRecords() const {
return m_Records;
}
// (CHANGES) add const function
inline const BattleRecord::Node*
BattleRecord::Get(DWORD object_key) const {
Records::const_iterator it = m_Records.find(object_key);
return it != m_Records.end() ? &it->second
: NULL;
}
// (CHANGES) add const function
inline BattleRecord::Node*
BattleRecord::Get(DWORD object_key) {
Records::iterator it = m_Records.find(object_key);
return it != m_Records.end() ? &it->second
: NULL;
}
template<class RecordOperator>
void BattleRecord::ForEachRecord(RecordOperator& Opr)
{
Records::iterator it = m_Records.begin(),
itend = m_Records.end();
for( ; it != itend; ++it)
{
BattleRecord::Node* pRecord = &it->second;
Opr(pRecord);
}
}
template<class RecordOperator>
void BattleRecord::ForEachRecord(const RecordOperator& Opr) const
{
Records::const_iterator it = m_Records.begin(),
itend = m_Records.end();
for( ; it != itend; ++it)
{
const BattleRecord::Node* pRecord = &it->second;
Opr(pRecord);
}
}
#endif //__GAMESERVER_BATTLE_RECORD_H__