feat: add witnessed knowledge and wind ambience
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
class_name EventKnowledgeSystem
|
||||
extends RefCounted
|
||||
|
||||
const WITNESS_RADIUS := 10.0
|
||||
|
||||
var known_events: Dictionary = {}
|
||||
|
||||
|
||||
func observe_event(event: EconomicEventRecord, npcs: Array[SimNPC]) -> Array[KnownEventStateRecord]:
|
||||
var learned: Array[KnownEventStateRecord] = []
|
||||
if not _is_witnessable(event):
|
||||
return learned
|
||||
var actor := _find_npc(int(event.data["actor_id"]), npcs)
|
||||
if actor == null:
|
||||
return learned
|
||||
var actor_record := _remember(actor.id, int(event.data["event_id"]))
|
||||
if actor_record != null:
|
||||
learned.append(actor_record)
|
||||
var witness_radius_squared := WITNESS_RADIUS * WITNESS_RADIUS
|
||||
var event_position := event.get_world_position()
|
||||
for npc in npcs:
|
||||
if npc.id == actor.id or npc.is_dead:
|
||||
continue
|
||||
if npc.position.distance_squared_to(event_position) > witness_radius_squared:
|
||||
continue
|
||||
var witness_record := _remember(npc.id, int(event.data["event_id"]))
|
||||
if witness_record != null:
|
||||
learned.append(witness_record)
|
||||
learned.sort_custom(_sort_records)
|
||||
return learned
|
||||
|
||||
|
||||
func knows_event(knower_id: int, event_id: int) -> bool:
|
||||
return known_events.has(_key(knower_id, event_id))
|
||||
|
||||
|
||||
func get_knowers(event_id: int) -> Array[int]:
|
||||
var knower_ids: Array[int] = []
|
||||
for record in known_events.values():
|
||||
if record.get_event_id() == event_id:
|
||||
knower_ids.append(record.get_knower_id())
|
||||
knower_ids.sort()
|
||||
return knower_ids
|
||||
|
||||
|
||||
func get_known_event_ids(knower_id: int, max_count: int = 3) -> Array[int]:
|
||||
var event_ids: Array[int] = []
|
||||
for record in known_events.values():
|
||||
if record.get_knower_id() == knower_id:
|
||||
event_ids.append(record.get_event_id())
|
||||
event_ids.sort()
|
||||
if max_count <= 0 or event_ids.size() <= max_count:
|
||||
return event_ids
|
||||
var recent_ids: Array[int] = []
|
||||
for index in range(event_ids.size() - max_count, event_ids.size()):
|
||||
recent_ids.append(event_ids[index])
|
||||
return recent_ids
|
||||
|
||||
|
||||
func get_all_sorted() -> Array[KnownEventStateRecord]:
|
||||
var records: Array[KnownEventStateRecord] = []
|
||||
for record in known_events.values():
|
||||
records.append(record)
|
||||
records.sort_custom(_sort_records)
|
||||
return records
|
||||
|
||||
|
||||
func restore(records: Array[KnownEventStateRecord]) -> void:
|
||||
known_events.clear()
|
||||
for record in records:
|
||||
known_events[_key(record.get_knower_id(), record.get_event_id())] = record
|
||||
|
||||
|
||||
func _remember(knower_id: int, event_id: int) -> KnownEventStateRecord:
|
||||
var key := _key(knower_id, event_id)
|
||||
if known_events.has(key):
|
||||
return null
|
||||
var record := KnownEventStateRecord.create(knower_id, event_id)
|
||||
known_events[key] = record
|
||||
return record
|
||||
|
||||
|
||||
func _is_witnessable(event: EconomicEventRecord) -> bool:
|
||||
return (
|
||||
StringName(event.data["event_type"]) == SimulationIds.EVENT_STORAGE_DEPOSITED
|
||||
and StringName(event.data["item_id"]) == SimulationIds.RESOURCE_FOOD
|
||||
and float(event.data["amount"]) > 0.0
|
||||
)
|
||||
|
||||
|
||||
static func _find_npc(npc_id: int, npcs: Array[SimNPC]) -> SimNPC:
|
||||
for npc in npcs:
|
||||
if npc.id == npc_id:
|
||||
return npc
|
||||
return null
|
||||
|
||||
|
||||
static func _key(knower_id: int, event_id: int) -> String:
|
||||
return "%d:%d" % [knower_id, event_id]
|
||||
|
||||
|
||||
static func _sort_records(first: KnownEventStateRecord, second: KnownEventStateRecord) -> bool:
|
||||
if first.get_knower_id() != second.get_knower_id():
|
||||
return first.get_knower_id() < second.get_knower_id()
|
||||
return first.get_event_id() < second.get_event_id()
|
||||
Reference in New Issue
Block a user