79 lines
3.0 KiB
GDScript
79 lines
3.0 KiB
GDScript
class_name ActionDefinition
|
|
extends Resource
|
|
|
|
const ActionEffectScript := preload("res://simulation/commands/ActionEffect.gd")
|
|
|
|
@export var action_id: StringName
|
|
@export var display_name: String
|
|
@export_range(0.0, 1000.0, 0.1) var default_duration := 1.0
|
|
@export var preferred_profession_id: StringName
|
|
@export var target_type: StringName = SimulationIds.TARGET_ACTIVITY
|
|
@export var resource_action_id: StringName
|
|
@export var completion_cost_resource_id: StringName
|
|
@export_range(0.0, 1000.0, 0.1) var completion_cost_amount := 0.0
|
|
@export var actor_capability_tags: Array[StringName] = []
|
|
@export var target_capability_tags: Array[StringName] = []
|
|
@export var selection_policy_id: StringName
|
|
@export var target_policy_id: StringName
|
|
@export var completion_handler_id: StringName
|
|
@export var effects: Array[Resource] = []
|
|
@export var event_type_id: StringName
|
|
@export var presentation_cue_id: StringName
|
|
|
|
|
|
func validate() -> Array[String]:
|
|
var errors: Array[String] = []
|
|
if action_id.is_empty():
|
|
errors.append("action_id is empty")
|
|
if display_name.is_empty():
|
|
errors.append("display_name is empty for '%s'" % action_id)
|
|
if default_duration <= 0.0:
|
|
errors.append("default_duration must be positive for '%s'" % action_id)
|
|
if (
|
|
target_type
|
|
not in [
|
|
SimulationIds.TARGET_RESOURCE,
|
|
SimulationIds.TARGET_ACTIVITY,
|
|
SimulationIds.TARGET_ANIMAL,
|
|
SimulationIds.TARGET_FREE,
|
|
]
|
|
):
|
|
errors.append("target_type '%s' is invalid for '%s'" % [target_type, action_id])
|
|
if target_type == SimulationIds.TARGET_RESOURCE and resource_action_id.is_empty():
|
|
errors.append("resource_action_id is required for '%s'" % action_id)
|
|
if completion_cost_resource_id.is_empty() and completion_cost_amount > 0.0:
|
|
errors.append("completion cost resource is required for '%s'" % action_id)
|
|
if not completion_cost_resource_id.is_empty() and completion_cost_amount <= 0.0:
|
|
errors.append("completion cost amount must be positive for '%s'" % action_id)
|
|
_validate_unique_tags(actor_capability_tags, "actor capability", errors)
|
|
_validate_unique_tags(target_capability_tags, "target capability", errors)
|
|
var effect_ids := {}
|
|
for effect in effects:
|
|
if effect == null or effect.get_script() != ActionEffectScript:
|
|
errors.append("effects contains a null definition for '%s'" % action_id)
|
|
continue
|
|
for error in effect.call("validate"):
|
|
errors.append("ActionEffect: " + error)
|
|
var effect_id: StringName = effect.get("effect_id")
|
|
if effect_ids.has(effect_id):
|
|
errors.append("duplicate effect_id '%s' for '%s'" % [effect_id, action_id])
|
|
effect_ids[effect_id] = true
|
|
return errors
|
|
|
|
|
|
func has_completion_cost() -> bool:
|
|
return not completion_cost_resource_id.is_empty() and completion_cost_amount > 0.0
|
|
|
|
|
|
static func _validate_unique_tags(
|
|
tags: Array[StringName], label: String, errors: Array[String]
|
|
) -> void:
|
|
var seen := {}
|
|
for tag in tags:
|
|
if tag.is_empty():
|
|
errors.append("%s is empty" % label)
|
|
elif seen.has(tag):
|
|
errors.append("duplicate %s '%s'" % [label, tag])
|
|
else:
|
|
seen[tag] = true
|