﻿# ---------------------------------------------------------------------------
# DYNASTIC KIDNAPPING
# ---------------------------------------------------------------------------
# A hostile expedition rather than a free force-marriage button. The target is taken prisoner and
# made part of the actor's court; subsequent marriage/recruitment still uses normal CK3 mechanics.

# Actor scope. Requires scope:ddm_kidnap_target.
ddm_prepare_kidnap_context_effect = {
    save_scope_as = ddm_kidnap_actor
    # A vassal can lead the raid personally, but any external retaliation is a realm-to-realm war.
    # Save the actor's current top liege so the retrieval CB can target a legal war participant.
    top_liege = { save_scope_as = ddm_kidnap_defending_top_liege }
    clear_variable_list = ddm_kidnap_party_knights
    clear_variable_list = ddm_kidnap_local_pool
    clear_variable_list = ddm_kidnap_three_brides
    clear_variable_list = ddm_kidnap_elite_brides

    set_variable = { name = ddm_kidnap_knight_prowess value = 0 }
    set_variable = { name = ddm_kidnap_defender_knight_prowess value = 0 }
    set_variable = { name = ddm_kidnap_party_count value = 0 }
    set_variable = { name = ddm_kidnap_defender_count value = 0 }
    set_variable = { name = ddm_kidnap_three_count value = 0 }
    set_variable = { name = ddm_kidnap_elite_count value = 0 }
    set_variable = { name = ddm_kidnap_three_attached_count value = 0 }
    set_variable = { name = ddm_kidnap_elite_attached_count value = 0 }
    set_variable = { name = ddm_kidnap_relationship_heat value = 0 }
    remove_variable = ddm_kidnap_solo
    remove_variable = ddm_kidnap_caught
    remove_variable = ddm_kidnap_caught_chance
    remove_variable = ddm_kidnap_captured_retinue_count

    # The ruler/court responsible for the target. Their top liege is saved separately for possible
    # retaliation so a duke inside a kingdom does not create an impossible external war by himself.
    if = {
        limit = { scope:ddm_kidnap_target = { exists = liege } }
        scope:ddm_kidnap_target = { liege = { save_scope_as = ddm_kidnap_local_ruler } }
    }
    else = {
        scope:ddm_kidnap_target = { save_scope_as = ddm_kidnap_local_ruler }
    }
    scope:ddm_kidnap_local_ruler = { top_liege = { save_scope_as = ddm_kidnap_retaliator } }
    ddm_calculate_kidnap_relationship_heat_effect = yes

    # The ruler personally leads every available active knight/champion who can join the expedition.
    # There is no arbitrary four-person ceiling anymore. The strongest four contribute full Prowess,
    # then additional bodies contribute with diminishing returns: 60% for #5-8, 35% for #9-12 and
    # 20% thereafter. This lets a deep knight bench offset a difficult raid without making raw headcount
    # a linear certainty engine. The iterator remains culture-title agnostic: CK3 resolves Knight/Champion/etc.
    ordered_knight = {
        order_by = prowess
        max = 100
        check_range_bounds = no
        save_temporary_scope_as = ddm_kidnap_party_knight
        scope:ddm_kidnap_actor = {
            add_to_variable_list = { name = ddm_kidnap_party_knights target = scope:ddm_kidnap_party_knight }
            change_variable = { name = ddm_kidnap_party_count add = 1 }
            if = {
                limit = { var:ddm_kidnap_party_count <= 4 }
                change_variable = { name = ddm_kidnap_knight_prowess add = scope:ddm_kidnap_party_knight.prowess }
            }
            else_if = {
                limit = { var:ddm_kidnap_party_count <= 8 }
                set_variable = { name = ddm_kidnap_knight_tmp value = scope:ddm_kidnap_party_knight.prowess }
                change_variable = { name = ddm_kidnap_knight_tmp multiply = 0.60 }
                change_variable = { name = ddm_kidnap_knight_prowess add = var:ddm_kidnap_knight_tmp }
            }
            else_if = {
                limit = { var:ddm_kidnap_party_count <= 12 }
                set_variable = { name = ddm_kidnap_knight_tmp value = scope:ddm_kidnap_party_knight.prowess }
                change_variable = { name = ddm_kidnap_knight_tmp multiply = 0.35 }
                change_variable = { name = ddm_kidnap_knight_prowess add = var:ddm_kidnap_knight_tmp }
            }
            else = {
                set_variable = { name = ddm_kidnap_knight_tmp value = scope:ddm_kidnap_party_knight.prowess }
                change_variable = { name = ddm_kidnap_knight_tmp multiply = 0.20 }
                change_variable = { name = ddm_kidnap_knight_prowess add = var:ddm_kidnap_knight_tmp }
            }
        }
    }

    # The defending ruler can likewise draw on the full local knight bench. This keeps the operation
    # symmetrical: bringing more of your own elite companions helps, but raiding a court with a deep
    # defensive roster remains meaningfully harder. The same diminishing-return bands apply.
    scope:ddm_kidnap_local_ruler = {
        ordered_knight = {
            order_by = prowess
            max = 100
            check_range_bounds = no
            save_temporary_scope_as = ddm_kidnap_defender_knight
            scope:ddm_kidnap_actor = {
                change_variable = { name = ddm_kidnap_defender_count add = 1 }
                if = {
                    limit = { var:ddm_kidnap_defender_count <= 4 }
                    change_variable = { name = ddm_kidnap_defender_knight_prowess add = scope:ddm_kidnap_defender_knight.prowess }
                }
                else_if = {
                    limit = { var:ddm_kidnap_defender_count <= 8 }
                    set_variable = { name = ddm_kidnap_defender_tmp value = scope:ddm_kidnap_defender_knight.prowess }
                    change_variable = { name = ddm_kidnap_defender_tmp multiply = 0.60 }
                    change_variable = { name = ddm_kidnap_defender_knight_prowess add = var:ddm_kidnap_defender_tmp }
                }
                else_if = {
                    limit = { var:ddm_kidnap_defender_count <= 12 }
                    set_variable = { name = ddm_kidnap_defender_tmp value = scope:ddm_kidnap_defender_knight.prowess }
                    change_variable = { name = ddm_kidnap_defender_tmp multiply = 0.35 }
                    change_variable = { name = ddm_kidnap_defender_knight_prowess add = var:ddm_kidnap_defender_tmp }
                }
                else = {
                    set_variable = { name = ddm_kidnap_defender_tmp value = scope:ddm_kidnap_defender_knight.prowess }
                    change_variable = { name = ddm_kidnap_defender_tmp multiply = 0.20 }
                    change_variable = { name = ddm_kidnap_defender_knight_prowess add = var:ddm_kidnap_defender_tmp }
                }
            }
        }
    }

    # Build a real-character pool from the target ruler's court and political sub-realm. Existing
    # characters are always preferred. If fewer than three genuinely high-quality candidates exist,
    # the player may generate the missing local noblewomen only after choosing a multi-person raid.
    scope:ddm_kidnap_local_ruler = {
        every_courtier_or_guest = {
            limit = {
                ddm_kidnap_bride_candidate_trigger = yes
                this != scope:ddm_kidnap_target
            }
            save_temporary_scope_as = ddm_kidnap_pool_person
            scope:ddm_kidnap_actor = {
                add_to_variable_list = { name = ddm_kidnap_local_pool target = scope:ddm_kidnap_pool_person }
            }
        }
        every_vassal_or_below = {
            every_courtier_or_guest = {
                limit = {
                    ddm_kidnap_bride_candidate_trigger = yes
                    this != scope:ddm_kidnap_target
                }
                save_temporary_scope_as = ddm_kidnap_pool_person
                scope:ddm_kidnap_actor = {
                    add_to_variable_list = { name = ddm_kidnap_local_pool target = scope:ddm_kidnap_pool_person }
                }
            }
        }
    }

    # Retinue-scaled carrying capacity. The principal target never consumes a slot. A solo ruler can
    # sometimes drag one additional high-value captive out; larger expeditionary parties can secure
    # progressively more people, up to a hard ceiling of twenty-five additional captives.
    ddm_set_kidnap_capacity_effect = yes
    ddm_rebuild_kidnap_capture_lists_effect = yes

    ddm_calculate_kidnap_chances_effect = yes
}

