﻿# DDM 2.0 — Household / Harem Office
# The household layer is deliberately player-local. It never changes faith marriage doctrines, never
# alters the dynasty-wide Marriage Planner, and as of 2.0.3 never mutates vanilla spouse/concubine bonds.
# Harem mode is a DDM registry: existing relationships remain exactly what CK3 says they are while DDM
# adds permanent household numbers for lineage. Marriage/council spouse mechanics are left entirely to CK3.
ddm_convert_existing_spouses_to_harem_effect = {
    # Compatibility name retained for old scripted calls. 2.0.3 no longer converts, divorces or marries
    # anybody. Harem is a DDM household register layered over whatever relationship CK3 already uses.
    save_scope_as = ddm_household_owner
    every_spouse = {
        limit = { is_alive = yes age >= 18 }
        save_temporary_scope_as = ddm_household_seed_member
        scope:ddm_household_owner = { ddm_register_household_member_effect = yes }
    }
    every_concubine = {
        limit = { is_alive = yes age >= 18 }
        save_temporary_scope_as = ddm_household_seed_member
        scope:ddm_household_owner = { ddm_register_household_member_effect = yes }
    }
}

# Ends concubinage without erasing the permanent slot/lineage metadata. Re-taking the same person later
# restores the same household number rather than recycling or duplicating it.
ddm_release_household_concubine_effect = {
    # Release means "remove from the DDM harem register" only. It never divorces a spouse, removes a
    # vanilla concubine, or writes a marriage/concubinage memory. Permanent slot metadata is retained so
    # children remain attributable to the same household number.
    save_scope_as = ddm_household_owner
    if = {
        limit = {
            exists = scope:ddm_household_release_target
            scope:ddm_household_release_target = {
                has_variable = ddm_harem_patron
                var:ddm_harem_patron = scope:ddm_household_owner
                has_variable = ddm_harem_active
                var:ddm_harem_active = 1
            }
        }
        scope:ddm_household_release_target = { remove_variable = ddm_harem_active }
        ddm_prepare_household_effect = yes
    }
}

ddm_register_household_member_effect = {
    # Run from the household owner with scope:ddm_household_seed_member saved.
    save_scope_as = ddm_household_register_owner
    if = { limit = { NOT = { has_variable = ddm_harem_next_slot } } set_variable = { name = ddm_harem_next_slot value = 0 } }
    if = {
        limit = { exists = scope:ddm_household_seed_member }
        if = {
            limit = {
                scope:ddm_household_seed_member = {
                    OR = {
                        NOT = { has_variable = ddm_harem_patron }
                        NOT = { var:ddm_harem_patron = scope:ddm_household_register_owner }
                        NOT = { has_variable = ddm_harem_slot }
                    }
                }
            }
            change_variable = { name = ddm_harem_next_slot add = 1 }
            scope:ddm_household_seed_member = {
                set_variable = { name = ddm_harem_patron value = scope:ddm_household_register_owner }
                set_variable = { name = ddm_harem_slot value = scope:ddm_household_register_owner.var:ddm_harem_next_slot }
            }
        }
        scope:ddm_household_seed_member = { set_variable = { name = ddm_harem_active value = 1 } }
    }
}

ddm_assign_harem_slots_effect = {
    # Seed the register once, the first time a ruler uses Harem mode (or the first 2.0.3 refresh of an
    # older Harem-mode save). After that, Release must remain meaningful: ordinary Refresh/maintenance
    # never silently re-enrolls a spouse or native concubine the player deliberately released.
    save_scope_as = ddm_household_owner
    if = {
        limit = {
            has_variable = ddm_household_mode
            var:ddm_household_mode = 1
            NOT = { has_variable = ddm_harem_registry_seeded }
        }
        ddm_convert_existing_spouses_to_harem_effect = yes
        set_variable = { name = ddm_harem_registry_seeded value = 1 }
    }
}

