feat: unify authored activity commands
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
class_name ContentCatalog
|
||||
extends RefCounted
|
||||
# gdlint: disable=max-file-lines
|
||||
|
||||
const CORE_PACK_PATH := "res://simulation/definitions/packs/core.tres"
|
||||
const DEFAULT_SITUATION_EVENT_PREDICATE_IDS: Array[StringName] = [
|
||||
@@ -11,6 +12,7 @@ const DEFAULT_SITUATION_STATE_PREDICATE_IDS: Array[StringName] = [
|
||||
const DEFAULT_SITUATION_EXPIRY_PREDICATE_IDS: Array[StringName] = [
|
||||
&"state_number_gt", &"age_reached"
|
||||
]
|
||||
const BUILTIN_HANDLER_IDS: Array[StringName] = [SimulationIds.ACTION_HANDLER_ACTIVITY_METRIC_DELTA]
|
||||
|
||||
var _valid := false
|
||||
var _errors: Array[String] = []
|
||||
@@ -81,11 +83,14 @@ func rebuild(
|
||||
var pack_list := content_packs.duplicate()
|
||||
pack_list.sort_custom(_sort_packs)
|
||||
var supported_handlers := {}
|
||||
for handler_id in BUILTIN_HANDLER_IDS:
|
||||
supported_handlers[handler_id] = true
|
||||
for handler_id in supported_handler_ids:
|
||||
if handler_id.is_empty():
|
||||
errors.append("Supported handler ID is empty")
|
||||
elif supported_handlers.has(handler_id):
|
||||
errors.append("Duplicate supported handler '%s'" % handler_id)
|
||||
if handler_id not in BUILTIN_HANDLER_IDS:
|
||||
errors.append("Duplicate supported handler '%s'" % handler_id)
|
||||
else:
|
||||
supported_handlers[handler_id] = true
|
||||
var cue_ids := (
|
||||
@@ -202,7 +207,9 @@ func rebuild(
|
||||
actions_by_id,
|
||||
professions_by_id,
|
||||
items_by_id,
|
||||
storages_by_id,
|
||||
capability_tags_by_id,
|
||||
event_types_by_id,
|
||||
supported_handlers,
|
||||
supported_cues,
|
||||
errors
|
||||
@@ -670,7 +677,9 @@ static func _validate_action_references(
|
||||
actions_by_id: Dictionary,
|
||||
professions_by_id: Dictionary,
|
||||
items_by_id: Dictionary,
|
||||
storages_by_id: Dictionary,
|
||||
capability_tags_by_id: Dictionary,
|
||||
event_types_by_id: Dictionary,
|
||||
supported_handlers: Dictionary,
|
||||
supported_cues: Dictionary,
|
||||
errors: Array[String]
|
||||
@@ -696,6 +705,16 @@ static func _validate_action_references(
|
||||
supported_cues,
|
||||
errors
|
||||
)
|
||||
if (
|
||||
not definition.event_type_id.is_empty()
|
||||
and not event_types_by_id.has(definition.event_type_id)
|
||||
):
|
||||
errors.append(
|
||||
(
|
||||
"Action '%s' references unknown event type '%s'"
|
||||
% [definition.action_id, definition.event_type_id]
|
||||
)
|
||||
)
|
||||
for handler_field in [
|
||||
["selection policy", definition.selection_policy_id],
|
||||
["target policy", definition.target_policy_id],
|
||||
@@ -769,6 +788,64 @@ static func _validate_action_references(
|
||||
% [definition.action_id, scheduled_action_id]
|
||||
)
|
||||
)
|
||||
_validate_builtin_action_handler_contract(definition, items_by_id, storages_by_id, errors)
|
||||
|
||||
|
||||
static func _validate_builtin_action_handler_contract(
|
||||
definition: ActionDefinition,
|
||||
items_by_id: Dictionary,
|
||||
storages_by_id: Dictionary,
|
||||
errors: Array[String]
|
||||
) -> void:
|
||||
if definition.completion_handler_id != SimulationIds.ACTION_HANDLER_ACTIVITY_METRIC_DELTA:
|
||||
return
|
||||
var label := "Action '%s' activity_metric_delta" % definition.action_id
|
||||
if definition.target_type != SimulationIds.TARGET_ACTIVITY:
|
||||
errors.append("%s handler requires an activity target" % label)
|
||||
if definition.effects.size() != 1:
|
||||
errors.append("%s handler requires exactly one effect" % label)
|
||||
return
|
||||
var effect := definition.effects[0] as ActionEffect
|
||||
if effect == null or effect.effect_kind != ActionEffect.KIND_METRIC_DELTA:
|
||||
errors.append("%s handler requires one metric_delta effect" % label)
|
||||
return
|
||||
if effect.subject_key not in [&"safety", &"knowledge"]:
|
||||
errors.append("%s metric must be safety or knowledge" % label)
|
||||
if not is_finite(effect.value) or effect.value <= 0.0:
|
||||
errors.append("%s effect value must be finite and positive" % label)
|
||||
var allowed_parameters := {"player_multiplier": true, "npc_productivity": true}
|
||||
for raw_key in effect.parameters:
|
||||
var key := String(raw_key)
|
||||
if not allowed_parameters.has(key):
|
||||
errors.append("%s has unsupported effect parameter '%s'" % [label, key])
|
||||
var player_multiplier: Variant = effect.parameters.get("player_multiplier", 1.0)
|
||||
if player_multiplier is not int and player_multiplier is not float:
|
||||
errors.append("%s player_multiplier must be numeric" % label)
|
||||
elif not is_finite(float(player_multiplier)) or float(player_multiplier) <= 0.0:
|
||||
errors.append("%s player_multiplier must be finite and positive" % label)
|
||||
var npc_productivity: Variant = effect.parameters.get("npc_productivity", false)
|
||||
if npc_productivity is not bool:
|
||||
errors.append("%s npc_productivity must be a bool" % label)
|
||||
if definition.event_type_id.is_empty():
|
||||
errors.append("%s handler requires a nonempty event_type_id" % label)
|
||||
if not definition.has_completion_cost():
|
||||
return
|
||||
var cost_item := items_by_id.get(definition.completion_cost_resource_id) as ItemDefinition
|
||||
if cost_item == null:
|
||||
return
|
||||
var has_storage_route := false
|
||||
for storage_value in storages_by_id.values():
|
||||
var storage := storage_value as StorageDefinition
|
||||
if storage != null and storage.accepts_item(cost_item):
|
||||
has_storage_route = true
|
||||
break
|
||||
if not has_storage_route:
|
||||
errors.append(
|
||||
(
|
||||
"%s completion cost item '%s' has no authored storage route"
|
||||
% [label, definition.completion_cost_resource_id]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
static func _validate_item_references(
|
||||
|
||||
Reference in New Issue
Block a user