document Ep3 assist AI parameters
This commit is contained in:
+54
-19
@@ -729,7 +729,7 @@ string CardDefinition::Effect::str_for_arg(const string& arg) {
|
|||||||
|
|
||||||
string CardDefinition::Effect::str() const {
|
string CardDefinition::Effect::str() const {
|
||||||
uint8_t type = static_cast<uint8_t>(this->type);
|
uint8_t type = static_cast<uint8_t>(this->type);
|
||||||
string cmd_str = string_printf("(%hhu) %02hhX", this->effect_num, type);
|
string cmd_str = string_printf("%02hhX", type);
|
||||||
try {
|
try {
|
||||||
const char* name = description_for_condition_type.at(type).name;
|
const char* name = description_for_condition_type.at(type).name;
|
||||||
if (name) {
|
if (name) {
|
||||||
@@ -747,8 +747,8 @@ string CardDefinition::Effect::str() const {
|
|||||||
string arg1str = this->str_for_arg(this->arg1);
|
string arg1str = this->str_for_arg(this->arg1);
|
||||||
string arg2str = this->str_for_arg(this->arg2);
|
string arg2str = this->str_for_arg(this->arg2);
|
||||||
string arg3str = this->str_for_arg(this->arg3);
|
string arg3str = this->str_for_arg(this->arg3);
|
||||||
return string_printf("(cmd=%s%s, when=%02hhX, arg1=%s, arg2=%s, arg3=%s, cond=%02hhX, a2=%02hhX)",
|
return string_printf("((%hhu) cmd=%s%s, when=%02hhX, arg1=%s, arg2=%s, arg3=%s, cond=%02hhX, a2=%02hhX)",
|
||||||
cmd_str.c_str(), expr_str.c_str(), this->when, arg1str.data(),
|
this->effect_num, cmd_str.c_str(), expr_str.c_str(), this->when, arg1str.data(),
|
||||||
arg2str.data(), arg3str.data(), static_cast<uint8_t>(this->apply_criterion), this->unknown_a2);
|
arg2str.data(), arg3str.data(), static_cast<uint8_t>(this->apply_criterion), this->unknown_a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -962,6 +962,36 @@ string string_for_drop_rate(uint16_t drop_rate) {
|
|||||||
return string_printf("[%hu: %s]", drop_rate, description.c_str());
|
return string_printf("[%hu: %s]", drop_rate, description.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* short_name_for_assist_ai_param_target(uint8_t target) {
|
||||||
|
switch (target) {
|
||||||
|
case 0:
|
||||||
|
return "ANY";
|
||||||
|
case 1:
|
||||||
|
return "SELF";
|
||||||
|
case 2:
|
||||||
|
return "SELF_OR_ALLY";
|
||||||
|
case 3:
|
||||||
|
return "ENEMY";
|
||||||
|
default:
|
||||||
|
return "__UNKNOWN__";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* name_for_assist_ai_param_target(uint8_t target) {
|
||||||
|
switch (target) {
|
||||||
|
case 0:
|
||||||
|
return "any player";
|
||||||
|
case 1:
|
||||||
|
return "self";
|
||||||
|
case 2:
|
||||||
|
return "self or ally";
|
||||||
|
case 3:
|
||||||
|
return "enemy player";
|
||||||
|
default:
|
||||||
|
return "__UNKNOWN__";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string CardDefinition::str(bool single_line) const {
|
string CardDefinition::str(bool single_line) const {
|
||||||
string type_str;
|
string type_str;
|
||||||
try {
|
try {
|
||||||
@@ -1010,21 +1040,28 @@ string CardDefinition::str(bool single_line) const {
|
|||||||
string drop0_str = string_for_drop_rate(this->drop_rates[0]);
|
string drop0_str = string_for_drop_rate(this->drop_rates[0]);
|
||||||
string drop1_str = string_for_drop_rate(this->drop_rates[1]);
|
string drop1_str = string_for_drop_rate(this->drop_rates[1]);
|
||||||
|
|
||||||
|
string cost_str = string_printf("%hhX", this->self_cost);
|
||||||
|
if (this->ally_cost) {
|
||||||
|
if (single_line) {
|
||||||
|
cost_str += string_printf("+%hhX", this->ally_cost);
|
||||||
|
} else {
|
||||||
|
cost_str += string_printf(" (self) + %hhX (ally)", this->ally_cost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (single_line) {
|
if (single_line) {
|
||||||
string range_str = string_for_range(this->range);
|
string range_str = string_for_range(this->range);
|
||||||
return string_printf(
|
return string_printf(
|
||||||
"[Card: %04" PRIX32 " name=%s type=%s usable_condition=%s rare=%s "
|
"[Card: %04" PRIX32 " name=%s type=%s usable_condition=%s rare=%s "
|
||||||
"cost=%hhX+%hhX target=%s range=%s assist_turns=%s cannot_move=%s "
|
"cost=%s target=%s range=%s assist_turns=%s cannot_move=%s "
|
||||||
"cannot_attack=%s cannot_drop=%s hp=%s ap=%s tp=%s mv=%s left=%s right=%s "
|
"cannot_attack=%s cannot_drop=%s hp=%s ap=%s tp=%s mv=%s left=%s right=%s "
|
||||||
"top=%s a2=%04hX class=%s assist_effect=[%hu, %hu] "
|
"top=%s class=%s assist_ai_params=[target=%s priority=%hhu effect=%hhu] drop_rates=[%s, %s] effects=[%s]]",
|
||||||
"drop_rates=[%s, %s] effects=[%s]]",
|
|
||||||
this->card_id.load(),
|
this->card_id.load(),
|
||||||
this->en_name.data(),
|
this->en_name.data(),
|
||||||
type_str.c_str(),
|
type_str.c_str(),
|
||||||
criterion_str.c_str(),
|
criterion_str.c_str(),
|
||||||
rarity_str.c_str(),
|
rarity_str.c_str(),
|
||||||
this->self_cost,
|
cost_str.c_str(),
|
||||||
this->ally_cost,
|
|
||||||
target_mode_str.c_str(),
|
target_mode_str.c_str(),
|
||||||
range_str.c_str(),
|
range_str.c_str(),
|
||||||
assist_turns_str.c_str(),
|
assist_turns_str.c_str(),
|
||||||
@@ -1038,10 +1075,10 @@ string CardDefinition::str(bool single_line) const {
|
|||||||
left_str.c_str(),
|
left_str.c_str(),
|
||||||
right_str.c_str(),
|
right_str.c_str(),
|
||||||
top_str.c_str(),
|
top_str.c_str(),
|
||||||
this->unknown_a2.load(),
|
|
||||||
card_class_str.c_str(),
|
card_class_str.c_str(),
|
||||||
this->assist_effect[0].load(),
|
short_name_for_assist_ai_param_target((this->assist_ai_params / 1000) % 10),
|
||||||
this->assist_effect[1].load(),
|
static_cast<uint8_t>((this->assist_ai_params / 100) % 10),
|
||||||
|
static_cast<uint8_t>(this->assist_ai_params % 100),
|
||||||
drop0_str.c_str(),
|
drop0_str.c_str(),
|
||||||
drop1_str.c_str(),
|
drop1_str.c_str(),
|
||||||
effects_str.c_str());
|
effects_str.c_str());
|
||||||
@@ -1069,15 +1106,14 @@ Card: %04" PRIX32 " \"%s\"\n\
|
|||||||
Type: %s, class: %s\n\
|
Type: %s, class: %s\n\
|
||||||
Usability condition: %s\n\
|
Usability condition: %s\n\
|
||||||
Rarity: %s\n\
|
Rarity: %s\n\
|
||||||
Cost: %hhX (self) + %hhX (ally)\n\
|
Cost: %s\n\
|
||||||
Target mode: %s\n\
|
Target mode: %s\n\
|
||||||
Range:%s\n\
|
Range:%s\n\
|
||||||
Assist turns: %s\n\
|
Assist turns: %s\n\
|
||||||
Capabilities: %s move, %s attack\n\
|
Capabilities: %s move, %s attack\n\
|
||||||
HP: %s, AP: %s, TP: %s, MV: %s\n\
|
HP: %s, AP: %s, TP: %s, MV: %s\n\
|
||||||
Left colors: %s; right colors: %s; top colors: %s\n\
|
Left colors: %s; right colors: %s; top colors: %s\n\
|
||||||
Unknown a2: %04hX\n\
|
Assist AI parameters: [target %s, priority %hu, effect %hu]\n\
|
||||||
Assist effect: [%hu, %hu]\n\
|
|
||||||
Drop rates: [%s, %s] (%s drop)\n\
|
Drop rates: [%s, %s] (%s drop)\n\
|
||||||
Effects:%s",
|
Effects:%s",
|
||||||
this->card_id.load(),
|
this->card_id.load(),
|
||||||
@@ -1086,8 +1122,7 @@ Card: %04" PRIX32 " \"%s\"\n\
|
|||||||
card_class_str.c_str(),
|
card_class_str.c_str(),
|
||||||
criterion_str.c_str(),
|
criterion_str.c_str(),
|
||||||
rarity_str.c_str(),
|
rarity_str.c_str(),
|
||||||
this->self_cost,
|
cost_str.c_str(),
|
||||||
this->ally_cost,
|
|
||||||
target_mode_str.c_str(),
|
target_mode_str.c_str(),
|
||||||
range_str.c_str(),
|
range_str.c_str(),
|
||||||
assist_turns_str.c_str(),
|
assist_turns_str.c_str(),
|
||||||
@@ -1100,9 +1135,9 @@ Card: %04" PRIX32 " \"%s\"\n\
|
|||||||
left_str.c_str(),
|
left_str.c_str(),
|
||||||
right_str.c_str(),
|
right_str.c_str(),
|
||||||
top_str.c_str(),
|
top_str.c_str(),
|
||||||
this->unknown_a2.load(),
|
name_for_assist_ai_param_target((this->assist_ai_params / 1000) % 10),
|
||||||
this->assist_effect[0].load(),
|
static_cast<uint8_t>((this->assist_ai_params / 100) % 10),
|
||||||
this->assist_effect[1].load(),
|
static_cast<uint8_t>(this->assist_ai_params % 100),
|
||||||
drop0_str.c_str(),
|
drop0_str.c_str(),
|
||||||
drop1_str.c_str(),
|
drop1_str.c_str(),
|
||||||
this->cannot_drop ? "cannot" : "can",
|
this->cannot_drop ? "cannot" : "can",
|
||||||
|
|||||||
+45
-42
@@ -518,24 +518,27 @@ struct CardDefinition {
|
|||||||
/* 0091 */ uint8_t cannot_drop;
|
/* 0091 */ uint8_t cannot_drop;
|
||||||
/* 0092 */ CriterionCode usable_criterion;
|
/* 0092 */ CriterionCode usable_criterion;
|
||||||
/* 0093 */ CardRarity rarity;
|
/* 0093 */ CardRarity rarity;
|
||||||
/* 0094 */ be_uint16_t unknown_a2;
|
/* 0094 */ be_uint16_t unused4;
|
||||||
// The card class is used for checking attributes (e.g. item types). It's
|
// The card class is used for checking attributes (e.g. item types). It's
|
||||||
// stored big-endian here, so there's a helper function (card_class()) that
|
// stored big-endian here, so there's a helper function (card_class()) that
|
||||||
// returns a usable CardClass enum value.
|
// returns a usable CardClass enum value.
|
||||||
/* 0096 */ be_uint16_t be_card_class;
|
/* 0096 */ be_uint16_t be_card_class;
|
||||||
|
|
||||||
// The two fields of this array seem to always contain the same value, and
|
// If this card is an assist card, this field controls how COM players handle
|
||||||
// are always 0 for non-assist cards and nonzero for assists. Each assist
|
// playing it. (This field is ignored for other card types.) This integer
|
||||||
// card has a unique value here and no effects, though the server ignores
|
// encodes the following fields:
|
||||||
// these values - assist effects are hardcoded based on the card ID instead.
|
// - assist_ai_params % 100 (that is, the two lowest decimal places) appears
|
||||||
// There seems to be some 1k-modulation going on here; most cards have values
|
// to specify the effect, though a few unrelated cards share values in this
|
||||||
// here in the range 101-174 but a few have e.g. 1150, 2141. A few pairs of
|
// field. It's not yet known how exactly this is used by the COM logic.
|
||||||
// cards have the same effect, so this cannot be used by the server anyway to
|
// - (assist_ai_params / 100) % 10 specifies the priority. It appears the COM
|
||||||
// determine assist cards' effects (see e.g. Skip Draw / Skip Move, Dice
|
// logic always chooses the assist card with the highest value in this field
|
||||||
// Fever / Dice Fever +, Reverse Card / Rich +).
|
// if there are multiple cards to consider.
|
||||||
/* 0098 */ parray<be_uint16_t, 2> assist_effect;
|
// - (assist_ai_params / 1000) % 10 specifies on who the assist card may be
|
||||||
|
// played (0 = any player, 1 = self, 2 = self or ally, 3 = enemy only).
|
||||||
|
/* 0098 */ be_uint16_t assist_ai_params;
|
||||||
|
/* 009A */ be_uint16_t unused5;
|
||||||
|
|
||||||
// Drop rates are decimal-encoded with the following fields:
|
// Drop rates are integers which encode the following data:
|
||||||
// - rate % 10 (that is, the lowest decimal place) specifies the required game
|
// - rate % 10 (that is, the lowest decimal place) specifies the required game
|
||||||
// mode. 0 means any mode, 1 means offline story mode, 2 means 1P free
|
// mode. 0 means any mode, 1 means offline story mode, 2 means 1P free
|
||||||
// battle, 3 means 2P+ free battle (specifically, PvP - two humans vs. two
|
// battle, 3 means 2P+ free battle (specifically, PvP - two humans vs. two
|
||||||
@@ -568,40 +571,40 @@ struct CardDefinition {
|
|||||||
// Finally, cards are chosen from the buckets with a weighted distribution
|
// Finally, cards are chosen from the buckets with a weighted distribution
|
||||||
// according to these tables (row is player's level class, column is card's
|
// according to these tables (row is player's level class, column is card's
|
||||||
// rarity class):
|
// rarity class):
|
||||||
// Offline
|
// Offline:
|
||||||
// 1 2 3 4 5 6 7 8 9 10
|
// LC | RC = 0 1 2 3 4 5 6 7 8 9
|
||||||
// 1 => 8000 2000 50
|
// 1 | 8000 2000 50
|
||||||
// 2 => 6000 3500 500 50
|
// 2 | 6000 3500 500 50
|
||||||
// 3 => 4500 3500 1500 400 100
|
// 3 | 4500 3500 1500 400 100
|
||||||
// 4 => 3000 3000 2500 1000 450 50
|
// 4 | 3000 3000 2500 1000 450 50
|
||||||
// 5 => 2000 2600 2750 2000 500 100 50
|
// 5 | 2000 2600 2750 2000 500 100 50
|
||||||
// 6 => 1900 2200 2500 2100 830 350 100 20
|
// 6 | 1900 2200 2500 2100 830 350 100 20
|
||||||
// 7 => 1900 2000 2000 2000 1000 500 500 100
|
// 7 | 1900 2000 2000 2000 1000 500 500 100
|
||||||
// 8 => 160000 160000 190000 190000 130000 100000 50000 19999 1
|
// 8 | 160000 160000 190000 190000 130000 100000 50000 19999 1
|
||||||
// 9 => 120000 120000 150000 160000 150000 150000 100000 49989 10 1
|
// 9 | 120000 120000 150000 160000 150000 150000 100000 49989 10 1
|
||||||
// 10 => 120000 120000 130000 150000 160000 150000 100000 69965 30 5
|
// 10 | 120000 120000 130000 150000 160000 150000 100000 69965 30 5
|
||||||
// Online
|
// Online
|
||||||
// 1 2 3 4 5 6 7 8 9 10
|
// LC | RC = 0 1 2 3 4 5 6 7 8 9
|
||||||
// 1 => 8000 2000 50
|
// 1 | 8000 2000 50
|
||||||
// 2 => 6000 3500 500 20
|
// 2 | 6000 3500 500 20
|
||||||
// 3 => 4500 4000 1500 200
|
// 3 | 4500 4000 1500 200
|
||||||
// 4 => 3500 3500 2300 700 20
|
// 4 | 3500 3500 2300 700 20
|
||||||
// 5 => 2700 2800 2500 1500 500 10
|
// 5 | 2700 2800 2500 1500 500 10
|
||||||
// 6 => 2300 2300 2300 1900 900 300 1
|
// 6 | 2300 2300 2300 1900 900 300 1
|
||||||
// 7 => 1995 2100 2100 2100 1000 700 5
|
// 7 | 1995 2100 2100 2100 1000 700 5
|
||||||
// 8 => 1789 2100 2100 2100 1100 800 10 1
|
// 8 | 1789 2100 2100 2100 1100 800 10 1
|
||||||
// 9 => 14620 20000 21000 22000 13000 9000 300 80
|
// 9 | 14620 20000 21000 22000 13000 9000 300 80
|
||||||
// 10 => 133997 190000 200000 200000 150000 120000 5000 1000 2 1
|
// 10 | 133997 190000 200000 200000 150000 120000 5000 1000 2 1
|
||||||
// These values are all relative to other values in the same row. For example,
|
// These values are all relative to other values in the same row. For example,
|
||||||
// if your character is in level class 1, you'll get cards of rarity class 1
|
// if your character is in level class 1, you'll get cards of rarity class 0
|
||||||
// about 80% of the time, cards of rarity class 2 about 20% of the time, and
|
// about 80% of the time, cards of rarity class 1 about 20% of the time, and
|
||||||
// cards of rarity class 3 about 0.5% of the time. (The actual probabilities
|
// cards of rarity class 2 about 0.5% of the time. (The actual probabilities
|
||||||
// are 8000/10050, 2000/10050, and 50/10050.)
|
// are 8000/10050, 2000/10050, and 50/10050.)
|
||||||
// The drop rates are completely ignored if any of the following are true
|
// The drop rates for a card are completely ignored if any of the following
|
||||||
// (which means the card can never be found in a normal post-battle draw):
|
// are true (which means it can never be found in a normal post-battle draw):
|
||||||
// - type is SC_HUNTERS or SC_ARKZ
|
// - type is SC_HUNTERS or SC_ARKZ
|
||||||
// - card_class is BOSS_ATTACK_ACTION (0x23) or BOSS_TECH (0x24)
|
// - card_class is BOSS_ATTACK_ACTION (0x23) or BOSS_TECH (0x24)
|
||||||
// - rarity is E, D1, D2, or INVIS
|
// - rarity is E, D1, or D2
|
||||||
// - cannot_drop is 1 (specifically 1; other nonzero values here don't
|
// - cannot_drop is 1 (specifically 1; other nonzero values here don't
|
||||||
// prevent the card from appearing in post-battle draws)
|
// prevent the card from appearing in post-battle draws)
|
||||||
/* 009C */ parray<be_uint16_t, 2> drop_rates;
|
/* 009C */ parray<be_uint16_t, 2> drop_rates;
|
||||||
@@ -610,7 +613,7 @@ struct CardDefinition {
|
|||||||
/* 00B4 */ ptext<char, 0x0B> jp_short_name;
|
/* 00B4 */ ptext<char, 0x0B> jp_short_name;
|
||||||
/* 00BF */ ptext<char, 0x08> en_short_name;
|
/* 00BF */ ptext<char, 0x08> en_short_name;
|
||||||
/* 00C7 */ parray<Effect, 3> effects;
|
/* 00C7 */ parray<Effect, 3> effects;
|
||||||
/* 0127 */ uint8_t unused4;
|
/* 0127 */ uint8_t unused6;
|
||||||
/* 0128 */
|
/* 0128 */
|
||||||
|
|
||||||
bool is_sc() const;
|
bool is_sc() const;
|
||||||
|
|||||||
+11
-4
@@ -382,6 +382,7 @@ int main(int argc, char** argv) {
|
|||||||
bool compress_optimal = false;
|
bool compress_optimal = false;
|
||||||
bool json = false;
|
bool json = false;
|
||||||
bool download = false;
|
bool download = false;
|
||||||
|
bool one_line = false;
|
||||||
const char* find_decryption_seed_ciphertext = nullptr;
|
const char* find_decryption_seed_ciphertext = nullptr;
|
||||||
vector<const char*> find_decryption_seed_plaintexts;
|
vector<const char*> find_decryption_seed_plaintexts;
|
||||||
const char* input_filename = nullptr;
|
const char* input_filename = nullptr;
|
||||||
@@ -398,6 +399,8 @@ int main(int argc, char** argv) {
|
|||||||
return 0;
|
return 0;
|
||||||
} else if (!strncmp(argv[x], "--threads=", 10)) {
|
} else if (!strncmp(argv[x], "--threads=", 10)) {
|
||||||
num_threads = strtoull(&argv[x][10], nullptr, 0);
|
num_threads = strtoull(&argv[x][10], nullptr, 0);
|
||||||
|
} else if (!strcmp(argv[x], "--one-line")) {
|
||||||
|
one_line = true;
|
||||||
} else if (!strcmp(argv[x], "--download")) {
|
} else if (!strcmp(argv[x], "--download")) {
|
||||||
download = true;
|
download = true;
|
||||||
} else if (!strcmp(argv[x], "--patch")) {
|
} else if (!strcmp(argv[x], "--patch")) {
|
||||||
@@ -1512,10 +1515,14 @@ int main(int argc, char** argv) {
|
|||||||
log_info("%zu card definitions", card_ids.size());
|
log_info("%zu card definitions", card_ids.size());
|
||||||
for (uint32_t card_id : card_ids) {
|
for (uint32_t card_id : card_ids) {
|
||||||
auto entry = card_index.definition_for_id(card_id);
|
auto entry = card_index.definition_for_id(card_id);
|
||||||
string s = entry->def.str(false);
|
string s = entry->def.str(one_line);
|
||||||
string tags = entry->debug_tags.empty() ? "(none)" : join(entry->debug_tags, ", ");
|
if (one_line) {
|
||||||
string text = entry->text.empty() ? "(No text available)" : str_replace_all(entry->text, "\n", "\n ");
|
fprintf(stdout, "%s\n", s.c_str());
|
||||||
fprintf(stdout, "%s\n Tags: %s\n Text:\n %s\n\n", s.c_str(), tags.c_str(), text.c_str());
|
} else {
|
||||||
|
string tags = entry->debug_tags.empty() ? "(none)" : join(entry->debug_tags, ", ");
|
||||||
|
string text = entry->text.empty() ? "(No text available)" : str_replace_all(entry->text, "\n", "\n ");
|
||||||
|
fprintf(stdout, "%s\n Tags: %s\n Text:\n %s\n\n", s.c_str(), tags.c_str(), text.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user