﻿##################################################
# Rise and Fall — Puppet Master scripted effects
# NOTE: Placeholder math/tokens; adjust to your mod's canonical script_values and effects

# Keep the Puppet Master court position aligned to the active puppet-regency diarch.
# Expected scope: root = liege
riseandfall_queue_puppet_master_court_position_resync_se = {
	# Court-position death cleanup can fire invalidated and vacated callbacks in
	# the same transition. Coalesce them and wait until the old engine object is gone.
	add_character_flag = { flag = rf_puppet_master_position_teardown days = 7 }
	if = {
		limit = { NOT = { has_character_flag = rf_puppet_master_resync_queued } }
		add_character_flag = { flag = rf_puppet_master_resync_queued days = 7 }
		trigger_event = {
			id = riseandfall_puppet_master.100
			days = 5
		}
	}
}

riseandfall_sync_puppet_master_court_position = {
        riseandfall_sync_native_ruler_puppet_se = yes
        clear_saved_scope = rf_puppet_master_liege
        clear_saved_scope = rf_current_puppet_master_diarch
        clear_saved_scope = rf_current_puppet_master_holder
        save_scope_as = rf_puppet_master_liege

        # The diarchy is authoritative; every successful sync refreshes the
        # persistent marker and recoverable diarch reference.
        if = {
                limit = {
                        has_diarchy_type = puppet_regency
                        has_active_diarchy = yes
                }
                add_character_flag = rf_puppet_regency_persistent
                if = {
                        limit = { exists = diarch }
                        set_variable = { name = rf_puppet_regency_diarch value = diarch }
                }
                if = {
                        limit = { exists = diarchy_successor }
                        set_variable = { name = rf_puppet_regency_successor value = diarchy_successor }
                }
        }

        if = {
		limit = {
			has_diarchy_type = puppet_regency
			has_active_diarchy = yes
			exists = diarch
			diarch = {
				is_alive = yes
			}
		}
		diarch = { save_scope_as = rf_current_puppet_master_diarch }
	}

	if = {
		limit = { employs_court_position = riseandfall_puppet_master_court_position }
		random_court_position_holder = {
			type = riseandfall_puppet_master_court_position
			save_scope_as = rf_current_puppet_master_holder
		}
	}

	if = {
		limit = {
			exists = scope:rf_current_puppet_master_holder
			scope:rf_puppet_master_liege = {
				NOT = { has_character_flag = rf_puppet_master_position_teardown }
			}
			scope:rf_current_puppet_master_holder = {
				has_court_position = riseandfall_puppet_master_court_position
			}
			NOT = { exists = scope:rf_current_puppet_master_diarch }
		}
		scope:rf_puppet_master_liege = {
			revoke_court_position = {
				recipient = scope:rf_current_puppet_master_holder
				court_position = riseandfall_puppet_master_court_position
			}
		}
	}

	if = {
		limit = {
			exists = scope:rf_puppet_master_liege
			exists = scope:rf_current_puppet_master_diarch
			scope:rf_current_puppet_master_diarch = {
				is_alive = yes
			}
		}
		scope:rf_current_puppet_master_diarch = {
			if = {
				limit = {
					is_ruler = no
					NOT = { employer = scope:rf_puppet_master_liege }
				}
				set_employer = scope:rf_puppet_master_liege
			}
		}
		if = {
			limit = {
				exists = scope:rf_current_puppet_master_holder
				scope:rf_puppet_master_liege = {
					NOT = { has_character_flag = rf_puppet_master_position_teardown }
				}
				scope:rf_current_puppet_master_holder = {
					has_court_position = riseandfall_puppet_master_court_position
				}
				NOT = { scope:rf_current_puppet_master_holder ?= scope:rf_current_puppet_master_diarch }
				# Landed or displaced diarchs can be valid regents but invalid
				# court employees; skip the court-position write in that case.
				scope:rf_current_puppet_master_diarch = {
					would_be_valid_for_court_position = {
						employer = scope:rf_puppet_master_liege
						court_position = riseandfall_puppet_master_court_position
					}
				}
			}
			scope:rf_puppet_master_liege = {
				replace_court_position = {
					recipient = scope:rf_current_puppet_master_diarch
					holder = scope:rf_current_puppet_master_holder
					court_position = riseandfall_puppet_master_court_position
				}
			}
		}
		else_if = {
			limit = {
				exists = scope:rf_current_puppet_master_holder
				scope:rf_puppet_master_liege = {
					NOT = { has_character_flag = rf_puppet_master_position_teardown }
				}
				scope:rf_current_puppet_master_holder = {
					has_court_position = riseandfall_puppet_master_court_position
				}
				NOT = { scope:rf_current_puppet_master_holder ?= scope:rf_current_puppet_master_diarch }
				scope:rf_current_puppet_master_diarch = {
					NOT = {
						would_be_valid_for_court_position = {
							employer = scope:rf_puppet_master_liege
							court_position = riseandfall_puppet_master_court_position
						}
					}
				}
			}
			# A landed vassal can remain the actual puppet-regency diarch even
			# when they cannot be shown as a court-position employee. Remove any
			# stale office holder so the UI does not name the wrong puppet master.
			scope:rf_puppet_master_liege = {
				revoke_court_position = {
					recipient = scope:rf_current_puppet_master_holder
					court_position = riseandfall_puppet_master_court_position
				}
			}
		}
		else_if = {
			limit = {
				NOT = { exists = scope:rf_current_puppet_master_holder }
				scope:rf_puppet_master_liege = {
					NOT = { has_character_flag = rf_puppet_master_position_teardown }
					# Vanilla's appointment guard also rejects a candidate who already
					# holds this office, including during an engine teardown race.
					can_appoint_char_to_court_position = {
						COURT_POS = riseandfall_puppet_master_court_position
						CHAR = scope:rf_current_puppet_master_diarch
					}
				}
			}
			scope:rf_puppet_master_liege = {
				appoint_court_position = {
					recipient = scope:rf_current_puppet_master_diarch
					court_position = riseandfall_puppet_master_court_position
				}
			}
		}
	}
}

