﻿# Dominion of Communion 2.5.1 — player household agency against autonomous AI intimacy.
# These helpers never alter ordinary AI-vs-AI sex that already occurred through another system; they
# intercept Dominion's own autonomous escalation before sex with a human player's lawful consort.

# Run from the spouse/concubine/consort being pursued. Requires scope:domcom_tantalize_patron.
domcom_queue_ai_courtship_against_player_effect = {
    save_scope_as = domcom_guard_partner
    if = {
        limit = {
            exists = scope:domcom_tantalize_patron
            scope:domcom_tantalize_patron = { is_alive = yes is_ai = yes age >= 18 }
            NOT = { is_consort_of = scope:domcom_tantalize_patron }
            NOT = { has_character_flag = domcom_household_guarded }
            NOT = { has_variable = domcom_pending_ai_suitor }
            any_consort = {
                is_alive = yes
                age >= 18
                is_ai = no
                NOT = { this = scope:domcom_tantalize_patron }
            }
        }

        scope:domcom_tantalize_patron = { save_scope_as = domcom_guard_suitor }
        set_variable = { name = domcom_pending_ai_suitor value = scope:domcom_tantalize_patron }
        add_character_flag = domcom_ai_courtship_pending

        # Prefer the primary human spouse where one exists; plural-marriage edge cases fall back to any
        # living human consort. In ordinary single-player games this resolves to the player character.
        if = {
            limit = {
                exists = primary_spouse
                primary_spouse = {
                    is_alive = yes
                    age >= 18
                    is_ai = no
                    NOT = { this = scope:domcom_tantalize_patron }
                }
            }
            primary_spouse = { save_scope_as = domcom_guardian_spouse }
        }
        else = {
            every_consort = {
                limit = {
                    is_alive = yes
                    age >= 18
                    is_ai = no
                    NOT = { this = scope:domcom_tantalize_patron }
                }
                save_scope_as = domcom_guardian_spouse
            }
        }

        if = {
            limit = { exists = scope:domcom_guardian_spouse }
            scope:domcom_guardian_spouse = {
                trigger_event = { id = domcom_guard.100 }
            }
            # The warning comes first. The actual sexual attempt occurs later, giving the player a real
            # period in which they know somebody is pressing their luck.
            trigger_event = { id = domcom_guard.105 days = { 60 150 } }
        }
        else = {
            remove_variable = domcom_pending_ai_suitor
            remove_character_flag = domcom_ai_courtship_pending
        }
    }
}

# Run from the pursued partner.
domcom_clear_pending_ai_courtship_effect = {
    if = { limit = { has_variable = domcom_pending_ai_suitor } remove_variable = domcom_pending_ai_suitor }
    remove_character_flag = domcom_ai_courtship_pending
}

# Run from the human defender. The event chain stores partner/suitor as character variables because CK3's
# duel and board-game output events do not reliably preserve arbitrary saved scopes across every route.
domcom_household_guard_success_effect = {
    if = {
        limit = {
            has_variable = domcom_guard_partner
            has_variable = domcom_guard_suitor
            var:domcom_guard_partner = { is_alive = yes }
            var:domcom_guard_suitor = { is_alive = yes }
        }
        var:domcom_guard_partner = { save_scope_as = domcom_guard_partner }
        var:domcom_guard_suitor = { save_scope_as = domcom_guard_suitor }

        scope:domcom_guard_partner = {
            add_character_flag = { flag = domcom_household_guarded days = 365 }
            add_character_modifier = { modifier = domcom_household_guarded_modifier days = 365 }
            domcom_clear_pending_ai_courtship_effect = yes
            add_opinion = { target = root modifier = domcom_defended_household_opinion }
        }
        scope:domcom_guard_suitor = {
            add_opinion = { target = root modifier = domcom_thwarted_suitor_opinion }
        }
        add_prestige = 100
        send_interface_toast = {
            type = event_toast_effect_good
            title = domcom_guard_defense_success_toast
            left_icon = root
            right_icon = scope:domcom_guard_partner
        }
    }
    if = { limit = { has_variable = domcom_guard_partner } remove_variable = domcom_guard_partner }
    if = { limit = { has_variable = domcom_guard_suitor } remove_variable = domcom_guard_suitor }
    remove_character_flag = domcom_guard_stood_aside
}

