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.
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…”).
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):
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 },
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.
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:
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:
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:
Add a similar chunk of code for our new card to this section:
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:
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
...
The function TA7 has the following prototype:
▲ランク
is the card rarity rank. You should set this to 0 (common), 10 (rare) or 20 (ultra rare) in most cases. Other possible values are 4/14 (for scripted drops) and 9/19 (prevents the card from dropping as a duplicate).▲箱
is the chest level. 0 means a common chest, 1 means a rare chest. You should pass the the variable fg
for this argument.v
is the name of the card. You should pass the variable v
for this argument.識別名
is the character requirement. For example, if you want to add variant cards which require the player to first collect the base card, you would pass the name of the character for this argument.条件
is the star rank requirement. It can be one of three values: “★20”, “★40” or “★80”. If this argument is not "", then the character named in the 識別名
argument must be at that star rank before the card will drop.▲フラグ
can be 0, 1 or 2. Most of the time you should pass 0. If you’re adding a nude card, you should pass 2. The value 1 doesn’t appear to be used for anything (I think the intention was to restrict certain cards from dropping until you’ve completed part 2, but the code implementing this was probably commented out).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
.
That’s it. If you launch the game and start a new game, you should find your Akuji card in the JAPAN faction.