# Claim the puppet master office when the active diarch is not currently the court position holder
riseandfall_claim_puppet_master_office_effect = {
	scope:recipient = {
		if = {
			limit = {
				scope:actor = {
					is_alive = yes
					is_diarch_of_target = scope:recipient
				}
			}
			if = {
				limit = {
					scope:actor = { is_ruler = no }
					NOR = {
						scope:actor = { is_courtier_of = scope:recipient }
						scope:actor = { is_vassal_of = scope:recipient }
						scope:actor = { employer = scope:recipient }
					}
				}
				scope:actor = { set_employer = scope:recipient }
			}

			if = {
				limit = {
					employs_court_position = riseandfall_puppet_master_court_position
				}
				random_court_position_holder = {
					type = riseandfall_puppet_master_court_position
					save_scope_as = old_puppet_master
				}
				if = {
					limit = {
						scope:actor = {
							would_be_valid_for_court_position = {
								employer = scope:recipient
								court_position = riseandfall_puppet_master_court_position
							}
						}
					}
					replace_court_position = {
						recipient = scope:actor
						holder = scope:old_puppet_master
						court_position = riseandfall_puppet_master_court_position
					}
				}
			}
			else = {
				if = {
					limit = {
						NOT = { has_character_flag = rf_puppet_master_position_teardown }
						can_appoint_char_to_court_position = {
							COURT_POS = riseandfall_puppet_master_court_position
							CHAR = scope:actor
						}
					}
					appoint_court_position = {
						recipient = scope:actor
						court_position = riseandfall_puppet_master_court_position
					}
				}
			}
		}
	}
}

# Steal 5% of liege short-term gold and give it to diarch
riseandfall_steal_gold_effect = {
	# actor = diarch, recipient = liege
	# Based on palace coup gold transfer
	scope:recipient = {
		# Initialize the transfer amount so change_variable always operates on a value variable
		set_variable = { name = rf_transfer_gold value = 0 }
		# If the liege has gold, set the transfer amount to their gold first
		if = { limit = { gold > 1 } set_variable = { name = rf_transfer_gold value = gold } }
		# Use integer math: divide by 20 to transfer roughly 5%
		if = { limit = { var:rf_transfer_gold > 0 } change_variable = { name = rf_transfer_gold divide = 20 } }
	}
	# Give to diarch
	if = { limit = { scope:recipient = { has_variable = rf_transfer_gold } scope:recipient = { var:rf_transfer_gold > 0 } } scope:actor = { add_short_term_gold = scope:recipient.var:rf_transfer_gold } }
	# Remove from liege
	scope:recipient = {
		if = { limit = { var:rf_transfer_gold > 0 } remove_short_term_gold = var:rf_transfer_gold }
		remove_variable = rf_transfer_gold
	}

	# Gold theft further weakens the figurehead ruler's stability reserve.
	scope:recipient = {
		if = {
			limit = { has_variable = riseandfall_rs_puppet_stability_bonus }
			change_variable = { name = riseandfall_rs_puppet_stability_bonus add = -12 }
			clamp_variable = { name = riseandfall_rs_puppet_stability_bonus min = -35 max = 35 }
			round_variable = { name = riseandfall_rs_puppet_stability_bonus nearest = 1 }
		}
	}
}

