スコープ
※2025/10/6、英wikiよりkagi翻訳を通しました。機械翻訳なので一部不自然な日本語があるかもしれません。ぜひ編集してくれるとありがたいです。
スコープは、トリガーのチェックや効果の実行のために、スクリプト内で対象となるエンティティを選択するために使用されます。
定義[編集 | ソースを編集]
データベース・スコープ[編集 | ソースを編集]
スコープとは、最も一般的にはデータベース上のオブジェクトを指し、データベース自体はスコープの種類(スコープタイプ)として参照されます。例としてはキャラクター、称号、プロヴィンスなどが含まれます。
利用可能なスコープタイプの全一覧はevent_scopes.logにあります。
特に断りがない限り、スコープという用語は常にデータベース・スコープを指します。
データベース・スコープは通常、以下の3つの特性を持ちます。
一部のスコープはゲーム開始時に作成されます。/Crusader Kings III/historyファイル(歴史的キャラクター、称号)、/Crusader Kings III/map data(プロヴィンス)、/Crusader Kings III/commonフォルダ(文化、信仰、政体、特性…)などが出典です。
一部のスコープは実行時にも、コード上(例:自然出産したキャラクター)やスクリプト上(例:create_character効果で作られたキャラクター、動的称号)で作成されます。
プリミティブ・スコープ[編集 | ソースを編集]
数値、ブール値(yes/no)、フラグ値(flag:some_string)は、いわゆるプリミティブ・スコープです。これらは変更やアクセスができません。「数値もスコープである」という表現は初心者には混乱を招くかもしれませんが、上級機能やエラーログの理解には有用です。
トップ・スコープ[編集 | ソースを編集]
トップ・スコープは、ゲームが情報を保持するために作成する一時的かつ抽象的なオブジェクトで、ローカライズやGUIでの表示などに利用されます。
スコープへのアクセス[編集 | ソースを編集]
特に断りがない限り、スコープという用語は常にデータベース・スコープを指します。
スクリプトでは、効果とトリガーはコンテキスト内で実行され、多くは特定のスコープタイプから機能します。
例:トリガーis_ai = noは現在のスコープがプレイヤーかどうかを判定しますが、これはキャラクタースコープの文脈でのみ意味を持ちます。別のスコープタイプの文脈で用いるとエラーになります。
この章では、スクリプトが解釈されるコンテキストを変更する方法を説明します。スコープは効果やトリガーの引数としても使用でき、その場合も以下のアクセス方法が用いられます。
root[編集 | ソースを編集]
トリガーブロックや効果ブロックには、コード側でデフォルトのコンテキストが与えられていることがよくあります。その場合、コンテキストが変更されない限り、トリガーはそのスコープの文脈で評価され、効果は実行されます。
例:イベントのimmediate効果ブロックでは、コンテキストはイベントを受け取ったキャラクターであり、デフォルトではそのブロック内の全ての効果は当該キャラクタースコープの文脈で実行されます。
効果ブロックやトリガーブロックにデフォルトのコンテキストがある場合、rootはそのデフォルト・コンテキストへのショートカットです。よくある誤解に反して、rootはプレイヤーを意味しません。実際、このゲームでは複数のプレイヤーが存在し得るため、「プレイヤー」という概念自体が曖昧です。
すべての効果ブロックやトリガーブロックにrootがあるわけではありません。例えば、キャラクター相互作用内のものにはありません。送信者と受信者のどちらを指すか曖昧になり得るためです。
rootが必ずしもキャラクタースコープであるとは限りません。rootが存在するか、またそれがどのスコープかは、各効果ブロックやトリガーブロックに依存します。
コンテキスト切り替え[編集 | ソースを編集]
効果ブロックやトリガーブロックのコンテキストは、設定したいスコープ名の後に等号=と開き波括弧{を置いて新しいスクリプトブロックを開くことで、任意の時点で変更できます。対応する閉じ波括弧}が現れるまで、そのコンテキスト変更は有効です。
例:イベントのimmediate効果ブロック
immediate = {
< ここでのコンテキストはイベントを受け取ったキャラクター(キャラクタースコープ) >
title:k_france = {
< ここでのコンテキストはフランス王国(称号スコープ) >
}
< ブロックを閉じると、元のキャラクタースコープに戻る >
}
スクリプトブロックをネストしてさらに開くことで、コンテキストは複数回切り替えられます。新しいブロックを開くたびにインデントを増やし、閉じたら減らします。インデントを整えておくと、どの文脈でトリガーや効果が解釈されるのかが一目で分かります。
rootが提供されている場合は、いつでもそれにアクセスしてコンテキストを戻せます。
例:
immediate = {
title:k_france = {
< ここでのコンテキストはフランス王国 >
root = {
< ここでのコンテキストはイベント受領キャラクター >
}
}
}
無効なスコープにコンテキストを変更しようとすると、コンテキスト切り替えは失敗します。 例:
immediate = {
title:k_frnace = {
この誤字により、k_frnaceが未定義のためコンテキスト切り替えは失敗します。
データベースへのアクセス[編集 | ソースを編集]
スコープはデータベース・オブジェクトであるため、一意のキーやIDを持ちます。<scope type>:<scope key>という構文で識別されます。
例:title:k_franceはcommon/landed_titles/で定義されているフランス王国です。
title:k_france = {
# ここでのコンテキストはフランス王国
}
キャラクターには2種類のIDがあります。履歴IDと実行時IDです。 履歴IDは/Crusader Kings III/historyファイルで事前に決められているため、歴史的キャラクターはそのIDでアクセスできます。一方、非歴史的キャラクターは実行時に割り当てられるIDしか持たず、事前には分からずゲームごとに一貫しないため、スクリプトから参照できません。したがって非歴史的キャラクターにはこの方法でアクセスできません。
イベントターゲット[編集 | ソースを編集]
一意の関係で結ばれているスコープ同士は、イベントターゲットを通じてアクセスできます。ゲームは全てのイベントターゲットのスコープタイプを把握しているため、これらには接頭辞が付きません。
利用可能なイベントターゲットの全一覧はevent_targets.logにあります。
例:
holder - スコープ中の称号の保有者を取得 入力スコープ: landed_title 出力スコープ: character
出力スコープはイベントターゲットのスコープタイプです。
入力スコープはイベントターゲットを使用できるスコープタイプです。
称号は常に同時にただ一人のキャラクターにしか保有されません。そのため、holderイベントターゲットにより、称号スコープからその称号を保有する唯一のキャラクタースコープへ移動できます。
title:k_france = {
holder = {
イベントターゲットはドットで連結してチェーンできます。
例:
title:k_france.holder = {
以下のイベントターゲットには特有のコンテキスト動作があります。
this[編集 | ソースを編集]
thisは現在のスコープです。特にスコープ比較や、現在のスコープを引数として渡す際に有用です。
prev[編集 | ソースを編集]
prevは直前のスコープです。this同様、スコープ比較や直前のスコープを引数に渡す際に有用ですが、下記のリストビルダーと併用する場合にも役立ちます。
title:k_france = {
holder = {
prev = {
# ここでのコンテキストは一段戻って title:k_france になる
CK2とは異なり、prevは複数段さかのぼるためにチェーンすることはできません。
保存されたスコープ[編集 | ソースを編集]
保存されたスコープは、scope:<scope name>という構文で、特定のスコープへの任意の名前付きポインタです。
保存されたスコープはコード側で保存され、提供されることがあります。例えば、キャラクター相互作用では、scope:actorは相互作用を送るキャラクター、scope:recipientは受け取るキャラクターです。
一部のon_actionでも事前に保存されたスコープが提供されます。どのスコープが利用できるかはファイル内のコメントを確認してください。
保存されたスコープは、save_scope_as effectを使ってスクリプトからも保存できます。これは現在のスコープを指定した名前で保存します。
title:k_france.holder = {
save_scope_as = king_of_france
}
以後、その保存済みスコープにはいつでもアクセスできます。
scope:king_of_france = {
保存されたスコープは、UIからスクリプトGUIやスクリプト値/カスタムローカライズへ、AddScopeで受け渡しできます。
"[ScriptedGui.Execute( GuiScope.SetRoot( GetPlayer.MakeScope ).AddScope( 'target', CharacterWindow.GetCharacter.MakeScope ).End )]"
"[GuiScope.SetRoot( GetPlayer.MakeScope ).AddScope( 'target', CharacterWindow.GetCharacter.MakeScope ).ScriptValue('sval_name')|0]"
保存されたスコープは、連続した効果チェーンの間ずっと引き継がれます。例えば、イベントAでscope:king_of_franceを保存し、そのイベントAがイベントBを発火した場合、イベントBでもscope:king_of_franceにアクセスできます。
連続した効果チェーンが終わると、保存されたスコープは自動的にクリアされます。必要に応じて、clear_saved_scope effectで手動クリアも可能です。
save_temporary_scope_asはeffectとしてもtriggerとしても使えます。保存された一時スコープは連続効果チェーンを跨いで引き継がれず、保存された効果ブロックまたはトリガーブロックの終端で失効します。
同じ名前の保存スコープは同時にひとつしか存在できません。同名で新たに保存すると、以前のものは上書きされます。
リストビルダー[編集 | ソースを編集]
一対多の関係を持つスコープは、イベントターゲットではアクセスできません。
例えば、キャラクターには母親は常に一人であり、motherイベントターゲットでアクセスできます。しかし逆は成り立ちません。母親には複数の子がい得るため、曖昧になるchildイベントターゲットは存在しません。
この場合、スコープはリストとして提供され、リストビルダーを用いてアクセスできます。リストビルダーにはeffectの派生が3種、triggerの派生が1種あります。
以下の節では、全てキャラクタースコープの文脈でchildリストを用いたスクリプト例を示します。スクリプト内で構築されるリストを含め、さまざまな種類のリストがあります。
- メイン記事へ: Lists
every_X[編集 | ソースを編集]
every_Xはリスト内の全てのスコープに順にアクセスし、それぞれに対して内包された効果を実行するeffectです。
every_child = {
add_gold = 10
}
# 現在のキャラクタースコープの全ての子が金10を得る
リストが空であれば、内包された効果は実行されません。
limitブロック内のトリガーを使って、リストを絞り込むことができます。リミットがtrueと評価されたスコープに対してのみ効果が実行されます。
every_child = {
limit = { is_female = yes }
add_gold = 10
}
# 現在のキャラクタースコープの全ての娘が金10を得る
絞り込み後のリストが空であれば、内包された効果は実行されません。
前述の通り、リストビルダーではprevがよく使われ、リストビルダーを用いた元のスコープへ戻るのに役立ちます。
every_child = {
limit = { is_female = yes }
prev = {
add_gold = 10
}
}
# 対象キャラクターは、娘1人につき金10を得る
every_Xでスコープを保存するのは有用ですが、同名の保存スコープは同時に1つしか存在できないため、every_Xの実行が終わると、最終的に保存されているのはリストの最後のスコープのみです。
every_child = {
limit = { is_female = yes }
save_scope_as = female_child
}
scope:female_child = {
# これはリスト中の最後の娘であり、全員ではない
}
random_X[編集 | ソースを編集]
random_Xはリストからランダムに1つのスコープにアクセスし、そのスコープに対してのみ内包された効果を実行します。
random_child = {
add_gold = 10
}
# 子ども1人が金10を得る
リストが空であれば、内包された効果は実行されません。
limitブロック内のトリガーでリストを絞り込め、random_Xはtrueと評価されたスコープの中からランダムに1つを選びます。
random_child = {
limit = { is_female = yes }
add_gold = 10
}
# 娘1人が金10を得る
リスト内にlimitの条件を満たすスコープがない場合、内包された効果は実行されません。
保存スコープはrandom_Xと併用されることが多く、特定のキャラクターにスコープしたい場合に特に有用です。ゲーム内の多くのキャラクターは歴史的IDを持たずID参照ができないため、他のスコープから相対的にアクセスして保存スコープとして確保し、後で再アクセスしやすくします。
random_child = {
limit = {
is_female = yes
is_adult = yes
is_married = no
}
save_scope_as = celibate_daughter
}
ordered_X[編集 | ソースを編集]
ordered_Xはorder_byパラメータに従ってリストをソートし、デフォルトでは降順で最初のスコープにアクセスして、そのスコープに対してのみ内包された効果を実行します。order_byには名前付き値またはスクリプト値を指定でき、リスト中の各スコープの文脈で解釈されます。
注意:script mathでは、ordered_Xの既定動作はリスト中の全スコープを順に反復処理することです。これがバグなのか仕様なのかは不明です。
ordered_child = {
order_by = age
add_gold = 10
}
# 最年長の子が金10を得る
limitブロック内のトリガーでリストを絞り込め、ordered_Xはtrueと評価された中からリストの先頭のスコープを選びます。
ordered_child = {
limit = { is_female = yes }
order_by = age
add_gold = 10
}
# 最年長の娘が金10を得る
positionパラメータで既定の動作を上書きし、指定したインデックス(0始まり)のスコープにアクセスできます。整数または自動的に小数点以下切り捨てのスクリプト値を使えます。position = 0は先頭のスコープです。
ordered_child = {
limit = { is_female = yes }
order_by = age
position = 1
}
# 上から2番目に年長の娘が金10を得る
minとmaxパラメータにより、ordered_Xはインデックスがmin以上max以下の範囲にある全スコープを順に処理します。check_range_boundsパラメータは、指定範囲がリストサイズを超える場合のエラーを回避します。
ordered_child = {
limit = { is_female = yes }
order_by = age
max = 2
check_range_bounds = no
}
# 最年長から数えて上位3人の娘が順に金10を得る
any_X[編集 | ソースを編集]
any_Xは、リスト内のスコープに不定順でアクセスし、内包されたトリガーがいずれかのスコープでtrueになるまで評価を続け、trueになった時点でany_X自体がtrueと評価されます。全てのスコープでfalseになる、またはリストが空なら、any_Xはfalseです。
any_child = {
age > 10
}
# 子どものうち誰かが厳密に10歳を超えていればtrue
filterブロック内のトリガーでリストを絞り込めます。any_X内のトリガーは、filterがtrueと評価されたスコープに対してのみチェックされます。
any_child = {
filter = { is_female = yes }
age > 10
}
# 娘のうち誰かが厳密に10歳を超えていればtrue
save_temporary_scope_asを使うと、内包トリガーが全てtrueになった最初のオブジェクトを保存し、同じトリガーブロック内で後から参照できます。
any_child = {
filter = { is_female = yes }
age > 10
save_temporary_scope_as = teenage_daughter
}
countパラメータを使うと、any_X内のトリガーがtrueになるスコープの数に任意の下限を要求できます。
any_child = {
condition = { is_female = yes }
age > 10
count >= 2
}
# 10歳を厳密に超える娘が少なくとも2人いればtrue
percentパラメータを使うと、any_X内のトリガーがtrueになるスコープの割合に任意の下限を要求できます。
any_child = {
condition = { is_female = yes }
age > 10
percent >= 0.5
}
# 10歳を厳密に超える娘が半数以上いればtrue
保存されたスコープ値[編集 | ソースを編集]
保存されたスコープ値は、scope:<scope name>という構文で、特定のプリミティブ・スコープへの任意の名前付きポインタです。
保存されたスコープ値はコード側で保存・提供されることもありますが、保存スコープに比べると稀です。例えば、キャラクター相互作用にoption_1という選択肢がある場合、scope:option_1はブールのスコープ値で、選択されていればtrue、されていなければfalseです。
保存されたスコープ値は、save_scope_value_as効果を使ってスクリプトからも保存できます。指定したスコープ値を、指定名で保存します。
save_scope_value_as = {
name = some_name
value = <boolean>/<number>/<flag value>
}
同様に、save_temporary_scope_value_asトリガーまたは効果で一時的な保存スコープ値を保存できます。
保存されたスコープ値や一時保存スコープ値の利用範囲は、保存スコープと同じ規則に従います。
参考[編集 | ソースを編集]
| ドキュメンテーション | スクリプト • スコープ • 効果 • トリガー • 変数 • 補正リスト |
| スクリプト | AI • ブックマーク • キャラクター • コマンド • 評議会 • 文化 • ディシジョン • 王朝 • イベント • 政府 • 歴史 • 領地 • ライフスタイル • 連隊 • 宗教 • スクリプト値 • ストーリーサイクル • 闘争 • 称号 • 特性 |
| インターフェース | インターフェース • データ型 • ローカライズ • カスタムローカライズ • フレーバー化 |
| マップ | マップ • 地形 |
| グラフィック | 3Dモデル • エクスポーター • 紋章 • グラフィックアセット • フォント • パーティクル • シェーダー • ユニットモデル |
| オーディオ | 音楽 • サウンド |
| その他 | コンソールコマンド • チェックサム • Modの構造 • Mod制作ツール • トラブルシューティング |