# Actor scope. The target is separate from this capacity. Retinue size affects how many additional
# captives can be controlled during extraction; it does not lower the underlying political difficulty.
ddm_set_kidnap_capacity_effect = {
    if = {
        limit = { has_variable = ddm_kidnap_solo }
        set_variable = { name = ddm_kidnap_capacity value = 1 }
    }
    else_if = {
        limit = { var:ddm_kidnap_party_count <= 0 }
        set_variable = { name = ddm_kidnap_capacity value = 1 }
    }
    else_if = {
        limit = { var:ddm_kidnap_party_count <= 4 }
        set_variable = { name = ddm_kidnap_capacity value = 3 }
    }
    else_if = {
        limit = { var:ddm_kidnap_party_count <= 9 }
        set_variable = { name = ddm_kidnap_capacity value = 6 }
    }
    else_if = {
        limit = { var:ddm_kidnap_party_count <= 19 }
        set_variable = { name = ddm_kidnap_capacity value = 10 }
    }
    else_if = {
        limit = { var:ddm_kidnap_party_count <= 29 }
        set_variable = { name = ddm_kidnap_capacity value = 15 }
    }
    else = {
        set_variable = { name = ddm_kidnap_capacity value = 25 }
    }
}

# Rebuild both multi-person objectives after the player chooses whether the retinue rides. Internally the
# old three_brides list name remains for save/script compatibility, but it now means the best captives up
# to expedition capacity rather than exactly three.
ddm_rebuild_kidnap_capture_lists_effect = {
    clear_variable_list = ddm_kidnap_three_brides
    clear_variable_list = ddm_kidnap_elite_brides
    set_variable = { name = ddm_kidnap_three_count value = 0 }
    set_variable = { name = ddm_kidnap_elite_count value = 0 }
    set_variable = { name = ddm_kidnap_three_attached_count value = 0 }
    set_variable = { name = ddm_kidnap_elite_attached_count value = 0 }

    if = {
        limit = { has_variable_list = ddm_kidnap_local_pool }
        ordered_in_list = {
            variable = ddm_kidnap_local_pool
            limit = { ddm_kidnap_quality_bride_trigger = yes }
            order_by = ddm_kidnap_bride_quality_value
            max = 25
            check_range_bounds = no
            save_temporary_scope_as = ddm_kidnap_extra_bride
            scope:ddm_kidnap_actor = {
                if = {
                    limit = { var:ddm_kidnap_three_count < var:ddm_kidnap_capacity }
                    add_to_variable_list = { name = ddm_kidnap_three_brides target = scope:ddm_kidnap_extra_bride }
                    change_variable = { name = ddm_kidnap_three_count add = 1 }
                    if = {
                        limit = { scope:ddm_kidnap_extra_bride = { OR = { is_married = yes is_betrothed = yes is_concubine = yes } } }
                        change_variable = { name = ddm_kidnap_three_attached_count add = 1 }
                    }
                }
            }
        }

        # The exceptional sweep is no longer an uncapped court vacuum. It takes every qualifying high-status
        # woman it can physically secure, strongest first, up to the same expedition capacity.
        ordered_in_list = {
            variable = ddm_kidnap_local_pool
            limit = { ddm_kidnap_elite_stock_trigger = yes }
            order_by = ddm_kidnap_bride_quality_value
            max = 25
            check_range_bounds = no
            save_temporary_scope_as = ddm_kidnap_elite_bride
            scope:ddm_kidnap_actor = {
                if = {
                    limit = { var:ddm_kidnap_elite_count < var:ddm_kidnap_capacity }
                    add_to_variable_list = { name = ddm_kidnap_elite_brides target = scope:ddm_kidnap_elite_bride }
                    change_variable = { name = ddm_kidnap_elite_count add = 1 }
                    if = {
                        limit = { scope:ddm_kidnap_elite_bride = { OR = { is_married = yes is_betrothed = yes is_concubine = yes } } }
                        change_variable = { name = ddm_kidnap_elite_attached_count add = 1 }
                    }
                }
            }
        }
    }
}

# Actor scope. Existing lawful/contractual bonds do not make a target immune to kidnapping; they create
# escalating "relationship heat." The scale is deliberately nonlinear once squared in the chance/cost
# calculations below. Ordinary unmarried targets remain heat 0 and keep the old behavior.
ddm_calculate_kidnap_relationship_heat_effect = {
    set_variable = { name = ddm_kidnap_relationship_heat value = 0 }
    if = { limit = { scope:ddm_kidnap_target = { is_betrothed = yes } } change_variable = { name = ddm_kidnap_relationship_heat add = 1 } }
    if = { limit = { scope:ddm_kidnap_target = { is_concubine = yes } } change_variable = { name = ddm_kidnap_relationship_heat add = 2 } }
    if = { limit = { scope:ddm_kidnap_target = { is_married = yes } } change_variable = { name = ddm_kidnap_relationship_heat add = 3 } }

    # Stealing somebody directly from the ruler whose court is being penetrated is substantially hotter.
    if = { limit = { scope:ddm_kidnap_target = { is_spouse_of = scope:ddm_kidnap_local_ruler } } change_variable = { name = ddm_kidnap_relationship_heat add = 2 } }
    if = { limit = { scope:ddm_kidnap_target = { is_consort_of = scope:ddm_kidnap_local_ruler } } change_variable = { name = ddm_kidnap_relationship_heat add = 2 } }

    # A landed/royal spouse has guards, prestige and a political constituency beyond an ordinary marriage.
    if = { limit = { scope:ddm_kidnap_target = { any_spouse = { is_landed = yes } } } change_variable = { name = ddm_kidnap_relationship_heat add = 1 } }
    if = { limit = { scope:ddm_kidnap_target = { any_spouse = { highest_held_title_tier >= tier_kingdom } } } change_variable = { name = ddm_kidnap_relationship_heat add = 1 } }
}

