ItemRTレアドロップ表

← ホームへ戻る

ItemRT(Item Rare Table)はPSOのレアドロップ表です。敵や箱からレアアイテムが出る際の種類と確率を定義します。「ドラゴンスレイヤー1/456」「総督恩賜パラソル1/3660」などの数値はItemRTに由来します。ItemPT(ドロップの有無と大分類)、ItemPMT(アイテム自体のパラメータ)と合わせて、PSOのドロップシステムを構成します。

概要

PSOではレアドロップ判定が通常ドロップ判定から独立しています。敵の撃破や箱の破壊時には、まずレア判定を行います。

  1. ItemRTから対象の敵・箱のレア候補を取得します。
  2. 候補のレアアイテムを順番に1つずつ判定し、当選した時点で終了します(Sega純正の方式。newservは1回の乱数でまとめて判定します。下記「ドロップ判定の全体像」を参照)。
  3. いずれかが成功したら、そのレアアイテムがドロップとなり、ItemPTの通常ドロップ処理を省略します。
  4. すべて失敗したら、ItemPTの通常ドロップ処理へ進みます。

同じ敵でも、通常アイテムとレアアイテムの選択は別経路です。通常アイテムの種類が多いことで、レアドロップ率がさらに下がるわけではありません。

ファイル構成

ItemRTは難易度×セクションIDの組み合わせごとにサブテーブルを持ち、合計4 × 10 = 40個です(EP4は別のテーブルを持ちます)。各サブテーブルは次の2部分に分かれます。

  • エネミーのレア候補(Monster Rares):敵の種類で索引され、各種類に最大1つのレアアイテムとその確率を持ちます。
  • 箱のレア候補(Box Rares):エリア別です。同じエリアの箱に通常は複数の候補があり、例えば遺跡3には10種近い候補があります。

PSOBBでは2つのファイルを使用します:ItemRT.gsl(EP1・EP2)とItemRT_Ep4.gsl。GSLはSega独自の小規模なアーカイブ形式(GStreamLib)で、各エントリにサブテーブルを格納します。

レアドロップの生成手順

  1. サブテーブルの選択:現在の難易度と部屋のセクションIDで選択します。
  2. 候補の取得:
    • エネミー:敵種別の索引から(アイテムID, 確率)。
    • 箱:エリアの索引から候補一覧を取得します。
  3. 確率判定:Sega純正は候補ごとに順番に32ビット乱数を生成して確率値と比較し、当選した時点で終了します。newservは32ビット乱数を1回だけ生成し、各候補の確率を順に引いて負になった時点で当選とします。両者の違いは下記「ドロップ判定の全体像」を参照してください。
  4. 成功時:アイテムを生成します。武器は現在のエリアに対応するItemPTの属性・エクストラアタック生成も行い、鎧・盾ではスロット数を決定します。最後にItemPMTから名称とモデルを取得します。

確率を圧縮して格納する理由

PSOBBのItemRTでは、レアアイテムの確率を分数のまま格納しません。代わりにuint8(1バイト)に圧縮し、小さなファイルに数百件のレア情報を格納します。このバイトはSSSSS VVVとして解釈します。

  • 上位5ビットがシフト量、下位3ビットが基準値です。
  • 展開式の概略は(2 << shift) × (value + 7)で、32ビットの確率値になります。
  • 最終ドロップ率=この32ビット値÷0xFFFFFFFF(4,294,967,295)。

例:

  • 0x40000000:最終ドロップ率=25%(0x40000000 / 0xFFFFFFFF ≈ 1/4)
  • 0x00FFFFFF:最終ドロップ率≒1/256

圧縮形式には256通りの値しかなく、任意の確率を正確には表せません。1/456、1/3660、1/11702などの端数を含む数値は、この形式で表現できる値のうち最も近いものです。

セクションIDの役割