# When a guest arrives at a court, ensure a visiting puppet master (diarch)
# who is a foreign guest (not already a courtier) becomes employed by the host
# so they are treated as a courtier in that court.
# Expected invocation context: root = guest, host = host
riseandfall_set_guest_puppet_master_employer_se = {
	# Run in the guest scope (root)
	root = {
		if = {
			limit = {
				# Is the root character the active diarch of the host?
				is_diarch_of_target = scope:host
				# Is the root a foreign court guest of the host (they have a liege)
				is_foreign_court_guest_of = scope:host
				# Rulers cannot be moved into another ruler's court.
				is_ruler = no
				# Make sure they are not already a courtier of the host
				NOT = { is_courtier_of = scope:host }
			}
			# Move the guest into the host's court (set them as employed by the host)
			set_employer = scope:host
		}
	}
}

# Grant a strong hook on the liege to the diarch
riseandfall_curry_favor_effect = {
	# Give the actor a strong favor hook on the recipient
	scope:actor = {
		add_hook = {
			target = scope:recipient
			type = strong_favor_hook
		}
	}

	# Favor-seeking also spends stability, even without taking land or money.
	scope:recipient = {
		if = {
			limit = { has_variable = riseandfall_rs_puppet_stability_bonus }
			change_variable = { name = riseandfall_rs_puppet_stability_bonus add = -15 }
			clamp_variable = { name = riseandfall_rs_puppet_stability_bonus min = -35 max = 35 }
			round_variable = { name = riseandfall_rs_puppet_stability_bonus nearest = 1 }
		}
	}
}