# Actor scope; computes three displayed success chances, nonlinear relationship costs, and associated risk.
ddm_calculate_kidnap_chances_effect = {
    # Expedition leadership now has three distinct parts:
    #   Intrigue = route, secrecy, access and deception
    #   Martial  = planning and commanding the team once the operation is in motion
    #   Prowess  = the ruler's own ability when the extraction becomes physical
    # The accompanying knight bench then adds its diminishing-return Prowess contribution.
    set_variable = { name = ddm_kidnap_attack_score value = intrigue }
    change_variable = { name = ddm_kidnap_attack_score multiply = 1.75 }
    set_variable = { name = ddm_kidnap_tmp value = martial }
    change_variable = { name = ddm_kidnap_tmp multiply = 1.25 }
    change_variable = { name = ddm_kidnap_attack_score add = var:ddm_kidnap_tmp }
    change_variable = { name = ddm_kidnap_attack_score add = prowess }
    change_variable = { name = ddm_kidnap_attack_score add = var:ddm_kidnap_knight_prowess }

    # Opposition mirrors the same idea. The target supplies personal resistance; the local ruler supplies
    # security planning/command; and the available defensive knights provide the physical screen.
    set_variable = { name = ddm_kidnap_defense_score value = scope:ddm_kidnap_target.intrigue }
    change_variable = { name = ddm_kidnap_defense_score add = scope:ddm_kidnap_target.prowess }
    set_variable = { name = ddm_kidnap_tmp value = scope:ddm_kidnap_target.martial }
    change_variable = { name = ddm_kidnap_tmp multiply = 0.50 }
    change_variable = { name = ddm_kidnap_defense_score add = var:ddm_kidnap_tmp }
    change_variable = { name = ddm_kidnap_defense_score add = scope:ddm_kidnap_local_ruler.intrigue }
    change_variable = { name = ddm_kidnap_defense_score add = scope:ddm_kidnap_local_ruler.martial }
    set_variable = { name = ddm_kidnap_tmp value = scope:ddm_kidnap_local_ruler.prowess }
    change_variable = { name = ddm_kidnap_tmp multiply = 0.50 }
    change_variable = { name = ddm_kidnap_defense_score add = var:ddm_kidnap_tmp }
    change_variable = { name = ddm_kidnap_defense_score add = var:ddm_kidnap_defender_knight_prowess }

    # Difference is moderated so even a large skill advantage does not produce 100% certainty.
    set_variable = { name = ddm_kidnap_score_delta value = var:ddm_kidnap_attack_score }
    change_variable = { name = ddm_kidnap_score_delta subtract = var:ddm_kidnap_defense_score }
    change_variable = { name = ddm_kidnap_score_delta multiply = 0.75 }

    set_variable = { name = ddm_kidnap_chance_single value = 58 }
    change_variable = { name = ddm_kidnap_chance_single add = var:ddm_kidnap_score_delta }

    set_variable = { name = ddm_kidnap_chance_three value = 48 }
    change_variable = { name = ddm_kidnap_chance_three add = var:ddm_kidnap_score_delta }
    # Each additional person makes extraction a little harder, but not absurdly so.
    set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_three_count }
    change_variable = { name = ddm_kidnap_tmp multiply = 2.25 }
    change_variable = { name = ddm_kidnap_chance_three subtract = var:ddm_kidnap_tmp }

    set_variable = { name = ddm_kidnap_chance_elite value = 38 }
    change_variable = { name = ddm_kidnap_chance_elite add = var:ddm_kidnap_score_delta }
    set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_elite_count }
    change_variable = { name = ddm_kidnap_tmp multiply = 1.35 }
    change_variable = { name = ddm_kidnap_chance_elite subtract = var:ddm_kidnap_tmp }
    if = {
        limit = { has_variable = ddm_kidnap_solo }
        change_variable = { name = ddm_kidnap_chance_three subtract = 12 }
        change_variable = { name = ddm_kidnap_chance_elite subtract = 18 }
    }

    # Existing marriage/concubinage/betrothal is a nonlinear complication, not a hard blocker. The
    # principal target's heat is squared: stealing an ordinary married courtier is meaningfully harder,
    # while taking a ruler's own spouse can become a truly dangerous operation.
    set_variable = { name = ddm_kidnap_relationship_heat_sq value = var:ddm_kidnap_relationship_heat }
    change_variable = { name = ddm_kidnap_relationship_heat_sq multiply = var:ddm_kidnap_relationship_heat }
    set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_relationship_heat_sq }
    change_variable = { name = ddm_kidnap_tmp multiply = 1.25 }
    change_variable = { name = ddm_kidnap_chance_single subtract = var:ddm_kidnap_tmp }
    change_variable = { name = ddm_kidnap_chance_three subtract = var:ddm_kidnap_tmp }
    change_variable = { name = ddm_kidnap_chance_elite subtract = var:ddm_kidnap_tmp }

    # Multi-person raids pay additional risk for every already-attached woman included in the extraction.
    set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_three_attached_count }
    change_variable = { name = ddm_kidnap_tmp multiply = 6 }
    change_variable = { name = ddm_kidnap_chance_three subtract = var:ddm_kidnap_tmp }
    set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_elite_attached_count }
    change_variable = { name = ddm_kidnap_tmp multiply = 4 }
    change_variable = { name = ddm_kidnap_chance_elite subtract = var:ddm_kidnap_tmp }

    # Operational bribes/logistics are likewise nonlinear for the principal target. Unattached targets
    # retain the original zero resource cost. Additional attached captives add a smaller per-person cost.
    set_variable = { name = ddm_kidnap_gold_cost_single value = var:ddm_kidnap_relationship_heat_sq }
    change_variable = { name = ddm_kidnap_gold_cost_single multiply = 50 }
    set_variable = { name = ddm_kidnap_prestige_cost_single value = var:ddm_kidnap_relationship_heat_sq }
    change_variable = { name = ddm_kidnap_prestige_cost_single multiply = 100 }

    set_variable = { name = ddm_kidnap_gold_cost_three value = var:ddm_kidnap_gold_cost_single }
    set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_three_attached_count }
    change_variable = { name = ddm_kidnap_tmp multiply = 150 }
    change_variable = { name = ddm_kidnap_gold_cost_three add = var:ddm_kidnap_tmp }
    set_variable = { name = ddm_kidnap_prestige_cost_three value = var:ddm_kidnap_prestige_cost_single }
    set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_three_attached_count }
    change_variable = { name = ddm_kidnap_tmp multiply = 300 }
    change_variable = { name = ddm_kidnap_prestige_cost_three add = var:ddm_kidnap_tmp }

    set_variable = { name = ddm_kidnap_gold_cost_elite value = var:ddm_kidnap_gold_cost_single }
    set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_elite_attached_count }
    change_variable = { name = ddm_kidnap_tmp multiply = 100 }
    change_variable = { name = ddm_kidnap_gold_cost_elite add = var:ddm_kidnap_tmp }
    set_variable = { name = ddm_kidnap_prestige_cost_elite value = var:ddm_kidnap_prestige_cost_single }
    set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_elite_attached_count }
    change_variable = { name = ddm_kidnap_tmp multiply = 200 }
    change_variable = { name = ddm_kidnap_prestige_cost_elite add = var:ddm_kidnap_tmp }

    # Larger political jurisdictions are harder to penetrate. Empire/Hegemony is a natural extension
    # of county/duchy/kingdom and is intentionally only moderately harder, not an astronomical wall.
    if = { limit = { scope:ddm_kidnap_local_ruler = { highest_held_title_tier = tier_duchy } } change_variable = { name = ddm_kidnap_chance_single subtract = 3 } change_variable = { name = ddm_kidnap_chance_three subtract = 4 } change_variable = { name = ddm_kidnap_chance_elite subtract = 5 } }
    else_if = { limit = { scope:ddm_kidnap_local_ruler = { highest_held_title_tier = tier_kingdom } } change_variable = { name = ddm_kidnap_chance_single subtract = 6 } change_variable = { name = ddm_kidnap_chance_three subtract = 8 } change_variable = { name = ddm_kidnap_chance_elite subtract = 10 } }
    else_if = { limit = { scope:ddm_kidnap_local_ruler = { highest_held_title_tier >= tier_empire } } change_variable = { name = ddm_kidnap_chance_single subtract = 10 } change_variable = { name = ddm_kidnap_chance_three subtract = 12 } change_variable = { name = ddm_kidnap_chance_elite subtract = 15 } }

    if = { limit = { var:ddm_kidnap_chance_single < 15 } set_variable = { name = ddm_kidnap_chance_single value = 15 } }
    if = { limit = { var:ddm_kidnap_chance_single > 90 } set_variable = { name = ddm_kidnap_chance_single value = 90 } }
    if = { limit = { var:ddm_kidnap_chance_three < 12 } set_variable = { name = ddm_kidnap_chance_three value = 12 } }
    if = { limit = { var:ddm_kidnap_chance_three > 85 } set_variable = { name = ddm_kidnap_chance_three value = 85 } }
    if = { limit = { var:ddm_kidnap_chance_elite < 8 } set_variable = { name = ddm_kidnap_chance_elite value = 8 } }
    if = { limit = { var:ddm_kidnap_chance_elite > 75 } set_variable = { name = ddm_kidnap_chance_elite value = 75 } }
}