# Copies the other parent's permanent household slot to a child. Slots are never renumbered, so a child
# remains "Concubine #N's child" even if that concubine later leaves court or dies.
ddm_mark_harem_child_effect = {
    save_scope_as = ddm_household_child
    if = {
        limit = {
            exists = mother
            mother = { has_variable = ddm_harem_patron has_variable = ddm_harem_slot }
        }
        mother = { save_scope_as = ddm_household_parent }
        set_variable = { name = ddm_harem_origin_parent value = scope:ddm_household_parent }
        set_variable = { name = ddm_harem_origin_owner value = scope:ddm_household_parent.var:ddm_harem_patron }
        set_variable = { name = ddm_harem_origin_slot value = scope:ddm_household_parent.var:ddm_harem_slot }
    }
    else_if = {
        limit = {
            exists = father
            father = { has_variable = ddm_harem_patron has_variable = ddm_harem_slot }
        }
        father = { save_scope_as = ddm_household_parent }
        set_variable = { name = ddm_harem_origin_parent value = scope:ddm_household_parent }
        set_variable = { name = ddm_harem_origin_owner value = scope:ddm_household_parent.var:ddm_harem_patron }
        set_variable = { name = ddm_harem_origin_slot value = scope:ddm_household_parent.var:ddm_harem_slot }
    }
}

# Birth-time hook. We only mark a child when the numbered concubine's stored Patron is the child's other
# legal/biological parent. This prevents a concubine's child by somebody else from being misfiled.
ddm_household_on_birth_effect = {
    save_scope_as = ddm_household_child
    if = {
        limit = { exists = mother exists = father }
        mother = { save_scope_as = ddm_birth_mother }
        father = { save_scope_as = ddm_birth_father }

        if = {
            limit = {
                scope:ddm_birth_mother = {
                    has_variable = ddm_harem_patron
                    has_variable = ddm_harem_slot
                    var:ddm_harem_patron = scope:ddm_birth_father
                }
            }
            scope:ddm_birth_mother = { save_scope_as = ddm_household_parent }
            set_variable = { name = ddm_harem_origin_parent value = scope:ddm_household_parent }
            set_variable = { name = ddm_harem_origin_owner value = scope:ddm_birth_father }
            set_variable = { name = ddm_harem_origin_slot value = scope:ddm_household_parent.var:ddm_harem_slot }
        }
        else_if = {
            limit = {
                scope:ddm_birth_father = {
                    has_variable = ddm_harem_patron
                    has_variable = ddm_harem_slot
                    var:ddm_harem_patron = scope:ddm_birth_mother
                }
            }
            scope:ddm_birth_father = { save_scope_as = ddm_household_parent }
            set_variable = { name = ddm_harem_origin_parent value = scope:ddm_household_parent }
            set_variable = { name = ddm_harem_origin_owner value = scope:ddm_birth_mother }
            set_variable = { name = ddm_harem_origin_slot value = scope:ddm_household_parent.var:ddm_harem_slot }
        }
    }
}