PSOBBのキャラクターは10色のセクションIDのいずれかを持ちます。本ページでは作成時の名前のハッシュで決まる固定のIDとして説明しています。IDは次の役割を持ちます。

  • 各難易度で参照するItemRTサブテーブルを選択します。使われるのは部屋を作成したプレイヤーのセクションIDです。
  • IDごとにレア候補が異なり、特定IDでしか出ないものもあります。
  • 例えば、侵食遺伝子「フロウ」は、OranのプレイヤーがUltimateのオルガ・フロウを倒すとドロップすることがあります。

特定のレアを狙う際にIDを選ぶのはこのためです。セクションID計算機で目的のIDになる名前を探せます。

エネミーと箱のレア候補

エネミーのレア候補

  • 索引はrt_index(敵種別の列挙値)で、各種類に1レコードあります。
  • 固定長レコードの内容は(アイテムID, 圧縮確率)です。
  • 敵1種につきレア1つが上限です。同じ敵でもIDによって候補が変わる場合(ヒルデベアから異なる剣が出る例など)は、IDによってサブテーブルが切り替わります。すべての候補を同時に判定するわけではありません。

箱のレア候補

  • 索引はエリアで、各エリアに複数の候補を設定できます。
  • 通常、エリアごとに1~30の候補があり、それぞれに確率を持ちます。
  • 候補一覧を1件ずつ判定し、各候補に当選の機会があります(判定方法は上記「確率判定」を参照)。
  • 遺跡3・セントラルコントロールエリア・コントロールタワー・地下砂漠3などで箱のレア候補が豊富なのは、この仕組みによります。

レアドロップ率補正

ItemRTの元の確率はSegaが設定した基準値です。サーバーでは通常、全体のドロップ率倍率を掛けます。

  • Ephineaの標準倍率は1x(基準値)です。周年イベントのマイルストーンで倍率が上がる場合があります。
  • 全体倍率はすべてのレアアイテムの確率に適用されます。

データ構造

ItemRTのバイナリ形式は、圧縮確率とアイテムコードの固定長レコードを最小単位とします。難易度×IDの各サブテーブルは次のオフセットヘッダーで始まります。

サブテーブルヘッダー:Offsets(0x10バイト)

オフセットフィールド型説明
0x00monster_rares_offsetu32エネミーのレア候補へのポインター→PackedDrop[0x65](v1は0x33件)。rt_indexで索引します。
0x04box_countu32箱のレアエントリ総数。通常は30(0x1E)固定です。
0x08box_areas_offsetu32箱のエリア配列→u8[box_count]。要素iはレアエントリiのエリアを示します。
0x0Cbox_rares_offsetu32箱のレア候補へのポインター→PackedDrop[box_count]。box_areasと1対1で対応します。

圧縮確率レコード:PackedDrop(4バイト)

レアレコードは4バイトで、ItemRTの最小単位です。敵と箱で同じ構造を使用します。

オフセットフィールド型説明
0x00probabilityu8圧縮確率(SSSSS VVVのビット配置)。
0x01item_codeu8×3アイテムコードdata1[0..2]。例えば、00 01 00はSaberを表します。

確率の圧縮と展開

1バイトのprobabilityはSSSSS VVVとして解釈します。

  • 上位5ビットのSでシフト量を決定:shift = S − 4、範囲は[−4, 27]。負値は0として扱います。
  • 下位3ビットのVで基準値を決定:value = V + 7、範囲は[7, 14]です。
  • 展開後の32ビット確率=(2 << shift) × value。これをレアドロップ率の分子とし、分母は0xFFFFFFFF(全32ビット)です。
  • 最終ドロップ率=展開値÷0xFFFFFFFF

例:

packed(16進数)shiftvalueexpanded近似値
0xFF27140xE000000087.5%
0xC02070x01C00000約1/152
0x801270x0001C000約1/38836
0x00070x0000000E極めて小さい(3億分の1未満)

