From 13dacc013a99aa4b044e6610bf9eef89020fa6e1 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Tue, 17 Oct 2023 15:51:29 -0700 Subject: [PATCH] document CardDefinition and a few other things --- src/Episode3/DataIndexes.cc | 10 ++--- src/Episode3/DataIndexes.hh | 90 +++++++++++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 13 deletions(-) diff --git a/src/Episode3/DataIndexes.cc b/src/Episode3/DataIndexes.cc index 4c707cd4..c608883a 100644 --- a/src/Episode3/DataIndexes.cc +++ b/src/Episode3/DataIndexes.cc @@ -859,27 +859,27 @@ void CardDefinition::decode_range() { if (index != 0) { this->range.clear(0); switch (index) { - case 1: // Single cell in front of FC + case 1: // Single cell in front of FC (Attack) this->range[3] = 0x00000100; break; case 2: // Cell in front of FC and the front-left and front-right (Slash) this->range[3] = 0x00001110; break; - case 3: // 3 cells in a line in front of FC + case 3: // 3 cells in a line in front of FC (Long Arm) this->range[1] = 0x00000100; this->range[2] = 0x00000100; this->range[3] = 0x00000100; break; - case 4: // All 8 cells around FC + case 4: // All 8 cells around FC (Gifoie) this->range[3] = 0x00001110; this->range[4] = 0x00001010; this->range[5] = 0x00001110; break; - case 5: // 2 cells in a line in front of FC + case 5: // 2 cells in a line in front of FC (Mechgun) this->range[2] = 0x00000100; this->range[3] = 0x00000100; break; - case 6: // Entire field (renders as "A") + case 6: // Entire field (Grants) for (size_t x = 0; x < 6; x++) { this->range[x] = 0x000FFFFF; } diff --git a/src/Episode3/DataIndexes.hh b/src/Episode3/DataIndexes.hh index 48f3f035..ca851a40 100644 --- a/src/Episode3/DataIndexes.hh +++ b/src/Episode3/DataIndexes.hh @@ -482,13 +482,29 @@ struct CardDefinition { } __attribute__((packed)); struct Effect { + // effect_num is the 1-based index of this effect within the card definition + // (that is, .effects[0] should have effect_num == 1 if it is used). /* 00 */ uint8_t effect_num; /* 01 */ ConditionType type; - /* 02 */ ptext expr; // May be blank if the condition type doesn't use it + // For ConditionTypes that need it, expr specifies "how much". (For those + // that don't, expr may be blank.) The value may contain tokens that refer + // to stats from the current battle (see description_for_expr_token) and + // operators to perform basic computations on them. Operators are evaluated + // left-to-right in the expression, and there are no operator precedence + // rules; for example, the expression "4+4//2" results in 4, not 6. + /* 02 */ ptext expr; + // when specifies in which phase the effect should activate. + // TODO: There are many values that can be used here; document them. /* 11 */ uint8_t when; + // arg1 generally specifies how long the effect activates for. /* 12 */ ptext arg1; + // arg2 generally specifies a condition for when the effect activates. /* 16 */ ptext arg2; + // arg3 generally specifies who is targeted by the effect. /* 1A */ ptext arg3; + // apply_criterion can be used to apply an additional condition for when the + // effect should activate. For example, it can be used to make the effect + // only activate if the target is not a Story Character. /* 1E */ CriterionCode apply_criterion; // name_index specifies which string from TextEnglish.pr2 is shown next to // the card when it is attacking or defending. Zero in this field means no @@ -503,28 +519,69 @@ struct CardDefinition { /* 0000 */ be_uint32_t card_id; /* 0004 */ parray jp_name; - /* 0044 */ CardType type; // If <0 (signed), then this is the end of the card list + + // The list of card definitions ends with a "sentinel" definition that isn't a + // real card, but instead has a negative number in the type field here. + /* 0044 */ CardType type; + /* 0045 */ uint8_t self_cost; // ATK dice points required /* 0046 */ uint8_t ally_cost; // ATK points from allies required; PBs use this /* 0047 */ uint8_t unused1; + + // In the definitions file, only .code is populated here; .decode_code() must + // be called to fill in .type and .stat within each of these. /* 0048 */ Stat hp; /* 004C */ Stat ap; /* 0050 */ Stat tp; /* 0054 */ Stat mv; + + // See name_for_link_color for the list of values used here. /* 0058 */ parray left_colors; /* 0060 */ parray right_colors; /* 0068 */ parray top_colors; + + // The card's attack range is defined in a somewhat odd format here. Each + // field in this array corresponds to a single row of the range, and every + // fourth bit, starting with bit 15, corresponds to a tile in that row. The + // rest of the bits are ignored, except in two special cases described below. + // For example, Ohgun's range is: + // [0] = 0x00000000 => ----- + // [1] = 0x00001110 => -***- + // [2] = 0x00001110 => -***- + // [3] = 0x00000000 => ----- + // [4] = 0x00000000 => ----- (the card itself is in the center of this row) + // [5] = 0x00000000 => ----- + // + // The two special cases are as follows: + // 1. If all six values in the range array are 0x000FFFFF, then the card's + // range is the entire field. + // 2. If the cell corresponding to the card itself ((range[4] >> 8) & 0x0F) is + // not zero, then the rest of the range array is ignored and the card's + // range comes from a fixed set of ranges instead. See decode_range() for + // more information. /* 0070 */ parray range; + /* 0088 */ be_uint32_t unused2; /* 008C */ TargetMode target_mode; /* 008D */ uint8_t assist_turns; // 90 (dec) = once, 99 (dec) = forever - /* 008E */ uint8_t cannot_move; // 0 for SC and creature cards; 1 for everything else - /* 008F */ uint8_t cannot_attack; // 1 for shields, mags, defense actions, and assist cards + // This field is 1 if the card cannot move by itself. Item cards hare 1 here + // because they cannot move on their own and automatically move along with + // their SC instead. Generally only SCs and creatures have 0 here. + /* 008E */ uint8_t cannot_move; + // This field is 1 if the card cannot take part in an attack. Unlike + // cannot_move, cards that cannot attack on their own but can take part in an + // attack (such as action cards) have 0 here. Most shields, mags, defense + // actions, and assist cards have 1 here. + /* 008F */ uint8_t cannot_attack; /* 0090 */ uint8_t unused3; // If cannot_drop is 0, this card can't appear in post-battle rewards. A // value of 0 here also prevents the card from being used as a God Whim // random assist. /* 0091 */ uint8_t cannot_drop; + // This criterion code specifies who can use the card, and when it can be + // used. This specifies which Hero-side SCs can use which items, for example, + // and when action cards can be played (when SC or FC is attacking, on self or + // ally, etc.). /* 0092 */ CriterionCode usable_criterion; /* 0093 */ CardRank rank; /* 0094 */ be_uint16_t unused4; @@ -534,7 +591,7 @@ struct CardDefinition { /* 0096 */ be_uint16_t be_card_class; // If this card is an assist card, this field controls how COM players handle - // playing it. (This field is ignored for other card types.) This integer + // playing it. This field is ignored for non-assist cards. This integer // encodes the following fields: // - assist_ai_params % 100 (that is, the two lowest decimal places) appears // to specify the effect, though a few unrelated cards share values in this @@ -542,9 +599,12 @@ struct CardDefinition { // - (assist_ai_params / 100) % 10 specifies the priority. It appears the COM // logic always chooses the assist card with the highest value in this field // if there are multiple cards to consider. - // - (assist_ai_params / 1000) % 10 specifies on who the assist card may be + // - (assist_ai_params / 1000) % 10 specifies on whom 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; + // Most cards in the official definitions file have the same value stored in + // unused5 as in assist_ai_params. Unlike assist_ai_params, unused5 does not + // appear to be used anywhere. /* 009A */ be_uint16_t unused5; // The card drop rates control how likely the card is to appear in a standard @@ -554,8 +614,8 @@ struct CardDefinition { // - type is SC_HUNTERS or SC_ARKZ // - card_class is BOSS_ATTACK_ACTION (0x23) or BOSS_TECH (0x24) // - rank is E, D1, or D2 - // - cannot_drop is 1 (specifically 1; other nonzero values here don't - // prevent the card from appearing in post-battle draws) + // - cannot_drop is 1 (specifically 1; other nonzero values for cannot_drop + // don't prevent the card from appearing in post-battle draws) // If none of these conditions apply, the logic below is used. // // Drop rates are integers which encode the following data: @@ -707,6 +767,8 @@ struct CardDefinition { /* 00A0 */ ptext en_name; /* 00B4 */ ptext jp_short_name; /* 00BF */ ptext en_short_name; + // These effects modify the card's behavior in various situations. Only + // effects for which effect_num is not zero are used. /* 00C7 */ parray effects; /* 0127 */ uint8_t unused6; /* 0128 */ @@ -1200,6 +1262,17 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests /* 2760 */ ptext dispatch_message; struct DialogueSet { + // Dialogue sets specify lines that COMs can say at certain points during + // the battle. They only apply to COMs which are defined as NPCs in the map + // definition; human players and COMs chosen by humans never say lines from + // dialogue sets. + + // when specifies the situation in which this dialogue set activates. The + // values 0000-000C (inclusive) can be used here, or FFFF if the entire + // dialogue set is unused. The known values are: + // 0001: Activates at battle start if player is an opponent + // 0006: Activates when below 50% HP + // 0008: Activates at battle start if player is an ally /* 0000 */ be_int16_t when; // 0x00-0x0C, or FFFF if unused /* 0002 */ be_uint16_t percent_chance; // 0-100, or FFFF if unused // If the dialogue set activates, the game randomly chooses one of these @@ -1207,6 +1280,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests /* 0004 */ parray, 4> strings; /* 0104 */ } __attribute__((packed)); + // There are up to 0x10 of these per valid NPC, but only the first 13 of them // are used, since each one must have a unique value for .when and the values // there can only be 0-12.