﻿# Rise and Fall - Coalition low-stability triggers

# True while this ruler is involved in an already active Coalition war, either
# as the target or as a Coalition attacker.
riseandfall_coalition_target_has_active_war_trigger = {
    any_character_war = {
        using_cb = riseandfall_coalition_cb
    }
}

# Realm Stability stores the ruler's rounded share of world realm size as a
# negative component: controlling 5% of the world produces -5. Coalition is
# restricted to rulers at that threshold or larger in Restricted mode and
# the separately configured Low Stability incident.
riseandfall_coalition_target_controls_five_percent_world_trigger = {
    has_variable = riseandfall_rs_realm_size_component
    NOT = { var:riseandfall_rs_realm_size_component >= -4 }
}

# Shared switch for threat pulses, inheritance, conquest hooks and interaction AI.
riseandfall_independent_coalitions_active_trigger = {
    OR = {
        has_game_rule = riseandfall_independent_coalitions_enabled
        has_game_rule = riseandfall_independent_coalitions_unrestricted
    }
}

# Keep Low Stability incidents on their existing territorial contract even when
# the separate interaction rule permits unrestricted targets.
riseandfall_coalition_target_territory_valid_trigger = {
    riseandfall_coalition_target_controls_five_percent_world_trigger = yes
    OR = {
        AND = {
            var:rf_coalition_uses_dejure_core = 1
            has_variable = rf_coalition_peripheral_pct
            var:rf_coalition_peripheral_pct >= 25
            has_variable = rf_coalition_core_counties
            var:rf_coalition_core_counties > 0
        }
        # A ruler with no duchy-or-higher non-titular crown has no meaningful
        # de-jure core, so world scale is the sole territorial gate.
        var:rf_coalition_uses_dejure_core = 0
    }
}

# Cheap pre-filter for the yearly county scan. This mirrors the low-stability
# Coalition selector's minimum: the ruler must be large enough to qualify and
# have at least two independent rulers who could receive an invitation.
riseandfall_coalition_tracking_candidate_trigger = {
    # Unrestricted tracks every independent landed ruler before threat reaches
    # 100; applying the Restricted pre-filter would prevent small realms gaining it.
    OR = {
        has_game_rule = riseandfall_independent_coalitions_unrestricted
        AND = {
            # World pulses have no character root; each caller saves its tracked ruler.
            exists = scope:rf_coalition_tracking_ruler
            riseandfall_coalition_target_controls_five_percent_world_trigger = yes
            any_independent_ruler = {
                count >= 2
                riseandfall_coalition_potential_invitee_trigger = yes
                NOT = { target_is_same_character_or_above = scope:rf_coalition_tracking_ruler }
                in_diplomatic_range = scope:rf_coalition_tracking_ruler
                NOT = { is_allied_to = scope:rf_coalition_tracking_ruler }
                NOT = { has_truce = scope:rf_coalition_tracking_ruler }
            }
        }
    }
}

# This trigger is evaluated from a Coalition interaction, where scope:actor
# is the initiating neighbor and this is the proposed target.
riseandfall_coalition_target_threat_valid_trigger = {
    has_variable = rf_coalition_threat
    var:rf_coalition_threat >= 100
    OR = {
        has_game_rule = riseandfall_independent_coalitions_unrestricted
        AND = {
            riseandfall_coalition_target_territory_valid_trigger = yes
            realm_size >= { value = scope:actor.realm_size multiply = 2 }
        }
    }
}

# Stable target requirements shared by selection, preparation, and final assembly.
riseandfall_coalition_target_core_valid_trigger = {
    is_alive = yes
    is_landed = yes
    is_independent_ruler = yes
    exists = primary_title
    riseandfall_coalition_target_territory_valid_trigger = yes
    NOT = { primary_title = { has_variable = rf_coalition_postwar_cooldown } }
    NOT = { has_character_flag = rf_coalition_under_attack }
    NOT = { riseandfall_coalition_target_has_active_war_trigger = yes }
}