256通りの値しかないため、任意の確率を正確には格納できません。1/456、1/3660、1/11702などは表現可能な値のうち最も近いものです。例えば正確に1/500という確率は指定できません。

展開後の構造:ExpandedDrop

newservは各PackedDropを計算・操作・シリアライズ用のメモリ上の構造体に展開します。

フィールド型説明
probabilityu32展開後の32ビット確率(分子。分母は0xFFFFFFFF固定)
dataItemData3バイトのIDだけでなくdata1/data2を含む完全なアイテムデータ

箱のレア:BoxRare

箱のレアレコードは、エリアで直接索引する代わりにエリア番号をレコード内に持ちます。

フィールド型説明
area_norm_plus_1u8エリア番号+1(0は未使用)
dropExpandedDrop確率+アイテムデータ

サブテーブル全体:SpecCollection

最上位の各サブテーブルは難易度×セクションIDのキーに対応し、展開後は次を含みます。

フィールド型説明
enemy_specsmap⟨Enemy, ExpandedDrop[]⟩各敵種別のレア候補。
box_specsExpandedDrop[][]外側の配列はarea_normで索引され、各エリアに個別判定される候補一覧を持ちます。

ドロップ判定の全体像

敵の撃破または箱の破壊でドロップ処理が始まります。両者は別経路で、まずレア判定を行い、失敗するとItemPTの通常処理へ進みます。

エネミーのドロップ

// ① 前提判定:敵がアイテムを落とすか
type_drop_prob = pt.enemy_type_drop_probs[enemy_type]   // 0–100
if rand(0..99) >= type_drop_prob:
    return nothing                                       // ドロップなし

// ② レア判定(stacking:1回の乱数で全specを判定)
specs = rare_item_set.get_enemy_specs(mode, episode, difficulty, section_id, enemy_type)
det = rand(0, 0x100000000)                               // 32ビット+1
for spec in specs:
    det -= spec.probability                              // 順に減算
    if det < 0:
        return create_rare_item(spec.data, area)          // レア当選、処理終了

// ③ ItemPTの通常処理:大分類を選択
determinant = allow_meseta ? rand(0..2) : rand(0..1) + 1
switch determinant:
    case 0: item_class = 5 (メセタ)
    case 1: item_class = 4 (消耗品)
    case 2: item_class = pt.enemy_type_item_classes[enemy_type]   // 0..3:武器・鎧・盾・ユニット

// ④ 大分類に応じて生成(重み・付加・属性・エクストラアタックなど)
generate_common_item_variances(item, area)

箱のドロップ

// ① レア判定(敵と同じstacking方式)
table_index = table_index_for_area(area)
specs = rare_item_set.get_box_specs(mode, episode, difficulty, section_id, table_index)
det = rand(0, 0x100000000)
for spec in specs:
    det -= spec.probability
    if det < 0:
        return create_rare_item(spec.data, area)

// ② レアなし→box_item_class_prob_tableの重みで大分類を選択
item_class = weighted_pick(pt.box_item_class_prob_table, table_index)
    // 0=武器 1=鎧 2=盾 3=ユニット 4=消耗品 5=メセタ 6=空

// ③ item_class < 6ならアイテムを生成
if item_class < 6:
    generate_common_item_variances(item, area)

stackingに関する注意:
stackingは初期値detから各specの確率を順に引き、負になった時点で当選とします。これは1回の乱数ですべてのspecから結果を決める方式であり、specの順番は最終的な分布に影響しません。
一方、Segaの元のクライアントでは、各specに対して独立に乱数rand(0, 0xFFFFFFFF)を生成し、spec.probabilityと比較します。前の候補が当選すると処理が終了するため、後ろの候補ほど実際の出現率が低くなります。候補が1つの敵では差はありませんが、多数の候補を持つ箱ではstackingと結果が異なります。newservの作者もコメントでこの点を説明しています。

関連ページ