# Seize one smart de jure bundle from the puppet liege: an eligible county outside
# the capital duchy, plus personally held duchy/kingdom titles when they rank up
# or consolidate the puppet master's existing de jure sphere.
riseandfall_seize_liege_land_effect = {
	clear_saved_scope = rf_puppet_seized_county
	clear_saved_scope = rf_puppet_seized_duchy
	clear_saved_scope = rf_puppet_seized_kingdom
	clear_saved_scope = rf_puppet_seized_empire

	scope:recipient = {
		# Prefer land that belongs under the puppet master's existing titles.
		random_held_title = {
			title_tier = county
			limit = {
				riseandfall_puppet_seize_liege_land_eligible_county = yes
				riseandfall_puppet_seize_liege_land_in_actor_sphere = yes
			}
			save_scope_as = rf_puppet_seized_county
		}

		# Fallback: seize land only when the bundle can raise the puppet master's rank.
		if = {
			limit = { NOT = { exists = scope:rf_puppet_seized_county } }
			random_held_title = {
				title_tier = county
				limit = {
					riseandfall_puppet_seize_liege_land_eligible_county = yes
					riseandfall_puppet_seize_liege_land_can_rank_actor = yes
				}
				save_scope_as = rf_puppet_seized_county
			}
		}

		# Final fallback: a personally held higher title can be seized directly when
		# it ranks up the puppet master, even if the liege holds no seed county there.
		if = {
			limit = { NOT = { exists = scope:rf_puppet_seized_county } }
			random_held_title = {
				title_tier = empire
				limit = {
					NOT = { this ?= scope:recipient.capital_county.de_jure_liege.de_jure_liege.de_jure_liege }
					NOT = { this ?= scope:recipient.primary_title }
					scope:recipient = { primary_title.tier > tier_empire }
					scope:actor = {
						AND = {
							exists = primary_title
							primary_title.tier < tier_empire
						}
					}
				}
				save_scope_as = rf_puppet_seized_empire
			}
		}
		if = {
			limit = {
				NOT = { exists = scope:rf_puppet_seized_county }
				NOT = { exists = scope:rf_puppet_seized_empire }
			}
			random_held_title = {
				title_tier = kingdom
				limit = {
					NOT = { this ?= scope:recipient.capital_county.de_jure_liege.de_jure_liege }
					NOT = { this ?= scope:recipient.primary_title }
					scope:recipient = { primary_title.tier > tier_kingdom }
					scope:actor = {
						AND = {
							exists = primary_title
							primary_title.tier < tier_kingdom
						}
					}
				}
				save_scope_as = rf_puppet_seized_kingdom
			}
		}
		if = {
			limit = {
				NOT = { exists = scope:rf_puppet_seized_county }
				NOT = { exists = scope:rf_puppet_seized_empire }
				NOT = { exists = scope:rf_puppet_seized_kingdom }
			}
			random_held_title = {
				title_tier = duchy
				limit = {
					NOT = { this ?= scope:recipient.capital_county.de_jure_liege }
					NOT = { this ?= scope:recipient.primary_title }
					scope:recipient = { primary_title.tier > tier_duchy }
					scope:actor = {
						AND = {
							exists = primary_title
							primary_title.tier < tier_duchy
						}
					}
				}
				save_scope_as = rf_puppet_seized_duchy
			}
		}
	}

	if = {
		limit = {
			OR = {
				exists = scope:rf_puppet_seized_county
				exists = scope:rf_puppet_seized_duchy
				exists = scope:rf_puppet_seized_kingdom
				exists = scope:rf_puppet_seized_empire
			}
		}
		if = {
			limit = { exists = scope:rf_puppet_seized_county }
			scope:rf_puppet_seized_county = {
				# Save any personally held higher title that should travel with the county.
				if = {
					limit = {
						de_jure_liege ?= { holder = scope:recipient }
						scope:recipient = { primary_title.tier > tier_duchy }
						NOT = { de_jure_liege ?= scope:recipient.primary_title }
						OR = {
							scope:actor = { NOT = { exists = primary_title } }
							scope:actor = {
								AND = {
									exists = primary_title
									primary_title.tier < tier_duchy
								}
							}
							de_jure_liege.de_jure_liege ?= { holder = scope:actor }
							de_jure_liege.de_jure_liege.de_jure_liege ?= { holder = scope:actor }
						}
					}
					de_jure_liege = { save_scope_as = rf_puppet_seized_duchy }
				}
				if = {
					limit = {
						de_jure_liege.de_jure_liege ?= { holder = scope:recipient }
						scope:recipient = { primary_title.tier > tier_kingdom }
						NOT = { de_jure_liege.de_jure_liege ?= scope:recipient.primary_title }
						OR = {
							scope:actor = { NOT = { exists = primary_title } }
							scope:actor = {
								AND = {
									exists = primary_title
									primary_title.tier < tier_kingdom
								}
							}
							de_jure_liege.de_jure_liege.de_jure_liege ?= { holder = scope:actor }
						}
					}
					de_jure_liege.de_jure_liege = { save_scope_as = rf_puppet_seized_kingdom }
				}
				if = {
					limit = {
						de_jure_liege.de_jure_liege.de_jure_liege ?= { holder = scope:recipient }
						scope:recipient = { primary_title.tier > tier_empire }
						NOT = { de_jure_liege.de_jure_liege.de_jure_liege ?= scope:recipient.primary_title }
						OR = {
							scope:actor = { NOT = { exists = primary_title } }
							scope:actor = {
								AND = {
									exists = primary_title
									primary_title.tier < tier_empire
								}
							}
							de_jure_liege.de_jure_liege.de_jure_liege.de_jure_liege ?= { holder = scope:actor }
						}
					}
					de_jure_liege.de_jure_liege.de_jure_liege = { save_scope_as = rf_puppet_seized_empire }
				}
			}
		}

		scope:recipient = {
			create_title_and_vassal_change = {
				type = granted
				save_scope_as = rf_puppet_seize_change
				add_claim_on_loss = no
			}
		}

		if = {
			limit = { exists = scope:rf_puppet_seized_empire }
			scope:recipient = {
				every_held_title = {
					title_tier = county
					limit = {
						de_jure_liege.de_jure_liege.de_jure_liege ?= scope:rf_puppet_seized_empire
						NOT = { this = scope:recipient.capital_county }
						NOT = { de_jure_liege ?= scope:recipient.capital_county.de_jure_liege }
					}
					change_title_holder = {
						holder = scope:actor
						change = scope:rf_puppet_seize_change
						take_baronies = yes
					}
				}
			}
		}
		else_if = {
			limit = { exists = scope:rf_puppet_seized_kingdom }
			scope:recipient = {
				every_held_title = {
					title_tier = county
					limit = {
						de_jure_liege.de_jure_liege ?= scope:rf_puppet_seized_kingdom
						NOT = { this = scope:recipient.capital_county }
						NOT = { de_jure_liege ?= scope:recipient.capital_county.de_jure_liege }
					}
					change_title_holder = {
						holder = scope:actor
						change = scope:rf_puppet_seize_change
						take_baronies = yes
					}
				}
			}
		}
		else_if = {
			limit = { exists = scope:rf_puppet_seized_duchy }
			scope:recipient = {
				every_held_title = {
					title_tier = county
					limit = {
						de_jure_liege ?= scope:rf_puppet_seized_duchy
						NOT = { this = scope:recipient.capital_county }
						NOT = { de_jure_liege ?= scope:recipient.capital_county.de_jure_liege }
					}
					change_title_holder = {
						holder = scope:actor
						change = scope:rf_puppet_seize_change
						take_baronies = yes
					}
				}
			}
		}
		else = {
			scope:rf_puppet_seized_county = {
				change_title_holder = {
					holder = scope:actor
					change = scope:rf_puppet_seize_change
					take_baronies = yes
				}
			}
		}
		if = {
			limit = { exists = scope:rf_puppet_seized_duchy }
			scope:rf_puppet_seized_duchy = {
				change_title_holder_include_vassals = {
					holder = scope:actor
					change = scope:rf_puppet_seize_change
					take_baronies = no
				}
			}
		}
		if = {
			limit = { exists = scope:rf_puppet_seized_kingdom }
			scope:rf_puppet_seized_kingdom = {
				change_title_holder_include_vassals = {
					holder = scope:actor
					change = scope:rf_puppet_seize_change
					take_baronies = no
				}
			}
		}
		if = {
			limit = { exists = scope:rf_puppet_seized_empire }
			scope:rf_puppet_seized_empire = {
				change_title_holder_include_vassals = {
					holder = scope:actor
					change = scope:rf_puppet_seize_change
					take_baronies = no
				}
			}
		}

		scope:recipient = { resolve_title_and_vassal_change = scope:rf_puppet_seize_change }

		# Make the new title visible as the puppet master's primary if it promoted them.
		scope:actor = {
			if = {
				limit = {
					exists = scope:rf_puppet_seized_empire
					OR = {
						NOT = { exists = primary_title }
						AND = {
							exists = primary_title
							primary_title.tier < tier_empire
						}
					}
				}
				set_primary_title_to = scope:rf_puppet_seized_empire
			}
			else_if = {
				limit = {
					exists = scope:rf_puppet_seized_kingdom
					OR = {
						NOT = { exists = primary_title }
						AND = {
							exists = primary_title
							primary_title.tier < tier_kingdom
						}
					}
				}
				set_primary_title_to = scope:rf_puppet_seized_kingdom
			}
			else_if = {
				limit = {
					exists = scope:rf_puppet_seized_duchy
					OR = {
						NOT = { exists = primary_title }
						AND = {
							exists = primary_title
							primary_title.tier < tier_duchy
						}
					}
				}
				set_primary_title_to = scope:rf_puppet_seized_duchy
			}
			else_if = {
				limit = {
					exists = scope:rf_puppet_seized_county
					NOT = { exists = primary_title }
				}
				set_primary_title_to = scope:rf_puppet_seized_county
			}
		}

		# A territorial power grab is the strongest direct hit to puppet stability.
		scope:recipient = {
			if = {
				limit = { has_variable = riseandfall_rs_puppet_stability_bonus }
				change_variable = { name = riseandfall_rs_puppet_stability_bonus add = -25 }
				clamp_variable = { name = riseandfall_rs_puppet_stability_bonus min = -35 max = 35 }
				round_variable = { name = riseandfall_rs_puppet_stability_bonus nearest = 1 }
			}
		}
	}
}


	riseandfall_overthrow_liege_effect = {
	# Based on palace coup overthrow
	create_title_and_vassal_change = {
		type = conquest
		save_scope_as = change
	}
	# Transfer all held titles from recipient to actor
		scope:recipient = {
			if = {
				limit = { has_active_diarchy = yes }
				riseandfall_end_puppet_regency_forcefully_se = yes
			}
		# If the recipient has a capital county, transfer that county first
        if = {
            limit = { scope:recipient = { capital_county = { exists = yes } } }
            scope:recipient = {
                capital_county = {
                    change_title_holder = {
                        holder = scope:actor
                        change = scope:change
                        take_baronies = yes
                    }
                }
            }
        }
		# Now iterate through all held titles explicitly and assign them to actor
		scope:recipient = {
			every_held_title = {
				limit = {
					# Don't transfer the baronies again if we transfer the top county, but we just skip baronies
					NOT = { tier = tier_barony }
					NOT = { is_noble_family_title = yes }
					NOT = { is_head_of_faith = yes }
				}
				change_title_holder = {
					holder = scope:actor
					change = scope:change
					take_baronies = yes
				}
			}
		}
		every_vassal = {
			limit = {
				NOT = { this = scope:actor }
				liege = scope:recipient
			}
			change_liege = {
				liege = scope:actor
				change = scope:change
			}
		}
		if = {
			limit = { is_landed = yes }
			change_liege = {
				liege = scope:actor
				change = scope:change
			}
		}
		else = {
			set_employer = scope:actor
		}
	}
	resolve_title_and_vassal_change = scope:change
}
