use crate::block::{BV, Block};
use crate::ck3::tables::misc::AI_TARGETS;
use crate::context::ScopeContext;
use crate::desc::validate_desc;
use crate::everything::Everything;
use crate::item::Item;
use crate::report::{ErrorKey, err, fatal};
use crate::scopes::Scopes;
use crate::tooltipped::Tooltipped;
use crate::trigger::{validate_target, validate_target_ok_this};
use crate::validate::{validate_modifiers_with_base, validate_scope_chain};
use crate::validator::Validator;
pub fn validate_theme_background(bv: &BV, data: &Everything, sc: &mut ScopeContext) {
match bv {
BV::Value(token) => {
data.verify_exists(Item::EventBackground, token);
let block = Block::new(token.loc);
data.validate_call(Item::EventBackground, token, &block, sc);
}
BV::Block(block) => {
let mut vd = Validator::new(block, data);
vd.field_trigger("trigger", Tooltipped::No, sc);
if vd.field_value("event_background").is_some() {
let msg = "`event_background` now causes a crash. It has been replaced by `reference` since 1.9";
fatal(ErrorKey::Crash)
.msg(msg)
.loc(block.get_key("event_background").unwrap())
.push();
}
vd.req_field("reference");
if let Some(token) = vd.field_value("reference") {
data.verify_exists(Item::EventBackground, token);
data.validate_call(Item::EventBackground, token, block, sc);
}
}
}
}
pub fn validate_theme_header_background(bv: &BV, data: &Everything, sc: &mut ScopeContext) {
match bv {
BV::Value(token) => data.verify_exists(Item::File, token),
BV::Block(block) => {
let mut vd = Validator::new(block, data);
vd.field_trigger("trigger", Tooltipped::No, sc);
vd.req_field("reference");
if let Some(token) = vd.field_value("reference") {
data.verify_exists(Item::File, token);
}
}
}
}
pub fn validate_theme_icon(bv: &BV, data: &Everything, sc: &mut ScopeContext) {
validate_theme_header_background(bv, data, sc);
}
pub fn validate_theme_sound(block: &Block, data: &Everything, sc: &mut ScopeContext) {
let mut vd = Validator::new(block, data);
vd.field_trigger("trigger", Tooltipped::No, sc);
vd.field_item("reference", Item::Sound);
}
pub fn validate_theme_transition(block: &Block, data: &Everything, sc: &mut ScopeContext) {
let mut vd = Validator::new(block, data);
vd.field_trigger("trigger", Tooltipped::No, sc);
if let Some(token) = vd.field_value("reference") {
data.verify_exists(Item::EventTransition, token);
data.validate_call(Item::EventTransition, token, block, sc);
}
}
pub fn validate_theme_effect_2d(bv: &BV, data: &Everything, sc: &mut ScopeContext) {
match bv {
BV::Value(token) => data.verify_exists(Item::EventEffect2d, token),
BV::Block(block) => {
let mut vd = Validator::new(block, data);
vd.field_trigger("trigger", Tooltipped::No, sc);
if let Some(token) = vd.field_value("reference") {
data.verify_exists(Item::EventEffect2d, token);
}
}
}
}
pub fn validate_cost(block: &Block, data: &Everything, sc: &mut ScopeContext) {
let mut vd = Validator::new(block, data);
vd.field_script_value("barter_goods", sc);
vd.field_script_value("gold", sc);
vd.field_script_value("herd", sc);
vd.field_script_value("influence", sc);
vd.field_script_value("prestige", sc);
vd.field_script_value("piety", sc);
vd.field_script_value("renown", sc);
vd.field_script_value("treasury", sc);
vd.field_script_value("treasury_or_gold", sc);
vd.field_bool("round");
}
pub fn validate_traits(block: &Block, data: &Everything) {
let mut vd = Validator::new(block, data);
vd.field_validated_block("virtues", validate_virtues_sins);
vd.field_validated_block("sins", validate_virtues_sins);
}
pub fn validate_virtues_sins(block: &Block, data: &Everything) {
let mut vd = Validator::new(block, data);
for token in vd.values() {
data.verify_exists(Item::Trait, token);
}
vd.unknown_value_fields(|key, value| {
data.verify_exists(Item::Trait, key);
value.expect_number();
});
vd.unknown_block_fields(|key, block| {
data.verify_exists(Item::Trait, key);
let mut vd = Validator::new(block, data);
vd.field_numeric("scale");
vd.field_numeric("weight");
});
}
pub fn validate_compare_modifier(block: &Block, data: &Everything, sc: &mut ScopeContext) {
let mut vd = Validator::new(block, data);
sc.open_builder();
let mut valid_target = false;
vd.field_validated_value("target", |_, mut vd| {
valid_target = validate_scope_chain(vd.value(), data, sc, false);
vd.accept();
});
sc.finalize_builder();
if valid_target {
vd.field_script_value("value", sc);
vd.field_script_value("factor", sc);
} else {
vd.field("value");
vd.field("factor");
}
sc.close();
vd.multi_field_script_value("multiplier", sc);
vd.field_script_value("min", sc);
vd.field_script_value("max", sc);
vd.field_script_value("step", sc); vd.field_script_value("offset", sc); vd.field_validated_sc("desc", sc, validate_desc);
vd.field_trigger("trigger", Tooltipped::No, sc);
}
pub fn validate_opinion_modifier(block: &Block, data: &Everything, sc: &mut ScopeContext) {
let mut vd = Validator::new(block, data);
if let Some(target) = vd.field_value("who") {
validate_target_ok_this(target, data, sc, Scopes::Character);
}
vd.req_field("opinion_target");
if let Some(target) = vd.field_value("opinion_target") {
validate_target_ok_this(target, data, sc, Scopes::Character);
}
vd.field_script_value("multiplier", sc);
vd.field_validated_sc("desc", sc, validate_desc);
vd.field_script_value("min", sc);
vd.field_script_value("max", sc);
vd.field_script_value("step", sc); vd.field_trigger("trigger", Tooltipped::No, sc);
}
pub fn validate_ai_value_modifier(block: &Block, data: &Everything, sc: &mut ScopeContext) {
let mut vd = Validator::new(block, data);
if let Some(target) = vd.field_value("who") {
validate_target_ok_this(target, data, sc, Scopes::Character);
}
vd.field_validated_block("dread_modified_ai_boldness", |block, data| {
let mut vd = Validator::new(block, data);
vd.req_field("dreaded_character");
vd.req_field("value");
vd.field_target_ok_this("dreaded_character", sc, Scopes::Character);
vd.field_script_value("value", sc);
});
vd.field_script_value("ai_boldness", sc);
vd.field_script_value("ai_compassion", sc);
vd.field_script_value("ai_energy", sc);
vd.field_script_value("ai_greed", sc);
vd.field_script_value("ai_honor", sc);
vd.field_script_value("ai_rationality", sc);
vd.field_script_value("ai_sociability", sc);
vd.field_script_value("ai_vengefulness", sc);
vd.field_script_value("ai_zeal", sc);
vd.field_script_value("min", sc);
vd.field_script_value("max", sc);
vd.field_trigger("trigger", Tooltipped::No, sc);
}
pub fn validate_compatibility_modifier(block: &Block, data: &Everything, sc: &mut ScopeContext) {
let mut vd = Validator::new(block, data);
if let Some(target) = vd.field_value("who") {
validate_target_ok_this(target, data, sc, Scopes::Character);
}
if let Some(target) = vd.field_value("compatibility_target") {
validate_target_ok_this(target, data, sc, Scopes::Character);
}
vd.field_script_value("multiplier", sc);
vd.field_script_value("min", sc);
vd.field_script_value("max", sc);
vd.field_trigger("trigger", Tooltipped::No, sc);
}
pub fn validate_activity_modifier(block: &Block, data: &Everything, sc: &mut ScopeContext) {
let mut vd = Validator::new(block, data);
vd.field_target("object", sc, Scopes::Activity);
vd.field_target("target", sc, Scopes::Character);
}
pub fn validate_scheme_modifier(block: &Block, data: &Everything, sc: &mut ScopeContext) {
let mut vd = Validator::new(block, data);
vd.field_target("object", sc, Scopes::Scheme);
vd.field_target("target", sc, Scopes::Character);
}
pub fn validate_random_traits_list(block: &Block, data: &Everything, sc: &mut ScopeContext) {
let mut vd = Validator::new(block, data);
vd.field_script_value("count", sc);
vd.unknown_block_fields(|key, block| {
data.verify_exists(Item::Trait, key);
let mut vd = Validator::new(block, data);
vd.field_validated_block_sc("weight", sc, validate_modifiers_with_base);
vd.field_trigger("trigger", Tooltipped::No, sc);
});
}
pub fn validate_random_culture(block: &Block, data: &Everything, sc: &mut ScopeContext) {
let mut vd = Validator::new(block, data);
vd.unknown_block_fields(|key, block| {
validate_target(key, data, sc, Scopes::Culture);
let mut vd = Validator::new(block, data);
vd.field_validated_block_sc("weight", sc, validate_modifiers_with_base);
vd.field_trigger("trigger", Tooltipped::No, sc);
});
}
pub fn validate_random_faith(block: &Block, data: &Everything, sc: &mut ScopeContext) {
let mut vd = Validator::new(block, data);
vd.unknown_block_fields(|key, block| {
validate_target(key, data, sc, Scopes::Faith);
let mut vd = Validator::new(block, data);
vd.field_validated_block_sc("weight", sc, validate_modifiers_with_base);
vd.field_trigger("trigger", Tooltipped::No, sc);
});
}
pub fn validate_maa_stats(vd: &mut Validator) {
vd.field_numeric("pursuit");
vd.field_numeric("screen");
vd.field_numeric("damage");
vd.field_numeric("toughness");
vd.field_numeric("siege_value");
}
pub fn validate_portrait_modifier_overrides(block: &Block, data: &Everything) {
let mut vd = Validator::new(block, data);
vd.unknown_value_fields(|key, value| {
data.verify_exists(Item::PortraitModifierGroup, key);
if !data.item_has_property(Item::PortraitModifierGroup, key.as_str(), value.as_str()) {
let msg = format!("portrait modifier group {key} does not have the modifier {value}");
err(ErrorKey::MissingItem).msg(msg).loc(value).push();
}
});
}
pub fn validate_quick_trigger(block: &Block, data: &Everything) {
let mut vd = Validator::new(block, data);
vd.field_bool("adult");
vd.field_bool("attracted_to_owner");
vd.field_bool("owner_attracted");
vd.field_bool("prison");
}
pub fn validate_ai_targets(block: &Block, data: &Everything) {
let mut vd = Validator::new(block, data);
vd.req_field("ai_recipients");
vd.multi_field_choice("ai_recipients", AI_TARGETS);
vd.field_integer_range("max", 0..);
vd.field_numeric_range("chance", 0.0..=1.0);
let mut found = false;
for value in block.get_field_values("ai_recipients") {
if value.is("situation_participant_group") {
vd.field_item("parameter", Item::Situation);
found = true;
}
}
if !found {
vd.ban_field("parameter", || "`ai_recipients = situation_participant_group`");
}
}