# Run from the human defender after losing a duel/board game or deliberately standing aside. Losing the
# confrontation only opens the door: the spouse still makes a separate acceptance check. No sex means no
# Cucked state.
domcom_household_guard_failure_effect = {
    if = {
        limit = {
            has_variable = domcom_guard_partner
            has_variable = domcom_guard_suitor
            var:domcom_guard_partner = { is_alive = yes }
            var:domcom_guard_suitor = { is_alive = yes }
        }
        var:domcom_guard_partner = { save_scope_as = domcom_guard_partner }
        var:domcom_guard_suitor = { save_scope_as = domcom_guard_suitor }

        scope:domcom_guard_partner = {
            add_character_flag = domcom_guard_partner_accepts_roll
            random = {
                chance = domcom_ai_guarded_intimacy_acceptance_value
                remove_character_flag = domcom_guard_partner_accepts_roll
            }
        }

        if = {
            # The flag remaining means the random success did NOT fire, so the partner refuses.
            limit = { scope:domcom_guard_partner = { has_character_flag = domcom_guard_partner_accepts_roll } }
            scope:domcom_guard_partner = {
                remove_character_flag = domcom_guard_partner_accepts_roll
                domcom_clear_pending_ai_courtship_effect = yes
                add_opinion = { target = scope:domcom_guard_suitor modifier = domcom_rejected_after_confrontation_opinion }
            }
            trigger_event = { id = domcom_guard.141 }
        }
        else = {
            # Actual intimacy happens only here, after the player has had the chance to intervene and the
            # spouse has independently accepted. The ordinary direct-sex recorder then creates the Cucked
            # state from real evidence rather than from a relationship label.
            # This is a Dominion-generated sex scene, so Dominion owns the Mastery award. Guard both
            # participants while had_sex_with_effect fires so an installed Carnalitas bridge cannot score
            # the same encounter a second time, then grade each participant against the actual partner.
            scope:domcom_guard_suitor = { add_character_flag = domcom_mastery_direct_sex_guard }
            scope:domcom_guard_partner = { add_character_flag = domcom_mastery_direct_sex_guard }
            scope:domcom_guard_suitor = {
                had_sex_with_effect = {
                    CHARACTER = scope:domcom_guard_partner
                    PREGNANCY_CHANCE = pregnancy_chance
                }
                save_scope_as = domcom_direct_sex_patron
            }
            scope:domcom_guard_suitor = { remove_character_flag = domcom_mastery_direct_sex_guard }
            scope:domcom_guard_partner = { remove_character_flag = domcom_mastery_direct_sex_guard }

            scope:domcom_guard_partner = {
                save_scope_as = domcom_mastery_partner
                save_scope_as = domcom_breast_mastery_partner
            }
            scope:domcom_guard_suitor = {
                if = { limit = { is_male = yes age >= 18 } domcom_endowment_mastery_rate_carnalitas_partner_effect = yes }
                if = { limit = { is_female = yes age >= 18 } domcom_breast_mastery_rate_partner_effect = yes }
            }
            scope:domcom_guard_suitor = {
                save_scope_as = domcom_mastery_partner
                save_scope_as = domcom_breast_mastery_partner
            }
            scope:domcom_guard_partner = {
                if = { limit = { is_male = yes age >= 18 } domcom_endowment_mastery_rate_carnalitas_partner_effect = yes }
                if = { limit = { is_female = yes age >= 18 } domcom_breast_mastery_rate_partner_effect = yes }
                domcom_clear_pending_ai_courtship_effect = yes
                domcom_record_direct_dominion_sex_effect = yes
            }

            # Persist the most recent qualifying cause so the player can be told who, with whom, and how.
            set_variable = { name = domcom_last_cuck_patron value = scope:domcom_guard_suitor }
            set_variable = { name = domcom_last_cuck_partner value = scope:domcom_guard_partner }
            if = { limit = { has_character_flag = domcom_guard_stood_aside } add_character_flag = domcom_last_cuck_stood_aside }
            else = { remove_character_flag = domcom_last_cuck_stood_aside }
            trigger_event = { id = domcom_guard.140 }
        }
    }
    if = { limit = { has_variable = domcom_guard_partner } remove_variable = domcom_guard_partner }
    if = { limit = { has_variable = domcom_guard_suitor } remove_variable = domcom_guard_suitor }
    remove_character_flag = domcom_guard_stood_aside
}

