extends RefCounted ## Local mirror for GET [code]/game/players/{id}/cooldown-snapshot[/code] (NEO-32). ## Uses [code]serverTimeUtc[/code] + receive tick to approximate server "now" between polls. const SLOT_COUNT: int = 8 var _slot_end_unix: PackedFloat64Array = PackedFloat64Array() var _server_unix_at_receive: float = 0.0 var _ticks_msec_at_receive: int = 0 func _init() -> void: _slot_end_unix.resize(SLOT_COUNT) for i in range(SLOT_COUNT): _slot_end_unix[i] = 0.0 func apply_snapshot(snapshot: Dictionary) -> void: for i in range(SLOT_COUNT): _slot_end_unix[i] = 0.0 var st: Variant = snapshot.get("serverTimeUtc", "") if st is String: var su: String = st as String if not su.is_empty(): _server_unix_at_receive = Time.get_unix_time_from_datetime_string(su) _ticks_msec_at_receive = Time.get_ticks_msec() var slots: Variant = snapshot.get("slots", []) if slots is Array: for item in slots as Array: if not item is Dictionary: continue var d: Dictionary = item var idx: int = int(d.get("slotIndex", -1)) if idx < 0 or idx >= SLOT_COUNT: continue var end_v: Variant = d.get("cooldownEndsAtUtc", null) if end_v is String and not (end_v as String).is_empty(): var end_s: String = end_v as String _slot_end_unix[idx] = Time.get_unix_time_from_datetime_string(end_s) func _effective_server_unix() -> float: return _server_unix_at_receive + (Time.get_ticks_msec() - _ticks_msec_at_receive) * 0.001 func remaining_for_slot(slot_index: int) -> float: if slot_index < 0 or slot_index >= _slot_end_unix.size(): return 0.0 var end_u: float = _slot_end_unix[slot_index] if end_u <= 0.0: return 0.0 return maxf(0.0, end_u - _effective_server_unix()) func is_slot_cooling(slot_index: int) -> bool: return remaining_for_slot(slot_index) > 0.0 func any_slot_cooling() -> bool: for i in range(_slot_end_unix.size()): if remaining_for_slot(i) > 0.0: return true return false func build_hud_line() -> String: var parts: PackedStringArray = PackedStringArray() for i in range(_slot_end_unix.size()): var rem: float = remaining_for_slot(i) if rem > 0.0: parts.append("slot %d: %.1fs" % [i, rem]) if parts.is_empty(): return "Cooldowns: (ready)" return "Cooldowns: " + ", ".join(parts)