feat: add witnessed knowledge and wind ambience
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user