Adding cards to Rance X

This tutorial will demonstrate how to add a new card to Rance X with a custom CG and skills.

You will need alice-tools and SLC’s ALDExplorer program.

Creating a new .afa archive

First, create a new archive with ALDExplorer (File menu, “New empty archive file”). Choose “AFA File v2” as the file format.

Then add your custom CG to the archive (Import/Export menu, “Import and add new files…”). Select .qnt for the file format (NOTE: the game rejects .ajp files encoded by ALDExplorer, so you can’t use the .ajp format).

Make sure the the file is named “カード/akuji.qnt” (the “カード/” prefix is important, do not forget it). Rename it if necessary (right-click, “Properties”).

Finally, save the new archive into your game directory and call it Rance10CGmod.afa (File menu, “Save As…”).

Adding the new archive to the game

First, dump the game’s bytecode with alice-tools:

alice ain dump -c -o r10.jam Rance10.ain

Then open the file r10.jam in a text editor and locate the function LoadAdditionalAFAFile. Add the following 3 lines to the end of the function (just before the RETURN instruction):

S_PUSH "Rance10CGmod"
CALLFUNC AFL_AFA_CG_Add
POP

Adding a new card

First, dump the file Rance10EX.ex with alice-tools:

alice ex dump -o r10.x --split Rance10EX.ex

This will generate a number of .x files in the current directory. Open the file 8_カードデータ.x in a text editor. The first line in the table gives the names and types of the columns (formatted vertically here for readability):

{
    indexed string Id,      // unique ID for the card, and the name that appears in game
    string 識別名,          // the character's name
    string CG名,          // name of the CG *without* the "カード/" prefix
    int 所属,               // the faction the card belongs to
    int 属性,               // attribute (fire, ice, etc.)
    int 性別,               // gender (1 = male, 2 = female)
    int スキル1,           // ID of the first skill
    int スキル2,           // ID of the second skill
    int HP,               // hit points
    int ATK,             // attack
    int 種別,               // ?
    string 詳細CG,        // CG to use for details page (when you first get the card)
    int イベント種別,       // ?
    int 大人子供,           // adult or child (adult = 0, child = 1)
    int 裸,                 // nude (0 = normal, 2 = nude)
    int SR,               // card rarity?
    int 削除,               // ?
    int 発生,               // ?
    int 情報時カード表示,   // ?
    int 割り込みバトル倍率, // ?
    int 必殺連撃効果        // ?
},

To add a new card, we need to add a new row to this table. In this tutorial, we’re going to add a card to the JAPAN faction with the same stats as the default Rance card and (superficially) different skills. So we copy the line beginning with “Lv42 ランス” and change it like so:

{ "Lv42 ランス",    "ランス", "ランス/基本", 1, 0, 1, 1004, 1008, 50, 42, 0, "立ち/ランス/基本", 0, 0, 0, 87, 0, 1, 0, 2, 0 },
{ "Yamamoto Akuji", "Akuji",  "akuji",        6, 0, 1, 2500, 2501, 50, 42, 0, "",                   0, 0, 0, 87, 0, 1, 0, 2, 0 },

Adding new skills

Open the file 11_スキルデータ.x. This file contains a table with the data for every skill in the game. We will be adding two new rows by copying the skills used by the default Rance card:

{ 1004, "突撃-零-",     1, 3, "", 0, 100, 1, 100, 0, 0, 0, 0, "", 0, 0, "攻撃(1倍)" },
{ 2500, "Akuji Kick",     1, 3, "", 0, 100, 1, 100, 0, 0, 0, 0, "", 0, 0, "攻撃(1倍)" },
{ 1008, "ランスアタック", 1, 3, "", 3, 100, 1, 300, 7, 0, 0, 0, "", 1, 0, "攻撃(3倍)r 必中" },
{ 2501, "Akuji Punch",    1, 3, "", 3, 100, 1, 300, 7, 0, 0, 0, "", 1, 0, "攻撃(3倍)r 必中" },

Note that the numbers 2500 and 2501 match the numbers that we used in the row for our new card above. Other than that nothing has been changed about these skills.

Giving the player the new card

We will give the player the new card at the beginning of the game. Open r10.jam again and locate the function T初期化1. Partway though the function you should see a bunch of lines that look like this:

S_PUSH "card name"
CALLFUNC T味方カード生成
POP

This is the code that gives a card to the player at the start of a game. Add the following lines to this section of code:

S_PUSH "Yamamoto Akuji"
CALLFUNC T味方カード生成
POP

Note that the string “Yamamoto Akuji” matches the name given to the card above.

We should also register the card with the Tc function. I’m not entirely sure what this does but every card seems to be registered this way, so we should do it too. Locate the function Tカード一覧. You should see a section of code with the following pattern repeated many times:

S_PUSH "card name"
CALLFUNC Tc

Add a similar chunk of code for our new card to this section:

S_PUSH "Yamamoto Akuji"
CALLFUNC Tc

Adding the card to the gacha pool

Getting the card to show up in chests is a bit more complicated. locate the function Tカード箱 and find the section towards the end with the string “1級神 クエルプラン” (it’s probably easier to just search for this string, as this is a very long function). You should see the following pattern repeated many times in this function:

    ...
check_card_label_1:
    .S_LOCALASSIGN v "card name" ; set card name
    PUSH 20                      ; card rarity
    .LOCALREF fg                 ; chest flag (0=common, 1=rare)
    .LOCALREF v                  ; card name
    A_REF
    S_PUSH ""                    ; character requirement
    S_PUSH ""                    ; star rank requirement
    PUSH 1                       ; "flag" (0=normal, 1=???, 2=nude)
    CALLFUNC TA7              ; TA7(20, fg, v, "", "", 1)
    PUSH 1
    EQUALE
    IFNZ add_card_label_1        ; if TA7 returned 1, jump to add_card_label_1
    JUMP check_card_label_2      ; otherwise, jump to check_card_label_2
add_card_label_1:
    .LOCALINC2 aa
    .LOCALREF カードBOX
    .LOCALREF aa
    REF
    .LOCALREF v
    A_REF
    S_ASSIGN
    DELETE
check_card_label_2:
    ...

The code between check_card_label_1 and add_card_label_1 calls the function TA7 to see if it should add the card to the gacha pool. The code between add_card_label_1 and check_card_label_2 adds the card to the pool. This code would decompile to something like this:

v = "card name";
if (TA7(20, fg, v, "", "", 1) == 1) {
    aa++;
    カードBOX[aa] = v;
}

To add our card to the gacha pool, we have to add add another chunk of bytecode with the same pattern. We will add it just beneath the code for “1級神 クエルプラン”:

    ...
0xd42422:
    .S_LOCALASSIGN v "1級神 クエルプラン"
    PUSH 20
    .LOCALREF fg
    .LOCALREF v
    A_REF
    S_PUSH ""
    S_PUSH ""
    PUSH 1
    CALLFUNC TA7
    PUSH 1
    EQUALE
    IFNZ 0xd4247e
    JUMP 0xd424b8
0xd4247e:
    .LOCALINC2 aa
    .LOCALREF カードBOX
    .LOCALREF aa
    REF
    .LOCALREF v
    A_REF
    S_ASSIGN
    DELETE
0xd424b8:
    ; NEW CODE STARTS HERE
    .S_LOCALASSIGN v "Yamamoto Akuji"
    PUSH 0       ; ▲ランク = 0
    .LOCALREF fg ; ▲箱     = fg
    .LOCALREF v  ; v       = v
    A_REF
    S_PUSH ""    ; 識別名  = ""
    S_PUSH ""    ; 条件    = ""
    PUSH 0       ; ▲フラグ = 0
    CALLFUNC TA7
    PUSH 1
    EQUALE
    IFNZ gacha_add_akuji
    JUMP gacha_mod_end
gacha_add_akuji:
    .LOCALINC2 aa
    .LOCALREF カードBOX
    .LOCALREF aa
    REF
    .LOCALREF v
    A_REF
    S_ASSIGN
    DELETE
gacha_mod_end:
    ; NEW CODE ENDS HERE
    .LOCALREF aa
    PUSH 0
    ...

TA7 arguments

The function TA7 has the following prototype:

int TA7(int ▲ランク, int ▲箱, string v, string 識別名, string 条件, int ▲フラグ)

Rebuilding the files

Rebuild the .ain file with alice-tools:

alice ain edit -c r10.jam -o r10.ain Rance10.ain

Then replace Rance10.ain in the game directory with the modified r10.ain.

Rebuild the .ex file with alice-tools:

alice ex build -o r10.ex r10.x

Then replace Rance10EX.ex in the game directory with the modified r10.ex.

End

That’s it. If you launch the game and start a new game, you should find your Akuji card in the JAPAN faction.