# Human composition choice. The preparation pass initially records the full available retinue. Going
# alone deliberately discards that Prowess contribution and therefore lowers success naturally; the
# benefit is that nobody else can be captured with the ruler if the operation is blown.
ddm_kidnap_choose_retinue_effect = {
    remove_variable = ddm_kidnap_solo
    ddm_set_kidnap_capacity_effect = yes
    ddm_rebuild_kidnap_capture_lists_effect = yes
    ddm_calculate_kidnap_chances_effect = yes
}

ddm_kidnap_choose_solo_effect = {
    set_variable = { name = ddm_kidnap_solo value = 1 }
    clear_variable_list = ddm_kidnap_party_knights
    set_variable = { name = ddm_kidnap_knight_prowess value = 0 }
    set_variable = { name = ddm_kidnap_party_count value = 0 }
    ddm_set_kidnap_capacity_effect = yes
    ddm_rebuild_kidnap_capture_lists_effect = yes
    ddm_calculate_kidnap_chances_effect = yes
}

# Player-only fallback generator. Existing candidates are always used first. When a thin political
# sub-realm cannot supply the variable expedition floor, create only the missing number in the target
# ruler's court. Generated women are young local noblewomen with strong hereditary/personality packages.
ddm_generate_kidnap_bride_effect = {
    scope:ddm_kidnap_local_ruler = {
        create_character = {
            age = { 18 30 }
            gender_female_chance = 100
            culture = scope:ddm_kidnap_local_ruler.culture
            faith = scope:ddm_kidnap_local_ruler.faith
            employer = scope:ddm_kidnap_local_ruler
            dynasty = generate
            random_traits = no
            fertility = 0.75
            random_traits_list = {
                count = 3
                diligent = {}
                patient = {}
                brave = {}
                calm = {}
                temperate = {}
                just = {}
                honest = {}
                compassionate = {}
                generous = {}
                gregarious = {}
            }
            diplomacy = { min_template_decent_skill max_template_high_skill }
            martial = { min_template_low_skill max_template_high_skill }
            stewardship = { min_template_decent_skill max_template_high_skill }
            intrigue = { min_template_decent_skill max_template_high_skill }
            learning = { min_template_decent_skill max_template_high_skill }
            prowess = { min_template_low_skill max_template_high_skill }
            save_scope_as = ddm_generated_bride
        }
    }

    scope:ddm_generated_bride = {
        add_character_flag = ddm_generated_kidnap_bride
        random_list = {
            30 = { add_trait = intellect_good_1 add_trait = physique_good_1 add_trait = beauty_good_1 }
            25 = { add_trait = intellect_good_2 add_trait = physique_good_2 }
            20 = { add_trait = intellect_good_2 add_trait = beauty_good_2 }
            15 = { add_trait = intellect_good_3 add_trait = physique_good_1 }
            10 = { add_trait = physique_good_3 add_trait = beauty_good_1 }
        }
        add_prestige = 300
    }

    if = {
        limit = { var:ddm_kidnap_mode = 2 }
        add_to_variable_list = { name = ddm_kidnap_three_brides target = scope:ddm_generated_bride }
        change_variable = { name = ddm_kidnap_three_count add = 1 }
    }
    else = {
        add_to_variable_list = { name = ddm_kidnap_elite_brides target = scope:ddm_generated_bride }
        change_variable = { name = ddm_kidnap_elite_count add = 1 }
    }
}

# Called only from human event choices. Real candidates remain preferred. If the political sub-realm is
# unusually thin, generate a *variable* local fallback scaled to expedition capacity instead of always
# forcing exactly three additional captives. This prevents the old principal+3 = four-person result while
# still avoiding an automatic factory that fills every 15/25-capacity expedition to the hard ceiling.
ddm_ensure_kidnap_bride_minimum_effect = {
    set_variable = { name = ddm_kidnap_generation_floor value = 1 }

    if = {
        limit = { var:ddm_kidnap_capacity <= 1 }
        set_variable = { name = ddm_kidnap_generation_floor value = 1 }
    }
    else_if = {
        limit = { var:ddm_kidnap_capacity <= 3 }
        random_list = {
            25 = { set_variable = { name = ddm_kidnap_generation_floor value = 1 } }
            45 = { set_variable = { name = ddm_kidnap_generation_floor value = 2 } }
            30 = { set_variable = { name = ddm_kidnap_generation_floor value = 3 } }
        }
    }
    else_if = {
        limit = { var:ddm_kidnap_capacity <= 6 }
        random_list = {
            15 = { set_variable = { name = ddm_kidnap_generation_floor value = 2 } }
            30 = { set_variable = { name = ddm_kidnap_generation_floor value = 3 } }
            30 = { set_variable = { name = ddm_kidnap_generation_floor value = 4 } }
            20 = { set_variable = { name = ddm_kidnap_generation_floor value = 5 } }
            5 = { set_variable = { name = ddm_kidnap_generation_floor value = 6 } }
        }
    }
    else_if = {
        limit = { var:ddm_kidnap_capacity <= 10 }
        random_list = {
            10 = { set_variable = { name = ddm_kidnap_generation_floor value = 3 } }
            20 = { set_variable = { name = ddm_kidnap_generation_floor value = 4 } }
            25 = { set_variable = { name = ddm_kidnap_generation_floor value = 5 } }
            20 = { set_variable = { name = ddm_kidnap_generation_floor value = 6 } }
            15 = { set_variable = { name = ddm_kidnap_generation_floor value = 7 } }
            7 = { set_variable = { name = ddm_kidnap_generation_floor value = 8 } }
            2 = { set_variable = { name = ddm_kidnap_generation_floor value = 9 } }
            1 = { set_variable = { name = ddm_kidnap_generation_floor value = 10 } }
        }
    }
    else_if = {
        limit = { var:ddm_kidnap_capacity <= 15 }
        random_list = {
            8 = { set_variable = { name = ddm_kidnap_generation_floor value = 4 } }
            15 = { set_variable = { name = ddm_kidnap_generation_floor value = 5 } }
            20 = { set_variable = { name = ddm_kidnap_generation_floor value = 6 } }
            20 = { set_variable = { name = ddm_kidnap_generation_floor value = 7 } }
            15 = { set_variable = { name = ddm_kidnap_generation_floor value = 8 } }
            10 = { set_variable = { name = ddm_kidnap_generation_floor value = 9 } }
            6 = { set_variable = { name = ddm_kidnap_generation_floor value = 10 } }
            3 = { set_variable = { name = ddm_kidnap_generation_floor value = 11 } }
            2 = { set_variable = { name = ddm_kidnap_generation_floor value = 12 } }
            1 = { set_variable = { name = ddm_kidnap_generation_floor value = 15 } }
        }
    }
    else = {
        random_list = {
            5 = { set_variable = { name = ddm_kidnap_generation_floor value = 5 } }
            10 = { set_variable = { name = ddm_kidnap_generation_floor value = 7 } }
            20 = { set_variable = { name = ddm_kidnap_generation_floor value = 9 } }
            25 = { set_variable = { name = ddm_kidnap_generation_floor value = 11 } }
            20 = { set_variable = { name = ddm_kidnap_generation_floor value = 13 } }
            10 = { set_variable = { name = ddm_kidnap_generation_floor value = 15 } }
            6 = { set_variable = { name = ddm_kidnap_generation_floor value = 18 } }
            3 = { set_variable = { name = ddm_kidnap_generation_floor value = 21 } }
            1 = { set_variable = { name = ddm_kidnap_generation_floor value = 25 } }
        }
    }

    if = {
        limit = { var:ddm_kidnap_generation_floor > var:ddm_kidnap_capacity }
        set_variable = { name = ddm_kidnap_generation_floor value = var:ddm_kidnap_capacity }
    }

    if = {
        limit = { var:ddm_kidnap_mode = 2 }
        # Stop if the callback fails to advance the counter; never spin indefinitely.
        set_variable = { name = ddm_generation_attempts value = 0 }
        set_variable = { name = ddm_generation_progress value = 1 }
        while = {
            limit = {
                var:ddm_kidnap_three_count < var:ddm_kidnap_generation_floor
                var:ddm_generation_attempts < 25
                var:ddm_generation_progress = 1
            }
            change_variable = { name = ddm_generation_attempts add = 1 }
            set_variable = { name = ddm_generation_previous_count value = var:ddm_kidnap_three_count }
            ddm_generate_kidnap_bride_effect = yes
            if = {
                limit = { var:ddm_kidnap_three_count <= var:ddm_generation_previous_count }
                set_variable = { name = ddm_generation_progress value = 0 }
            }
        }
        remove_variable = ddm_generation_attempts
        remove_variable = ddm_generation_progress
        remove_variable = ddm_generation_previous_count
    }
    else_if = {
        limit = { var:ddm_kidnap_mode = 3 }
        # Stop if the callback fails to advance the counter; never spin indefinitely.
        set_variable = { name = ddm_generation_attempts value = 0 }
        set_variable = { name = ddm_generation_progress value = 1 }
        while = {
            limit = {
                var:ddm_kidnap_elite_count < var:ddm_kidnap_generation_floor
                var:ddm_generation_attempts < 25
                var:ddm_generation_progress = 1
            }
            change_variable = { name = ddm_generation_attempts add = 1 }
            set_variable = { name = ddm_generation_previous_count value = var:ddm_kidnap_elite_count }
            ddm_generate_kidnap_bride_effect = yes
            if = {
                limit = { var:ddm_kidnap_elite_count <= var:ddm_generation_previous_count }
                set_variable = { name = ddm_generation_progress value = 0 }
            }
        }
        remove_variable = ddm_generation_attempts
        remove_variable = ddm_generation_progress
        remove_variable = ddm_generation_previous_count
    }
    remove_variable = ddm_kidnap_generation_floor
    ddm_calculate_kidnap_chances_effect = yes
}

