feat: add witnessed knowledge and wind ambience

This commit is contained in:
Rijad Zuzo
2026-07-11 11:27:40 +02:00
parent 2ed93de6d1
commit 81409650df
72 changed files with 3001 additions and 606 deletions
@@ -0,0 +1,173 @@
extends RefCounted
const AID_HUNGER_THRESHOLD := 80.0
const TRUSTED_HELP_THRESHOLD := 0.6
const FOOD_AID_TRUST_GAIN := 0.15
const SHARED_WORK_FAMILIARITY_GAIN := 0.1
var relationships: Dictionary = {}
func initialize_households(npcs: Array[SimNPC]) -> void:
relationships.clear()
for first_index in range(npcs.size()):
for second_index in range(first_index + 1, npcs.size()):
var first := npcs[first_index]
var second := npcs[second_index]
if first.home_position.distance_to(second.home_position) >= 4.0:
continue
_add(RelationshipStateRecord.create(first.id, second.id, 0.5))
_add(RelationshipStateRecord.create(second.id, first.id, 0.5))
func restore(records: Array[RelationshipStateRecord]) -> void:
relationships.clear()
for record in records:
_add(record)
func get_all_sorted() -> Array[RelationshipStateRecord]:
var records: Array[RelationshipStateRecord] = []
for record in relationships.values():
records.append(record)
records.sort_custom(_sort_relationships)
return records
func get_relationship(observer_id: int, subject_id: int) -> RelationshipStateRecord:
return relationships.get(_key(observer_id, subject_id)) as RelationshipStateRecord
func increase_shared_work_familiarity(first_id: int, second_id: int) -> void:
var first_to_second := _get_or_create(first_id, second_id)
var second_to_first := _get_or_create(second_id, first_id)
first_to_second.increase_familiarity(SHARED_WORK_FAMILIARITY_GAIN)
second_to_first.increase_familiarity(SHARED_WORK_FAMILIARITY_GAIN)
func apply_event(
event: EconomicEventRecord, npcs: Array[SimNPC], knower_ids: Array[int]
) -> Array[RelationshipStateRecord]:
var changed: Array[RelationshipStateRecord] = []
if StringName(event.data["event_type"]) != SimulationIds.EVENT_STORAGE_DEPOSITED:
return changed
if StringName(event.data["item_id"]) != SimulationIds.RESOURCE_FOOD:
return changed
var contributor_id := int(event.data["actor_id"])
var event_id := int(event.data["event_id"])
if contributor_id < 0 or event_id < 0 or float(event.data["amount"]) <= 0.0:
return changed
for observer in npcs:
if observer.id == contributor_id or observer.is_dead:
continue
if observer.id not in knower_ids:
continue
if observer.hunger < AID_HUNGER_THRESHOLD:
continue
var relationship := get_relationship(observer.id, contributor_id)
if relationship == null or relationship.get_familiarity() <= 0.0:
continue
if event_id <= relationship.get_last_trust_cause_event_id():
continue
var applied := relationship.increase_trust(FOOD_AID_TRUST_GAIN, event_id)
if applied <= 0.0:
continue
changed.append(relationship)
return changed
func get_primary_relationship(observer_id: int) -> RelationshipStateRecord:
var best: RelationshipStateRecord
for relationship in relationships.values():
if relationship.get_observer_id() != observer_id:
continue
if best == null or _is_stronger(relationship, best):
best = relationship
return best
func get_most_familiar_living_subject(observer_id: int, npcs: Array[SimNPC]) -> SimNPC:
var living_by_id := {}
for npc in npcs:
if not npc.is_dead:
living_by_id[npc.id] = npc
var best_relationship: RelationshipStateRecord
for relationship in relationships.values():
if relationship.get_observer_id() != observer_id:
continue
if not living_by_id.has(relationship.get_subject_id()):
continue
if (
best_relationship == null
or relationship.get_familiarity() > best_relationship.get_familiarity()
or (
is_equal_approx(relationship.get_familiarity(), best_relationship.get_familiarity())
and relationship.get_subject_id() < best_relationship.get_subject_id()
)
):
best_relationship = relationship
if best_relationship == null:
return null
return living_by_id[best_relationship.get_subject_id()] as SimNPC
func get_trusted_starving_subject(observer_id: int, npcs: Array[SimNPC]) -> SimNPC:
var starving_by_id := {}
for npc in npcs:
if not npc.is_dead and npc.is_starving:
starving_by_id[npc.id] = npc
var best_relationship: RelationshipStateRecord
for relationship in relationships.values():
if relationship.get_observer_id() != observer_id:
continue
if relationship.get_trust() < TRUSTED_HELP_THRESHOLD:
continue
if not starving_by_id.has(relationship.get_subject_id()):
continue
if (
best_relationship == null
or relationship.get_trust() > best_relationship.get_trust()
or (
is_equal_approx(relationship.get_trust(), best_relationship.get_trust())
and relationship.get_subject_id() < best_relationship.get_subject_id()
)
):
best_relationship = relationship
if best_relationship == null:
return null
return starving_by_id[best_relationship.get_subject_id()] as SimNPC
func _get_or_create(observer_id: int, subject_id: int) -> RelationshipStateRecord:
var relationship := get_relationship(observer_id, subject_id)
if relationship != null:
return relationship
relationship = RelationshipStateRecord.create(observer_id, subject_id, 0.0)
_add(relationship)
return relationship
func _add(relationship: RelationshipStateRecord) -> void:
relationships[_key(relationship.get_observer_id(), relationship.get_subject_id())] = relationship
static func _key(observer_id: int, subject_id: int) -> String:
return "%d:%d" % [observer_id, subject_id]
static func _sort_relationships(
first: RelationshipStateRecord, second: RelationshipStateRecord
) -> bool:
if first.get_observer_id() != second.get_observer_id():
return first.get_observer_id() < second.get_observer_id()
return first.get_subject_id() < second.get_subject_id()
static func _is_stronger(
candidate: RelationshipStateRecord, current: RelationshipStateRecord
) -> bool:
if not is_equal_approx(candidate.get_trust(), current.get_trust()):
return candidate.get_trust() > current.get_trust()
if not is_equal_approx(candidate.get_familiarity(), current.get_familiarity()):
return candidate.get_familiarity() > current.get_familiarity()
return candidate.get_subject_id() < current.get_subject_id()
@@ -0,0 +1 @@
uid://d4hehra0mfvdf