# Autonomous AI relationship Dominion now calls this from a prospective cuck with
# scope:domcom_ai_patron saved. A Lover/Soulmate relationship alone no longer creates public cuckoldry.
domcom_ai_resolve_relationship_dominion_target_effect = {
    save_scope_as = domcom_ai_cuck_target

    if = {
        limit = { domcom_has_qualifying_cuck_evidence_from_patron_trigger = { PATRON = scope:domcom_ai_patron } }
        scope:domcom_ai_patron = { save_scope_as = domcom_owner }
        if = { limit = { NOT = { has_character_flag = domcom_cucked } } domcom_register_cuck_generic_effect = yes }
        domcom_ai_progress_cuck_after_evidence_effect = yes
    }
    else = {
        # Find the actual partner through whom the AI Patron is pressing the relationship.
        every_consort = {
            limit = {
                is_alive = yes
                age >= 18
                NOT = { is_consort_of = scope:domcom_ai_patron }
                NOT = { has_character_flag = domcom_household_guarded }
                OR = {
                    has_relation_lover = scope:domcom_ai_patron
                    has_relation_soulmate = scope:domcom_ai_patron
                }
            }
            save_scope_as = domcom_ai_compromised_partner
        }

        if = {
            limit = { exists = scope:domcom_ai_compromised_partner }
            if = {
                # Human spouse: warn first and queue a later duel/chess intervention. No sex happens now.
                limit = { is_ai = no }
                scope:domcom_ai_patron = { save_scope_as = domcom_tantalize_patron }
                scope:domcom_ai_compromised_partner = { domcom_queue_ai_courtship_against_player_effect = yes }
            }
            else = {
                # AI-vs-AI keeps world activity alive, but public Cucked still requires actual sex. The
                # relationship influences the chance; the sex recorder creates the evidence/state.
                scope:domcom_ai_compromised_partner = {
                    add_character_flag = domcom_ai_relationship_intimacy_roll
                    random = {
                        chance = domcom_ai_relationship_intimacy_chance_value
                        remove_character_flag = domcom_ai_relationship_intimacy_roll
                    }
                }
                if = {
                    limit = { scope:domcom_ai_compromised_partner = { NOT = { has_character_flag = domcom_ai_relationship_intimacy_roll } } }
                    # Autonomous AI-vs-AI intimacy is also a Dominion-owned sex path. Suppress an
                    # optional Carnalitas double-award during had_sex_with_effect, then grade both people
                    # with the same relationship/opinion/attraction rules used by the sex bridge.
                    scope:domcom_ai_patron = { add_character_flag = domcom_mastery_direct_sex_guard }
                    scope:domcom_ai_compromised_partner = { add_character_flag = domcom_mastery_direct_sex_guard }
                    scope:domcom_ai_patron = {
                        had_sex_with_effect = {
                            CHARACTER = scope:domcom_ai_compromised_partner
                            PREGNANCY_CHANCE = pregnancy_chance
                        }
                        save_scope_as = domcom_direct_sex_patron
                    }
                    scope:domcom_ai_patron = { remove_character_flag = domcom_mastery_direct_sex_guard }
                    scope:domcom_ai_compromised_partner = { remove_character_flag = domcom_mastery_direct_sex_guard }

                    scope:domcom_ai_compromised_partner = {
                        save_scope_as = domcom_mastery_partner
                        save_scope_as = domcom_breast_mastery_partner
                    }
                    scope:domcom_ai_patron = {
                        if = { limit = { is_male = yes age >= 18 } domcom_endowment_mastery_rate_carnalitas_partner_effect = yes }
                        if = { limit = { is_female = yes age >= 18 } domcom_breast_mastery_rate_partner_effect = yes }
                    }
                    scope:domcom_ai_patron = {
                        save_scope_as = domcom_mastery_partner
                        save_scope_as = domcom_breast_mastery_partner
                    }
                    scope:domcom_ai_compromised_partner = {
                        if = { limit = { is_male = yes age >= 18 } domcom_endowment_mastery_rate_carnalitas_partner_effect = yes }
                        if = { limit = { is_female = yes age >= 18 } domcom_breast_mastery_rate_partner_effect = yes }
                        domcom_record_direct_dominion_sex_effect = yes
                    }
                    if = {
                        limit = {
                            has_character_flag = domcom_cucked
                            has_variable = domcom_cuck_patron
                            var:domcom_cuck_patron = scope:domcom_ai_patron
                        }
                        domcom_ai_progress_cuck_after_evidence_effect = yes
                    }
                }
                scope:domcom_ai_compromised_partner = { remove_character_flag = domcom_ai_relationship_intimacy_roll }
            }
        }
    }
}

# Run from a now-valid Cucked target with scope:domcom_ai_patron saved. This preserves the old autonomous
# Alpha/Dominion progression after the new evidence gate.
domcom_ai_progress_cuck_after_evidence_effect = {
    scope:domcom_ai_patron = { save_scope_as = domcom_owner }
    if = { limit = { NOT = { has_character_flag = domcom_cucked } } domcom_register_cuck_generic_effect = yes }

    add_character_flag = domcom_ai_alpha_failed_roll
    random = {
        chance = domcom_ai_alpha_check_chance_value
        remove_character_flag = domcom_ai_alpha_failed_roll
        scope:domcom_ai_patron = { save_scope_as = domcom_owner }
        if = { limit = { NOT = { has_character_flag = domcom_owned_cuck } } domcom_own_cuck_generic_effect = yes }
        if = { limit = { NOT = { has_variable = domcom_cuck_xp } } set_variable = { name = domcom_cuck_xp value = 0 } }
        change_variable = { name = domcom_cuck_xp add = 100 }
        if = { limit = { var:domcom_cuck_xp > 1000 } set_variable = { name = domcom_cuck_xp value = 1000 } }
        domcom_refresh_cuck_stage_effect = yes
    }
    if = {
        limit = { has_character_flag = domcom_ai_alpha_failed_roll }
        remove_character_flag = domcom_ai_alpha_failed_roll
        if = { limit = { NOT = { has_variable = domcom_cuck_xp } } set_variable = { name = domcom_cuck_xp value = 100 } }
        if = { limit = { var:domcom_cuck_xp >= 150 } change_variable = { name = domcom_cuck_xp subtract = 50 } }
        else = { set_variable = { name = domcom_cuck_xp value = 100 } }
        domcom_refresh_cuck_stage_effect = yes
    }
}