# Actor scope. Selects the mode and schedules the actual expedition, preserving the selected real people.
ddm_start_kidnap_expedition_effect = {
    add_character_flag = { flag = ddm_kidnap_operation_active days = 60 }

    # Annual quota bookkeeping: four base attempts/successes. Every failure grants one replacement
    # attempt, up to eight total attempts. Variables reset on yearly_playable_pulse.
    if = { limit = { NOT = { has_variable = ddm_kidnap_attempt_allowance_year } } set_variable = { name = ddm_kidnap_attempt_allowance_year value = 4 } }
    if = { limit = { NOT = { has_variable = ddm_kidnap_attempts_year } } set_variable = { name = ddm_kidnap_attempts_year value = 0 } }
    if = { limit = { NOT = { has_variable = ddm_kidnap_successes_year } } set_variable = { name = ddm_kidnap_successes_year value = 0 } }
    if = { limit = { NOT = { has_variable = ddm_kidnap_failures_year } } set_variable = { name = ddm_kidnap_failures_year value = 0 } }
    change_variable = { name = ddm_kidnap_attempts_year add = 1 }

    # Pay the relationship-driven operational cost at departure. This is allowed to push the raider into
    # debt/negative prestige: attempting to steal a king's spouse while unable to afford the network is
    # itself part of the consequence rather than a silent button disappearance.
    if = {
        limit = { var:ddm_kidnap_mode = 1 }
        set_variable = { name = ddm_kidnap_current_gold_cost value = var:ddm_kidnap_gold_cost_single }
        set_variable = { name = ddm_kidnap_current_prestige_cost value = var:ddm_kidnap_prestige_cost_single }
    }
    else_if = {
        limit = { var:ddm_kidnap_mode = 2 }
        set_variable = { name = ddm_kidnap_current_gold_cost value = var:ddm_kidnap_gold_cost_three }
        set_variable = { name = ddm_kidnap_current_prestige_cost value = var:ddm_kidnap_prestige_cost_three }
    }
    else = {
        set_variable = { name = ddm_kidnap_current_gold_cost value = var:ddm_kidnap_gold_cost_elite }
        set_variable = { name = ddm_kidnap_current_prestige_cost value = var:ddm_kidnap_prestige_cost_elite }
    }
    add_gold = { value = var:ddm_kidnap_current_gold_cost multiply = -1 }
    add_prestige = { value = var:ddm_kidnap_current_prestige_cost multiply = -1 }

    if = {
        limit = { var:ddm_kidnap_mode = 1 }
        set_variable = { name = ddm_kidnap_current_chance value = var:ddm_kidnap_chance_single }
        set_variable = { name = ddm_kidnap_harm_base value = 10 }
        trigger_event = { id = ddm_manager.5001 days = 14 }
    }
    else_if = {
        limit = { var:ddm_kidnap_mode = 2 }
        set_variable = { name = ddm_kidnap_current_chance value = var:ddm_kidnap_chance_three }
        set_variable = { name = ddm_kidnap_harm_base value = 18 }
        trigger_event = { id = ddm_manager.5001 days = 21 }
    }
    else = {
        set_variable = { name = ddm_kidnap_current_chance value = var:ddm_kidnap_chance_elite }
        set_variable = { name = ddm_kidnap_harm_base value = 28 }
        trigger_event = { id = ddm_manager.5001 days = 30 }
    }
}

# Actor scope. Put one victim physically under the actor's custody as a prisoner.
ddm_capture_kidnap_victim_effect = {
    # Requires scope:ddm_kidnap_victim and scope:ddm_kidnap_retaliator. Imprisonment itself is
    # the custody transfer; origin metadata lets retaliation/recovery restore the character later.
    scope:ddm_kidnap_victim = {
        save_temporary_scope_as = ddm_kidnap_capture_person
        set_variable = { name = ddm_kidnap_origin_top_liege value = scope:ddm_kidnap_retaliator }
        set_variable = { name = ddm_kidnap_abductor_top_liege value = scope:ddm_kidnap_defending_top_liege }
        add_opinion = { target = scope:ddm_kidnap_actor modifier = ddm_kidnapped_me_opinion }
    }
    # Imprisonment is the custody transfer. Do NOT also set_employer here: changing court and
    # imprisonment back-to-back fires two major character-transition chains for every captive.
    # Large raids multiplied that across 10-25 victims on a single simulation day and could visibly
    # pin the calendar. If a recovery war succeeds, its victory effect still explicitly returns the
    # released captive to the original ruler's court.
    imprison = { target = scope:ddm_kidnap_capture_person type = house_arrest }
    change_variable = { name = ddm_kidnap_captured_count add = 1 }

    # Preserve the first eight names for the human result event. Larger elite sweeps still report
    # the total count and an "and X more" line.
    if = { limit = { var:ddm_kidnap_captured_count = 1 } scope:ddm_kidnap_capture_person = { save_scope_as = ddm_kidnap_captured_1 } }
    else_if = { limit = { var:ddm_kidnap_captured_count = 2 } scope:ddm_kidnap_capture_person = { save_scope_as = ddm_kidnap_captured_2 } }
    else_if = { limit = { var:ddm_kidnap_captured_count = 3 } scope:ddm_kidnap_capture_person = { save_scope_as = ddm_kidnap_captured_3 } }
    else_if = { limit = { var:ddm_kidnap_captured_count = 4 } scope:ddm_kidnap_capture_person = { save_scope_as = ddm_kidnap_captured_4 } }
    else_if = { limit = { var:ddm_kidnap_captured_count = 5 } scope:ddm_kidnap_capture_person = { save_scope_as = ddm_kidnap_captured_5 } }
    else_if = { limit = { var:ddm_kidnap_captured_count = 6 } scope:ddm_kidnap_capture_person = { save_scope_as = ddm_kidnap_captured_6 } }
    else_if = { limit = { var:ddm_kidnap_captured_count = 7 } scope:ddm_kidnap_capture_person = { save_scope_as = ddm_kidnap_captured_7 } }
    else_if = { limit = { var:ddm_kidnap_captured_count = 8 } scope:ddm_kidnap_capture_person = { save_scope_as = ddm_kidnap_captured_8 } }
}