# 2.2.0 migration helper: remove every legacy synthetic Household Spouse skill tier from old saves.
# No new code applies these modifiers and DDM no longer touches councillor_spouse.
ddm_clear_recognized_consort_skill_modifiers_effect = {
    remove_character_modifier = ddm_recognized_consort_diplomacy_1
    remove_character_modifier = ddm_recognized_consort_diplomacy_2
    remove_character_modifier = ddm_recognized_consort_diplomacy_3
    remove_character_modifier = ddm_recognized_consort_diplomacy_4
    remove_character_modifier = ddm_recognized_consort_diplomacy_5
    remove_character_modifier = ddm_recognized_consort_diplomacy_6
    remove_character_modifier = ddm_recognized_consort_diplomacy_7
    remove_character_modifier = ddm_recognized_consort_diplomacy_8
    remove_character_modifier = ddm_recognized_consort_diplomacy_9
    remove_character_modifier = ddm_recognized_consort_diplomacy_10
    remove_character_modifier = ddm_recognized_consort_diplomacy_11
    remove_character_modifier = ddm_recognized_consort_diplomacy_12
    remove_character_modifier = ddm_recognized_consort_martial_1
    remove_character_modifier = ddm_recognized_consort_martial_2
    remove_character_modifier = ddm_recognized_consort_martial_3
    remove_character_modifier = ddm_recognized_consort_martial_4
    remove_character_modifier = ddm_recognized_consort_martial_5
    remove_character_modifier = ddm_recognized_consort_martial_6
    remove_character_modifier = ddm_recognized_consort_martial_7
    remove_character_modifier = ddm_recognized_consort_martial_8
    remove_character_modifier = ddm_recognized_consort_martial_9
    remove_character_modifier = ddm_recognized_consort_martial_10
    remove_character_modifier = ddm_recognized_consort_martial_11
    remove_character_modifier = ddm_recognized_consort_martial_12
    remove_character_modifier = ddm_recognized_consort_stewardship_1
    remove_character_modifier = ddm_recognized_consort_stewardship_2
    remove_character_modifier = ddm_recognized_consort_stewardship_3
    remove_character_modifier = ddm_recognized_consort_stewardship_4
    remove_character_modifier = ddm_recognized_consort_stewardship_5
    remove_character_modifier = ddm_recognized_consort_stewardship_6
    remove_character_modifier = ddm_recognized_consort_stewardship_7
    remove_character_modifier = ddm_recognized_consort_stewardship_8
    remove_character_modifier = ddm_recognized_consort_stewardship_9
    remove_character_modifier = ddm_recognized_consort_stewardship_10
    remove_character_modifier = ddm_recognized_consort_stewardship_11
    remove_character_modifier = ddm_recognized_consort_stewardship_12
    remove_character_modifier = ddm_recognized_consort_intrigue_1
    remove_character_modifier = ddm_recognized_consort_intrigue_2
    remove_character_modifier = ddm_recognized_consort_intrigue_3
    remove_character_modifier = ddm_recognized_consort_intrigue_4
    remove_character_modifier = ddm_recognized_consort_intrigue_5
    remove_character_modifier = ddm_recognized_consort_intrigue_6
    remove_character_modifier = ddm_recognized_consort_intrigue_7
    remove_character_modifier = ddm_recognized_consort_intrigue_8
    remove_character_modifier = ddm_recognized_consort_intrigue_9
    remove_character_modifier = ddm_recognized_consort_intrigue_10
    remove_character_modifier = ddm_recognized_consort_intrigue_11
    remove_character_modifier = ddm_recognized_consort_intrigue_12
    remove_character_modifier = ddm_recognized_consort_learning_1
    remove_character_modifier = ddm_recognized_consort_learning_2
    remove_character_modifier = ddm_recognized_consort_learning_3
    remove_character_modifier = ddm_recognized_consort_learning_4
    remove_character_modifier = ddm_recognized_consort_learning_5
    remove_character_modifier = ddm_recognized_consort_learning_6
    remove_character_modifier = ddm_recognized_consort_learning_7
    remove_character_modifier = ddm_recognized_consort_learning_8
    remove_character_modifier = ddm_recognized_consort_learning_9
    remove_character_modifier = ddm_recognized_consort_learning_10
    remove_character_modifier = ddm_recognized_consort_learning_11
    remove_character_modifier = ddm_recognized_consort_learning_12
}



ddm_prepare_household_effect = {
    ddm_initialize_settings_effect = yes
    save_scope_as = ddm_household_owner
    # 2.2.0 migration: Household Spouse was scrapped. Clean old state once, then never touch the vanilla
    # spouse council position again.
    if = {
        limit = { NOT = { has_variable = ddm_household_spouse_scrap_migrated } }
        if = { limit = { has_variable = ddm_recognized_consort } remove_variable = ddm_recognized_consort }
        ddm_clear_recognized_consort_skill_modifiers_effect = yes
        set_variable = { name = ddm_household_spouse_scrap_migrated value = 1 }
    }
    ddm_assign_harem_slots_effect = yes

    clear_variable_list = ddm_household_concubines
    clear_variable_list = ddm_household_children
    set_variable = { name = ddm_household_concubine_count value = 0 }
    set_variable = { name = ddm_household_child_count value = 0 }

    # Build the active household register from people physically attached to this court. Spouses and
    # native concubines were seeded above; purely DDM household members are found through their stored
    # Patron/active flags. No vanilla relationship changes are needed for any of them.
    every_spouse = {
        limit = {
            is_alive = yes age >= 18
            has_variable = ddm_harem_patron var:ddm_harem_patron = scope:ddm_household_owner
            has_variable = ddm_harem_active var:ddm_harem_active = 1
        }
        add_to_temporary_list = ddm_household_concubines_raw
    }
    every_concubine = {
        limit = {
            is_alive = yes age >= 18
            has_variable = ddm_harem_patron var:ddm_harem_patron = scope:ddm_household_owner
            has_variable = ddm_harem_active var:ddm_harem_active = 1
            NOT = { is_in_list = ddm_household_concubines_raw }
        }
        add_to_temporary_list = ddm_household_concubines_raw
    }
    every_courtier_or_guest = {
        limit = {
            is_alive = yes age >= 18
            has_variable = ddm_harem_patron var:ddm_harem_patron = scope:ddm_household_owner
            has_variable = ddm_harem_active var:ddm_harem_active = 1
            NOT = { is_in_list = ddm_household_concubines_raw }
        }
        add_to_temporary_list = ddm_household_concubines_raw
    }

    ordered_in_list = {
        list = ddm_household_concubines_raw
        order_by = var:ddm_harem_slot
        max = 100000
        check_range_bounds = no
        save_temporary_scope_as = ddm_household_member
        scope:ddm_household_owner = {
            add_to_variable_list = { name = ddm_household_concubines target = scope:ddm_household_member }
            change_variable = { name = ddm_household_concubine_count add = 1 }
        }
    }

    # Backfill and maintain child lineage from permanent household slots. This is genealogy only; it has
    # no succession priority of its own.
    every_child = {
        limit = { is_alive = yes }
        if = {
            limit = {
                NOT = { has_variable = ddm_harem_origin_owner }
                OR = {
                    AND = { exists = mother mother = { has_variable = ddm_harem_patron var:ddm_harem_patron = scope:ddm_household_owner } }
                    AND = { exists = father father = { has_variable = ddm_harem_patron var:ddm_harem_patron = scope:ddm_household_owner } }
                }
            }
            ddm_mark_harem_child_effect = yes
        }
        if = {
            limit = {
                has_variable = ddm_harem_origin_owner
                has_variable = ddm_harem_origin_slot
                var:ddm_harem_origin_owner = scope:ddm_household_owner
            }
            add_to_temporary_list = ddm_household_children_raw
        }
    }
    ordered_in_list = {
        list = ddm_household_children_raw
        order_by = var:ddm_harem_origin_slot
        max = 100000
        check_range_bounds = no
        save_temporary_scope_as = ddm_household_child_row
        scope:ddm_household_owner = {
            add_to_variable_list = { name = ddm_household_children target = scope:ddm_household_child_row }
            change_variable = { name = ddm_household_child_count add = 1 }
        }
    }

    ddm_build_household_concubine_page_effect = yes
    ddm_build_household_child_page_effect = yes
}

