Files
2022-10-26 12:25:11 +08:00

180 lines
4.9 KiB
C++

#pragma once
#ifndef GAMESERVER_NPC_HEARTBEAT_H
#define GAMESERVER_NPC_HEARTBEAT_H
namespace nsAI {
;
class NpcHeartbeat;
//==================================================================================================
//
// NOTE: this object support a milestone continual progressing timer for npc
// attributes = { automatic reset, enable instantly time expiration, automatic start }
// WARNING: this object can't support always running system,
// but the usage of short time interval enable to support similar system.
class HeartbeatTimer
{
public:
static const ulong kHeartbeatInterval = 128; // ms
HeartbeatTimer();
void Clear();
bool SetTimer(ulong interval);
bool IsExpired() const;
private:
ulong expiration_tick_;
ulong interval_;
//
friend class nsAI::NpcHeartbeat;
__DISABLE_COPY(HeartbeatTimer);
};
//==================================================================================================
// NOTE: this class support the generic npc ai timer such as Wander, and etc...
class HeartbeatStaticTimer
{
public:
static const ulong kHeartbeatInterval = nsAI::HeartbeatTimer::kHeartbeatInterval;
enum eStaticTimer {
eStaticTimer_None = 0,
eStaticTimer_MinSyncInterval,
eStaticTimer_Idle,
eStaticTimer_Search,
eStaticTimer_Track,
eStaticTimer_ReturnCheck,
eStaticTimer_Thrust,
eStaticTimer_Retreat,
eStaticTimer_FallApart,
eStaticTimer_Blind,
//
eStaticTimer_Counts
};
//
HeartbeatStaticTimer();
void Clear();
bool SetTimer(eStaticTimer timer_type, ulong custom_interval);
bool IsExpired() const;
private:
uint8_t timer_type_;
uint8_t __padding0;
uint16_t interval_multiplier_; // base_interval * [interval_multiplier_]
mutable uint32_t latest_checked_index_;
//
friend class nsAI::NpcHeartbeat;
__DISABLE_COPY(HeartbeatStaticTimer);
};
//==================================================================================================
//
class NpcHeartbeat
{
public:
static const uint64_t kHeartbeatInterval = HeartbeatTimer::kHeartbeatInterval;
static bool OnAiScriptLoaded();
// CHANGES: f110316.3L, changes fixed interval to statistics
static bool Update(const util::ServerTimeInfoPerFrame* time_info_per_frame);
private:
struct StaticTimerData {
uint8_t timer_type;
uint32_t current_index;
ulong interval;
uint64_t expiration_aged_ticks;
};
NpcHeartbeat();
~NpcHeartbeat();
static NpcHeartbeat* Instance();
static NpcHeartbeat* CreateInstance();
bool ConfigureStaticTimer(nsAI::HeartbeatStaticTimer* const timer,
HeartbeatStaticTimer::eStaticTimer timer_type, ulong custom_interval);
bool IsExpiredStaticTimer(const nsAI::HeartbeatStaticTimer* const timer) const;
//
uint64_t current_aged_ticks_;
uint64_t timeout_aged_ticks_;
bool ai_script_loaded_;
StaticTimerData static_timer_data_[HeartbeatStaticTimer::eStaticTimer_Counts];
//
static NpcHeartbeat* instance_static_;
//
friend class nsAI::HeartbeatTimer;
friend class nsAI::HeartbeatStaticTimer;
__DISABLE_COPY(NpcHeartbeat);
};
//==================================================================================================
// solid probability
// 25.00%
struct Npc25PercentageRegulator {
public:
Npc25PercentageRegulator() : increase_counter_(0) {}
bool Hit();
private:
ulong increase_counter_;
};
// 50.00%
struct Npc50PercentageRegulator {
public:
Npc50PercentageRegulator() : increase_counter_(0) {}
bool Hit();
private:
ulong increase_counter_;
};
// 75.00%
struct Npc75PercentageRegulator {
public:
Npc75PercentageRegulator() : increase_counter_(0) {}
bool Hit();
private:
ulong increase_counter_;
};
}; //end of namespace
//==================================================================================================
// implements
inline nsAI::HeartbeatTimer::HeartbeatTimer()
: expiration_tick_(ULONG_MAX)
, interval_(0)
{
}
inline void nsAI::HeartbeatTimer::Clear() {
expiration_tick_ = ULONG_MAX;
interval_ = 0;
};
inline nsAI::HeartbeatStaticTimer::HeartbeatStaticTimer()
: timer_type_(eStaticTimer_None)
, latest_checked_index_(0)
{
}
inline void nsAI::HeartbeatStaticTimer::Clear() {
timer_type_ = eStaticTimer_None;
latest_checked_index_ = 0;
};
inline nsAI::NpcHeartbeat* nsAI::NpcHeartbeat::Instance()
{
if (instance_static_ != NULL) {
return instance_static_;
}
return CreateInstance();
};
inline bool nsAI::Npc25PercentageRegulator::Hit() {
ulong counter = ++increase_counter_;
return ((counter & 0x3) == 0x0);
};
inline bool nsAI::Npc50PercentageRegulator::Hit() {
ulong counter = ++increase_counter_;
return ((counter & 0x1) != 0x0);
};
inline bool nsAI::Npc75PercentageRegulator::Hit() {
ulong counter = ++increase_counter_;
return ((counter & 0x3) != 0x0);
};
#endif //GAMESERVER_NPC_HEARTBEAT_H