# Actor scope. Applies the selected mode after a successful expedition.
ddm_apply_kidnap_success_effect = {
    set_variable = { name = ddm_kidnap_captured_count value = 0 }
    remove_variable = ddm_kidnap_captured_more

    # Principal target first. v1.8 incorrectly checked the attempt-cooldown flag here after setting it
    # at departure, so a successful roll could report success while capturing nobody.
    if = {
        limit = { scope:ddm_kidnap_target = { ddm_kidnap_resolution_target_trigger = yes } }
        scope:ddm_kidnap_target = { save_scope_as = ddm_kidnap_victim }
        ddm_capture_kidnap_victim_effect = yes
    }

    if = {
        limit = { var:ddm_kidnap_mode = 2 has_variable_list = ddm_kidnap_three_brides }
        every_in_list = {
            variable = ddm_kidnap_three_brides
            limit = { ddm_kidnap_resolution_target_trigger = yes }
            save_temporary_scope_as = ddm_kidnap_victim
            scope:ddm_kidnap_actor = { ddm_capture_kidnap_victim_effect = yes }
        }
    }
    else_if = {
        limit = { var:ddm_kidnap_mode = 3 has_variable_list = ddm_kidnap_elite_brides }
        every_in_list = {
            variable = ddm_kidnap_elite_brides
            limit = { ddm_kidnap_resolution_target_trigger = yes }
            save_temporary_scope_as = ddm_kidnap_victim
            scope:ddm_kidnap_actor = { ddm_capture_kidnap_victim_effect = yes }
        }
    }

    if = {
        limit = { var:ddm_kidnap_captured_count > 8 }
        set_variable = { name = ddm_kidnap_captured_more value = var:ddm_kidnap_captured_count }
        change_variable = { name = ddm_kidnap_captured_more subtract = 8 }
    }

    if = {
        limit = { var:ddm_kidnap_captured_count > 0 }
        scope:ddm_kidnap_local_ruler = {
            add_opinion = { target = scope:ddm_kidnap_actor modifier = ddm_kidnapped_family_opinion }
        }
        # A spouse/concubine's own partners also react directly. This matters when plural marriage or
        # modded relationship structures make the offended partner different from the target's liege.
        scope:ddm_kidnap_target = {
            every_consort = { add_opinion = { target = scope:ddm_kidnap_actor modifier = ddm_kidnapped_family_opinion } }
        }
        ddm_roll_kidnap_retaliation_effect = yes
    }
    else = {
        # A target becoming invalid during travel is a failed expedition, not a ghost success.
        remove_variable = ddm_kidnap_success
    }
}

# Actor scope. Wounds either the ruler or one of the participating knights. Existing wounds escalate.
ddm_apply_kidnap_injury_effect = {
    if = {
        limit = { has_variable_list = ddm_kidnap_party_knights }
        random_list = {
            25 = { save_scope_as = ddm_kidnap_injured }
            75 = {
                random_in_list = {
                    variable = ddm_kidnap_party_knights
                    limit = { is_alive = yes }
                    save_scope_as = ddm_kidnap_injured
                }
            }
        }
    }
    else = { save_scope_as = ddm_kidnap_injured }

    if = {
        limit = { exists = scope:ddm_kidnap_injured }
        scope:ddm_kidnap_injured = {
            if = {
                limit = { OR = { has_trait = wounded_1 has_trait = wounded_2 } }
                change_trait_rank = { trait = wounded rank = 1 max = 3 }
            }
            else_if = { limit = { has_trait = wounded_3 } }
            else = {
                random_list = {
                    80 = { add_trait = wounded_1 }
                    20 = { add_trait = wounded_2 }
                }
            }
        }
    }
}