# Household registry paging keeps large households from pushing the lower Heir Council out of the
# Office viewport. Full registries remain intact for maintenance and lineage logic.
ddm_build_household_concubine_page_effect = {
    if = { limit = { NOT = { has_variable = ddm_household_concubine_page } } set_variable = { name = ddm_household_concubine_page value = 0 } }
    clear_variable_list = ddm_household_concubines_page
    set_variable = { name = ddm_household_concubine_page_size value = 4 }
    set_variable = { name = ddm_household_concubine_last_page value = 0 }
    set_variable = { name = ddm_household_concubine_page_fill value = 0 }

    if = {
        limit = { has_variable_list = ddm_household_concubines }
        every_in_list = {
            variable = ddm_household_concubines
            prev = {
                if = {
                    limit = { var:ddm_household_concubine_page_fill >= var:ddm_household_concubine_page_size }
                    change_variable = { name = ddm_household_concubine_last_page add = 1 }
                    set_variable = { name = ddm_household_concubine_page_fill value = 0 }
                }
                change_variable = { name = ddm_household_concubine_page_fill add = 1 }
            }
        }
    }

    if = { limit = { var:ddm_household_concubine_page < 0 } set_variable = { name = ddm_household_concubine_page value = 0 } }
    if = { limit = { var:ddm_household_concubine_page > var:ddm_household_concubine_last_page } set_variable = { name = ddm_household_concubine_page value = var:ddm_household_concubine_last_page } }

    set_variable = { name = ddm_household_concubine_first value = var:ddm_household_concubine_page }
    change_variable = { name = ddm_household_concubine_first multiply = var:ddm_household_concubine_page_size }
    set_variable = { name = ddm_household_concubine_stop value = var:ddm_household_concubine_first }
    change_variable = { name = ddm_household_concubine_stop add = var:ddm_household_concubine_page_size }
    set_variable = { name = ddm_household_concubine_index value = 0 }

    if = {
        limit = { has_variable_list = ddm_household_concubines }
        every_in_list = {
            variable = ddm_household_concubines
            save_temporary_scope_as = ddm_household_concubine_page_row
            prev = {
                if = {
                    limit = {
                        var:ddm_household_concubine_index >= var:ddm_household_concubine_first
                        var:ddm_household_concubine_index < var:ddm_household_concubine_stop
                    }
                    add_to_variable_list = { name = ddm_household_concubines_page target = scope:ddm_household_concubine_page_row }
                }
                change_variable = { name = ddm_household_concubine_index add = 1 }
            }
        }
    }

    set_variable = { name = ddm_household_concubine_page_display value = var:ddm_household_concubine_page }
    change_variable = { name = ddm_household_concubine_page_display add = 1 }
    set_variable = { name = ddm_household_concubine_pages_display value = var:ddm_household_concubine_last_page }
    change_variable = { name = ddm_household_concubine_pages_display add = 1 }
}

