51 lines
1.3 KiB
GDScript
51 lines
1.3 KiB
GDScript
## DpsTracker — DPS 环形缓冲区(Autoload: DpsTracker)
|
||
## 权威来源:implementation_plan.md §2.5.E(P6-N38、P6-N47)
|
||
extends Node
|
||
|
||
const DPS_WINDOW_SEC: float = 3.0
|
||
const _RB_SIZE: int = 256
|
||
|
||
var _rb_time: PackedFloat64Array = PackedFloat64Array()
|
||
var _rb_dmg: PackedFloat32Array = PackedFloat32Array()
|
||
var _rb_head: int = 0
|
||
var _rb_count: int = 0
|
||
var _accumulated_dmg: float = 0.0
|
||
|
||
func _ready() -> void:
|
||
_rb_time.resize(_RB_SIZE)
|
||
_rb_dmg.resize(_RB_SIZE)
|
||
|
||
func record_damage(amount: float) -> void:
|
||
if amount <= 0.0:
|
||
return
|
||
var now: float = Time.get_ticks_msec() / 1000.0
|
||
_rb_time[_rb_head] = now
|
||
_rb_dmg[_rb_head] = amount
|
||
_rb_head = (_rb_head + 1) % _RB_SIZE
|
||
if _rb_count < _RB_SIZE:
|
||
_rb_count += 1
|
||
_accumulated_dmg += amount
|
||
|
||
func get_dps() -> float:
|
||
_recalc_window(Time.get_ticks_msec() / 1000.0)
|
||
return _accumulated_dmg / DPS_WINDOW_SEC
|
||
|
||
func _recalc_window(now: float) -> void:
|
||
var sum: float = 0.0
|
||
var valid: int = 0
|
||
var tail: int = (_rb_head - _rb_count + _RB_SIZE) % _RB_SIZE
|
||
for k in _rb_count:
|
||
var idx: int = (tail + k) % _RB_SIZE
|
||
if (now - _rb_time[idx]) <= DPS_WINDOW_SEC:
|
||
sum += _rb_dmg[idx]
|
||
valid += 1
|
||
_accumulated_dmg = sum
|
||
_rb_count = valid
|
||
|
||
func reset() -> void:
|
||
_rb_head = 0
|
||
_rb_count = 0
|
||
_accumulated_dmg = 0.0
|
||
_rb_time.fill(0.0)
|
||
_rb_dmg.fill(0.0)
|