# Actor scope. Retaliation is a political choice represented as a probability. The more people taken and
# the more important the target, the more likely the victim's top liege starts an event-only retrieval war.
ddm_roll_kidnap_retaliation_effect = {
    # Recovery wars are intentionally exceptional. The principal captive must matter, AI rulers only
    # escalate for their own close household/dynastic interests, and every successful declaration
    # creates shared attacker/defender/captive cooldowns so one kidnapping campaign cannot generate a
    # chain of repetitive wars.
    set_variable = { name = ddm_kidnap_war_chance value = 0 }

    if = {
        limit = {
            exists = scope:ddm_kidnap_target
            scope:ddm_kidnap_target = {
                is_alive = yes
                is_imprisoned = yes
                NOT = { has_character_flag = ddm_retrieval_war_attempted }
                OR = {
                    is_close_family_of = scope:ddm_kidnap_local_ruler
                    is_spouse_of = scope:ddm_kidnap_local_ruler
                    is_consort_of = scope:ddm_kidnap_local_ruler
                    is_heir_of = scope:ddm_kidnap_local_ruler
                    is_close_family_of = scope:ddm_kidnap_retaliator
                    is_spouse_of = scope:ddm_kidnap_retaliator
                    is_consort_of = scope:ddm_kidnap_retaliator
                    is_heir_of = scope:ddm_kidnap_retaliator
                }
            }
            # AI top lieges no longer start realm-wide recovery wars merely because a distant vassal's
            # spouse/courtier was taken. Human rulers may still choose to defend a subordinate household.
            OR = {
                scope:ddm_kidnap_retaliator = { is_ai = no }
                scope:ddm_kidnap_target = {
                    OR = {
                        is_close_family_of = scope:ddm_kidnap_retaliator
                        is_spouse_of = scope:ddm_kidnap_retaliator
                        is_consort_of = scope:ddm_kidnap_retaliator
                        is_heir_of = scope:ddm_kidnap_retaliator
                    }
                }
            }
        }

        # Human retaliation remains dramatic; AI retaliation is tuned by the existing kidnapping rule.
        # Disabled means no autonomous DDM recovery war. Player Only still lets an AI realm react to a
        # player kidnapping, but at a deliberately very low rate rather than turning every abduction into war.
        if = {
            limit = { scope:ddm_kidnap_retaliator = { is_ai = yes } }
            if = {
                limit = { has_game_rule = ddm_kidnap_disabled }
                set_variable = { name = ddm_kidnap_war_chance value = 0 }
            }
            else_if = {
                limit = { has_game_rule = ddm_kidnap_player_only }
                set_variable = { name = ddm_kidnap_war_chance value = 3 }
            }
            else_if = {
                limit = { has_game_rule = ddm_kidnap_aggressive_ai }
                set_variable = { name = ddm_kidnap_war_chance value = 12 }
            }
            else = {
                set_variable = { name = ddm_kidnap_war_chance value = 6 }
            }
        }
        else = {
            set_variable = { name = ddm_kidnap_war_chance value = 18 }
        }

        if = { limit = { scope:ddm_kidnap_target = { is_close_family_of = scope:ddm_kidnap_retaliator } } change_variable = { name = ddm_kidnap_war_chance add = 10 } }
        if = { limit = { scope:ddm_kidnap_target = { is_heir_of = scope:ddm_kidnap_retaliator } } change_variable = { name = ddm_kidnap_war_chance add = 18 } }
        if = { limit = { scope:ddm_kidnap_target = { OR = { is_spouse_of = scope:ddm_kidnap_retaliator is_consort_of = scope:ddm_kidnap_retaliator } } } change_variable = { name = ddm_kidnap_war_chance add = 14 } }

        # A broader raid raises the political temperature, but no longer turns retaliation into a near
        # certainty.
        if = { limit = { var:ddm_kidnap_mode = 2 } change_variable = { name = ddm_kidnap_war_chance add = 3 } }
        if = { limit = { var:ddm_kidnap_mode = 3 } change_variable = { name = ddm_kidnap_war_chance add = 5 } }
        if = { limit = { scope:ddm_kidnap_retaliator = { OR = { has_trait = wrathful has_trait = brave has_trait = arrogant } } } change_variable = { name = ddm_kidnap_war_chance add = 4 } }
        if = { limit = { scope:ddm_kidnap_retaliator = { OR = { has_trait = craven has_trait = content } } } change_variable = { name = ddm_kidnap_war_chance subtract = 8 } }
    }

    if = { limit = { var:ddm_kidnap_war_chance < 0 } set_variable = { name = ddm_kidnap_war_chance value = 0 } }
    if = {
        limit = { scope:ddm_kidnap_retaliator = { is_ai = yes } has_game_rule = ddm_kidnap_player_only var:ddm_kidnap_war_chance > 20 }
        set_variable = { name = ddm_kidnap_war_chance value = 20 }
    }
    else_if = {
        limit = { scope:ddm_kidnap_retaliator = { is_ai = yes } has_game_rule = ddm_kidnap_aggressive_ai var:ddm_kidnap_war_chance > 50 }
        set_variable = { name = ddm_kidnap_war_chance value = 50 }
    }
    else_if = {
        limit = { scope:ddm_kidnap_retaliator = { is_ai = yes } var:ddm_kidnap_war_chance > 35 }
        set_variable = { name = ddm_kidnap_war_chance value = 35 }
    }
    else_if = {
        limit = { var:ddm_kidnap_war_chance > 70 }
        set_variable = { name = ddm_kidnap_war_chance value = 70 }
    }

    if = {
        limit = {
            var:ddm_kidnap_war_chance > 0
            exists = scope:ddm_kidnap_defending_top_liege
            scope:ddm_kidnap_retaliator = {
                is_alive = yes
                is_landed = yes
                is_at_war = no
                is_imprisoned = no
                NOT = { this = scope:ddm_kidnap_defending_top_liege }
                NOT = { has_character_flag = ddm_kidnap_retrieval_war_cooldown }
                # Human rulers are not strength-gated; AI avoids wars against a stronger kidnapper realm.
                OR = {
                    is_ai = no
                    current_military_strength >= scope:ddm_kidnap_defending_top_liege.current_military_strength
                }
            }
            scope:ddm_kidnap_defending_top_liege = {
                is_alive = yes
                is_landed = yes
                is_at_war = no
                NOT = { has_character_flag = ddm_retrieval_war_target_cooldown }
            }
        }
        # Mark the captive as considered even if the ruler ultimately chooses not to escalate. This
        # prevents multiple callbacks from rerolling the same political decision.
        scope:ddm_kidnap_target = { add_character_flag = { flag = ddm_retrieval_war_attempted years = 10 } }

        random = {
            chance = var:ddm_kidnap_war_chance
            scope:ddm_kidnap_retaliator = {
                set_variable = { name = ddm_kidnap_retrieval_target value = scope:ddm_kidnap_target }
                if = {
                    limit = { is_ai = no }
                    add_character_flag = { flag = ddm_kidnap_retrieval_war_cooldown years = 5 }
                }
                else_if = {
                    limit = { has_game_rule = ddm_kidnap_aggressive_ai }
                    add_character_flag = { flag = ddm_kidnap_retrieval_war_cooldown years = 7 }
                }
                else = {
                    add_character_flag = { flag = ddm_kidnap_retrieval_war_cooldown years = 10 }
                }
                start_war = { casus_belli = ddm_kidnap_retrieval_cb target = scope:ddm_kidnap_defending_top_liege }
            }
            scope:ddm_kidnap_defending_top_liege = {
                add_character_flag = { flag = ddm_retrieval_war_target_cooldown years = 3 }
            }
            set_variable = { name = ddm_kidnap_war_started value = 1 }
        }
    }
}

# Actor scope. A failed expedition can be exposed and physically trapped. When the ruler brought a
# retinue, the same local ruler who catches the raider also takes every participating knight/champion
# prisoner. A solo raider risks only themselves.
ddm_apply_kidnap_caught_effect = {
    set_variable = { name = ddm_kidnap_caught value = 1 }
    set_variable = { name = ddm_kidnap_captured_retinue_count value = 0 }

    scope:ddm_kidnap_local_ruler = {
        add_opinion = { target = scope:ddm_kidnap_actor modifier = ddm_kidnapped_family_opinion }
        imprison = { target = scope:ddm_kidnap_actor type = dungeon }
    }

    # Existing lawful/recognized partners of the intended target remember the attempt even though it failed.
    # every_consort covers the marriage/concubinage relationship set in CK3 and remains compatible with
    # plural-marriage playsets.
    scope:ddm_kidnap_target = {
        every_consort = { add_opinion = { target = scope:ddm_kidnap_actor modifier = ddm_kidnapped_family_opinion } }
    }

    if = {
        limit = { NOT = { has_variable = ddm_kidnap_solo } has_variable_list = ddm_kidnap_party_knights }
        every_in_list = {
            variable = ddm_kidnap_party_knights
            limit = { is_alive = yes is_imprisoned = no }
            save_temporary_scope_as = ddm_kidnap_caught_knight
            scope:ddm_kidnap_local_ruler = {
                imprison = { target = scope:ddm_kidnap_caught_knight type = dungeon }
            }
            scope:ddm_kidnap_actor = { change_variable = { name = ddm_kidnap_captured_retinue_count add = 1 } }
        }
    }
}

# Actor scope. Being caught is not the same roll as failing: some failed expeditions escape cleanly.
# Existing relationship heat is squared, so attempting to steal a ruler's lawful spouse is much more
# likely to end with the raider physically captured than an ordinary failed courtier snatch.
ddm_roll_kidnap_caught_effect = {
    set_variable = { name = ddm_kidnap_caught_chance value = 8 }
    if = { limit = { var:ddm_kidnap_mode = 2 } set_variable = { name = ddm_kidnap_caught_chance value = 14 } }
    else_if = { limit = { var:ddm_kidnap_mode = 3 } set_variable = { name = ddm_kidnap_caught_chance value = 22 } }

    set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_relationship_heat_sq }
    change_variable = { name = ddm_kidnap_tmp multiply = 1.5 }
    change_variable = { name = ddm_kidnap_caught_chance add = var:ddm_kidnap_tmp }

    if = {
        limit = { var:ddm_kidnap_mode = 2 }
        set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_three_attached_count }
        change_variable = { name = ddm_kidnap_tmp multiply = 5 }
        change_variable = { name = ddm_kidnap_caught_chance add = var:ddm_kidnap_tmp }
    }
    else_if = {
        limit = { var:ddm_kidnap_mode = 3 }
        set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_elite_attached_count }
        change_variable = { name = ddm_kidnap_tmp multiply = 4 }
        change_variable = { name = ddm_kidnap_caught_chance add = var:ddm_kidnap_tmp }
    }

    if = {
        limit = { has_variable = ddm_kidnap_solo }
        change_variable = { name = ddm_kidnap_caught_chance subtract = 5 }
    }
    else = {
        # Large teams are stronger but much harder to make disappear when the plan collapses.
        set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_party_count }
        change_variable = { name = ddm_kidnap_tmp multiply = 0.5 }
        if = { limit = { var:ddm_kidnap_tmp > 15 } set_variable = { name = ddm_kidnap_tmp value = 15 } }
        change_variable = { name = ddm_kidnap_caught_chance add = var:ddm_kidnap_tmp }
    }

    if = { limit = { scope:ddm_kidnap_local_ruler = { highest_held_title_tier = tier_kingdom } } change_variable = { name = ddm_kidnap_caught_chance add = 5 } }
    else_if = { limit = { scope:ddm_kidnap_local_ruler = { highest_held_title_tier >= tier_empire } } change_variable = { name = ddm_kidnap_caught_chance add = 10 } }

    if = { limit = { var:ddm_kidnap_caught_chance < 2 } set_variable = { name = ddm_kidnap_caught_chance value = 2 } }
    if = { limit = { var:ddm_kidnap_caught_chance > 75 } set_variable = { name = ddm_kidnap_caught_chance value = 75 } }

    random = {
        chance = var:ddm_kidnap_caught_chance
        ddm_apply_kidnap_caught_effect = yes
    }
}

