﻿ddm_assess_dynasty_member_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    desc = ddm_assess_dynasty_member_interaction_desc
    icon = support_candidacy

    is_shown = {
        scope:recipient != scope:actor
        scope:actor = { exists = dynasty }
        scope:recipient = { dynasty = scope:actor.dynasty }
    }
    is_valid_showing_failures_only = { always = yes }
    on_accept = {
        scope:actor = {
            ddm_initialize_settings_effect = yes
            save_scope_as = ddm_actor
        }
        scope:recipient = {
            save_scope_as = ddm_subject
            ddm_refresh_one_subject_regard_effect = yes
        }
        scope:actor = { trigger_event = ddm_manager.0300 }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_protect_dynasty_member_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    desc = ddm_protect_dynasty_member_interaction_desc
    icon = alliance
    is_shown = {
        scope:recipient != scope:actor
        scope:actor = { exists = dynasty }
        scope:recipient = {
            dynasty = scope:actor.dynasty
            NOT = { has_character_flag = ddm_protected_from_automation }
        }
    }
    on_accept = { scope:recipient = { add_character_flag = ddm_protected_from_automation } }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_unprotect_dynasty_member_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    desc = ddm_unprotect_dynasty_member_interaction_desc
    icon = revoke_title
    is_shown = {
        scope:actor = { exists = dynasty }
        scope:recipient = {
            dynasty = scope:actor.dynasty
            has_character_flag = ddm_protected_from_automation
        }
    }
    on_accept = { scope:recipient = { remove_character_flag = ddm_protected_from_automation } }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_favor_for_land_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    desc = ddm_favor_for_land_interaction_desc
    icon = support_candidacy
    is_shown = {
        scope:recipient != scope:actor
        scope:actor = { exists = dynasty }
        scope:recipient = {
            dynasty = scope:actor.dynasty
            NOT = { has_character_flag = ddm_favored_for_land }
        }
    }
    on_accept = {
        scope:recipient = {
            add_character_flag = ddm_favored_for_land
            remove_character_flag = ddm_never_grant_land
        }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_never_grant_land_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    desc = ddm_never_grant_land_interaction_desc
    icon = revoke_title
    is_shown = {
        scope:recipient != scope:actor
        scope:actor = { exists = dynasty }
        scope:recipient = {
            dynasty = scope:actor.dynasty
            NOT = { has_character_flag = ddm_never_grant_land }
        }
    }
    on_accept = {
        scope:recipient = {
            add_character_flag = ddm_never_grant_land
            remove_character_flag = ddm_favored_for_land
        }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_clear_land_preference_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    desc = ddm_clear_land_preference_interaction_desc
    icon = icon_contract_modification_single
    is_shown = {
        scope:actor = { exists = dynasty }
        scope:recipient = {
            dynasty = scope:actor.dynasty
            OR = {
                has_character_flag = ddm_favored_for_land
                has_character_flag = ddm_never_grant_land
            }
        }
    }
    on_accept = {
        scope:recipient = {
            remove_character_flag = ddm_favored_for_land
            remove_character_flag = ddm_never_grant_land
        }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_protect_holding_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    target_type = title
    target_filter = actor_domain_titles
    desc = ddm_protect_holding_interaction_desc
    icon = icon_contract_modification_single

    is_shown = {
        scope:actor = { is_landed = yes }
        OR = {
            scope:recipient = scope:actor
            AND = { exists = scope:actor.player_heir scope:recipient = scope:actor.player_heir }
        }
    }
    can_be_picked_title = {
        scope:target = {
            holder = scope:actor
            OR = {
                tier = tier_county
                AND = { tier = tier_barony title_province = { is_county_capital = no } }
            }
            NOT = { has_variable = ddm_manual_core }
        }
    }
    on_accept = {
        scope:target = {
            set_variable = ddm_manual_core
            remove_variable = ddm_manual_shed
            remove_variable = ddm_manual_neutral
        }
        scope:actor = {
            set_variable = { name = ddm_domain_core_mode value = 1 }
            ddm_refresh_adaptive_domain_core_effect = yes
        }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_unprotect_holding_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    target_type = title
    target_filter = actor_domain_titles
    desc = ddm_unprotect_holding_interaction_desc
    icon = revoke_title

    is_shown = {
        scope:actor = { is_landed = yes }
        OR = {
            scope:recipient = scope:actor
            AND = { exists = scope:actor.player_heir scope:recipient = scope:actor.player_heir }
        }
    }
    can_be_picked_title = {
        scope:target = {
            holder = scope:actor
            has_variable = ddm_manual_core
        }
    }
    on_accept = {
        scope:target = {
            remove_variable = ddm_manual_core
            set_variable = ddm_manual_neutral
        }
        scope:actor = {
            set_variable = { name = ddm_domain_core_mode value = 1 }
            ddm_refresh_adaptive_domain_core_effect = yes
        }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}


ddm_prioritize_holding_for_distribution_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    target_type = title
    target_filter = actor_domain_titles
    desc = ddm_prioritize_holding_for_distribution_interaction_desc
    icon = support_candidacy

    is_shown = {
        scope:actor = { is_landed = yes }
        OR = {
            scope:recipient = scope:actor
            AND = { exists = scope:actor.player_heir scope:recipient = scope:actor.player_heir }
        }
    }
    can_be_picked_title = {
        scope:target = {
            holder = scope:actor
            OR = {
                tier = tier_county
                AND = { tier = tier_barony title_province = { is_county_capital = no } }
            }
            NOT = { this = scope:actor.capital_county }
            NOT = { has_variable = ddm_manual_shed }
        }
    }
    on_accept = {
        scope:target = {
            set_variable = ddm_manual_shed
            remove_variable = ddm_manual_core
            remove_variable = ddm_manual_neutral
        }
        scope:actor = { ddm_refresh_adaptive_domain_core_effect = yes }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_clear_holding_distribution_priority_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    target_type = title
    target_filter = actor_domain_titles
    desc = ddm_clear_holding_distribution_priority_interaction_desc
    icon = revoke_title

    is_shown = {
        scope:actor = { is_landed = yes }
        OR = {
            scope:recipient = scope:actor
            AND = { exists = scope:actor.player_heir scope:recipient = scope:actor.player_heir }
        }
    }
    can_be_picked_title = {
        scope:target = {
            holder = scope:actor
            has_variable = ddm_manual_shed
        }
    }
    on_accept = {
        scope:target = {
            remove_variable = ddm_manual_shed
            set_variable = ddm_manual_neutral
        }
        scope:actor = { ddm_refresh_adaptive_domain_core_effect = yes }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_reserve_title_for_recipient_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    target_type = title
    target_filter = actor_domain_titles
    desc = ddm_reserve_title_for_recipient_interaction_desc
    icon = support_candidacy

    is_shown = {
        scope:recipient != scope:actor
        scope:actor = { is_landed = yes }
        scope:recipient = {
            is_alive = yes
            NOT = { has_character_flag = ddm_never_grant_land }
            NOT = { has_character_flag = ddm_protected_from_automation }
            NOT = { has_trait = incapable }
            NOT = { has_trait = devoted }
            NOT = { has_trait = gallivanter }
            NOT = { is_at_war_with = scope:actor }
            can_be_granted_titles_by = { RULER = scope:actor }
            trigger_if = { limit = { is_ruler = no } is_imprisoned = no }
            OR = {
                AND = { exists = dynasty scope:actor = { exists = dynasty } dynasty = scope:actor.dynasty }
                AND = {
                    OR = { NOT = { exists = dynasty } scope:actor = { exists = dynasty } dynasty != scope:actor.dynasty }
                    OR = { is_courtier_of = scope:actor is_vassal_or_below_of = scope:actor }
                }
            }
            OR = { is_landed = no highest_held_title_tier < scope:actor.highest_held_title_tier }
        }
    }

    can_be_picked_title = {
        scope:target = {
            holder = scope:actor
            tier >= tier_county
            tier < scope:actor.highest_held_title_tier
            this != scope:actor.primary_title
            NOT = { this = scope:actor.capital_county }
            is_head_of_faith = no
            is_landless_type_title = no
            is_noble_family_title = no
            is_nomad_title = no
            trigger_if = {
                limit = { exists = scope:actor.faith exists = scope:actor.faith.religious_head_title }
                this != scope:actor.faith.religious_head_title
            }
            NOT = { exists = var:ddm_reserved_recipient var:ddm_reserved_recipient = scope:recipient }
        }
        scope:recipient = {
            can_be_granted_titles_by = { RULER = scope:actor }
            trigger_if = {
                limit = {
                    scope:actor.var:ddm_gender_alignment = 1
                    OR = {
                        scope:actor = { has_realm_law = male_only_law }
                        scope:actor.primary_title = { has_title_law = male_only_law }
                        scope:target = { has_title_law = male_only_law }
                    }
                }
                is_male = yes
            }
            trigger_if = {
                limit = {
                    scope:actor.var:ddm_gender_alignment = 1
                    OR = {
                        scope:actor = { has_realm_law = female_only_law }
                        scope:actor.primary_title = { has_title_law = female_only_law }
                        scope:target = { has_title_law = female_only_law }
                    }
                }
                is_female = yes
            }
        }
    }

    on_accept = {
        scope:target = { set_variable = { name = ddm_reserved_recipient value = scope:recipient } }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_clear_title_reservation_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    target_type = title
    target_filter = actor_domain_titles
    desc = ddm_clear_title_reservation_interaction_desc
    icon = revoke_title

    is_shown = {
        scope:recipient != scope:actor
        scope:actor = {
            any_held_title = { exists = var:ddm_reserved_recipient var:ddm_reserved_recipient = scope:recipient }
        }
    }
    can_be_picked_title = {
        scope:target = {
            holder = scope:actor
            exists = var:ddm_reserved_recipient
            var:ddm_reserved_recipient = scope:recipient
        }
    }
    on_accept = { scope:target = { remove_variable = ddm_reserved_recipient } }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}


# ---------------------------------------------------------------------------
# DYNASTIC KIDNAPPING
# ---------------------------------------------------------------------------
# Right-click access to the same hostile acquisition workflow used by Marriage Planner. The hard
# geographic boundary is CK3 diplomatic range so DDM remains standalone and does not depend on DoC.
ddm_kidnap_interaction = {
    # `prison` is a vanilla character-interaction icon key used by CK3 itself.
    icon = prison
    category = interaction_category_hostile
    common_interaction = yes
    use_diplomatic_range = yes
    interface_priority = 80
    desc = ddm_kidnap_interaction_desc

    # Keep the interaction visible on normal right-click menus for broadly plausible targets.
    # Temporary blockers are validation failures instead of silently removing the button.
    is_shown = {
        NOT = { has_game_rule = ddm_kidnap_disabled }
        scope:actor = { is_alive = yes }
        scope:recipient = { is_alive = yes is_landed = no }
        scope:actor != scope:recipient
    }

    is_valid_showing_failures_only = {
        scope:actor = {
            is_imprisoned = no
            custom_tooltip = {
                text = ddm_kidnap_operation_active_tt
                NOT = { has_character_flag = ddm_kidnap_operation_active }
            }
            custom_tooltip = {
                text = ddm_kidnap_yearly_quota_tt
                ddm_kidnap_quota_available_trigger = yes
            }
        }
        scope:recipient = {
            custom_tooltip = { text = ddm_kidnap_target_must_be_unlanded_tt is_landed = no }
            custom_tooltip = { text = ddm_kidnap_target_must_be_free_tt is_imprisoned = no }
            # Marriage/concubinage is no longer a blocker. Existing bonds are converted into
            # relationship heat during expedition preparation and sharply raise cost/risk.
            custom_tooltip = { text = ddm_kidnap_target_needs_liege_tt exists = liege }
            custom_tooltip = { text = ddm_kidnap_target_range_tt in_diplomatic_range = scope:actor }
            custom_tooltip = { text = ddm_kidnap_target_foreign_court_tt NOT = { is_in_the_same_court_as_or_guest = scope:actor } }
        }
    }

    on_accept = {
        scope:actor = { save_scope_as = ddm_kidnap_actor }
        scope:recipient = { save_scope_as = ddm_kidnap_target }
        scope:actor = {
            ddm_prepare_kidnap_context_effect = yes
            trigger_event = ddm_manager.4999
        }
    }

    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}


# ---------------------------------------------------------------------------
# HOUSEHOLD / HAREM OFFICE (2.0)
# ---------------------------------------------------------------------------
ddm_move_spouse_to_harem_interaction = {
    icon = lover
    category = interaction_category_friendly
    common_interaction = yes
    interface_priority = 74
    desc = ddm_move_spouse_to_harem_interaction_desc
    is_shown = {
        scope:actor = { is_alive = yes is_ai = no age >= 18 has_variable = ddm_household_mode var:ddm_household_mode = 1 }
        scope:recipient = { is_alive = yes age >= 18 }
        scope:actor != scope:recipient
        scope:actor = { any_spouse = { this = scope:recipient } }
    }
    is_valid_showing_failures_only = { scope:recipient = { custom_tooltip = { text = ddm_household_target_free_tt is_imprisoned = no } } }
    on_accept = {
        scope:recipient = { save_scope_as = ddm_household_seed_member }
        scope:actor = { ddm_register_household_member_effect = yes ddm_prepare_household_effect = yes }
        scope:actor = { send_interface_toast = { type = event_toast_effect_good title = DDM_HOUSEHOLD_SPOUSE_MOVED_TOAST left_icon = scope:actor right_icon = scope:recipient } }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_release_concubine_interaction = {
    icon = lover
    category = interaction_category_friendly
    common_interaction = yes
    interface_priority = 70
    desc = ddm_release_concubine_interaction_desc
    is_shown = {
        scope:actor = { is_alive = yes is_ai = no age >= 18 }
        scope:recipient = {
            is_alive = yes age >= 18
            has_variable = ddm_harem_patron var:ddm_harem_patron = scope:actor
            has_variable = ddm_harem_active var:ddm_harem_active = 1
        }
    }
    on_accept = {
        scope:recipient = { save_scope_as = ddm_household_release_target }
        scope:actor = { ddm_release_household_concubine_effect = yes }
        scope:actor = { send_interface_toast = { type = event_toast_effect_neutral title = DDM_HOUSEHOLD_CONCUBINE_RELEASED_TOAST left_icon = scope:actor right_icon = scope:recipient } }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_take_as_concubine_interaction = {
    icon = lover
    category = interaction_category_friendly
    common_interaction = yes
    interface_priority = 72
    desc = ddm_take_as_concubine_interaction_desc
    is_shown = {
        scope:actor = { is_alive = yes is_ai = no age >= 18 has_variable = ddm_household_mode var:ddm_household_mode = 1 }
        scope:recipient = { is_alive = yes age >= 18 }
        scope:actor != scope:recipient
        NOT = { scope:recipient = { has_variable = ddm_harem_patron var:ddm_harem_patron = scope:actor has_variable = ddm_harem_active var:ddm_harem_active = 1 } }
    }
    is_valid_showing_failures_only = {
        scope:actor = { is_imprisoned = no }
        scope:recipient = {
            custom_tooltip = { text = ddm_household_target_free_tt is_imprisoned = no }
            custom_tooltip = { text = ddm_household_target_same_court_tt is_in_the_same_court_as_or_guest = scope:actor }
        }
    }
    on_accept = {
        scope:recipient = { save_scope_as = ddm_household_seed_member }
        scope:actor = { ddm_register_household_member_effect = yes ddm_prepare_household_effect = yes }
        scope:actor = { send_interface_toast = { type = event_toast_effect_good title = DDM_HOUSEHOLD_CONCUBINE_TAKEN_TOAST left_icon = scope:actor right_icon = scope:recipient } }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}








# ---------------------------------------------------------------------------
# PROSCRIPTIONS — Realm Office political bounty writs
# ---------------------------------------------------------------------------

ddm_proscribe_character_interaction = {
    # Vanilla CK3 interaction icon; no custom/generated art.
    icon = arbitrary
    category = interaction_category_hostile
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 86
    desc = ddm_proscribe_character_interaction_desc

    is_shown = {
        scope:actor = { is_alive = yes is_ai = no is_landed = yes }
        scope:recipient = {
            is_alive = yes
            NOT = { has_character_flag = ddm_bounty_hunter_immunity }
            NOT = { has_character_flag = ddm_proscription_recently_revoked }
        }
        scope:actor != scope:recipient
        OR = {
            # Existing political writs remain available to any landed player ruler.
            scope:recipient = { ddm_is_valid_proscription_target_trigger = yes }
            # Kings+ may use a discretionary writ against any target, including spouses/family.
            scope:actor = { ddm_can_use_personal_proscriptions_trigger = yes }
        }
        scope:recipient = { NOT = { has_variable = ddm_proscribed_by } }
    }

    is_valid_showing_failures_only = {
        scope:recipient = {
            custom_tooltip = { text = ddm_personal_proscription_target_free_tt is_imprisoned = no }
            custom_tooltip = { text = ddm_love_proscription_target_defied_tt NOT = { has_character_flag = ddm_bounty_hunter_immunity } }
        }
        OR = {
            scope:recipient = { ddm_is_valid_proscription_target_trigger = yes }
            AND = {
                scope:actor = {
                    custom_tooltip = { text = ddm_personal_proscription_rank_tt ddm_can_use_personal_proscriptions_trigger = yes }
                    custom_tooltip = { text = ddm_personal_proscription_quota_tt ddm_personal_proscription_quota_available_trigger = yes }
                }
                scope:recipient = { is_alive = yes }
            }
        }
    }

    on_accept = {
        scope:actor = { save_scope_as = ddm_proscriber }
        scope:recipient = { save_scope_as = ddm_proscription_target }
        if = {
            limit = { scope:recipient = { ddm_is_valid_proscription_target_trigger = yes } }
            scope:actor = { ddm_issue_proscription_effect = yes }
        }
        else = {
            scope:actor = { ddm_issue_personal_proscription_effect = yes }
        }
        scope:actor = { ddm_proscription_target_availability_effect = yes }
        scope:actor = {
            send_interface_toast = {
                type = event_toast_effect_neutral
                title = DDM_PROSCRIPTION_ISSUED_TOAST
                left_icon = scope:actor
                right_icon = scope:recipient
            }
        }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_revoke_proscription_interaction = {
    icon = prison
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 85
    desc = ddm_revoke_proscription_interaction_desc

    is_shown = {
        scope:actor = { is_alive = yes is_ai = no is_landed = yes }
        scope:recipient = {
            is_alive = yes
            NOT = { has_character_flag = ddm_bounty_hunter_immunity }
            has_variable = ddm_proscribed_by
            var:ddm_proscribed_by = scope:actor
        }
    }
    on_accept = {
        scope:actor = { save_scope_as = ddm_proscriber }
        scope:recipient = { save_scope_as = ddm_proscription_target }
        scope:actor = {
            ddm_revoke_proscription_effect = yes
            send_interface_toast = {
                type = event_toast_effect_neutral
                title = DDM_PROSCRIPTION_REVOKED_TOAST
                left_icon = scope:actor
                right_icon = scope:recipient
            }
        }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

# ---------------------------------------------------------------------------
# 2.5.0 — PROSCRIBE AN UNFAITHFUL LOVER
# ---------------------------------------------------------------------------
# This is intentionally independent of the political proscription system. A relationship writ gets one
# monthly hunter opportunity, with the player's incoming-pressure setting controlling the annual cap, and the confrontation is always
# a non-lethal CK3 duel. If the hunter wins, the unfaithful lover is delivered to the ruler's dungeon;
# what the ruler does with the prisoner afterwards is left to normal CK3 prisoner logic.
ddm_proscribe_unfaithful_lover_interaction = {
    icon = lover
    category = interaction_category_hostile
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 87
    desc = ddm_proscribe_unfaithful_lover_interaction_desc

    is_shown = {
        scope:actor = { is_alive = yes is_landed = yes }
        scope:recipient = {
            is_alive = yes
            NOT = { has_variable = ddm_love_proscribed_by }
            OR = {
                has_relation_lover = scope:actor
                has_relation_soulmate = scope:actor
            }
            OR = {
                any_relation = { type = lover is_alive = yes this != scope:actor }
                any_relation = { type = soulmate is_alive = yes this != scope:actor }
            }
        }
        scope:actor != scope:recipient
    }

    is_valid_showing_failures_only = {
        scope:actor = {
            custom_tooltip = { text = ddm_love_proscription_actor_free_tt is_imprisoned = no }
        }
        scope:recipient = {
            custom_tooltip = { text = ddm_love_proscription_target_free_tt is_imprisoned = no }
            custom_tooltip = { text = ddm_love_proscription_target_defied_tt NOT = { has_character_flag = ddm_bounty_hunter_immunity } }
        }
    }

    on_accept = {
        scope:actor = { save_scope_as = ddm_love_proscriber }
        scope:recipient = { save_scope_as = ddm_love_proscription_target }
        scope:actor = { ddm_issue_love_proscription_effect = yes }
        if = {
            limit = { scope:actor = { is_ai = no } }
            scope:actor = {
                send_interface_toast = {
                    type = event_toast_effect_neutral
                    title = DDM_LOVE_PROSCRIPTION_ISSUED_TOAST
                    left_icon = scope:actor
                    right_icon = scope:recipient
                }
            }
        }
    }

    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_revoke_love_proscription_interaction = {
    icon = lover
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 84
    desc = ddm_revoke_love_proscription_interaction_desc

    is_shown = {
        scope:actor = { is_alive = yes is_landed = yes }
        scope:recipient = {
            is_alive = yes
            has_variable = ddm_love_proscribed_by
            var:ddm_love_proscribed_by = scope:actor
        }
    }
    on_accept = {
        scope:actor = { save_scope_as = ddm_love_proscriber }
        scope:recipient = { save_scope_as = ddm_love_proscription_target }
        scope:actor = {
            ddm_clear_love_proscription_effect = yes
            send_interface_toast = {
                type = event_toast_effect_neutral
                title = DDM_LOVE_PROSCRIPTION_REVOKED_TOAST
                left_icon = scope:actor
                right_icon = scope:recipient
            }
        }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

# -----------------------------------------------------------------------------
# Bounty Office — persistent hunter management
# -----------------------------------------------------------------------------
ddm_select_preferred_bounty_hunter_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    desc = ddm_select_preferred_bounty_hunter_interaction_desc
    is_shown = {
        scope:actor = { is_ai = no }
        scope:recipient = {
            has_character_flag = ddm_registered_bounty_hunter
            has_variable = ddm_bounty_hunter_patron
            var:ddm_bounty_hunter_patron = scope:actor
        }
    }
    on_accept = {
        scope:actor = {
            save_scope_as = ddm_hunter_roster_owner
            if = { limit = { has_variable_list = ddm_bounty_hunter_roster } every_in_list = { variable = ddm_bounty_hunter_roster limit = { has_variable = ddm_bounty_hunter_patron var:ddm_bounty_hunter_patron = scope:ddm_hunter_roster_owner } remove_character_flag = ddm_preferred_bounty_hunter } }
            set_variable = { name = ddm_selected_bounty_hunter value = scope:recipient }
        }
        scope:recipient = { add_character_flag = ddm_preferred_bounty_hunter }
        scope:actor = { ddm_rebuild_hunter_roster_ui_effect = yes }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_train_bounty_hunter_gold_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    desc = ddm_train_bounty_hunter_gold_interaction_desc
    is_shown = { scope:actor = { is_ai = no } scope:recipient = { has_character_flag = ddm_registered_bounty_hunter has_variable = ddm_bounty_hunter_patron var:ddm_bounty_hunter_patron = scope:actor } }
    is_valid_showing_failures_only = { scope:actor = { gold >= 250 } }
    on_accept = {
        scope:actor = { remove_short_term_gold = 250 }
        scope:recipient = { change_variable = { name = ddm_hunter_xp add = 25 } add_prowess_skill = 1 ddm_update_hunter_level_effect = yes }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_train_bounty_hunter_prestige_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    desc = ddm_train_bounty_hunter_prestige_interaction_desc
    is_shown = { scope:actor = { is_ai = no } scope:recipient = { has_character_flag = ddm_registered_bounty_hunter has_variable = ddm_bounty_hunter_patron var:ddm_bounty_hunter_patron = scope:actor } }
    is_valid_showing_failures_only = { scope:actor = { prestige >= 500 } }
    on_accept = {
        scope:actor = { add_prestige = -500 }
        scope:recipient = { change_variable = { name = ddm_hunter_xp add = 30 } add_martial_skill = 1 ddm_update_hunter_level_effect = yes }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_train_bounty_hunter_piety_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    desc = ddm_train_bounty_hunter_piety_interaction_desc
    is_shown = { scope:actor = { is_ai = no } scope:recipient = { has_character_flag = ddm_registered_bounty_hunter has_variable = ddm_bounty_hunter_patron var:ddm_bounty_hunter_patron = scope:actor } }
    is_valid_showing_failures_only = { scope:actor = { piety >= 300 } }
    on_accept = {
        scope:actor = { add_piety = -300 }
        scope:recipient = { change_variable = { name = ddm_hunter_xp add = 25 } add_intrigue_skill = 1 ddm_update_hunter_level_effect = yes }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_train_bounty_hunter_elite_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    desc = ddm_train_bounty_hunter_elite_interaction_desc
    is_shown = { scope:actor = { is_ai = no } scope:recipient = { has_character_flag = ddm_registered_bounty_hunter has_variable = ddm_bounty_hunter_patron var:ddm_bounty_hunter_patron = scope:actor } }
    is_valid_showing_failures_only = { scope:actor = { gold >= 500 prestige >= 750 piety >= 500 } }
    on_accept = {
        scope:actor = { remove_short_term_gold = 500 add_prestige = -750 add_piety = -500 }
        scope:recipient = { change_variable = { name = ddm_hunter_xp add = 75 } add_prowess_skill = 2 add_martial_skill = 1 add_intrigue_skill = 1 ddm_update_hunter_level_effect = yes }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}


# -----------------------------------------------------------------------------
# 2.6 — Writ Hostages and Political Coercion
# -----------------------------------------------------------------------------
ddm_ransom_writ_hostage_interaction = {
    icon = prison
    category = interaction_category_prison
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 93
    desc = ddm_ransom_writ_hostage_interaction_desc
    is_shown = {
        scope:recipient = {
            is_alive = yes
            is_imprisoned_by = scope:actor
            has_character_flag = ddm_writ_hostage
            has_variable = ddm_writ_ransom_amount
        }
    }
    on_accept = {
        scope:recipient = { save_scope_as = ddm_writ_hostage_target }
        scope:actor = {
            set_variable = { name = ddm_writ_temp_payment value = scope:recipient.var:ddm_writ_ransom_amount }
            set_variable = { name = ddm_writ_temp_payment_negative value = scope:recipient.var:ddm_writ_ransom_amount }
            change_variable = { name = ddm_writ_temp_payment_negative multiply = -1 }
        }
        if = {
            limit = { scope:recipient = { has_variable = ddm_writ_ransom_sponsor var:ddm_writ_ransom_sponsor = { is_alive = yes } } }
            scope:recipient.var:ddm_writ_ransom_sponsor = { add_gold = scope:actor.var:ddm_writ_temp_payment_negative }
        }
        else = { scope:recipient = { add_gold = scope:actor.var:ddm_writ_temp_payment_negative } }
        scope:actor = { add_gold = var:ddm_writ_temp_payment }
        scope:recipient = {
            release_from_prison = yes
            if = {
                limit = { is_landed = no has_variable = ddm_writ_original_employer var:ddm_writ_original_employer = { is_alive = yes } }
                var:ddm_writ_original_employer = { save_scope_as = ddm_writ_ransom_restore_employer }
                set_employer = scope:ddm_writ_ransom_restore_employer
            }
            ddm_clear_writ_origin_effect = yes
        }
        scope:actor = { remove_variable = ddm_writ_temp_payment remove_variable = ddm_writ_temp_payment_negative }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_extort_writ_hostage_interaction = {
    icon = prison
    category = interaction_category_prison
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 92
    desc = ddm_extort_writ_hostage_interaction_desc
    is_shown = {
        scope:recipient = { is_alive = yes is_imprisoned_by = scope:actor has_character_flag = ddm_writ_hostage }
    }
    on_accept = {
        scope:recipient = { save_scope_as = ddm_writ_hostage_target }
        scope:actor = { add_gold = 250 add_prestige = 250 add_piety = 150 }
        scope:recipient = { add_gold = { value = 250 multiply = -1 } add_prestige = -250 add_piety = -150 add_stress = 25 }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_force_writ_hostage_courtier_interaction = {
    icon = prison
    category = interaction_category_prison
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 91
    desc = ddm_force_writ_hostage_courtier_interaction_desc
    # Deliberately available on ordinary unlanded prisoners too. A political writ hostage keeps
    # Retrieval-War restoration data; an ordinary prisoner simply joins the actor's court.
    is_shown = {
        scope:recipient = {
            is_alive = yes
            is_landed = no
            is_ruler = no
            NOT = { is_landless_adventurer = yes }
            is_imprisoned_by = scope:actor
            NOT = { employer = scope:actor }
        }
    }
    on_accept = {
        scope:recipient = {
            if = {
                limit = { has_character_flag = ddm_writ_hostage }
                set_variable = { name = ddm_writ_coerced_by value = scope:actor }
                set_variable = { name = ddm_writ_coercion_type value = 1 }
            }
            release_from_prison = yes
            set_employer = scope:actor
            if = {
                limit = { has_character_flag = ddm_writ_hostage }
                ddm_clear_writ_hostage_state_effect = yes
                trigger_event = { id = ddm_manager.5310 days = 15 }
            }
        }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_force_writ_hostage_vassal_interaction = {
    icon = prison
    category = interaction_category_prison
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 90
    desc = ddm_force_writ_hostage_vassal_interaction_desc
    is_shown = {
        scope:actor = { is_landed = yes }
        scope:recipient = { is_alive = yes is_landed = yes is_imprisoned_by = scope:actor has_character_flag = ddm_writ_hostage }
    }
    is_valid_showing_failures_only = {
        scope:actor = { highest_held_title_tier > scope:recipient.highest_held_title_tier }
        scope:recipient = { NOT = { government_has_flag = cannot_be_vassal_or_liege } }
    }
    on_accept = {
        scope:recipient = {
            set_variable = { name = ddm_writ_coerced_by value = scope:actor }
            set_variable = { name = ddm_writ_coercion_type value = 2 }
            release_from_prison = yes
        }
        create_title_and_vassal_change = { type = swear_fealty save_scope_as = ddm_writ_vassal_change add_claim_on_loss = no }
        scope:recipient = { change_liege = { liege = scope:actor change = scope:ddm_writ_vassal_change } }
        resolve_title_and_vassal_change = scope:ddm_writ_vassal_change
        scope:recipient = { ddm_clear_writ_hostage_state_effect = yes trigger_event = { id = ddm_manager.5310 days = 15 } }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_force_writ_hostage_tributary_interaction = {
    icon = prison
    category = interaction_category_prison
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 89
    desc = ddm_force_writ_hostage_tributary_interaction_desc
    is_shown = {
        scope:actor = { is_landed = yes }
        scope:recipient = { is_alive = yes is_landed = yes is_independent_ruler = yes is_imprisoned_by = scope:actor has_character_flag = ddm_writ_hostage }
    }
    on_accept = {
        scope:recipient = {
            set_variable = { name = ddm_writ_coerced_by value = scope:actor }
            set_variable = { name = ddm_writ_coercion_type value = 3 }
            release_from_prison = yes
        }
        start_tributary_interaction_effect = { TRIBUTARY = scope:recipient SUZERAIN = scope:actor }
        scope:recipient = { ddm_clear_writ_hostage_state_effect = yes trigger_event = { id = ddm_manager.5310 days = 15 } }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

# Pick any living character as the destination for a later forced abdication.
# This is deliberately a separate lightweight interaction so the prisoner command can remain
# compatible with CK3 interaction windows that do not expose a reliable second-recipient picker.
ddm_set_writ_abdication_beneficiary_interaction = {
    icon = revoke_title
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 40
    desc = ddm_set_writ_abdication_beneficiary_interaction_desc
    is_shown = {
        scope:actor = { is_ai = no }
        scope:recipient = { is_alive = yes }
        scope:recipient != scope:actor
    }
    on_accept = {
        scope:actor = {
            set_variable = { name = ddm_writ_abdication_beneficiary value = scope:recipient }
            send_interface_toast = { type = event_toast_effect_neutral title = DDM_WRIT_ABDICATION_BENEFICIARY_SET left_icon = scope:recipient }
        }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

# Force the hostage to surrender every county-or-higher title directly to the captor.
ddm_force_writ_hostage_abdication_interaction = {
    icon = prison
    category = interaction_category_prison
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 88
    desc = ddm_force_writ_hostage_abdication_interaction_desc
    is_shown = {
        scope:actor = { is_landed = yes }
        scope:recipient = { is_alive = yes is_landed = yes is_imprisoned_by = scope:actor has_character_flag = ddm_writ_hostage }
    }
    on_accept = {
        scope:recipient = { save_scope_as = ddm_writ_abdicator }
        scope:actor = { save_scope_as = ddm_writ_abdication_successor_scope }
        scope:recipient = {
            clear_variable_list = ddm_writ_abdicated_titles
            every_held_title = {
                limit = { tier > tier_barony }
                save_temporary_scope_as = ddm_writ_abdicated_title
                scope:ddm_writ_abdicator = { add_to_variable_list = { name = ddm_writ_abdicated_titles target = scope:ddm_writ_abdicated_title } }
            }
            set_variable = { name = ddm_writ_abdication_successor value = scope:ddm_writ_abdication_successor_scope }
            set_variable = { name = ddm_writ_coerced_by value = scope:actor }
            set_variable = { name = ddm_writ_coercion_type value = 4 }
            release_from_prison = yes
        }
        create_title_and_vassal_change = { type = granted save_scope_as = ddm_writ_abdication_change add_claim_on_loss = no }
        scope:ddm_writ_abdicator = {
            every_in_list = {
                variable = ddm_writ_abdicated_titles
                change_title_holder = { holder = scope:ddm_writ_abdication_successor_scope change = scope:ddm_writ_abdication_change government_base = scope:ddm_writ_abdication_successor_scope }
            }
        }
        resolve_title_and_vassal_change = scope:ddm_writ_abdication_change
        scope:ddm_writ_abdicator = { ddm_clear_writ_hostage_state_effect = yes trigger_event = { id = ddm_manager.5310 days = 15 } }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

# Same coercion, but hand the titles to the player-selected beneficiary rather than the captive's heir.
ddm_force_writ_hostage_abdication_beneficiary_interaction = {
    icon = prison
    category = interaction_category_prison
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 87
    desc = ddm_force_writ_hostage_abdication_beneficiary_interaction_desc
    is_shown = {
        scope:actor = {
            has_variable = ddm_writ_abdication_beneficiary
            var:ddm_writ_abdication_beneficiary = { is_alive = yes }
        }
        scope:recipient = { is_alive = yes is_landed = yes is_imprisoned_by = scope:actor has_character_flag = ddm_writ_hostage }
    }
    is_valid_showing_failures_only = {
        scope:actor = { NOT = { var:ddm_writ_abdication_beneficiary = scope:recipient } }
    }
    on_accept = {
        scope:recipient = { save_scope_as = ddm_writ_abdicator }
        scope:actor.var:ddm_writ_abdication_beneficiary = { save_scope_as = ddm_writ_abdication_successor_scope }
        scope:recipient = {
            clear_variable_list = ddm_writ_abdicated_titles
            every_held_title = {
                limit = { tier > tier_barony }
                save_temporary_scope_as = ddm_writ_abdicated_title
                scope:ddm_writ_abdicator = { add_to_variable_list = { name = ddm_writ_abdicated_titles target = scope:ddm_writ_abdicated_title } }
            }
            set_variable = { name = ddm_writ_abdication_successor value = scope:ddm_writ_abdication_successor_scope }
            set_variable = { name = ddm_writ_coerced_by value = scope:actor }
            set_variable = { name = ddm_writ_coercion_type value = 4 }
            release_from_prison = yes
        }
        create_title_and_vassal_change = { type = granted save_scope_as = ddm_writ_abdication_change add_claim_on_loss = no }
        scope:ddm_writ_abdicator = {
            every_in_list = {
                variable = ddm_writ_abdicated_titles
                change_title_holder = { holder = scope:ddm_writ_abdication_successor_scope change = scope:ddm_writ_abdication_change government_base = scope:ddm_writ_abdication_successor_scope }
            }
        }
        resolve_title_and_vassal_change = scope:ddm_writ_abdication_change
        scope:ddm_writ_abdicator = { ddm_clear_writ_hostage_state_effect = yes trigger_event = { id = ddm_manager.5310 days = 15 } }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

# Deliberately bypasses cultural/religious access requirements; physical validity is still handled by vanilla's effects.
ddm_blind_prisoner_interaction = {
    icon = prison
    category = interaction_category_prison
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 72
    desc = ddm_blind_prisoner_interaction_desc
    is_shown = { scope:recipient = { is_alive = yes is_imprisoned_by = scope:actor NOT = { has_trait = blind } } }
    on_accept = { blind_recipient_effect = yes }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}

ddm_castrate_prisoner_interaction = {
    icon = prison
    category = interaction_category_prison
    common_interaction = yes
    use_diplomatic_range = no
    interface_priority = 71
    desc = ddm_castrate_prisoner_interaction_desc
    is_shown = { scope:recipient = { is_alive = yes is_imprisoned_by = scope:actor is_male = yes NOT = { has_trait = eunuch } } }
    on_accept = { castrate_recipient_effect = yes }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}


ddm_pedigree_loop_report_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    use_diplomatic_range = no
    desc = ddm_pedigree_loop_report_interaction_desc
    icon = support_candidacy

    is_shown = {
        scope:actor = { is_ai = no }
        scope:recipient != scope:actor
    }
    is_valid_showing_failures_only = { scope:recipient = { is_alive = yes } }
    on_accept = {
        scope:actor = { save_scope_as = ddm_pedigree_actor }
        scope:recipient = { save_scope_as = ddm_pedigree_target }
        scope:actor = {
            ddm_habsburg_prepare_pedigree_loop_report_effect = yes
            ddm_habsburg_refresh_dynasty_analytics_effect = yes
            set_variable = { name = ddm_ui_page value = flag:habsburg }
            set_variable = { name = ddm_ui_open value = yes }
        }
    }
    auto_accept = yes
    ai_accept = { base = 100 }
    ai_frequency = 0
}


# ---------------------------------------------------------------------------
# PATRON FAMILY AUTHORITY — direct child marriage access
# ---------------------------------------------------------------------------
# This is intentionally a dedicated marriage interface rather than an override of vanilla marry_off_interaction.
# It keeps compatibility with mods that edit the vanilla character window / marriage interaction while giving
# the player direct access from an Owned subject's child.
ddm_patron_marry_off_interaction = {
    icon = icon_marriage
    category = interaction_category_diplomacy
    common_interaction = yes
    interface_priority = 96

    desc = ddm_patron_marry_off_interaction_desc
    send_name = marry_off_send

    needs_recipient_to_open = no
    special_interaction = arrange_marriage_interaction
    interface = marriage

    redirect = {
        if = {
            limit = { exists = scope:secondary_actor }
            scope:recipient = {
                save_scope_as = secondary_recipient
                matchmaker = { save_scope_as = recipient }
            }
        }
        else = {
            scope:recipient = { save_scope_as = secondary_actor }
            clear_saved_scope = recipient
        }
    }

    # Use CK3's spouse-candidate iterators so faith, gender, age/betrothal rules and other marriage mods
    # continue to define the actual legal pool.
    populate_recipient_list = {
        scope:secondary_actor = {
            every_opposite_sex_spouse_candidate = { add_to_list = characters }
            if = {
                limit = { allowed_to_marry_same_sex_trigger = yes }
                every_same_sex_spouse_candidate = {
                    limit = { scope:secondary_actor != this }
                    add_to_list = characters
                }
            }
        }
    }

    is_shown = {
        scope:actor = { is_ai = no }
        scope:secondary_actor = {
            is_alive = yes
            can_marry_trigger = yes
            is_married = no
            is_betrothed = no
            ddm_patron_owned_child_marriage_trigger = yes
        }
        NOR = {
            scope:secondary_actor ?= { has_been_promised_grand_wedding = yes }
            scope:secondary_recipient ?= { has_been_promised_grand_wedding = yes }
        }
    }

    is_valid_showing_failures_only = {
        scope:secondary_actor = {
            custom_tooltip = { text = DDM_PATRON_MARRIAGE_CHILD_AVAILABLE_TT is_imprisoned = no }
            bp2_valid_for_standard_interactions_trigger = yes
        }
    }

    has_valid_target_showing_failures_only = {
        marriage_interaction_valid_target_trigger = yes
        scope:recipient = { is_imprisoned = no }
        NOT = { scope:actor = { is_at_war_with = scope:recipient } }
        trigger_if = {
            limit = { scope:recipient != scope:secondary_recipient }
            scope:secondary_recipient = {
                is_imprisoned = no
                bp2_valid_for_standard_interactions_trigger = yes
            }
        }
    }

    on_accept = {
        marriage_interaction_on_accept_effect = yes
    }

    auto_accept = {
        marriage_interaction_auto_accept_trigger = yes
    }

    ai_accept = {
        base = 0
        marriage_ai_accept_modifier = yes
    }

    # Preserve the most important marriage term in the direct shortcut.
    send_option = {
        flag = matrilineal
        localization = "MATRILINEAL_OFFER"
        is_shown = {
            NAND = {
                scope:secondary_actor ?= { is_male = yes }
                scope:secondary_recipient ?= { is_male = yes }
            }
        }
        starts_enabled = {
            scope:actor = {
                OR = {
                    faith = { has_doctrine = doctrine_gender_female_dominated }
                    AND = {
                        scope:secondary_actor ?= { is_female = yes }
                        faith = { has_doctrine = doctrine_gender_equal }
                    }
                    AND = {
                        scope:secondary_actor ?= { is_female = yes }
                        scope:secondary_recipient ?= { is_female = yes }
                    }
                }
            }
        }
        can_be_changed = {
            NAND = {
                scope:secondary_actor ?= { is_female = yes }
                scope:secondary_recipient ?= { is_female = yes }
            }
        }
    }

    send_options_exclusive = no
    show_effects_in_notification = no
    greeting = positive
    ai_frequency = 0
}
