/* * V-Gears * Copyright (C) 2022 V-Gears Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "common/TypeDefine.h" #include "data/GameData.h" /** * An enemy formation */ struct Formation{ /** * Battle layouts. */ enum class Layout{ /** * Normal fight. */ NORMAL = 0, /** * Preemptive attack. * * Enemies are on their back, they bars are empty. When attacked, or * after a certain time, they turn and their bars start to fill. */ PREEMPTIVE, /** * Back attack. * * Players are on their back, they bars are empty. When attacked, or * after a certain time, they turn and their bars start to fill. * Player rows are reversed. */ BACK_ATTACK, /** * Side attack. * * Players in both sides, enemies in center, facing one or other * direction. Change command disabled. */ SIDE_ATTACK, /** * Enemies in both sides, player in center, front row, facing one or the * other direction. Change command disabled. Unescapable until one of * the sides is cleared. */ PINCER_ATTACK, /** * Locked position fight. * * Like a normal one, but all players in the front row. Change command * disabled. */ LOCKED }; /** * Each enemy in the formation. */ struct Enemy{ /** * Enemy ID. */ unsigned int id; /** * Enemy X position. */ int x; /** * Enemy Y position. */ int y; /** * Enemy Z position. */ int z; /** * Enemy row. */ unsigned int row; /** * Cover flags. * * These flags are used in conjunction with row to determine if a target * can be selected as the target of a short-range attack. The * determination of this is worked out in this way: An enemy exists in * row 1 and another in row 2. If the enemy in row 1 shares a cover flag * with the enemy in row 2 then the enemy in row 2 cannot be targeted * until all enemies in row 1 that share a cover flag with the row 2 * enemy are defeated. It works like this. Two active enemies exist, A * and B. * * If ((B's row > A's row) and (B's flags AND A's flags) > 0) * then enemy B cannot be targeted by short-range attacks. * * For any enemies A and B. * * Example: * Consider the Battery Cap x6 battle in the forest between Nibelheim * and Rocket Town. Their cover flags (in binary) are: * * Row 1: 00100 * Row 2: 00110 01100 * Row 3: 00011 00100 11000 * * The battery caps in row 2 cannot be targeted by a short-range attack * until the one in row 1 has been defeated because they share the 0x4 * cover flag. Once row 1 has been cleared: * * Row 2: 00110 01100 * Row 3: 00011 00100 11000 * * The battery cap on left in row 2 covers the left two in row 3 because * it shares flag 0x4 with the one in the middle and flag 0x2 with the * one on the far left. As long as it is active these in row 3 cannot be * targeted. Similarly, the battery cap on the right in row 2 shares the * 0x4 flag with the middle of row 3 and the 0x8 flag with the far right * of row 3 so these cannot be targeted until the right side of row 2 is * defeated. It is also necessary to note that because row 1 does not * share any flags with the extreme right and left of row 3, they can be * targeted if the corresponding enemy in row 2 is defeated even if the * row 1 enemy is still active. Also of note is that enemies in the same * row that share cover flags are not considered. */ char cover[5]; /** * Indicates if the enemy is initially visible. */ bool visible; /** * Indicates initial direction facing if players get a side attack. */ int direction; /** * Indicates if the enemy is targeteable. */ bool targeteable; /** * @todo Understand and document. */ bool main_script_active; /** * Constructor. * * Initializes to default values. */ Enemy(): id(0), x(0), y(0), z(0), row(0), visible(true), direction(0), targeteable(true), main_script_active(true) { for (int c = 0; c < 5; c ++) cover[c] = '0'; } }; /** * Position for a camera. */ struct Camera{ /** * X position. */ int x; /** * Y position. */ int y; /** * z position. */ int z; /** * X direction. */ int d_x; /** * Y direction. */ int d_y; /** * z direction. */ int d_z; /** * Constructor. * * Initializes to default values. */ Camera(): x(0), y(0), z(0), d_x(0), d_y(0), d_z(0){} }; /** * Formation ID. */ unsigned int id; /** * When all enemies are defeated, begin battle with this ID without ending * battle scene. */ int next_formation; /** * Difficulty to escape. */ float escape_counter; /** * Indicates if the battle can be escaped. */ bool escapable; /** * If true, the victory pose will be played after the battle. */ bool skip_victory_pose; /** * If true, spoils (item, ap, money...) will not be obtained after the * battle. * * The spoil screens will not be displayed. */ bool skip_spoils; /** * If false, this battle can never be preemtied. */ bool preemptive_disabled; /** * Battle layout. */ Layout layout; /** * The enemies in the formation. */ std::vector enemies; /** * Location ID. * * Must be set, except for formations referenced by other formation's * {@see next_formation} or {@see next_arena_formation_candidates}. In those * cases, it can be -1. */ int location; /** * Location name. * * Never used, it's to have descriptive XML files. */ std::string location_name; /** * Camera positions. */ std::vector camera_positions; /** * Index of the initial camera position. */ int initial_camera_position; /** * Indicates if the formation is an arena battle. */ bool is_arena_battle; /** * For arena battles, candidates for the next formation. */ std::vector next_arena_formation_candidates; /** * Constructor. * * Initializes to default values. */ Formation(): id(0), next_formation(-1), escape_counter(0.0f), escapable(true), skip_victory_pose(false), skip_spoils(false), preemptive_disabled(false), layout(Layout::NORMAL), location(-1), location_name(""), initial_camera_position(0),is_arena_battle(false) { enemies.clear(); camera_positions.clear(); next_arena_formation_candidates.clear(); } };