ddm_build_household_child_page_effect = {
    if = { limit = { NOT = { has_variable = ddm_household_child_page } } set_variable = { name = ddm_household_child_page value = 0 } }
    clear_variable_list = ddm_household_children_page
    set_variable = { name = ddm_household_child_page_size value = 4 }
    set_variable = { name = ddm_household_child_last_page value = 0 }
    set_variable = { name = ddm_household_child_page_fill value = 0 }

    if = {
        limit = { has_variable_list = ddm_household_children }
        every_in_list = {
            variable = ddm_household_children
            prev = {
                if = {
                    limit = { var:ddm_household_child_page_fill >= var:ddm_household_child_page_size }
                    change_variable = { name = ddm_household_child_last_page add = 1 }
                    set_variable = { name = ddm_household_child_page_fill value = 0 }
                }
                change_variable = { name = ddm_household_child_page_fill add = 1 }
            }
        }
    }

    if = { limit = { var:ddm_household_child_page < 0 } set_variable = { name = ddm_household_child_page value = 0 } }
    if = { limit = { var:ddm_household_child_page > var:ddm_household_child_last_page } set_variable = { name = ddm_household_child_page value = var:ddm_household_child_last_page } }

    set_variable = { name = ddm_household_child_first value = var:ddm_household_child_page }
    change_variable = { name = ddm_household_child_first multiply = var:ddm_household_child_page_size }
    set_variable = { name = ddm_household_child_stop value = var:ddm_household_child_first }
    change_variable = { name = ddm_household_child_stop add = var:ddm_household_child_page_size }
    set_variable = { name = ddm_household_child_index value = 0 }

    if = {
        limit = { has_variable_list = ddm_household_children }
        every_in_list = {
            variable = ddm_household_children
            save_temporary_scope_as = ddm_household_child_page_row
            prev = {
                if = {
                    limit = {
                        var:ddm_household_child_index >= var:ddm_household_child_first
                        var:ddm_household_child_index < var:ddm_household_child_stop
                    }
                    add_to_variable_list = { name = ddm_household_children_page target = scope:ddm_household_child_page_row }
                }
                change_variable = { name = ddm_household_child_index add = 1 }
            }
        }
    }

    set_variable = { name = ddm_household_child_page_display value = var:ddm_household_child_page }
    change_variable = { name = ddm_household_child_page_display add = 1 }
    set_variable = { name = ddm_household_child_pages_display value = var:ddm_household_child_last_page }
    change_variable = { name = ddm_household_child_pages_display add = 1 }
}

ddm_household_maintenance_effect = {
    if = { limit = { is_alive = yes is_ai = no } ddm_prepare_household_effect = yes }
}

# The ruler's recommendation card can enroll a physically present candidate into the DDM household in
# one click. Foreign candidates remain a Kidnap target first; the existing hostile expedition handles
# getting them to court. Vanilla relationship status is irrelevant to registry membership.
ddm_take_selected_match_as_concubine_effect = {
    # Harem-mode recommendation action: enroll the selected same-court candidate in the DDM household.
    # No marriage/concubine relationship is created, so this cannot create memories, divorce spam or
    # doctrine/UI inconsistencies.
    save_scope_as = ddm_match_subject
    if = {
        limit = {
            exists = var:ddm_match_planner_owner
            exists = var:ddm_match_sel
            this = var:ddm_match_planner_owner
        }
        var:ddm_match_sel = { save_scope_as = ddm_household_candidate save_scope_as = ddm_household_seed_member }
        var:ddm_match_planner_owner = { save_scope_as = ddm_household_owner }
        if = {
            limit = {
                scope:ddm_household_candidate = {
                    is_alive = yes age >= 18 is_imprisoned = no
                    is_in_the_same_court_as_or_guest = scope:ddm_household_owner
                }
            }
            scope:ddm_household_owner = { ddm_register_household_member_effect = yes ddm_prepare_household_effect = yes }
            send_interface_toast = { type = event_toast_effect_good title = DDM_HOUSEHOLD_CONCUBINE_TAKEN_TOAST left_icon = scope:ddm_household_owner right_icon = scope:ddm_household_candidate }
            scope:ddm_household_owner = { ddm_refresh_player_match_effect = yes }
        }
    }
}
