70 lines
1.9 KiB
GDScript
70 lines
1.9 KiB
GDScript
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
|