# Actor scope. Resolve the expedition and then roll injury. Failed operations are more dangerous.
ddm_resolve_kidnap_expedition_effect = {
    remove_variable = ddm_kidnap_success
    remove_variable = ddm_kidnap_war_started
    if = {
        limit = { scope:ddm_kidnap_target = { ddm_kidnap_resolution_target_trigger = yes } }
        random = {
            chance = var:ddm_kidnap_current_chance
            set_variable = { name = ddm_kidnap_success value = 1 }
            ddm_apply_kidnap_success_effect = yes
        }
    }

    if = {
        limit = { has_variable = ddm_kidnap_success }
        change_variable = { name = ddm_kidnap_successes_year add = 1 }
    }
    else = {
        change_variable = { name = ddm_kidnap_failures_year add = 1 }
        if = {
            limit = { var:ddm_kidnap_attempt_allowance_year < 8 }
            change_variable = { name = ddm_kidnap_attempt_allowance_year add = 1 }
        }
        ddm_roll_kidnap_caught_effect = yes
    }

    set_variable = { name = ddm_kidnap_harm_chance value = var:ddm_kidnap_harm_base }
    if = { limit = { NOT = { has_variable = ddm_kidnap_success } } change_variable = { name = ddm_kidnap_harm_chance add = 12 } }
    set_variable = { name = ddm_kidnap_tmp value = var:ddm_kidnap_relationship_heat }
    change_variable = { name = ddm_kidnap_tmp multiply = 3 }
    change_variable = { name = ddm_kidnap_harm_chance add = var:ddm_kidnap_tmp }
    random = {
        chance = var:ddm_kidnap_harm_chance
        ddm_apply_kidnap_injury_effect = yes
    }
}

# AI entry point. A ruler considers a nearby foreign court only. Strategic AI usually takes one high-value
# person; Aggressive AI is more willing to raid for several. This avoids global character scans.
ddm_ai_kidnap_yearly_effect = {
    save_scope_as = ddm_kidnap_actor
    if = {
        limit = {
            is_ai = yes
            is_alive = yes
            is_landed = yes
            is_imprisoned = no
            is_at_war = no
            NOT = { has_game_rule = ddm_kidnap_disabled }
            NOT = { has_game_rule = ddm_kidnap_player_only }
            NOT = { has_character_flag = ddm_kidnap_operation_active }
            ddm_kidnap_quota_available_trigger = yes
        }
        random = {
            chance = 2
            modifier = { add = 3 has_game_rule = ddm_kidnap_aggressive_ai }
            random_neighboring_and_across_water_top_liege_realm_owner = {
                limit = {
                    is_alive = yes
                    is_landed = yes
                    NOT = { this = scope:ddm_kidnap_actor }
                }
                save_scope_as = ddm_kidnap_local_ruler
                ordered_courtier_or_guest = {
                    limit = { ddm_kidnap_ai_candidate_trigger = yes }
                    order_by = ddm_kidnap_ai_target_value
                    position = 0
                    check_range_bounds = no
                    save_scope_as = ddm_kidnap_target
                }
            }
            if = {
                limit = { exists = scope:ddm_kidnap_target }
                ddm_prepare_kidnap_context_effect = yes
                set_variable = { name = ddm_kidnap_mode value = 1 }
                if = {
                    limit = { has_game_rule = ddm_kidnap_aggressive_ai }
                    # Aggressive AI can use the same escalation ladder as the player, but mass raids
                    # remain uncommon so this mode does not vacuum every neighboring court.
                    if = {
                        limit = { var:ddm_kidnap_elite_count > 0 }
                        random = { chance = 10 set_variable = { name = ddm_kidnap_mode value = 3 } }
                    }
                    if = {
                        limit = { var:ddm_kidnap_mode = 1 var:ddm_kidnap_three_count > 0 }
                        random = { chance = 25 set_variable = { name = ddm_kidnap_mode value = 2 } }
                    }
                }
                ddm_start_kidnap_expedition_effect = yes
            }
        }
    }
}

# Actor scope. Clear transient expedition bookkeeping after the result has been reported.
ddm_cleanup_kidnap_effect = {
    # Clear the operation lock immediately whenever the expedition resolves/cancels.
    # The 60-day timed flag remains only as a failsafe if an event is interrupted.
    remove_character_flag = ddm_kidnap_operation_active
    clear_variable_list = ddm_kidnap_party_knights
    clear_variable_list = ddm_kidnap_local_pool
    clear_variable_list = ddm_kidnap_three_brides
    clear_variable_list = ddm_kidnap_elite_brides
    remove_variable = ddm_kidnap_knight_prowess
    remove_variable = ddm_kidnap_defender_knight_prowess
    remove_variable = ddm_kidnap_party_count
    remove_variable = ddm_kidnap_defender_count
    remove_variable = ddm_kidnap_knight_tmp
    remove_variable = ddm_kidnap_defender_tmp
    remove_variable = ddm_kidnap_three_count
    remove_variable = ddm_kidnap_elite_count
    remove_variable = ddm_kidnap_attack_score
    remove_variable = ddm_kidnap_defense_score
    remove_variable = ddm_kidnap_score_delta
    remove_variable = ddm_kidnap_chance_single
    remove_variable = ddm_kidnap_chance_three
    remove_variable = ddm_kidnap_chance_elite
    remove_variable = ddm_kidnap_current_chance
    remove_variable = ddm_kidnap_harm_base
    remove_variable = ddm_kidnap_harm_chance
    remove_variable = ddm_kidnap_mode
    remove_variable = ddm_kidnap_tmp
    remove_variable = ddm_kidnap_success
    remove_variable = ddm_kidnap_war_chance
    remove_variable = ddm_kidnap_captured_count
    remove_variable = ddm_kidnap_captured_more
    remove_variable = ddm_kidnap_war_started
    remove_variable = ddm_kidnap_three_attached_count
    remove_variable = ddm_kidnap_elite_attached_count
    remove_variable = ddm_kidnap_relationship_heat
    remove_variable = ddm_kidnap_relationship_heat_sq
    remove_variable = ddm_kidnap_gold_cost_single
    remove_variable = ddm_kidnap_prestige_cost_single
    remove_variable = ddm_kidnap_gold_cost_three
    remove_variable = ddm_kidnap_prestige_cost_three
    remove_variable = ddm_kidnap_gold_cost_elite
    remove_variable = ddm_kidnap_prestige_cost_elite
    remove_variable = ddm_kidnap_current_gold_cost
    remove_variable = ddm_kidnap_current_prestige_cost
    remove_variable = ddm_kidnap_solo
    remove_variable = ddm_kidnap_caught
    remove_variable = ddm_kidnap_caught_chance
    remove_variable = ddm_kidnap_captured_retinue_count
    remove_variable = ddm_kidnap_capacity
    remove_variable = ddm_kidnap_generation_floor
}