riseandfall_coalition_interaction_target_valid_trigger = {
    riseandfall_independent_coalitions_active_trigger = yes
    riseandfall_coalition_target_still_valid_trigger = yes
    NOT = { has_character_flag = rf_coalition_formation_active }
    OR = {
        has_game_rule = riseandfall_independent_coalitions_unrestricted
        AND = {
            riseandfall_coalition_target_territory_valid_trigger = yes
            NOT = { primary_title = { has_variable = rf_coalition_postwar_cooldown } }
            NOT = { primary_title = { has_variable = rf_coalition_interaction_cooldown } }
        }
    }
}

# The dynamic cause is checked before Coalition is selected from the
# low-stability pool. Once that incident fires, do not recheck transient
# percentage/cooldown values during invitation assembly: only a genuinely
# invalid target may stop the already-started Coalition.
riseandfall_coalition_target_still_valid_trigger = {
    is_alive = yes
    is_landed = yes
    is_independent_ruler = yes
    exists = primary_title
    NOT = { has_character_flag = rf_coalition_under_attack }
    NOT = { riseandfall_coalition_target_has_active_war_trigger = yes }
}

# Target-independent requirements for a ruler who could occupy a Coalition
# attacker slot. Cross-scope checks stay at each iterator call site because a
# nested scripted trigger does not retain that caller's root scope.
riseandfall_coalition_potential_invitee_trigger = {
    is_alive = yes
    is_landed = yes
    is_independent_ruler = yes
    exists = primary_title
    is_at_war = no
    NOT = { has_variable = rf_coalition_target }
    NOR = {
        government_has_flag = government_is_landless_adventurer
    }
}

# Selector-facing availability. The peripheral percentage is calculated by the
# yearly incident effect from counties, never vassal primary titles.
# Invitation-time legality. The target is saved on the invitee so tooltip and
# event option evaluation never dereference a missing transient scope.
riseandfall_coalition_invitee_can_join_trigger = {
    has_variable = rf_coalition_target
    var:rf_coalition_target ?= scope:coalition_target
    is_alive = yes
    is_landed = yes
    is_independent_ruler = yes
    exists = primary_title
    is_at_war = no
    NOT = { is_allied_to = scope:coalition_target }
    NOT = { has_truce = scope:coalition_target }
    scope:coalition_target = {
        riseandfall_coalition_target_still_valid_trigger = yes
        has_character_flag = rf_coalition_formation_active
    }
}

# Direct vassals may join the external Coalition as internal rebels. They must
# still serve the target when the invitation resolves, and existing wars or a
# personal alliance with their liege make rebellion unavailable.
riseandfall_coalition_vassal_can_join_trigger = {
    has_variable = rf_coalition_target
    var:rf_coalition_target ?= scope:coalition_target
    is_alive = yes
    is_landed = yes
    is_independent_ruler = no
    exists = primary_title
    highest_held_title_tier >= tier_county
    is_at_war = no
    NOT = { is_allied_to = scope:coalition_target }
    # This is the engine's direct-vassal check. It excludes the target's
    # subvassals and every ruler belonging to another realm.
    is_vassal_of = scope:coalition_target
    # Only vassals with actual peripheral land can use the Coalition to break
    # away. A core primary title cannot hide their outer counties.
    any_held_title = {
        tier = tier_county
        NOT = { target_is_de_jure_liege_or_above = scope:coalition_target.var:rf_coalition_core_title }
    }
    NOR = {
        government_has_flag = government_is_landless_adventurer
    }
    scope:coalition_target = {
        riseandfall_coalition_target_still_valid_trigger = yes
        has_character_flag = rf_coalition_formation_active
    }
}

# A failed assembly may reroll another low-stability incident only while the
# original ruler remains a valid recipient and is not already under Coalition attack.
