feat: score resource discovery by comfort and safety
This commit is contained in:
@@ -30,16 +30,16 @@ func _resolve_resource(
|
||||
active_world_adapter: Node
|
||||
) -> Dictionary:
|
||||
var best: Dictionary = {}
|
||||
var best_distance := INF
|
||||
var best_score := INF
|
||||
for candidate in active_world_adapter.get_resource_candidates(definition.resource_action_id):
|
||||
var node_id := StringName(candidate["target_id"])
|
||||
var state: ResourceStateRecord = simulation_manager.get_resource_state(node_id)
|
||||
if state == null or not state.can_npc_use() or not state.is_available_for(npc.id):
|
||||
continue
|
||||
var position: Vector3 = candidate["position"]
|
||||
var distance := origin.distance_squared_to(position)
|
||||
if distance < best_distance:
|
||||
best_distance = distance
|
||||
var score := score_resource_candidate(npc, origin, position, state)
|
||||
if score < best_score:
|
||||
best_score = score
|
||||
best = candidate
|
||||
if best.is_empty():
|
||||
return {}
|
||||
@@ -47,3 +47,17 @@ func _resolve_resource(
|
||||
if not simulation_manager.reserve_resource(target_id, npc.id):
|
||||
return {}
|
||||
return best
|
||||
|
||||
|
||||
func score_resource_candidate(
|
||||
npc: SimNPC, origin: Vector3, position: Vector3, state: ResourceStateRecord
|
||||
) -> float:
|
||||
var distance := origin.distance_to(position)
|
||||
var comfort_overage := maxf(distance - state.get_comfort_distance(), 0.0)
|
||||
var risk_weight := 20.0 + maxf(100.0 - npc.energy, 0.0) * 0.2
|
||||
return (
|
||||
distance
|
||||
+ comfort_overage * 2.5
|
||||
+ state.get_safety_risk() * risk_weight
|
||||
- state.get_discovery_priority()
|
||||
)
|
||||
|
||||
@@ -4,8 +4,9 @@ extends RefCounted
|
||||
signal changed(state: ResourceStateRecord)
|
||||
signal depleted(state: ResourceStateRecord)
|
||||
|
||||
const SCHEMA_VERSION := 2
|
||||
const SCHEMA_VERSION := 3
|
||||
const LEGACY_SCHEMA_VERSION := 1
|
||||
const DISCOVERY_LEGACY_SCHEMA_VERSION := 2
|
||||
|
||||
var data: Dictionary
|
||||
|
||||
@@ -26,7 +27,10 @@ static func create_from_node(node: ResourceNode) -> ResourceStateRecord:
|
||||
"reserved_by": -1,
|
||||
"enabled": node.initial_enabled,
|
||||
"can_npcs_use": node.can_npcs_use,
|
||||
"can_player_use": node.can_player_use
|
||||
"can_player_use": node.can_player_use,
|
||||
"safety_risk": node.safety_risk,
|
||||
"comfort_distance": node.comfort_distance,
|
||||
"discovery_priority": node.discovery_priority
|
||||
}
|
||||
)
|
||||
|
||||
@@ -35,6 +39,8 @@ static func from_dictionary(record_data: Dictionary) -> ResourceStateRecord:
|
||||
var version := int(record_data.get("schema_version", -1))
|
||||
if version == LEGACY_SCHEMA_VERSION:
|
||||
record_data = _migrate_v1(record_data)
|
||||
elif version == DISCOVERY_LEGACY_SCHEMA_VERSION:
|
||||
record_data = _migrate_v2(record_data)
|
||||
elif version != SCHEMA_VERSION:
|
||||
return null
|
||||
|
||||
@@ -48,7 +54,10 @@ static func from_dictionary(record_data: Dictionary) -> ResourceStateRecord:
|
||||
"reserved_by",
|
||||
"enabled",
|
||||
"can_npcs_use",
|
||||
"can_player_use"
|
||||
"can_player_use",
|
||||
"safety_risk",
|
||||
"comfort_distance",
|
||||
"discovery_priority"
|
||||
]
|
||||
):
|
||||
return null
|
||||
@@ -70,6 +79,15 @@ static func _migrate_v1(legacy_data: Dictionary) -> Dictionary:
|
||||
migrated["yield_per_action"] = 0.0
|
||||
migrated["can_npcs_use"] = false
|
||||
migrated["can_player_use"] = false
|
||||
return _migrate_v2(migrated)
|
||||
|
||||
|
||||
static func _migrate_v2(legacy_data: Dictionary) -> Dictionary:
|
||||
var migrated := legacy_data.duplicate(true)
|
||||
migrated["schema_version"] = SCHEMA_VERSION
|
||||
migrated["safety_risk"] = clampf(float(migrated.get("safety_risk", 0.0)), 0.0, 1.0)
|
||||
migrated["comfort_distance"] = maxf(float(migrated.get("comfort_distance", 18.0)), 0.1)
|
||||
migrated["discovery_priority"] = float(migrated.get("discovery_priority", 0.0))
|
||||
return migrated
|
||||
|
||||
|
||||
@@ -84,6 +102,9 @@ func apply_definition(node: ResourceNode) -> bool:
|
||||
data["yield_per_action"] = node.yield_per_action
|
||||
data["can_npcs_use"] = node.can_npcs_use
|
||||
data["can_player_use"] = node.can_player_use
|
||||
data["safety_risk"] = node.safety_risk
|
||||
data["comfort_distance"] = node.comfort_distance
|
||||
data["discovery_priority"] = node.discovery_priority
|
||||
data["schema_version"] = SCHEMA_VERSION
|
||||
return true
|
||||
|
||||
@@ -132,6 +153,18 @@ func can_player_use_resource() -> bool:
|
||||
return bool(data["can_player_use"])
|
||||
|
||||
|
||||
func get_safety_risk() -> float:
|
||||
return clampf(float(data["safety_risk"]), 0.0, 1.0)
|
||||
|
||||
|
||||
func get_comfort_distance() -> float:
|
||||
return maxf(float(data["comfort_distance"]), 0.1)
|
||||
|
||||
|
||||
func get_discovery_priority() -> float:
|
||||
return float(data["discovery_priority"])
|
||||
|
||||
|
||||
func is_depleted() -> bool:
|
||||
return get_amount_remaining() <= 0.0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user