class_name KeyedRandom extends RefCounted const MASK_32 := 0xFFFFFFFF const UINT32_RANGE := 4294967296.0 static func value_u32( world_seed: int, system_id: StringName, entity_id: StringName, occurrence: int ) -> int: var hash_value := int(world_seed) & MASK_32 hash_value = _mix_u32(hash_value ^ 0x9E3779B9) for byte in String(system_id).to_utf8_buffer(): hash_value = _mix_u32(hash_value ^ int(byte)) hash_value = _mix_u32(hash_value ^ 0x85EBCA6B) for byte in String(entity_id).to_utf8_buffer(): hash_value = _mix_u32(hash_value ^ int(byte)) hash_value = _mix_u32(hash_value ^ (occurrence & MASK_32)) return hash_value static func value_float( world_seed: int, system_id: StringName, entity_id: StringName, occurrence: int ) -> float: return float(value_u32(world_seed, system_id, entity_id, occurrence)) / UINT32_RANGE static func range_int( world_seed: int, system_id: StringName, entity_id: StringName, occurrence: int, minimum: int, maximum: int ) -> int: if maximum < minimum: return minimum var width := maximum - minimum + 1 return minimum + value_u32(world_seed, system_id, entity_id, occurrence) % width static func range_float( world_seed: int, system_id: StringName, entity_id: StringName, occurrence: int, minimum: float, maximum: float ) -> float: if maximum <= minimum: return minimum return lerpf(minimum, maximum, value_float(world_seed, system_id, entity_id, occurrence)) static func chance( world_seed: int, system_id: StringName, entity_id: StringName, occurrence: int, probability: float ) -> bool: return value_float(world_seed, system_id, entity_id, occurrence) < clampf(probability, 0.0, 1.0) static func _mix_u32(value: int) -> int: var mixed := value & MASK_32 mixed = ((mixed ^ (mixed >> 16)) * 0x7FEB352D) & MASK_32 mixed = ((mixed ^ (mixed >> 15)) * 0x846CA68B) & MASK_32 return (mixed ^ (mixed >> 16)) & MASK_32