diff --git a/.editorconfig b/.editorconfig index 395cb8e727c..ff49727e82b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -80,6 +80,18 @@ indent_brace_style = allman # This is unfortunately ignored in Visual Studio [Makefile] indent_style = tab -[*.yml] +[*.{yml,yaml}] indent_style = space indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.json] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.github/workflows/pr_checks.yml b/.github/workflows/pr_checks.yml index 581835f411f..38c4ce95531 100644 --- a/.github/workflows/pr_checks.yml +++ b/.github/workflows/pr_checks.yml @@ -29,7 +29,7 @@ jobs: # $GITHUB_WORKSPACE is the workspace in the container (/__w/server/server) - run: git config --global --add safe.directory $GITHUB_WORKSPACE - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 @@ -82,7 +82,7 @@ jobs: - run: git config --global --add safe.directory $GITHUB_WORKSPACE - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 if: ${{ steps.check-changes.outputs.lua_changes == 'true' }} with: fetch-depth: 0 @@ -93,6 +93,10 @@ jobs: python -m pip install --upgrade pip setuptools wheel python -m pip install --upgrade -r ./tools/requirements.txt + - name: Generate codegen Lua enums + if: ${{ steps.check-changes.outputs.lua_changes == 'true' }} + run: python -m tools.codegen "$RUNNER_TEMP/codegen-out" + - name: Run Lua Language Server id: run_lls if: ${{ steps.check-changes.outputs.lua_changes == 'true' }} @@ -129,6 +133,110 @@ jobs: echo "Lua Language Server failed. See summary for details." exit 1 + Schema_Validation: + needs: Sanity_Checks + name: Data validation + runs-on: ubuntu-latest + defaults: + run: + shell: bash + steps: + - name: Download Changed Files + uses: actions/download-artifact@v4 + with: + name: changed-files + + - name: Check for data/ or codegen changes + id: changed + run: | + mapfile -t changed_files < changed-files.txt + touched=false + for f in "${changed_files[@]}"; do + if [[ $f == data/* || $f == tools/codegen/* ]]; then + touched=true + break + fi + done + echo "touched=$touched" >> "$GITHUB_OUTPUT" + echo "Touched: $touched" + + - uses: actions/checkout@v6 + if: steps.changed.outputs.touched == 'true' + + - name: Setup Python + if: steps.changed.outputs.touched == 'true' + uses: actions/setup-python@v6 + with: + python-version: "3.14" + + - name: Install Python dependencies + if: steps.changed.outputs.touched == 'true' + run: python -m pip install jinja2 jsonschema pyyaml + + - name: Run codegen --validate + if: steps.changed.outputs.touched == 'true' + run: | + mkdir -p "$RUNNER_TEMP/codegen-out" + python -m tools.codegen "$RUNNER_TEMP/codegen-out" --validate + + Formatting: + needs: Sanity_Checks + name: Data formatting + runs-on: ubuntu-latest + defaults: + run: + shell: bash + steps: + - name: Download Changed Files + uses: actions/download-artifact@v4 + with: + name: changed-files + + - name: Filter data/ changed files + id: changed + run: | + mapfile -t changed_files < changed-files.txt + data_files=() + for f in "${changed_files[@]}"; do + if [[ $f == data/* ]]; then + data_files+=("$f") + fi + done + echo "files=${data_files[*]}" >> "$GITHUB_OUTPUT" + echo "Changed data files: ${data_files[*]}" + + - uses: actions/checkout@v6 + if: steps.changed.outputs.files != '' + + - name: Cache prettier results + if: steps.changed.outputs.files != '' + uses: actions/cache@v5 + with: + path: /tmp/prettier-cache + key: prettier-cache-${{ hashFiles('data/**/*.yaml', 'data/**/*.json') }} + restore-keys: prettier-cache- + + - name: Run prettier + if: steps.changed.outputs.files != '' + run: | + set +e + FAILED=$(npx --yes prettier@3 --cache --cache-strategy content --cache-location /tmp/prettier-cache --list-different ${{ steps.changed.outputs.files }}) + set -e + if [ -z "$FAILED" ]; then + echo "All files use Prettier code style!" + exit 0 + fi + echo "::group::Files needing reformat" + echo "$FAILED" + echo "::endgroup::" + echo "::group::Diff" + for f in $FAILED; do + diff -u "$f" <(npx --yes prettier@3 "$f") || true + done + echo "::endgroup::" + echo "Run \`npx prettier --write data\` locally to fix." + exit 1 + Clang_Tidy: needs: Sanity_Checks name: Clang Tidy diff --git a/.github/workflows/runner_build.yml b/.github/workflows/runner_build.yml index 227c88aac0b..2af1a4a5fdd 100644 --- a/.github/workflows/runner_build.yml +++ b/.github/workflows/runner_build.yml @@ -190,6 +190,10 @@ jobs: with: python-version: '3.12' + - name: Install Python codegen deps + if: ${{ env.SKIP_BUILD != 'true' }} + run: python -m pip install jinja2 jsonschema pyyaml + - name: Enable modules if: ${{ inputs.build_modules && env.SKIP_BUILD != 'true' }} run: | diff --git a/.github/workflows/runner_test.yml b/.github/workflows/runner_test.yml index 1a2e0fc4a57..193986abf7e 100644 --- a/.github/workflows/runner_test.yml +++ b/.github/workflows/runner_test.yml @@ -126,6 +126,9 @@ jobs: echo "${{ runner.os == 'Windows' && '.venv/Scripts' || '.venv/bin' }}" >> $GITHUB_PATH echo "VIRTUAL_ENV=$(pwd)/.venv" >> $GITHUB_ENV + - name: Generate codegen Lua enums + run: python -m tools.codegen "$RUNNER_TEMP/codegen-out" + - name: Download artifact if: ${{ github.event_name == 'pull_request' }} uses: actions/download-artifact@v4 diff --git a/.gitignore b/.gitignore index e1b5e25db35..523b220b0fb 100644 --- a/.gitignore +++ b/.gitignore @@ -266,3 +266,7 @@ __pycache__ sanity_checks_summary.md changed-files.txt clang_tidy_summary.md + +# YAML codegen +*.codegen.json +*.codegen.lua diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000000..a425df1675b --- /dev/null +++ b/.prettierignore @@ -0,0 +1,7 @@ +*.codegen.json +*.codegen.lua + +build/ +build*/ +cmake-*/ +out/ diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000000..b5c6b5bff34 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,15 @@ +{ + "tabWidth": 2, + "useTabs": false, + "printWidth": 120, + "endOfLine": "lf", + "overrides": [ + { + "files": ["**/*.yaml", "**/*.yml"], + "options": { + "singleQuote": false, + "bracketSpacing": true + } + } + ] +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 5378654677a..2001eafb5ff 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -11,6 +11,8 @@ "ms-vscode.cpptools-extension-pack", "ms-vscode.cpptools", "jeff-hykin.better-cpp-syntax", - "bierner.github-markdown-preview" + "bierner.github-markdown-preview", + "esbenp.prettier-vscode", + "redhat.vscode-yaml" ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 42d5c9fe7dd..3dda421424c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -355,6 +355,13 @@ "editor.defaultFormatter": "ms-python.black-formatter", "editor.formatOnSave": true }, + "[yaml]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "yaml.format.enable": false, "files.associations": { "algorithm": "cpp", "any": "cpp", diff --git a/CMakeLists.txt b/CMakeLists.txt index a18851baebc..046aa859eea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,6 +177,38 @@ if (NOT IPC_EXIT_CODE EQUAL 0) message(FATAL_ERROR "Failed to generate IPC stubs") endif() +execute_process( + COMMAND ${Python_EXECUTABLE} -c "import jinja2, jsonschema, yaml" + RESULT_VARIABLE CODEGEN_DEPS_EXIT_CODE + OUTPUT_QUIET + ERROR_QUIET +) +if(NOT CODEGEN_DEPS_EXIT_CODE EQUAL 0) + message(FATAL_ERROR "Run: ${Python_EXECUTABLE} -m pip install -r tools/requirements.txt") +endif() + +add_custom_target(data_codegen + COMMAND ${Python_EXECUTABLE} -m tools.codegen ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + BYPRODUCTS + ${CMAKE_BINARY_DIR}/generated/.codegen.stamp + ${CMAKE_BINARY_DIR}/generated/data/all.h + USES_TERMINAL + VERBATIM +) + +if(NOT EXISTS ${CMAKE_BINARY_DIR}/generated/.codegen.stamp) + message(STATUS "Bootstrapping data codegen") + execute_process( + COMMAND ${Python_EXECUTABLE} -m tools.codegen ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE CODEGEN_EXIT_CODE + ) + if(NOT CODEGEN_EXIT_CODE EQUAL 0) + message(FATAL_ERROR "Bootstrap codegen failed") + endif() +endif() + include_directories(${CMAKE_BINARY_DIR}/generated) # Globally include the build/generated directory add_subdirectory(src) diff --git a/data/enums/effect_overwrite.yaml b/data/enums/effect_overwrite.yaml new file mode 100644 index 00000000000..1bcbfb56847 --- /dev/null +++ b/data/enums/effect_overwrite.yaml @@ -0,0 +1,15 @@ +# yaml-language-server: $schema=../schemas/enums/_enum.schema.json + +meta: + cpp: + underlying: uint8_t + lua: + table: xi.effectOverwrite + +values: + equal_higher: 0 # only overwrite if equal or higher (tier, power) + higher: 1 # only overwrite if strictly higher + never: 2 + always: 3 + ignore_duplicate: 4 + tier_higher: 5 # only overwrite if tier is higher (regardless of power) diff --git a/data/enums/element.yaml b/data/enums/element.yaml new file mode 100644 index 00000000000..96997f4855c --- /dev/null +++ b/data/enums/element.yaml @@ -0,0 +1,18 @@ +# yaml-language-server: $schema=../schemas/enums/_enum.schema.json + +meta: + cpp: + underlying: uint8_t + lua: + table: xi.element + +values: + none: 0 + fire: 1 + ice: 2 + wind: 3 + earth: 4 + thunder: 5 + water: 6 + light: 7 + dark: 8 diff --git a/data/enums/status_effect_flag.yaml b/data/enums/status_effect_flag.yaml new file mode 100644 index 00000000000..8c02c34523c --- /dev/null +++ b/data/enums/status_effect_flag.yaml @@ -0,0 +1,42 @@ +# yaml-language-server: $schema=../schemas/enums/_enum.schema.json + +meta: + flags: true + cpp: + underlying: uint32_t + lua: + table: xi.effectFlag + +values: + none: 0x00000000 + dispelable: 0x00000001 + erasable: 0x00000002 + attack: 0x00000004 + empathy: 0x00000008 + damage: 0x00000010 + death: 0x00000020 + magic_begin: 0x00000040 + magic_end: 0x00000080 + on_zone: 0x00000100 + no_loss_message: 0x00000200 + invisible: 0x00000400 + detectable: 0x00000800 + no_rest: 0x00001000 + prevent_action: 0x00002000 + waltzable: 0x00004000 + food: 0x00008000 + song: 0x00010000 + roll: 0x00020000 + synth_support: 0x00040000 + confrontation: 0x00080000 + logout: 0x00100000 + bloodpact: 0x00200000 + on_jobchange: 0x00400000 + no_cancel: 0x00800000 + influence: 0x01000000 + offline_tick: 0x02000000 + aura: 0x04000000 + hide_timer: 0x08000000 + on_zone_pathos: 0x10000000 + always_expiring: 0x20000000 + on_attack: 0x40000000 diff --git a/data/schemas/_meta.schema.json b/data/schemas/_meta.schema.json new file mode 100644 index 00000000000..acc8a77d0c3 --- /dev/null +++ b/data/schemas/_meta.schema.json @@ -0,0 +1,43 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "_meta.schema.json", + "title": "Data-file codegen metadata", + "description": "Optional top-level `meta:` block in data yamls. Carries directives that drive codegen.", + "type": "object", + "unevaluatedProperties": false, + "properties": { + "enum": { + "type": "object", + "unevaluatedProperties": false, + "required": ["cpp"], + "description": "Emit a typed enum derived from a top-level section of the data file.", + "properties": { + "cpp": { + "type": "object", + "unevaluatedProperties": false, + "required": ["underlying", "class"], + "properties": { + "underlying": { "type": "string" }, + "class": { "type": "string", "pattern": "^[A-Z][A-Za-z0-9]*$" }, + "case": { "type": "string", "enum": ["pascal", "screaming"], "default": "pascal" } + } + }, + "lua": { + "type": "object", + "unevaluatedProperties": false, + "properties": { + "table": { "type": "string", "pattern": "^xi\\.[A-Za-z][A-Za-z0-9_]*$" } + } + }, + "section": { + "type": "string", + "description": "Which top-level YAML section to walk. Defaults to the filename." + }, + "name_from": { + "type": "string", + "description": "Dot-path inside each entry to a string that gets slugged into the enum value name (e.g., `name.en`). When set, the YAML key is treated as the integer id." + } + } + } + } +} diff --git a/data/schemas/enums/_enum.schema.json b/data/schemas/enums/_enum.schema.json new file mode 100644 index 00000000000..b01f8686863 --- /dev/null +++ b/data/schemas/enums/_enum.schema.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "_enum.schema.json", + "title": "Enum source", + "description": "Meta-schema for data/enums/*.yaml. Each file declares a typed enum: a `meta` block describing the C++/Lua surface, and a `values` map of name -> integer.", + "type": "object", + "unevaluatedProperties": false, + "required": ["meta", "values"], + + "properties": { + "meta": { + "type": "object", + "unevaluatedProperties": false, + "required": ["cpp"], + "properties": { + "flags": { + "description": "True if values are bitmask flags.", + "type": "boolean", + "default": false + }, + "cpp": { + "type": "object", + "unevaluatedProperties": false, + "required": ["underlying"], + "properties": { + "underlying": { + "description": "C++ underlying integer type for the enum class.", + "type": "string", + "enum": ["int8_t", "uint8_t", "int16_t", "uint16_t", "int32_t", "uint32_t", "int64_t", "uint64_t"] + }, + "class": { + "description": "Generated C++ enum class name (PascalCase).", + "type": "string", + "pattern": "^[A-Z][A-Za-z0-9]*$" + }, + "case": { + "description": "Case style for generated enum value names. `pascal` (default): `War`, `MysteryBox`. `screaming`: `WAR`, `MYSTERY_BOX`.", + "type": "string", + "enum": ["pascal", "screaming"], + "default": "pascal" + } + } + }, + "lua": { + "type": "object", + "unevaluatedProperties": false, + "properties": { + "table": { + "description": "Lua table path the values are exported under. Example: `xi.itemFlag`.", + "type": "string", + "pattern": "^xi\\.[A-Za-z][A-Za-z0-9_]*$" + } + } + } + } + }, + "values": { + "description": "Map of value name -> integer. Names must be snake_case and unique. Integers may be decimal or hex (0xNN).", + "type": "object", + "minProperties": 1, + "propertyNames": { "pattern": "^[a-z][a-z0-9_]*$" }, + "additionalProperties": { "type": "integer" } + } + } +} diff --git a/data/schemas/status_effects.schema.json b/data/schemas/status_effects.schema.json new file mode 100644 index 00000000000..28c3020b886 --- /dev/null +++ b/data/schemas/status_effects.schema.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "status_effects.schema.json", + "title": "StatusEffects", + "description": "Schema for data/status_effects.yaml.", + "type": "object", + "unevaluatedProperties": false, + "required": ["status_effects"], + + "properties": { + "meta": { "$ref": "_meta.schema.json" }, + "status_effects": { + "type": "object", + "description": "Status effects.", + "propertyNames": { "pattern": "^[a-z][a-z0-9_]*$" }, + "additionalProperties": { "$ref": "#/$defs/status_effect" } + } + }, + + "$defs": { + "status_effect": { + "type": "object", + "unevaluatedProperties": false, + "required": ["id"], + "properties": { + "id": { "type": "integer", "minimum": 0, "maximum": 65535 }, + "name": { + "type": "string", + "description": "Override for the Lua script lookup name. Defaults to the YAML key." + }, + "flags": { + "type": "array", + "items": { "$ref": "enums/status_effect_flag.codegen.json" }, + "uniqueItems": true, + "default": [] + }, + "exclusion_group": { + "$ref": "enums/status_effect.codegen.json", + "description": "Applying this effect removes all other effects sharing the same group (the group's representative effect). e.g. all spikes share blaze_spikes." + }, + "negative": { "$ref": "enums/status_effect.codegen.json" }, + "overwrite": { "$ref": "enums/effect_overwrite.codegen.json" }, + "block": { "$ref": "enums/status_effect.codegen.json" }, + "remove": { "$ref": "enums/status_effect.codegen.json" }, + "element": { "$ref": "enums/element.codegen.json" }, + "min_duration": { "type": "integer", "minimum": 0, "maximum": 65535 }, + "sort_key": { "type": "integer", "minimum": 0, "maximum": 65535 }, + "wear_off_message_id": { "type": "integer", "minimum": 0, "maximum": 65535 } + } + } + } +} diff --git a/data/status_effects.yaml b/data/status_effects.yaml new file mode 100644 index 00000000000..03f9d3729ed --- /dev/null +++ b/data/status_effects.yaml @@ -0,0 +1,5712 @@ +# yaml-language-server: $schema=schemas/status_effects.schema.json + +meta: + enum: + cpp: + underlying: uint16_t + class: StatusEffect + lua: + table: xi.effect + +status_effects: + ko: + id: 0 + flags: + - no_cancel + - hide_timer + wear_off_message_id: 204 + + weakness: + id: 1 + flags: + - no_cancel + overwrite: always + min_duration: 1 + wear_off_message_id: 204 + + sleep_i: + id: 2 + flags: + - damage + - death + - no_cancel + exclusion_group: sleep_i + negative: sleep_ii + overwrite: higher + block: lullaby + element: dark + min_duration: 1 + wear_off_message_id: 204 + + poison: + id: 3 + flags: + - death + - waltzable + - no_cancel + overwrite: never + element: water + min_duration: 1 + wear_off_message_id: 204 + + paralysis: + id: 4 + flags: + - death + - waltzable + - no_cancel + overwrite: higher + element: ice + min_duration: 1 + wear_off_message_id: 204 + + blindness: + id: 5 + flags: + - death + - waltzable + - no_cancel + overwrite: higher + element: dark + min_duration: 1 + wear_off_message_id: 204 + + silence: + id: 6 + flags: + - death + - waltzable + - no_cancel + overwrite: never + element: wind + min_duration: 1 + wear_off_message_id: 204 + + petrification: + id: 7 + flags: + - death + - no_cancel + exclusion_group: petrification + overwrite: never + block: stun + element: earth + min_duration: 1 + wear_off_message_id: 204 + + disease: + id: 8 + flags: + - death + - no_rest + - waltzable + - no_cancel + exclusion_group: disease + overwrite: never + element: fire + min_duration: 1 + wear_off_message_id: 204 + + curse_i: + id: 9 + flags: + - death + - waltzable + - no_cancel + exclusion_group: curse_i + overwrite: never + element: dark + min_duration: 1 + wear_off_message_id: 204 + + stun: + id: 10 + flags: + - erasable + - death + - no_cancel + overwrite: never + block: petrification + element: thunder + min_duration: 1 + wear_off_message_id: 204 + + bind: + id: 11 + flags: + - erasable + - death + - waltzable + - no_cancel + overwrite: never + element: ice + min_duration: 1 + wear_off_message_id: 204 + + weight: + id: 12 + flags: + - erasable + - death + - waltzable + - no_cancel + negative: flee + overwrite: higher + element: wind + min_duration: 1 + wear_off_message_id: 204 + + slow: + id: 13 + flags: + - erasable + - death + - waltzable + - no_cancel + negative: haste + overwrite: higher + element: earth + min_duration: 1 + + charm_i: + id: 14 + flags: + - death + - no_cancel + overwrite: never + element: light + wear_off_message_id: 204 + + doom: + id: 15 + flags: + - death + - no_cancel + overwrite: never + element: dark + min_duration: 1 + wear_off_message_id: 204 + + amnesia: + id: 16 + flags: + - death + - no_cancel + overwrite: never + element: fire + min_duration: 1 + wear_off_message_id: 204 + + charm_ii: + id: 17 + name: charm_i + flags: + - death + - no_cancel + overwrite: never + element: light + wear_off_message_id: 204 + + gradual_petrification: + id: 18 + flags: + - death + - no_cancel + exclusion_group: petrification + overwrite: never + element: earth + min_duration: 1 + wear_off_message_id: 204 + + sleep_ii: + id: 19 + name: sleep_i + flags: + - damage + - death + - no_cancel + exclusion_group: sleep_i + overwrite: higher + element: dark + min_duration: 1 + wear_off_message_id: 204 + + # Zombie + curse_ii: + id: 20 + name: curse_i + flags: + - death + - no_rest + - no_cancel + exclusion_group: curse_i + overwrite: never + element: dark + min_duration: 1 + wear_off_message_id: 204 + + addle: + id: 21 + flags: + - erasable + - death + - on_zone + - waltzable + - no_cancel + overwrite: never + element: fire + min_duration: 1 + + intimidate: + id: 22 + flags: + - death + - no_cancel + overwrite: never + min_duration: 1 + wear_off_message_id: 204 + + kaustra: + id: 23 + flags: + - death + - on_zone + - no_cancel + negative: embrava + wear_off_message_id: 204 + + terror: + id: 28 + flags: + - death + - no_cancel + exclusion_group: petrification + element: dark + min_duration: 1 + wear_off_message_id: 204 + + mute: + id: 29 + flags: + - death + - no_cancel + overwrite: never + remove: silence + element: wind + min_duration: 1 + wear_off_message_id: 204 + + bane: + id: 30 + flags: + - death + - waltzable + - no_cancel + overwrite: never + remove: curse_i + element: dark + min_duration: 1 + wear_off_message_id: 204 + + plague: + id: 31 + flags: + - death + - no_rest + - waltzable + - no_cancel + exclusion_group: disease + overwrite: never + element: fire + min_duration: 1 + wear_off_message_id: 204 + + flee: + id: 32 + flags: + - dispelable + - empathy + - death + negative: weight + element: wind + + haste: + id: 33 + flags: + - dispelable + - empathy + - death + negative: slow + element: wind + sort_key: 100 + + blaze_spikes: + id: 34 + flags: + - dispelable + - empathy + - death + exclusion_group: blaze_spikes + element: fire + sort_key: 800 + + ice_spikes: + id: 35 + flags: + - dispelable + - empathy + - death + exclusion_group: blaze_spikes + element: ice + sort_key: 800 + + blink: + id: 36 + flags: + - dispelable + - empathy + - death + exclusion_group: blink + block: copy_image + element: wind + sort_key: 50 + + stoneskin: + id: 37 + flags: + - dispelable + - empathy + - death + overwrite: tier_higher + element: earth + sort_key: 600 + + shock_spikes: + id: 38 + flags: + - dispelable + - empathy + - death + exclusion_group: blaze_spikes + element: thunder + sort_key: 800 + + aquaveil: + id: 39 + flags: + - dispelable + - empathy + - death + element: water + sort_key: 650 + + protect: + id: 40 + flags: + - dispelable + - empathy + - death + element: light + sort_key: 200 + + shell: + id: 41 + flags: + - dispelable + - empathy + - death + element: light + sort_key: 250 + + regen: + id: 42 + flags: + - dispelable + - empathy + - death + element: light + sort_key: 700 + + refresh: + id: 43 + flags: + - dispelable + - empathy + - death + element: light + sort_key: 750 + + mighty_strikes: + id: 44 + flags: + - death + - on_zone + - on_jobchange + element: fire + + boost: + id: 45 + flags: + - attack + - empathy + - death + - on_jobchange + element: fire + + hundred_fists: + id: 46 + flags: + - death + - on_zone + - on_jobchange + element: thunder + + manafont: + id: 47 + flags: + - death + - on_zone + - on_jobchange + element: water + + chainspell: + id: 48 + flags: + - death + - on_zone + - on_jobchange + element: thunder + + perfect_dodge: + id: 49 + flags: + - death + - on_zone + - on_jobchange + element: wind + + invincible: + id: 50 + flags: + - death + - on_zone + - on_jobchange + element: earth + + blood_weapon: + id: 51 + flags: + - death + - on_zone + - on_jobchange + exclusion_group: enfire + element: dark + + soul_voice: + id: 52 + flags: + - death + - on_zone + - on_jobchange + element: light + + eagle_eye_shot: + id: 53 + flags: + - death + - on_zone + - on_jobchange + element: thunder + + meikyo_shisui: + id: 54 + flags: + - death + - on_zone + - on_jobchange + element: thunder + + astral_flow: + id: 55 + flags: + - death + - on_zone + - on_jobchange + element: thunder + + berserk: + id: 56 + flags: + - dispelable + - empathy + - death + - on_zone + element: fire + + defender: + id: 57 + flags: + - dispelable + - death + - on_zone + element: earth + + aggressor: + id: 58 + flags: + - dispelable + - death + - on_zone + + focus: + id: 59 + flags: + - dispelable + - empathy + - death + - on_zone + + dodge: + id: 60 + flags: + - dispelable + - empathy + - death + - on_zone + + counterstance: + id: 61 + flags: + - dispelable + - death + - on_zone + + sentinel: + id: 62 + flags: + - dispelable + - death + - on_zone + + souleater: + id: 63 + flags: + - empathy + - death + - on_zone + - on_jobchange + + last_resort: + id: 64 + flags: + - dispelable + - empathy + - death + - on_zone + + sneak_attack: + id: 65 + flags: + - attack + - death + - on_zone + - on_jobchange + + copy_image: + id: 66 + flags: + - dispelable + - death + remove: blink + element: wind + sort_key: 50 + + third_eye: + id: 67 + flags: + - dispelable + - empathy + - death + + warcry: + id: 68 + flags: + - dispelable + - empathy + - death + remove: blood_rage + sort_key: 400 + + invisible: + id: 69 + flags: + - dispelable + - attack + - death + - magic_begin + - on_zone + - invisible + - detectable + - logout + overwrite: never + element: wind + sort_key: 850 + + deodorize: + id: 70 + flags: + - dispelable + - attack + - death + - on_zone + - detectable + - logout + overwrite: never + element: wind + sort_key: 1100 + + sneak: + id: 71 + flags: + - dispelable + - attack + - death + - on_zone + - detectable + - logout + overwrite: never + element: wind + sort_key: 1150 + + sharpshot: + id: 72 + flags: + - dispelable + - death + - on_zone + + barrage: + id: 73 + flags: + - dispelable + - death + - on_zone + exclusion_group: barrage + + holy_circle: + id: 74 + flags: + - dispelable + - empathy + - death + + arcane_circle: + id: 75 + flags: + - dispelable + - empathy + - death + + hide: + id: 76 + flags: + - dispelable + - attack + - death + - magic_begin + - on_zone + - invisible + - detectable + - logout + + camouflage: + id: 77 + flags: + - dispelable + - attack + - death + - magic_begin + - on_zone + - invisible + - detectable + - logout + + divine_seal: + id: 78 + flags: + - dispelable + - death + - magic_end + - on_zone + + elemental_seal: + id: 79 + flags: + - dispelable + - death + - magic_end + - on_zone + + str_boost: + id: 80 + flags: + - dispelable + - empathy + - death + - on_zone + negative: str_down + element: fire + + dex_boost: + id: 81 + flags: + - dispelable + - empathy + - death + - on_zone + negative: dex_down + element: thunder + + vit_boost: + id: 82 + flags: + - dispelable + - empathy + - death + - on_zone + negative: vit_down + element: earth + + agi_boost: + id: 83 + flags: + - dispelable + - empathy + - death + - on_zone + negative: agi_down + element: wind + + int_boost: + id: 84 + flags: + - dispelable + - empathy + - death + - on_zone + negative: int_down + element: ice + + mnd_boost: + id: 85 + flags: + - dispelable + - empathy + - death + - on_zone + negative: mnd_down + element: water + + chr_boost: + id: 86 + flags: + - dispelable + - empathy + - death + - on_zone + negative: chr_down + element: light + + trick_attack: + id: 87 + flags: + - attack + - death + - on_zone + - on_jobchange + + max_hp_boost: + id: 88 + flags: + - dispelable + - empathy + - death + - on_zone + negative: max_hp_down + element: light + + max_mp_boost: + id: 89 + flags: + - dispelable + - empathy + - death + - on_zone + negative: max_mp_down + element: dark + + accuracy_boost: + id: 90 + flags: + - dispelable + - empathy + - death + - on_zone + negative: accuracy_down + element: thunder + + attack_boost: + id: 91 + flags: + - dispelable + - empathy + - death + - on_zone + negative: attack_down + element: fire + + evasion_boost: + id: 92 + flags: + - dispelable + - empathy + - death + - on_zone + negative: evasion_down + element: wind + + defense_boost: + id: 93 + flags: + - dispelable + - empathy + - death + - on_zone + negative: defense_down + element: earth + + enfire: + id: 94 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: fire + sort_key: 1200 + + enblizzard: + id: 95 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: ice + sort_key: 1200 + + enaero: + id: 96 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: wind + sort_key: 1200 + + enstone: + id: 97 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: earth + sort_key: 1200 + + enthunder: + id: 98 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: thunder + sort_key: 1200 + + enwater: + id: 99 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: water + sort_key: 1200 + + barfire: + id: 100 + flags: + - dispelable + - empathy + - death + exclusion_group: barfire + element: water + sort_key: 500 + + barblizzard: + id: 101 + flags: + - dispelable + - empathy + - death + exclusion_group: barfire + element: fire + sort_key: 500 + + baraero: + id: 102 + flags: + - dispelable + - empathy + - death + exclusion_group: barfire + element: ice + sort_key: 500 + + barstone: + id: 103 + flags: + - dispelable + - empathy + - death + exclusion_group: barfire + element: wind + sort_key: 500 + + barthunder: + id: 104 + flags: + - dispelable + - empathy + - death + exclusion_group: barfire + element: earth + sort_key: 500 + + barwater: + id: 105 + flags: + - dispelable + - empathy + - death + exclusion_group: barfire + element: thunder + sort_key: 500 + + barsleep: + id: 106 + flags: + - dispelable + - empathy + - death + exclusion_group: barsleep + element: light + sort_key: 500 + + barpoison: + id: 107 + flags: + - dispelable + - empathy + - death + exclusion_group: barsleep + element: thunder + sort_key: 500 + + barparalyze: + id: 108 + flags: + - dispelable + - empathy + - death + exclusion_group: barsleep + element: fire + sort_key: 500 + + barblind: + id: 109 + flags: + - dispelable + - empathy + - death + exclusion_group: barsleep + element: light + sort_key: 500 + + barsilence: + id: 110 + flags: + - dispelable + - empathy + - death + exclusion_group: barsleep + element: ice + sort_key: 500 + + barpetrify: + id: 111 + flags: + - dispelable + - empathy + - death + exclusion_group: barsleep + element: wind + sort_key: 500 + + barvirus: + id: 112 + flags: + - dispelable + - empathy + - death + exclusion_group: barsleep + element: water + sort_key: 500 + + reraise: + id: 113 + flags: + - empathy + - death + - on_jobchange + element: light + sort_key: 900 + + cover: + id: 114 + flags: + - death + - on_jobchange + + unlimited_shot: + id: 115 + flags: + - death + - on_zone + - on_jobchange + exclusion_group: barrage + + phalanx: + id: 116 + flags: + - dispelable + - death + - on_zone + element: light + sort_key: 1050 + + warding_circle: + id: 117 + flags: + - dispelable + - empathy + - death + + ancient_circle: + id: 118 + flags: + - dispelable + - empathy + - death + + str_boost_ii: + id: 119 + name: str_boost + flags: + - dispelable + - empathy + - death + - on_zone + - no_cancel + element: fire + + dex_boost_ii: + id: 120 + name: dex_boost + flags: + - dispelable + - empathy + - death + - on_zone + - no_cancel + element: thunder + + vit_boost_ii: + id: 121 + name: vit_boost + flags: + - dispelable + - empathy + - death + - on_zone + - no_cancel + element: earth + + agi_boost_ii: + id: 122 + name: agi_boost + flags: + - dispelable + - empathy + - death + - on_zone + - no_cancel + element: wind + + int_boost_ii: + id: 123 + name: int_boost + flags: + - dispelable + - empathy + - death + - on_zone + - no_cancel + element: ice + + mnd_boost_ii: + id: 124 + name: mnd_boost + flags: + - dispelable + - empathy + - death + - on_zone + - no_cancel + element: water + + chr_boost_ii: + id: 125 + name: chr_boost + flags: + - dispelable + - empathy + - death + - on_zone + - no_cancel + element: light + + spirit_surge: + id: 126 + flags: + - death + - on_zone + - on_jobchange + + costume: + id: 127 + flags: + - attack + - death + - magic_end + - on_zone + + burn: + id: 128 + flags: + - erasable + - death + - waltzable + - no_cancel + block: drown + remove: frost + element: fire + + frost: + id: 129 + flags: + - erasable + - death + - waltzable + - no_cancel + block: burn + remove: choke + element: ice + + choke: + id: 130 + flags: + - erasable + - death + - waltzable + - no_cancel + block: frost + remove: rasp + element: wind + + rasp: + id: 131 + flags: + - erasable + - death + - waltzable + - no_cancel + block: choke + remove: shock + element: earth + + shock: + id: 132 + flags: + - erasable + - death + - waltzable + - no_cancel + block: rasp + remove: drown + element: thunder + + drown: + id: 133 + flags: + - erasable + - death + - waltzable + - no_cancel + block: shock + remove: burn + element: water + + dia: + id: 134 + flags: + - erasable + - death + - waltzable + - no_cancel + negative: dia + overwrite: higher + element: light + + bio: + id: 135 + flags: + - erasable + - death + - waltzable + - no_cancel + negative: dia + overwrite: higher + element: dark + + str_down: + id: 136 + flags: + - erasable + - death + - waltzable + - no_cancel + remove: str_boost + element: water + + dex_down: + id: 137 + flags: + - erasable + - death + - waltzable + - no_cancel + remove: dex_boost + element: earth + + vit_down: + id: 138 + flags: + - erasable + - death + - waltzable + - no_cancel + remove: vit_boost + element: wind + + agi_down: + id: 139 + flags: + - erasable + - death + - waltzable + - no_cancel + remove: agi_boost + element: ice + + int_down: + id: 140 + flags: + - erasable + - death + - waltzable + - no_cancel + remove: int_boost + element: fire + + mnd_down: + id: 141 + flags: + - erasable + - death + - waltzable + - no_cancel + remove: mnd_boost + element: thunder + + chr_down: + id: 142 + flags: + - erasable + - death + - waltzable + - no_cancel + remove: chr_boost + element: dark + + level_restriction: + id: 143 + flags: + - no_loss_message + - no_cancel + - hide_timer + + max_hp_down: + id: 144 + flags: + - erasable + - death + - waltzable + - no_cancel + remove: max_hp_boost + element: dark + + max_mp_down: + id: 145 + flags: + - erasable + - death + - waltzable + - no_cancel + remove: max_mp_boost + element: light + + accuracy_down: + id: 146 + flags: + - erasable + - death + - on_zone + - waltzable + - no_cancel + remove: accuracy_boost + element: earth + + attack_down: + id: 147 + flags: + - erasable + - death + - on_zone + - waltzable + - no_cancel + remove: attack_boost + element: water + + evasion_down: + id: 148 + flags: + - erasable + - death + - on_zone + - waltzable + - no_cancel + remove: evasion_boost + element: ice + + defense_down: + id: 149 + flags: + - erasable + - death + - on_zone + - waltzable + - no_cancel + remove: defense_boost + element: wind + + physical_shield: + id: 150 + flags: + - dispelable + - empathy + - death + + arrow_shield: + id: 151 + flags: + - dispelable + - death + - no_cancel + + magic_shield: + id: 152 + flags: + - dispelable + - empathy + - death + + damage_spikes: + id: 153 + flags: + - dispelable + - empathy + - death + - no_cancel + exclusion_group: blaze_spikes + sort_key: 800 + + shining_ruby: + id: 154 + flags: + - dispelable + - empathy + - death + - on_zone + - no_cancel + + medicine: + id: 155 + flags: + - no_cancel + wear_off_message_id: 204 + + flash: + id: 156 + flags: + - erasable + - death + - on_zone + - waltzable + - no_cancel + overwrite: higher + element: light + wear_off_message_id: 204 + + sj_restriction: + id: 157 + flags: + - on_zone + - no_loss_message + - no_cancel + + provoke: + id: 158 + flags: + - death + - no_cancel + wear_off_message_id: 204 + + penalty: + id: 159 + flags: + - death + - no_cancel + wear_off_message_id: 204 + + preparations: + id: 160 + flags: + - death + - no_cancel + wear_off_message_id: 204 + + sprint: + id: 161 + flags: + - death + - no_cancel + + enchantment: + id: 162 + flags: + - death + - on_zone + - no_cancel + overwrite: ignore_duplicate + wear_off_message_id: 204 + + azure_lore: + id: 163 + flags: + - death + - on_zone + - on_jobchange + + chain_affinity: + id: 164 + flags: + - death + - on_zone + - on_jobchange + + burst_affinity: + id: 165 + flags: + - death + - on_zone + - on_jobchange + + overdrive: + id: 166 + flags: + - death + - on_zone + - on_jobchange + + magic_def_down: + id: 167 + flags: + - erasable + - death + - on_zone + - waltzable + - no_cancel + + inhibit_tp: + id: 168 + flags: + - death + - no_cancel + element: dark + + potency: + id: 169 + flags: + - empathy + - death + - on_zone + + regain: + id: 170 + flags: + - empathy + - death + - on_zone + element: light + + pax: + id: 171 + flags: + - empathy + - death + - on_zone + + intension: + id: 172 + flags: + - empathy + - death + + dread_spikes: + id: 173 + flags: + - dispelable + - empathy + - death + exclusion_group: blaze_spikes + sort_key: 800 + + magic_acc_down: + id: 174 + flags: + - erasable + - death + - on_zone + - waltzable + - no_cancel + element: fire + + magic_atk_down: + id: 175 + flags: + - erasable + - death + - on_zone + - waltzable + - no_cancel + element: earth + + quickening: + id: 176 + flags: + - attack + - empathy + - damage + - death + - on_jobchange + - on_attack + wear_off_message_id: 204 + + encumbrance_ii: + id: 177 + name: encumbrance_i + flags: + - on_zone + - no_cancel + wear_off_message_id: 204 + + firestorm: + id: 178 + flags: + - death + - on_zone + - on_jobchange + + hailstorm: + id: 179 + flags: + - death + - on_zone + - on_jobchange + + windstorm: + id: 180 + flags: + - death + - on_zone + - on_jobchange + + sandstorm: + id: 181 + flags: + - death + - on_zone + - on_jobchange + + thunderstorm: + id: 182 + flags: + - death + - on_zone + - on_jobchange + + rainstorm: + id: 183 + flags: + - death + - on_zone + - on_jobchange + + aurorastorm: + id: 184 + flags: + - death + - on_zone + - on_jobchange + + voidstorm: + id: 185 + flags: + - death + - on_zone + - on_jobchange + + helix: + id: 186 + flags: + - death + - no_cancel + + sublimation_activated: + id: 187 + flags: + - death + - on_zone + - on_jobchange + - no_cancel + - hide_timer + + sublimation_complete: + id: 188 + flags: + - death + - on_jobchange + - no_cancel + + max_tp_down: + id: 189 + flags: + - erasable + - death + - on_zone + - waltzable + - no_cancel + element: dark + + magic_atk_boost: + id: 190 + flags: + - dispelable + - empathy + - death + - on_zone + element: ice + + magic_def_boost: + id: 191 + flags: + - dispelable + - empathy + - death + - on_zone + element: water + + requiem: + id: 192 + flags: + - erasable + - death + - on_zone + - song + - no_cancel + overwrite: higher + element: light + sort_key: 2000 + + lullaby: + id: 193 + flags: + - damage + - death + - on_zone + - song + - no_cancel + exclusion_group: sleep_i + negative: sleep_ii + overwrite: never + block: sleep_i + element: light + min_duration: 1 + sort_key: 2000 + + elegy: + id: 194 + flags: + - erasable + - death + - on_zone + - song + - no_cancel + element: earth + sort_key: 2000 + + paeon: + id: 195 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + element: light + sort_key: 2000 + + ballad: + id: 196 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + element: light + sort_key: 2000 + + minne: + id: 197 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + element: earth + sort_key: 2000 + + minuet: + id: 198 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + element: fire + sort_key: 2000 + + madrigal: + id: 199 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + element: thunder + sort_key: 2000 + + prelude: + id: 200 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + mambo: + id: 201 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + aubade: + id: 202 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + pastoral: + id: 203 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + hum: + id: 204 + flags: + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + fantasia: + id: 205 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + operetta: + id: 206 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + capriccio: + id: 207 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + serenade: + id: 208 + flags: + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + round: + id: 209 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + gavotte: + id: 210 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + fugue: + id: 211 + flags: + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + rhapsody: + id: 212 + flags: + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + aria: + id: 213 + flags: + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + march: + id: 214 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + etude: + id: 215 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + carol: + id: 216 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + threnody: + id: 217 + flags: + - empathy + - death + - on_zone + - no_loss_message + - song + - no_cancel + overwrite: higher + sort_key: 2000 + + hymnus: + id: 218 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + mazurka: + id: 219 + flags: + - dispelable + - attack + - damage + - death + - on_zone + - song + - no_cancel + - on_attack + sort_key: 2000 + + sirvente: + id: 220 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + dirge: + id: 221 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + scherzo: + id: 222 + flags: + - dispelable + - empathy + - death + - on_zone + - song + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + nocturne: + id: 223 + flags: + - death + - on_zone + - no_cancel + overwrite: ignore_duplicate + sort_key: 2000 + + store_tp: + id: 227 + flags: + - death + - on_zone + + embrava: + id: 228 + flags: + - death + - on_zone + - on_jobchange + negative: kaustra + + manawell: + id: 229 + flags: + - death + - on_zone + - on_jobchange + + spontaneity: + id: 230 + flags: + - death + - on_zone + - on_jobchange + + marcato: + id: 231 + flags: + - death + - on_zone + - on_jobchange + + auto_regen: + id: 233 + name: auto-regen + flags: + - death + overwrite: ignore_duplicate + + auto_refresh: + id: 234 + name: auto-refresh + flags: + - death + overwrite: ignore_duplicate + + fishing_imagery: + id: 235 + flags: + - death + - synth_support + - no_cancel + exclusion_group: imagery_1 + + woodworking_imagery: + id: 236 + flags: + - death + - synth_support + - no_cancel + exclusion_group: imagery_1 + + smithing_imagery: + id: 237 + flags: + - death + - synth_support + - no_cancel + exclusion_group: imagery_1 + + goldsmithing_imagery: + id: 238 + flags: + - death + - synth_support + - no_cancel + exclusion_group: imagery_1 + + clothcraft_imagery: + id: 239 + flags: + - death + - synth_support + - no_cancel + exclusion_group: imagery_1 + + leathercraft_imagery: + id: 240 + flags: + - death + - synth_support + - no_cancel + exclusion_group: imagery_1 + + bonecraft_imagery: + id: 241 + flags: + - death + - synth_support + - no_cancel + exclusion_group: imagery_1 + + alchemy_imagery: + id: 242 + flags: + - death + - synth_support + - no_cancel + exclusion_group: imagery_1 + + cooking_imagery: + id: 243 + flags: + - death + - synth_support + - no_cancel + exclusion_group: imagery_1 + + imagery_1: + id: 244 + name: imagery + flags: + - death + - no_cancel + exclusion_group: imagery_1 + + imagery_2: + id: 245 + name: imagery + flags: + - death + - no_cancel + exclusion_group: imagery_1 + + imagery_3: + id: 246 + name: imagery + flags: + - death + - no_cancel + exclusion_group: imagery_1 + + imagery_4: + id: 247 + name: imagery + flags: + - death + - no_cancel + exclusion_group: imagery_1 + + imagery_5: + id: 248 + name: imagery + flags: + - death + - no_cancel + exclusion_group: imagery_1 + + dedication: + id: 249 + flags: + - no_cancel + + ef_badge: + id: 250 + flags: + - death + - no_cancel + - hide_timer + + food: + id: 251 + flags: + - death + - food + - no_cancel + overwrite: never + + mounted: + id: 252 + flags: + - attack + - death + - magic_end + - no_cancel + + signet: + id: 253 + flags: + - no_cancel + - influence + sort_key: 1000 + + battlefield: + id: 254 + flags: + - confrontation + - no_cancel + - hide_timer + + sanction: + id: 256 + flags: + - no_cancel + - influence + sort_key: 1000 + + besieged: + id: 257 + flags: + - no_cancel + - hide_timer + + illusion: + id: 258 + flags: + - attack + - damage + - death + - magic_end + - on_zone + - no_rest + + encumbrance_i: + id: 259 + flags: + - no_cancel + - hide_timer + - on_zone_pathos + wear_off_message_id: 204 + + obliviscence: + id: 260 + flags: + - no_cancel + - hide_timer + - on_zone_pathos + + impairment: + id: 261 + flags: + - no_cancel + - hide_timer + - on_zone_pathos + wear_off_message_id: 204 + + omerta: + id: 262 + flags: + - no_cancel + - hide_timer + - on_zone_pathos + + debilitation: + id: 263 + flags: + - no_cancel + - hide_timer + - on_zone_pathos + wear_off_message_id: 204 + + pathos: + id: 264 + flags: + - no_cancel + - hide_timer + - on_zone_pathos + + flurry: + id: 265 + flags: + - death + - on_jobchange + - no_cancel + - hide_timer + + concentration: + id: 266 + flags: + - death + - no_cancel + - hide_timer + + allied_tags: + id: 267 + flags: + - death + - on_zone + - confrontation + - no_cancel + - hide_timer + + sigil: + id: 268 + flags: + - no_cancel + - influence + + level_sync: + id: 269 + flags: + - on_zone + - no_cancel + - hide_timer + + aftermath_lv1: + id: 270 + flags: + - death + - on_zone + - no_cancel + + aftermath_lv2: + id: 271 + flags: + - death + - on_zone + - no_cancel + + aftermath_lv3: + id: 272 + flags: + - death + - on_zone + - no_cancel + + aftermath: + id: 273 + flags: + - death + - on_zone + - no_cancel + + enlight: + id: 274 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: light + + auspice: + id: 275 + flags: + - death + - on_zone + - on_jobchange + exclusion_group: enfire + negative: blood_weapon + element: light + + confrontation: + id: 276 + flags: + - death + - on_zone + - confrontation + - no_cancel + - hide_timer + + enfire_ii: + id: 277 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: fire + + enblizzard_ii: + id: 278 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: ice + + enaero_ii: + id: 279 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: wind + + enstone_ii: + id: 280 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: earth + + enthunder_ii: + id: 281 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: thunder + + enwater_ii: + id: 282 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: water + + perfect_defense: + id: 283 + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + egg: + id: 284 + flags: + - death + - on_zone + + visitant: + id: 285 + flags: + - on_zone + - no_cancel + - offline_tick + + baramnesia: + id: 286 + flags: + - dispelable + - empathy + - death + exclusion_group: barsleep + sort_key: 500 + + atma: + id: 287 + flags: + - on_zone + - no_cancel + - hide_timer + overwrite: ignore_duplicate + + endark: + id: 288 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: enfire + negative: blood_weapon + element: dark + + enmity_boost: + id: 289 + flags: + - death + element: fire + + subtle_blow_plus: + id: 290 + flags: + - death + - on_zone + + enmity_down: + id: 291 + flags: + - erasable + - death + - waltzable + element: water + + pennant: + id: 292 + flags: + - death + - confrontation + - no_cancel + - hide_timer + + negate_petrify: + id: 293 + flags: + - dispelable + - death + - on_zone + block: petrification + + negate_terror: + id: 294 + flags: + - dispelable + - death + - on_zone + block: terror + + negate_amnesia: + id: 295 + flags: + - dispelable + - death + - on_zone + block: amnesia + + negate_doom: + id: 296 + flags: + - dispelable + - death + - on_zone + block: doom + + negate_poison: + id: 297 + flags: + - dispelable + - death + - on_zone + block: poison + + crit_hit_evasion_down: + id: 298 + name: critical_hit_evasion_down + flags: + - erasable + - death + - waltzable + - no_cancel + + overload: + id: 299 + flags: + - death + - on_zone + - no_cancel + wear_off_message_id: 204 + + fire_maneuver: + id: 300 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + sort_key: 3000 + + ice_maneuver: + id: 301 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + sort_key: 3000 + + wind_maneuver: + id: 302 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + sort_key: 3000 + + earth_maneuver: + id: 303 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + sort_key: 3000 + + thunder_maneuver: + id: 304 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + sort_key: 3000 + + water_maneuver: + id: 305 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + sort_key: 3000 + + light_maneuver: + id: 306 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + sort_key: 3000 + + dark_maneuver: + id: 307 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + sort_key: 3000 + + double_up_chance: + id: 308 + name: double-up_chance + flags: + - death + - on_zone + - on_jobchange + - no_cancel + sort_key: 2050 + + bust: + id: 309 + flags: + - death + - on_zone + - no_cancel + overwrite: ignore_duplicate + sort_key: 2050 + + fighters_roll: + id: 310 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + monks_roll: + id: 311 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + healers_roll: + id: 312 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + wizards_roll: + id: 313 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + warlocks_roll: + id: 314 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + rogues_roll: + id: 315 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + gallants_roll: + id: 316 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + chaos_roll: + id: 317 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + beast_roll: + id: 318 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + choral_roll: + id: 319 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + hunters_roll: + id: 320 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + samurai_roll: + id: 321 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + ninja_roll: + id: 322 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + drachen_roll: + id: 323 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + evokers_roll: + id: 324 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + maguss_roll: + id: 325 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + corsairs_roll: + id: 326 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + puppet_roll: + id: 327 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + dancers_roll: + id: 328 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + scholars_roll: + id: 329 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + bolters_roll: + id: 330 + flags: + - dispelable + - attack + - empathy + - damage + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + - on_attack + sort_key: 2000 + + casters_roll: + id: 331 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + coursers_roll: + id: 332 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + blitzers_roll: + id: 333 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + tacticians_roll: + id: 334 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + allies_roll: + id: 335 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + misers_roll: + id: 336 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + companions_roll: + id: 337 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + avengers_roll: + id: 338 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + naturalists_roll: + id: 339 + flags: + - dispelable + - empathy + - death + - on_zone + - roll + - logout + - on_jobchange + - no_cancel + sort_key: 2000 + + warriors_charge: + id: 340 + flags: + - attack + - death + - on_zone + - on_jobchange + + formless_strikes: + id: 341 + flags: + - death + - on_zone + - on_jobchange + + assassins_charge: + id: 342 + flags: + - attack + - death + - on_zone + - on_jobchange + + feint: + id: 343 + flags: + - death + - on_jobchange + + fealty: + id: 344 + flags: + - dispelable + - death + - on_zone + - on_jobchange + + dark_seal: + id: 345 + flags: + - dispelable + - death + - magic_end + - on_zone + + diabolic_eye: + id: 346 + flags: + - death + - on_zone + - on_jobchange + + nightingale: + id: 347 + flags: + - death + - on_zone + - on_jobchange + + troubadour: + id: 348 + flags: + - death + - on_zone + - on_jobchange + + killer_instinct: + id: 349 + flags: + - death + - on_jobchange + + stealth_shot: + id: 350 + flags: + - death + - on_zone + - on_jobchange + + flashy_shot: + id: 351 + flags: + - death + - on_zone + - on_jobchange + + sange: + id: 352 + flags: + - death + - on_zone + exclusion_group: barrage + + hasso: + id: 353 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: hasso + + seigan: + id: 354 + flags: + - dispelable + - empathy + - death + - on_zone + exclusion_group: hasso + + convergence: + id: 355 + flags: + - death + - on_zone + - on_jobchange + + diffusion: + id: 356 + flags: + - death + - on_zone + - on_jobchange + + snake_eye: + id: 357 + flags: + - death + - on_zone + - on_jobchange + + light_arts: + id: 358 + flags: + - death + - on_zone + - logout + - on_jobchange + - no_cancel + + dark_arts: + id: 359 + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + penury: + id: 360 + flags: + - death + - on_zone + - on_jobchange + + parsimony: + id: 361 + flags: + - death + - on_zone + - on_jobchange + + celerity: + id: 362 + flags: + - death + - on_zone + - on_jobchange + + alacrity: + id: 363 + flags: + - death + - on_zone + - on_jobchange + + rapture: + id: 364 + flags: + - death + - on_zone + - on_jobchange + + ebullience: + id: 365 + flags: + - death + - on_zone + - on_jobchange + + accession: + id: 366 + flags: + - death + - on_zone + - on_jobchange + + manifestation: + id: 367 + flags: + - death + - on_zone + - on_jobchange + + drain_samba: + id: 368 + flags: + - empathy + - death + - on_zone + - on_jobchange + exclusion_group: drain_samba + + aspir_samba: + id: 369 + flags: + - empathy + - death + - on_zone + - on_jobchange + exclusion_group: drain_samba + + haste_samba: + id: 370 + flags: + - empathy + - death + - on_zone + - on_jobchange + exclusion_group: drain_samba + + velocity_shot: + id: 371 + flags: + - death + - on_zone + - on_jobchange + + building_flourish: + id: 375 + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + trance: + id: 376 + flags: + - death + - on_zone + - on_jobchange + + tabula_rasa: + id: 377 + flags: + - death + - on_zone + - on_jobchange + + drain_daze: + id: 378 + flags: + - death + - no_cancel + + aspir_daze: + id: 379 + flags: + - death + - no_cancel + + haste_daze: + id: 380 + flags: + - death + - no_cancel + + finishing_move_1: + id: 381 + name: finishing_move + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + finishing_move_2: + id: 382 + name: finishing_move + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + finishing_move_3: + id: 383 + name: finishing_move + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + finishing_move_4: + id: 384 + name: finishing_move + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + finishing_move_5: + id: 385 + name: finishing_move + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + lethargic_daze_1: + id: 386 + flags: + - death + - no_cancel + + lethargic_daze_2: + id: 387 + flags: + - death + - no_cancel + + lethargic_daze_3: + id: 388 + flags: + - death + - no_cancel + + lethargic_daze_4: + id: 389 + flags: + - death + - no_cancel + + lethargic_daze_5: + id: 390 + flags: + - death + - no_cancel + + sluggish_daze_1: + id: 391 + flags: + - death + - no_cancel + + sluggish_daze_2: + id: 392 + flags: + - death + - no_cancel + + sluggish_daze_3: + id: 393 + flags: + - death + - no_cancel + + sluggish_daze_4: + id: 394 + flags: + - death + - no_cancel + + sluggish_daze_5: + id: 395 + flags: + - death + - no_cancel + + weakened_daze_1: + id: 396 + flags: + - death + - no_cancel + + weakened_daze_2: + id: 397 + flags: + - death + - no_cancel + + weakened_daze_3: + id: 398 + flags: + - death + - no_cancel + + weakened_daze_4: + id: 399 + flags: + - death + - no_cancel + + weakened_daze_5: + id: 400 + flags: + - death + - no_cancel + + addendum_white: + id: 401 + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + addendum_black: + id: 402 + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + reprisal: + id: 403 + flags: + - dispelable + - death + exclusion_group: blaze_spikes + + magic_evasion_down: + id: 404 + flags: + - erasable + - death + - waltzable + - no_cancel + + retaliation: + id: 405 + flags: + - death + - on_zone + - on_jobchange + + footwork: + id: 406 + flags: + - death + - on_zone + - on_jobchange + + klimaform: + id: 407 + flags: + - death + - on_zone + - on_jobchange + + sekkanoki: + id: 408 + flags: + - death + - on_zone + - on_jobchange + + pianissimo: + id: 409 + flags: + - death + - on_zone + - on_jobchange + + saber_dance: + id: 410 + flags: + - death + - on_zone + - on_jobchange + + fan_dance: + id: 411 + flags: + - death + - on_zone + - on_jobchange + + altruism: + id: 412 + flags: + - death + - on_zone + - on_jobchange + + focalization: + id: 413 + flags: + - death + - on_zone + - on_jobchange + + tranquility: + id: 414 + flags: + - death + - on_zone + - on_jobchange + + equanimity: + id: 415 + flags: + - death + - on_zone + - on_jobchange + + enlightenment: + id: 416 + flags: + - death + - on_zone + - on_jobchange + + afflatus_solace: + id: 417 + flags: + - dispelable + - death + - on_zone + + afflatus_misery: + id: 418 + flags: + - dispelable + - death + - on_zone + + composure: + id: 419 + flags: + - dispelable + - death + - on_zone + + yonin: + id: 420 + flags: + - dispelable + - death + - on_zone + exclusion_group: yonin + + innin: + id: 421 + flags: + - dispelable + - death + - on_zone + exclusion_group: yonin + + carbuncles_favor: + id: 422 + flags: + - death + - on_zone + - no_cancel + - hide_timer + + ifrits_favor: + id: 423 + flags: + - death + - on_zone + - no_cancel + - hide_timer + + shivas_favor: + id: 424 + flags: + - death + - on_zone + - no_cancel + - hide_timer + + garudas_favor: + id: 425 + flags: + - death + - on_zone + - no_cancel + - hide_timer + + titans_favor: + id: 426 + flags: + - death + - on_zone + - no_cancel + - hide_timer + + ramuhs_favor: + id: 427 + flags: + - death + - on_zone + - no_cancel + - hide_timer + + leviathans_favor: + id: 428 + flags: + - death + - on_zone + - no_cancel + - hide_timer + + fenrirs_favor: + id: 429 + flags: + - death + - on_zone + - no_cancel + - hide_timer + + diaboloss_favor: + id: 430 + flags: + - death + - on_zone + - no_cancel + - hide_timer + + avatars_favor: + id: 431 + flags: + - dispelable + - death + - on_zone + - on_jobchange + - offline_tick + - hide_timer + + multi_strikes: + id: 432 + flags: + - death + - on_zone + + double_shot: + id: 433 + flags: + - death + - on_zone + + transcendency: + id: 434 + flags: + - on_zone + - no_cancel + + restraint: + id: 435 + flags: + - death + - on_zone + - logout + - on_jobchange + + perfect_counter: + id: 436 + flags: + - death + - on_zone + - on_jobchange + + mana_wall: + id: 437 + flags: + - death + - on_zone + - on_jobchange + + divine_emblem: + id: 438 + flags: + - death + - on_zone + - on_jobchange + + nether_void: + id: 439 + flags: + - death + - on_zone + - on_jobchange + + sengikori: + id: 440 + flags: + - death + - on_zone + - on_jobchange + + futae: + id: 441 + flags: + - death + - on_zone + - on_jobchange + + presto: + id: 442 + flags: + - death + - on_zone + - on_jobchange + + climactic_flourish: + id: 443 + flags: + - death + - on_zone + - on_jobchange + + copy_image_2: + id: 444 + name: copy_image + flags: + - death + - on_jobchange + exclusion_group: blink + sort_key: 50 + + copy_image_3: + id: 445 + name: copy_image + flags: + - death + - on_jobchange + exclusion_group: blink + sort_key: 50 + + copy_image_4: + id: 446 + name: copy_image + flags: + - death + - on_jobchange + exclusion_group: blink + sort_key: 50 + + multi_shots: + id: 447 + flags: + - death + - on_zone + - on_jobchange + + bewildered_daze_1: + id: 448 + flags: + - death + - no_cancel + + bewildered_daze_2: + id: 449 + flags: + - death + - no_cancel + + bewildered_daze_3: + id: 450 + flags: + - death + - no_cancel + + bewildered_daze_4: + id: 451 + flags: + - death + - no_cancel + + bewildered_daze_5: + id: 452 + flags: + - death + - no_cancel + + divine_caress_i: + id: 453 + name: divine_caress + flags: + - death + - on_zone + - on_jobchange + + saboteur: + id: 454 + flags: + - death + - on_zone + - on_jobchange + + tenuto: + id: 455 + flags: + - death + - on_zone + - on_jobchange + + spur: + id: 456 + flags: + - death + + efflux: + id: 457 + flags: + - death + - on_zone + - on_jobchange + + earthen_armor: + id: 458 + flags: + - death + - on_zone + - on_jobchange + + divine_caress_ii: + id: 459 + name: divine_caress + flags: + - death + - on_zone + - on_jobchange + + blood_rage: + id: 460 + flags: + - death + - on_jobchange + remove: warcry + + impetus: + id: 461 + flags: + - death + - on_zone + - on_jobchange + + conspirator: + id: 462 + flags: + - dispelable + - death + - on_zone + + sepulcher: + id: 463 + flags: + - death + - no_cancel + + arcane_crest: + id: 464 + flags: + - death + - no_cancel + + hamanoha: + id: 465 + flags: + - death + - no_cancel + + dragon_breaker: + id: 466 + flags: + - death + - no_cancel + + triple_shot: + id: 467 + flags: + - death + - on_zone + - on_jobchange + + striking_flourish: + id: 468 + flags: + - death + - on_zone + - on_jobchange + + perpetuance: + id: 469 + flags: + - death + - on_zone + - on_jobchange + + immanence: + id: 470 + flags: + - death + - on_zone + - on_jobchange + + migawari: + id: 471 + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + # DNC 93 + ternary_flourish: + id: 472 + flags: + - death + - on_zone + - on_jobchange + + # MOB EFFECT + muddle: + id: 473 + flags: + - death + - on_zone + - no_cancel + + # GROUNDS OF VALOR + prowess: + id: 474 + flags: + - on_zone + - no_loss_message + - no_cancel + + # VOIDWATCH + voidwatcher: + id: 475 + flags: + - death + - no_cancel + - hide_timer + + # ATMACITE + ensphere: + id: 476 + flags: + - death + - no_cancel + - hide_timer + + # WHM 95 + sacrosanctity: + id: 477 + flags: + - death + - on_zone + - on_jobchange + + # PLD 95 + palisade: + id: 478 + flags: + - death + - on_zone + - on_jobchange + + # DRK 95 + scarlet_delirium: + id: 479 + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + # DRK 95 + scarlet_delirium_1: + id: 480 + name: scarlet_delirium + flags: + - death + - on_zone + - on_jobchange + + abdhaljs_seal: + id: 481 + flags: + - no_cancel + + # RNG 95 + decoy_shot: + id: 482 + flags: + - death + - on_jobchange + exclusion_group: decoy_shot + + # SAM 95 + hagakure: + id: 483 + flags: + - death + - on_zone + - on_jobchange + + # NIN 95 + issekigan: + id: 484 + flags: + - death + - on_zone + - on_jobchange + + # BLU 95 + unbridled_learning: + id: 485 + flags: + - death + - on_zone + - on_jobchange + + # ENDRAIN = 487, -- FENRIR 96 + counter_boost: + id: 486 + flags: + - death + + endrain: + id: 487 + flags: + - death + - on_zone + exclusion_group: enfire + + # FENRIR 96 + enaspir: + id: 488 + flags: + - death + - on_zone + exclusion_group: enfire + + # WS AFTEREFFECT + afterglow: + id: 489 + flags: + - death + - no_cancel + + # INNER_STRENGTH = 491, + brazen_rush: + id: 490 + flags: + - death + - on_zone + - on_jobchange + + inner_strength: + id: 491 + flags: + - death + - on_zone + - on_jobchange + + asylum: + id: 492 + flags: + - death + - on_zone + - on_jobchange + + subtle_sorcery: + id: 493 + flags: + - death + - on_zone + - on_jobchange + + stymie: + id: 494 + flags: + - death + - on_zone + - on_jobchange + + macro_test: + id: 495 + flags: + - death + - on_zone + - no_loss_message + - on_jobchange + - hide_timer + - always_expiring + + intervene: + id: 496 + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + soul_enslavement: + id: 497 + flags: + - death + - on_zone + - on_jobchange + + unleash: + id: 498 + flags: + - death + - on_zone + - on_jobchange + + clarion_call: + id: 499 + flags: + - death + - on_zone + - on_jobchange + + overkill: + id: 500 + flags: + - death + - on_zone + - on_jobchange + + yaegasumi: + id: 501 + flags: + - death + - on_zone + - on_jobchange + + mikage: + id: 502 + flags: + - death + - on_zone + - on_jobchange + + fly_high: + id: 503 + flags: + - death + - on_jobchange + + astral_conduit: + id: 504 + flags: + - death + - on_zone + - on_jobchange + + # NONE = 506, + unbridled_wisdom: + id: 505 + flags: + - death + - on_zone + - on_jobchange + + grace: + id: 506 + flags: + - death + - on_zone + - on_jobchange + - no_cancel + - hide_timer + + grand_pas: + id: 507 + flags: + - death + - on_zone + - on_jobchange + + widened_compass: + id: 508 + flags: + - death + - on_zone + - on_jobchange + + odyllic_subterfuge: + id: 509 + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + ergon_might: + id: 510 + flags: + - death + + reive_mark: + id: 511 + flags: + - death + - confrontation + - no_cancel + - hide_timer + + ionis: + id: 512 + flags: + - no_cancel + - influence + + # NONE = 514, + bolster: + id: 513 + flags: + - death + - on_zone + - on_jobchange + + lasting_emanation: + id: 515 + flags: + - death + - no_cancel + + ecliptic_attrition: + id: 516 + flags: + - death + - no_cancel + + collimated_fervor: + id: 517 + flags: + - death + - on_zone + + dematerialize: + id: 518 + flags: + - death + - no_cancel + + # NONE = 520, + theurgic_focus: + id: 519 + flags: + - death + - on_zone + + elemental_sforzo: + id: 522 + flags: + - death + - on_zone + - on_jobchange + + ignis: + id: 523 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + element: fire + + gelus: + id: 524 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + element: ice + + flabra: + id: 525 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + element: wind + + tellus: + id: 526 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + element: earth + + sulpor: + id: 527 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + element: thunder + + unda: + id: 528 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + element: water + + lux: + id: 529 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + element: light + + tenebrae: + id: 530 + flags: + - death + - on_zone + - no_loss_message + - logout + - on_jobchange + - no_cancel + overwrite: ignore_duplicate + element: dark + + vallation: + id: 531 + flags: + - death + - on_zone + - on_jobchange + + swordplay: + id: 532 + flags: + - death + - on_zone + - on_jobchange + + pflug: + id: 533 + flags: + - death + - on_zone + - on_jobchange + + embolden: + id: 534 + name: emboldened + flags: + - death + - on_zone + - on_jobchange + + valiance: + id: 535 + flags: + - death + - on_zone + - on_jobchange + block: vallation + + gambit: + id: 536 + flags: + - erasable + - death + - no_cancel + overwrite: never + + liement: + id: 537 + flags: + - death + - on_zone + - on_jobchange + + one_for_all: + id: 538 + flags: + - death + - on_zone + - on_jobchange + + geo_regen: + id: 539 + flags: + - death + - no_cancel + - hide_timer + element: light + + geo_poison: + id: 540 + flags: + - death + - no_cancel + - hide_timer + element: water + + geo_refresh: + id: 541 + flags: + - death + - no_cancel + - hide_timer + element: light + + geo_str_boost: + id: 542 + flags: + - death + - no_cancel + - hide_timer + element: fire + + geo_dex_boost: + id: 543 + flags: + - death + - no_cancel + - hide_timer + element: thunder + + geo_vit_boost: + id: 544 + flags: + - death + - no_cancel + - hide_timer + element: earth + + geo_agi_boost: + id: 545 + flags: + - death + - no_cancel + - hide_timer + element: wind + + geo_int_boost: + id: 546 + flags: + - death + - no_cancel + - hide_timer + element: ice + + geo_mnd_boost: + id: 547 + flags: + - death + - no_cancel + - hide_timer + element: water + + geo_chr_boost: + id: 548 + flags: + - death + - no_cancel + - hide_timer + element: light + + geo_attack_boost: + id: 549 + flags: + - death + - no_cancel + - hide_timer + element: fire + + geo_defense_boost: + id: 550 + flags: + - death + - no_cancel + - hide_timer + element: earth + + geo_magic_atk_boost: + id: 551 + flags: + - death + - no_cancel + - hide_timer + element: ice + + geo_magic_def_boost: + id: 552 + flags: + - death + - no_cancel + - hide_timer + element: water + + geo_accuracy_boost: + id: 553 + flags: + - death + - no_cancel + - hide_timer + element: thunder + + geo_evasion_boost: + id: 554 + flags: + - death + - no_cancel + - hide_timer + element: wind + + geo_magic_acc_boost: + id: 555 + flags: + - death + - no_cancel + - hide_timer + element: dark + + geo_magic_evasion_boost: + id: 556 + flags: + - death + - no_cancel + - hide_timer + element: light + + geo_attack_down: + id: 557 + flags: + - death + - no_cancel + - hide_timer + element: water + + geo_defense_down: + id: 558 + flags: + - death + - no_cancel + - hide_timer + element: wind + + geo_magic_atk_down: + id: 559 + flags: + - death + - no_cancel + - hide_timer + element: fire + + geo_magic_def_down: + id: 560 + flags: + - death + - no_cancel + - hide_timer + element: thunder + + geo_accuracy_down: + id: 561 + flags: + - death + - no_cancel + - hide_timer + element: earth + + geo_evasion_down: + id: 562 + flags: + - death + - no_cancel + - hide_timer + element: ice + + geo_magic_acc_down: + id: 563 + flags: + - death + - no_cancel + - hide_timer + element: light + + geo_magic_evasion_down: + id: 564 + flags: + - death + - no_cancel + - hide_timer + element: dark + + geo_slow: + id: 565 + flags: + - death + - no_cancel + - hide_timer + element: earth + + geo_paralysis: + id: 566 + flags: + - death + - no_cancel + - hide_timer + element: ice + + geo_weight: + id: 567 + flags: + - death + - no_cancel + - hide_timer + element: wind + + foil: + id: 568 + flags: + - death + - on_zone + - on_jobchange + + blaze_of_glory: + id: 569 + flags: + - death + - on_zone + - on_jobchange + + battuta: + id: 570 + flags: + - death + - on_zone + - logout + - on_jobchange + + rayke: + id: 571 + flags: + - erasable + - death + - no_cancel + overwrite: never + + avoidance_down: + id: 572 + flags: + - death + - no_cancel + + deluge_spikes: + id: 573 + flags: + - dispelable + - empathy + - death + exclusion_group: blaze_spikes + element: water + sort_key: 800 + + fast_cast: + id: 574 + flags: + - death + + gestation: + id: 575 + flags: + - death + + # Bully: Intimidation Enfeeble status + doubt: + id: 576 + flags: + - death + - no_cancel + wear_off_message_id: 204 + + cait_siths_favor: + id: 577 + flags: + - death + - on_zone + - no_cancel + - hide_timer + + fishy_intuition: + id: 578 + flags: + - death + - on_zone + - no_cancel + + commitment: + id: 579 + flags: + - no_cancel + + geo_haste: + id: 580 + flags: + - death + - no_cancel + - hide_timer + element: wind + + flurry_ii: + id: 581 + flags: + - death + - on_jobchange + + contradance: + id: 582 + flags: + - dispelable + - death + - on_zone + - on_jobchange + + apogee: + id: 583 + flags: + - dispelable + - death + - on_zone + - bloodpact + - no_cancel + + entrust: + id: 584 + flags: + - death + - on_zone + - on_jobchange + + costume_ii: + id: 585 + name: costume + flags: + - death + - on_zone + - no_cancel + wear_off_message_id: 204 + + curing_conduit: + id: 586 + flags: + - death + - on_zone + + tp_bonus: + id: 587 + flags: + - death + - on_zone + + finishing_move_6: + id: 588 + name: finishing_move + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + firestorm_ii: + id: 589 + flags: + - death + - on_zone + - on_jobchange + + hailstorm_ii: + id: 590 + flags: + - death + - on_zone + - on_jobchange + + windstorm_ii: + id: 591 + flags: + - death + - on_zone + - on_jobchange + + sandstorm_ii: + id: 592 + flags: + - death + - on_zone + - on_jobchange + + thunderstorm_ii: + id: 593 + flags: + - death + - on_zone + - on_jobchange + + rainstorm_ii: + id: 594 + flags: + - death + - on_zone + - on_jobchange + + aurorastorm_ii: + id: 595 + flags: + - death + - on_zone + - on_jobchange + + voidstorm_ii: + id: 596 + flags: + - death + - on_zone + - on_jobchange + + inundation: + id: 597 + flags: + - death + - no_cancel + + cascade: + id: 598 + flags: + - death + - on_zone + - on_jobchange + + consume_mana: + id: 599 + flags: + - dispelable + - death + - on_zone + + runeists_roll: + id: 600 + flags: + - empathy + - death + - on_zone + - roll + - no_cancel + + crooked_cards: + id: 601 + flags: + - death + - on_zone + - on_jobchange + + vorseal: + id: 602 + flags: + - death + - no_cancel + - hide_timer + + elvorseal: + id: 603 + flags: + - death + - no_cancel + - hide_timer + + mighty_guard: + id: 604 + flags: + - death + - on_zone + - on_jobchange + + gale_spikes: + id: 605 + flags: + - dispelable + - empathy + - death + exclusion_group: blaze_spikes + element: wind + sort_key: 800 + + clod_spikes: + id: 606 + flags: + - dispelable + - empathy + - death + exclusion_group: blaze_spikes + element: earth + sort_key: 800 + + glint_spikes: + id: 607 + flags: + - dispelable + - empathy + - death + exclusion_group: blaze_spikes + element: light + sort_key: 800 + + negate_virus: + id: 608 + flags: + - dispelable + - death + - on_zone + + negate_curse: + id: 609 + flags: + - dispelable + - death + - on_zone + + negate_charm: + id: 610 + flags: + - dispelable + - death + - on_zone + + magic_evasion_boost: + id: 611 + name: magic_evasion_boost_ii + flags: + - death + + colure_active: + id: 612 + flags: + - on_zone + - logout + - no_cancel + overwrite: always + + mumors_radiance: + id: 613 + flags: + - death + - on_zone + - on_jobchange + + ullegores_gloom: + id: 614 + flags: + - death + - no_cancel + - hide_timer + + boost_ii: + id: 615 + flags: + - attack + - empathy + - death + - on_jobchange + + artisanal_knowledge: + id: 616 + flags: + - no_cancel + + sacrifice: + id: 617 + flags: + - dispelable + - death + - on_zone + - on_jobchange + + emporoxs_gift: + id: 618 + flags: + - no_cancel + + spirit_bond: + id: 619 + flags: + - dispelable + - empathy + - death + - on_zone + - logout + - on_jobchange + + awaken: + id: 620 + flags: + - death + - on_zone + - on_jobchange + - no_cancel + + majesty: + id: 621 + flags: + - dispelable + - death + - on_zone + + guarding_rate_boost: + id: 622 + flags: + - dispelable + - empathy + - death + + rampart: + id: 623 + flags: + - death + - on_zone + - logout + - on_jobchange + + winds_blessing: + id: 624 + flags: + - dispelable + - death + - on_zone + - on_jobchange + - no_cancel + + sirens_favor: + id: 625 + flags: + - death + - on_zone + - no_cancel + - hide_timer + + negate_sleep: + id: 626 + flags: + - dispelable + - death + - on_zone + + mobilization: + id: 627 + flags: + - death + - on_zone + - on_jobchange + - on_attack + + hover_shot: + id: 628 + flags: + - dispelable + - death + - on_zone + exclusion_group: decoy_shot + + moogle_amplifier: + id: 629 + flags: + - no_cancel + + taint: + id: 630 + flags: + - death + - no_cancel + + haunt: + id: 631 + flags: + - death + - no_cancel + + black_sanctus: + id: 632 + flags: + - death + - no_cancel + + animated: + id: 633 + flags: + - death + - on_zone + - no_cancel + + serpents_guile: + id: 634 + flags: + - death + - on_zone + - no_cancel + + # Effect icons in packet can go from 0-767, so no custom effects should go in that range. + resolved: + id: 635 + flags: + - on_zone + - no_cancel + + abyssea_str: + id: 768 + flags: + - on_zone + element: fire + + abyssea_dex: + id: 769 + flags: + - on_zone + element: thunder + + abyssea_vit: + id: 770 + flags: + - on_zone + element: earth + + abyssea_agi: + id: 771 + flags: + - on_zone + element: wind + + abyssea_int: + id: 772 + flags: + - on_zone + element: ice + + abyssea_mnd: + id: 773 + flags: + - on_zone + element: water + + abyssea_chr: + id: 774 + flags: + - on_zone + element: light + + abyssea_hp: + id: 775 + flags: + - on_zone + element: light + + # *Prowess increases not currently retail accurate. + abyssea_mp: + id: 776 + flags: + - on_zone + element: dark + + # (Unimplemented) + prowess_casket_rate: + id: 777 + flags: + - on_zone + - no_loss_message + + # (Unimplemented) + prowess_skill_rate: + id: 778 + flags: + - on_zone + - no_loss_message + + # (Unimplemented) + prowess_crystal_yield: + id: 779 + name: prowess_crystal_yeild + flags: + - on_zone + - no_loss_message + + # +1 per tier + prowess_th: + id: 780 + flags: + - on_zone + - no_loss_message + + # *flat 4% for now + prowess_attack_speed: + id: 781 + flags: + - on_zone + - no_loss_message + + # Base 3% and another 1% per tier. + prowess_hp_mp: + id: 782 + flags: + - on_zone + - no_loss_message + + # *flat 4% for now + prowess_acc_racc: + id: 783 + flags: + - on_zone + - no_loss_message + + # *flat 4% for now + prowess_att_ratt: + id: 784 + flags: + - on_zone + - no_loss_message + + # *flat 4% for now + prowess_macc_matk: + id: 785 + flags: + - on_zone + - no_loss_message + + # *flat 4% for now + prowess_cure_potency: + id: 786 + flags: + - on_zone + - no_loss_message + + # (Unimplemented) 2% per tier. + prowess_ws_dmg: + id: 787 + flags: + - on_zone + - no_loss_message + + # *flat +4 for now + prowess_killer: + id: 788 + flags: + - on_zone + - no_loss_message + + # Tracks 30 min timer in ACP mission "Those Who Lurk in Shadows (II)" + mark_of_seed: + id: 790 + flags: + - on_zone + - no_loss_message + + # Indicates a target is unable to be hit by normal melee attacks (formerly TOO_HIGH) + all_miss: + id: 791 + flags: + - death + + super_buff: + id: 792 + flags: + - death + + ninjutsu_ele_debuff: + id: 793 + flags: + - death + - no_loss_message + + healing: + id: 794 + flags: + - attack + - damage + - death + - magic_begin + - on_zone + - logout + + leavegame: + id: 795 + flags: + - attack + - damage + - death + - magic_begin + - on_zone + - logout + + haste_samba_haste: + id: 796 + flags: + - magic_begin + - on_zone + + teleport: + id: 797 + flags: + - death + - on_jobchange + + chainbound: + id: 798 + flags: + - death + + skillchain: + id: 799 + flags: + - death + + dynamis: + id: 800 + flags: + - offline_tick + + # Dummy effect for SAM Meditate JA + meditate: + id: 801 + flags: + - death + - on_zone + element: light + + # Elemental resistance down + elementalres_down: + id: 802 + name: elemental_resistance_down + flags: + - death + - on_zone + - no_loss_message + - no_cancel + + # Helper for quest: Full Speed Ahead! + full_speed_ahead: + id: 803 + flags: + - on_zone + - no_loss_message + + # Silent status effect inflicted by a Warrior using the "Tomahawk" job ability + tomahawk: + id: 805 + flags: + - death + - no_loss_message + + # CHR Aura, +9.7% Defense Bonus, +5 Magic Defense Bonus and +5 CHR at lv. 99, stacks with player Indi/Geo CHR. + trust_aura_chr: + id: 807 + flags: + - death + - no_cancel + - hide_timer + + # HASTE Aura, Haste +20%, Accuracy +30, Ranged Accuracy +30 and Magic Accuracy +30 at lvl 99, stacks with player Indi/Geo HASTE. + trust_aura_haste: + id: 808 + flags: + - death + - no_cancel + - hide_timer + + # EXP Aura, +20% dedication effect for Experience Points and Capacity Points, stacks with other forms of dedication. + trust_aura_exp: + id: 809 + flags: + - death + - no_cancel + + # ACC Aura, Accuracy+24, Ranged accuracy+24, and DEX+5 at lvl 99, stacks with player Indi/Geo PRECISION. + trust_aura_acc: + id: 810 + flags: + - death + - no_cancel + - hide_timer + + # REFRESH Aura, 3 MP/tick at lvl 99 stacks with player Indi/Geo REFRESH, also grants an increase to magical skill gain rate. + trust_aura_refresh: + id: 811 + flags: + - death + - no_cancel + - hide_timer + + # REGEN Aura, 6 HP/tick at lvl 99 stacks with player Indi/Geo REGEN. also grants an increase to physical combat skill gain rate. + trust_aura_regen: + id: 812 + flags: + - death + - no_cancel + - hide_timer + + # MATT Aura, Magic Attack Boost +19 and +19 Magic Accuracy boost at lvl 99, stacks with player Indi/Geo ACUMEN. + trust_aura_magic_attack: + id: 813 + flags: + - death + - no_cancel + - hide_timer + + # Not a retail effect + na: + id: 232 + + # Not a retail effect + none: + id: 255 + + # Used for Hysteroanima to stop after readying a weaponskill with no msg. + hysteria: + id: 804 + + # Custom effect for NM type mobs only. + nuke_wall: + id: 806 diff --git a/scripts/enum/effect.lua b/scripts/enum/effect.lua deleted file mode 100644 index 8e684c20f6c..00000000000 --- a/scripts/enum/effect.lua +++ /dev/null @@ -1,696 +0,0 @@ ------------------------------------ --- Status Effects ------------------------------------ -xi = xi or {} - ----@enum xi.effect -xi.effect = -{ - KO = 0, - WEAKNESS = 1, - SLEEP_I = 2, - POISON = 3, - PARALYSIS = 4, - BLINDNESS = 5, - SILENCE = 6, - PETRIFICATION = 7, - DISEASE = 8, - CURSE_I = 9, - STUN = 10, - BIND = 11, - WEIGHT = 12, - SLOW = 13, - CHARM_I = 14, - DOOM = 15, - AMNESIA = 16, - CHARM_II = 17, - GRADUAL_PETRIFICATION = 18, - SLEEP_II = 19, - CURSE_II = 20, -- Zombie - ADDLE = 21, - INTIMIDATE = 22, - KAUSTRA = 23, - TERROR = 28, - MUTE = 29, - BANE = 30, - PLAGUE = 31, - FLEE = 32, - HASTE = 33, - BLAZE_SPIKES = 34, - ICE_SPIKES = 35, - BLINK = 36, - STONESKIN = 37, - SHOCK_SPIKES = 38, - AQUAVEIL = 39, - PROTECT = 40, - SHELL = 41, - REGEN = 42, - REFRESH = 43, - MIGHTY_STRIKES = 44, - BOOST = 45, - HUNDRED_FISTS = 46, - MANAFONT = 47, - CHAINSPELL = 48, - PERFECT_DODGE = 49, - INVINCIBLE = 50, - BLOOD_WEAPON = 51, - SOUL_VOICE = 52, - EAGLE_EYE_SHOT = 53, - MEIKYO_SHISUI = 54, - ASTRAL_FLOW = 55, - BERSERK = 56, - DEFENDER = 57, - AGGRESSOR = 58, - FOCUS = 59, - DODGE = 60, - COUNTERSTANCE = 61, - SENTINEL = 62, - SOULEATER = 63, - LAST_RESORT = 64, - SNEAK_ATTACK = 65, - COPY_IMAGE = 66, - THIRD_EYE = 67, - WARCRY = 68, - INVISIBLE = 69, - DEODORIZE = 70, - SNEAK = 71, - SHARPSHOT = 72, - BARRAGE = 73, - HOLY_CIRCLE = 74, - ARCANE_CIRCLE = 75, - HIDE = 76, - CAMOUFLAGE = 77, - DIVINE_SEAL = 78, - ELEMENTAL_SEAL = 79, - STR_BOOST = 80, - DEX_BOOST = 81, - VIT_BOOST = 82, - AGI_BOOST = 83, - INT_BOOST = 84, - MND_BOOST = 85, - CHR_BOOST = 86, - TRICK_ATTACK = 87, - MAX_HP_BOOST = 88, - MAX_MP_BOOST = 89, - ACCURACY_BOOST = 90, - ATTACK_BOOST = 91, - EVASION_BOOST = 92, - DEFENSE_BOOST = 93, - ENFIRE = 94, - ENBLIZZARD = 95, - ENAERO = 96, - ENSTONE = 97, - ENTHUNDER = 98, - ENWATER = 99, - BARFIRE = 100, - BARBLIZZARD = 101, - BARAERO = 102, - BARSTONE = 103, - BARTHUNDER = 104, - BARWATER = 105, - BARSLEEP = 106, - BARPOISON = 107, - BARPARALYZE = 108, - BARBLIND = 109, - BARSILENCE = 110, - BARPETRIFY = 111, - BARVIRUS = 112, - RERAISE = 113, - COVER = 114, - UNLIMITED_SHOT = 115, - PHALANX = 116, - WARDING_CIRCLE = 117, - ANCIENT_CIRCLE = 118, - STR_BOOST_II = 119, - DEX_BOOST_II = 120, - VIT_BOOST_II = 121, - AGI_BOOST_II = 122, - INT_BOOST_II = 123, - MND_BOOST_II = 124, - CHR_BOOST_II = 125, - SPIRIT_SURGE = 126, - COSTUME = 127, - BURN = 128, - FROST = 129, - CHOKE = 130, - RASP = 131, - SHOCK = 132, - DROWN = 133, - DIA = 134, - BIO = 135, - STR_DOWN = 136, - DEX_DOWN = 137, - VIT_DOWN = 138, - AGI_DOWN = 139, - INT_DOWN = 140, - MND_DOWN = 141, - CHR_DOWN = 142, - LEVEL_RESTRICTION = 143, - MAX_HP_DOWN = 144, - MAX_MP_DOWN = 145, - ACCURACY_DOWN = 146, - ATTACK_DOWN = 147, - EVASION_DOWN = 148, - DEFENSE_DOWN = 149, - PHYSICAL_SHIELD = 150, - ARROW_SHIELD = 151, - MAGIC_SHIELD = 152, - DAMAGE_SPIKES = 153, - SHINING_RUBY = 154, - MEDICINE = 155, - FLASH = 156, - SJ_RESTRICTION = 157, - PROVOKE = 158, - PENALTY = 159, - PREPARATIONS = 160, - SPRINT = 161, - ENCHANTMENT = 162, - AZURE_LORE = 163, - CHAIN_AFFINITY = 164, - BURST_AFFINITY = 165, - OVERDRIVE = 166, - MAGIC_DEF_DOWN = 167, - INHIBIT_TP = 168, - POTENCY = 169, - REGAIN = 170, - PAX = 171, - INTENSION = 172, - DREAD_SPIKES = 173, - MAGIC_ACC_DOWN = 174, - MAGIC_ATK_DOWN = 175, - QUICKENING = 176, - ENCUMBRANCE_II = 177, - FIRESTORM = 178, - HAILSTORM = 179, - WINDSTORM = 180, - SANDSTORM = 181, - THUNDERSTORM = 182, - RAINSTORM = 183, - AURORASTORM = 184, - VOIDSTORM = 185, - HELIX = 186, - SUBLIMATION_ACTIVATED = 187, - SUBLIMATION_COMPLETE = 188, - MAX_TP_DOWN = 189, - MAGIC_ATK_BOOST = 190, - MAGIC_DEF_BOOST = 191, - REQUIEM = 192, - LULLABY = 193, - ELEGY = 194, - PAEON = 195, - BALLAD = 196, - MINNE = 197, - MINUET = 198, - MADRIGAL = 199, - PRELUDE = 200, - MAMBO = 201, - AUBADE = 202, - PASTORAL = 203, - HUM = 204, - FANTASIA = 205, - OPERETTA = 206, - CAPRICCIO = 207, - SERENADE = 208, - ROUND = 209, - GAVOTTE = 210, - FUGUE = 211, - RHAPSODY = 212, - ARIA = 213, - MARCH = 214, - ETUDE = 215, - CAROL = 216, - THRENODY = 217, - HYMNUS = 218, - MAZURKA = 219, - SIRVENTE = 220, - DIRGE = 221, - SCHERZO = 222, - NOCTURNE = 223, - STORE_TP = 227, - EMBRAVA = 228, - MANAWELL = 229, - SPONTANEITY = 230, - MARCATO = 231, - NA = 232, - AUTO_REGEN = 233, - AUTO_REFRESH = 234, - FISHING_IMAGERY = 235, - WOODWORKING_IMAGERY = 236, - SMITHING_IMAGERY = 237, - GOLDSMITHING_IMAGERY = 238, - CLOTHCRAFT_IMAGERY = 239, - LEATHERCRAFT_IMAGERY = 240, - BONECRAFT_IMAGERY = 241, - ALCHEMY_IMAGERY = 242, - COOKING_IMAGERY = 243, - IMAGERY_1 = 244, - IMAGERY_2 = 245, - IMAGERY_3 = 246, - IMAGERY_4 = 247, - IMAGERY_5 = 248, - DEDICATION = 249, - EF_BADGE = 250, - FOOD = 251, - MOUNTED = 252, - SIGNET = 253, - BATTLEFIELD = 254, - NONE = 255, - SANCTION = 256, - BESIEGED = 257, - ILLUSION = 258, - ENCUMBRANCE_I = 259, - OBLIVISCENCE = 260, - IMPAIRMENT = 261, - OMERTA = 262, - DEBILITATION = 263, - PATHOS = 264, - FLURRY = 265, - CONCENTRATION = 266, - ALLIED_TAGS = 267, - SIGIL = 268, - LEVEL_SYNC = 269, - AFTERMATH_LV1 = 270, - AFTERMATH_LV2 = 271, - AFTERMATH_LV3 = 272, - AFTERMATH = 273, - ENLIGHT = 274, - AUSPICE = 275, - CONFRONTATION = 276, - ENFIRE_II = 277, - ENBLIZZARD_II = 278, - ENAERO_II = 279, - ENSTONE_II = 280, - ENTHUNDER_II = 281, - ENWATER_II = 282, - PERFECT_DEFENSE = 283, - EGG = 284, - VISITANT = 285, - BARAMNESIA = 286, - ATMA = 287, - ENDARK = 288, - ENMITY_BOOST = 289, - SUBTLE_BLOW_PLUS = 290, - ENMITY_DOWN = 291, - PENNANT = 292, - NEGATE_PETRIFY = 293, - NEGATE_TERROR = 294, - NEGATE_AMNESIA = 295, - NEGATE_DOOM = 296, - NEGATE_POISON = 297, - CRIT_HIT_EVASION_DOWN = 298, - OVERLOAD = 299, - FIRE_MANEUVER = 300, - ICE_MANEUVER = 301, - WIND_MANEUVER = 302, - EARTH_MANEUVER = 303, - THUNDER_MANEUVER = 304, - WATER_MANEUVER = 305, - LIGHT_MANEUVER = 306, - DARK_MANEUVER = 307, - DOUBLE_UP_CHANCE = 308, - BUST = 309, - FIGHTERS_ROLL = 310, - MONKS_ROLL = 311, - HEALERS_ROLL = 312, - WIZARDS_ROLL = 313, - WARLOCKS_ROLL = 314, - ROGUES_ROLL = 315, - GALLANTS_ROLL = 316, - CHAOS_ROLL = 317, - BEAST_ROLL = 318, - CHORAL_ROLL = 319, - HUNTERS_ROLL = 320, - SAMURAI_ROLL = 321, - NINJA_ROLL = 322, - DRACHEN_ROLL = 323, - EVOKERS_ROLL = 324, - MAGUSS_ROLL = 325, - CORSAIRS_ROLL = 326, - PUPPET_ROLL = 327, - DANCERS_ROLL = 328, - SCHOLARS_ROLL = 329, - BOLTERS_ROLL = 330, - CASTERS_ROLL = 331, - COURSERS_ROLL = 332, - BLITZERS_ROLL = 333, - TACTICIANS_ROLL = 334, - ALLIES_ROLL = 335, - MISERS_ROLL = 336, - COMPANIONS_ROLL = 337, - AVENGERS_ROLL = 338, - NATURALISTS_ROLL = 339, - WARRIORS_CHARGE = 340, - FORMLESS_STRIKES = 341, - ASSASSINS_CHARGE = 342, - FEINT = 343, - FEALTY = 344, - DARK_SEAL = 345, - DIABOLIC_EYE = 346, - NIGHTINGALE = 347, - TROUBADOUR = 348, - KILLER_INSTINCT = 349, - STEALTH_SHOT = 350, - FLASHY_SHOT = 351, - SANGE = 352, - HASSO = 353, - SEIGAN = 354, - CONVERGENCE = 355, - DIFFUSION = 356, - SNAKE_EYE = 357, - LIGHT_ARTS = 358, - DARK_ARTS = 359, - PENURY = 360, - PARSIMONY = 361, - CELERITY = 362, - ALACRITY = 363, - RAPTURE = 364, - EBULLIENCE = 365, - ACCESSION = 366, - MANIFESTATION = 367, - DRAIN_SAMBA = 368, - ASPIR_SAMBA = 369, - HASTE_SAMBA = 370, - VELOCITY_SHOT = 371, - BUILDING_FLOURISH = 375, - TRANCE = 376, - TABULA_RASA = 377, - DRAIN_DAZE = 378, - ASPIR_DAZE = 379, - HASTE_DAZE = 380, - FINISHING_MOVE_1 = 381, - FINISHING_MOVE_2 = 382, - FINISHING_MOVE_3 = 383, - FINISHING_MOVE_4 = 384, - FINISHING_MOVE_5 = 385, - LETHARGIC_DAZE_1 = 386, - LETHARGIC_DAZE_2 = 387, - LETHARGIC_DAZE_3 = 388, - LETHARGIC_DAZE_4 = 389, - LETHARGIC_DAZE_5 = 390, - SLUGGISH_DAZE_1 = 391, - SLUGGISH_DAZE_2 = 392, - SLUGGISH_DAZE_3 = 393, - SLUGGISH_DAZE_4 = 394, - SLUGGISH_DAZE_5 = 395, - WEAKENED_DAZE_1 = 396, - WEAKENED_DAZE_2 = 397, - WEAKENED_DAZE_3 = 398, - WEAKENED_DAZE_4 = 399, - WEAKENED_DAZE_5 = 400, - ADDENDUM_WHITE = 401, - ADDENDUM_BLACK = 402, - REPRISAL = 403, - MAGIC_EVASION_DOWN = 404, - RETALIATION = 405, - FOOTWORK = 406, - KLIMAFORM = 407, - SEKKANOKI = 408, - PIANISSIMO = 409, - SABER_DANCE = 410, - FAN_DANCE = 411, - ALTRUISM = 412, - FOCALIZATION = 413, - TRANQUILITY = 414, - EQUANIMITY = 415, - ENLIGHTENMENT = 416, - AFFLATUS_SOLACE = 417, - AFFLATUS_MISERY = 418, - COMPOSURE = 419, - YONIN = 420, - INNIN = 421, - CARBUNCLES_FAVOR = 422, - IFRITS_FAVOR = 423, - SHIVAS_FAVOR = 424, - GARUDAS_FAVOR = 425, - TITANS_FAVOR = 426, - RAMUHS_FAVOR = 427, - LEVIATHANS_FAVOR = 428, - FENRIRS_FAVOR = 429, - DIABOLOSS_FAVOR = 430, - AVATARS_FAVOR = 431, - MULTI_STRIKES = 432, - DOUBLE_SHOT = 433, - TRANSCENDENCY = 434, - RESTRAINT = 435, - PERFECT_COUNTER = 436, - MANA_WALL = 437, - DIVINE_EMBLEM = 438, - NETHER_VOID = 439, - SENGIKORI = 440, - FUTAE = 441, - PRESTO = 442, - CLIMACTIC_FLOURISH = 443, - COPY_IMAGE_2 = 444, - COPY_IMAGE_3 = 445, - COPY_IMAGE_4 = 446, - MULTI_SHOTS = 447, - BEWILDERED_DAZE_1 = 448, - BEWILDERED_DAZE_2 = 449, - BEWILDERED_DAZE_3 = 450, - BEWILDERED_DAZE_4 = 451, - BEWILDERED_DAZE_5 = 452, - DIVINE_CARESS_I = 453, - SABOTEUR = 454, - TENUTO = 455, - SPUR = 456, - EFFLUX = 457, - EARTHEN_ARMOR = 458, - DIVINE_CARESS_II = 459, - BLOOD_RAGE = 460, - IMPETUS = 461, - CONSPIRATOR = 462, - SEPULCHER = 463, - ARCANE_CREST = 464, - HAMANOHA = 465, - DRAGON_BREAKER = 466, - TRIPLE_SHOT = 467, - STRIKING_FLOURISH = 468, - PERPETUANCE = 469, - IMMANENCE = 470, - MIGAWARI = 471, - TERNARY_FLOURISH = 472, -- DNC 93 - MUDDLE = 473, -- MOB EFFECT - PROWESS = 474, -- GROUNDS OF VALOR - VOIDWATCHER = 475, -- VOIDWATCH - ENSPHERE = 476, -- ATMACITE - SACROSANCTITY = 477, -- WHM 95 - PALISADE = 478, -- PLD 95 - SCARLET_DELIRIUM = 479, -- DRK 95 - SCARLET_DELIRIUM_1 = 480, -- DRK 95 - ABDHALJS_SEAL = 481, - DECOY_SHOT = 482, -- RNG 95 - HAGAKURE = 483, -- SAM 95 - ISSEKIGAN = 484, -- NIN 95 - UNBRIDLED_LEARNING = 485, -- BLU 95 - COUNTER_BOOST = 486, -- - ENDRAIN = 487, -- FENRIR 96 - ENASPIR = 488, -- FENRIR 96 - AFTERGLOW = 489, -- WS AFTEREFFECT - BRAZEN_RUSH = 490, -- - INNER_STRENGTH = 491, - ASYLUM = 492, - SUBTLE_SORCERY = 493, - STYMIE = 494, - MACRO_TEST = 495, - INTERVENE = 496, - SOUL_ENSLAVEMENT = 497, - UNLEASH = 498, - CLARION_CALL = 499, - OVERKILL = 500, - YAEGASUMI = 501, - MIKAGE = 502, - FLY_HIGH = 503, - ASTRAL_CONDUIT = 504, - UNBRIDLED_WISDOM = 505, - -- NONE = 506, - GRAND_PAS = 507, - WIDENED_COMPASS = 508, - ODYLLIC_SUBTERFUGE = 509, - ERGON_MIGHT = 510, - REIVE_MARK = 511, - IONIS = 512, - BOLSTER = 513, - -- NONE = 514, - LASTING_EMANATION = 515, - ECLIPTIC_ATTRITION = 516, - COLLIMATED_FERVOR = 517, - DEMATERIALIZE = 518, - THEURGIC_FOCUS = 519, - -- NONE = 520, - -- NONE = 521, - ELEMENTAL_SFORZO = 522, - IGNIS = 523, - GELUS = 524, - FLABRA = 525, - TELLUS = 526, - SULPOR = 527, - UNDA = 528, - LUX = 529, - TENEBRAE = 530, - VALLATION = 531, - SWORDPLAY = 532, - PFLUG = 533, - EMBOLDEN = 534, - VALIANCE = 535, - GAMBIT = 536, - LIEMENT = 537, - ONE_FOR_ALL = 538, - GEO_REGEN = 539, - GEO_POISON = 540, - GEO_REFRESH = 541, - GEO_STR_BOOST = 542, - GEO_DEX_BOOST = 543, - GEO_VIT_BOOST = 544, - GEO_AGI_BOOST = 545, - GEO_INT_BOOST = 546, - GEO_MND_BOOST = 547, - GEO_CHR_BOOST = 548, - GEO_ATTACK_BOOST = 549, - GEO_DEFENSE_BOOST = 550, - GEO_MAGIC_ATK_BOOST = 551, - GEO_MAGIC_DEF_BOOST = 552, - GEO_ACCURACY_BOOST = 553, - GEO_EVASION_BOOST = 554, - GEO_MAGIC_ACC_BOOST = 555, - GEO_MAGIC_EVASION_BOOST = 556, - GEO_ATTACK_DOWN = 557, - GEO_DEFENSE_DOWN = 558, - GEO_MAGIC_ATK_DOWN = 559, - GEO_MAGIC_DEF_DOWN = 560, - GEO_ACCURACY_DOWN = 561, - GEO_EVASION_DOWN = 562, - GEO_MAGIC_ACC_DOWN = 563, - GEO_MAGIC_EVASION_DOWN = 564, - GEO_SLOW = 565, - GEO_PARALYSIS = 566, - GEO_WEIGHT = 567, - FOIL = 568, - BLAZE_OF_GLORY = 569, - BATTUTA = 570, - RAYKE = 571, - AVOIDANCE_DOWN = 572, - DELUGE_SPIKES = 573, - FAST_CAST = 574, - GESTATION = 575, - DOUBT = 576, -- Bully: Intimidation Enfeeble status - CAIT_SITHS_FAVOR = 577, - FISHY_INTUITION = 578, - COMMITMENT = 579, - GEO_HASTE = 580, - FLURRY_II = 581, - CONTRADANCE = 582, - APOGEE = 583, - ENTRUST = 584, - COSTUME_II = 585, - CURING_CONDUIT = 586, - TP_BONUS = 587, - FINISHING_MOVE_6 = 588, - FIRESTORM_II = 589, - HAILSTORM_II = 590, - WINDSTORM_II = 591, - SANDSTORM_II = 592, - THUNDERSTORM_II = 593, - RAINSTORM_II = 594, - AURORASTORM_II = 595, - VOIDSTORM_II = 596, - INUNDATION = 597, - CASCADE = 598, - CONSUME_MANA = 599, - RUNEISTS_ROLL = 600, - CROOKED_CARDS = 601, - VORSEAL = 602, - ELVORSEAL = 603, - MIGHTY_GUARD = 604, - GALE_SPIKES = 605, - CLOD_SPIKES = 606, - GLINT_SPIKES = 607, - NEGATE_VIRUS = 608, - NEGATE_CURSE = 609, - NEGATE_CHARM = 610, - MAGIC_EVASION_BOOST = 611, - COLURE_ACTIVE = 612, - MUMORS_RADIANCE = 613, - ULLEGORES_GLOOM = 614, - BOOST_II = 615, - ARTISANAL_KNOWLEDGE = 616, - SACRIFICE = 617, - EMPOROXS_GIFT = 618, - SPIRIT_BOND = 619, - AWAKEN = 620, - MAJESTY = 621, - GUARDING_RATE_BOOST = 622, - RAMPART = 623, - WINDS_BLESSING = 624, - SIRENS_FAVOR = 625, - NEGATE_SLEEP = 626, - MOBILIZATION = 627, - HOVER_SHOT = 628, - MOOGLE_AMPLIFIER = 629, - TAINT = 630, - HAUNT = 631, - BLACK_SANCTUS = 632, - ANIMATED = 633, - SERPENTS_GUILE = 634, - RESOLVED = 635, - - -- Effect icons in packet can go from 0-767, so no custom effects should go in that range. - - -- Purchased from Cruor Prospector - ABYSSEA_STR = 768, - ABYSSEA_DEX = 769, - ABYSSEA_VIT = 770, - ABYSSEA_AGI = 771, - ABYSSEA_INT = 772, - ABYSSEA_MND = 773, - ABYSSEA_CHR = 774, - ABYSSEA_HP = 775, - ABYSSEA_MP = 776, - - -- *Prowess increases not currently retail accurate. - -- GoV Prowess bonus effects, real effect at ID 474 - PROWESS_CASKET_RATE = 777, -- (Unimplemented) - PROWESS_SKILL_RATE = 778, -- (Unimplemented) - PROWESS_CRYSTAL_YIELD = 779, -- (Unimplemented) - PROWESS_TH = 780, -- +1 per tier - PROWESS_ATTACK_SPEED = 781, -- *flat 4% for now - PROWESS_HP_MP = 782, -- Base 3% and another 1% per tier. - PROWESS_ACC_RACC = 783, -- *flat 4% for now - PROWESS_ATT_RATT = 784, -- *flat 4% for now - PROWESS_MACC_MATK = 785, -- *flat 4% for now - PROWESS_CURE_POTENCY = 786, -- *flat 4% for now - PROWESS_WS_DMG = 787, -- (Unimplemented) 2% per tier. - PROWESS_KILLER = 788, -- *flat +4 for now - -- End GoV Prowess fakery - - MARK_OF_SEED = 790, -- Tracks 30 min timer in ACP mission "Those Who Lurk in Shadows (II)" - ALL_MISS = 791, -- Indicates a target is unable to be hit by normal melee attacks (formerly TOO_HIGH) - SUPER_BUFF = 792, - NINJUTSU_ELE_DEBUFF = 793, - HEALING = 794, - LEAVEGAME = 795, - HASTE_SAMBA_HASTE = 796, - TELEPORT = 797, - CHAINBOUND = 798, - SKILLCHAIN = 799, - DYNAMIS = 800, - MEDITATE = 801, -- Dummy effect for SAM Meditate JA - ELEMENTALRES_DOWN = 802, -- Elemental resistance down - FULL_SPEED_AHEAD = 803, -- Helper for quest: Full Speed Ahead! - HYSTERIA = 804, -- Used for Hysteroanima to stop after readying a weaponskill with no msg. - TOMAHAWK = 805, -- Silent status effect inflicted by a Warrior using the "Tomahawk" job ability - NUKE_WALL = 806, -- Custom effect for NM type mobs only. - - -- TRUST Aura Effects - TRUST_AURA_CHR = 807, -- CHR Aura, +9.7% Defense Bonus, +5 Magic Defense Bonus and +5 CHR at lv. 99, stacks with player Indi/Geo CHR. - TRUST_AURA_HASTE = 808, -- HASTE Aura, Haste +20%, Accuracy +30, Ranged Accuracy +30 and Magic Accuracy +30 at lvl 99, stacks with player Indi/Geo HASTE. - TRUST_AURA_EXP = 809, -- EXP Aura, +20% dedication effect for Experience Points and Capacity Points, stacks with other forms of dedication. - TRUST_AURA_ACC = 810, -- ACC Aura, Accuracy+24, Ranged accuracy+24, and DEX+5 at lvl 99, stacks with player Indi/Geo PRECISION. - TRUST_AURA_REFRESH = 811, -- REFRESH Aura, 3 MP/tick at lvl 99 stacks with player Indi/Geo REFRESH, also grants an increase to magical skill gain rate. - TRUST_AURA_REGEN = 812, -- REGEN Aura, 6 HP/tick at lvl 99 stacks with player Indi/Geo REGEN. also grants an increase to physical combat skill gain rate. - TRUST_AURA_MAGIC_ATTACK = 813, -- MATT Aura, Magic Attack Boost +19 and +19 Magic Accuracy boost at lvl 99, stacks with player Indi/Geo ACUMEN. - -- End of Trust Aura Effects - - -- 789 - -- 813-1022 - -- PLACEHOLDER = 1023 -- The client dat file seems to have only this many "slots", results of exceeding that are untested. -} diff --git a/scripts/enum/effect_flag.lua b/scripts/enum/effect_flag.lua deleted file mode 100644 index db36351e351..00000000000 --- a/scripts/enum/effect_flag.lua +++ /dev/null @@ -1,40 +0,0 @@ ------------------------------------ --- Effect Flags ------------------------------------ -xi = xi or {} - ----@enum xi.effectFlag -xi.effectFlag = -{ - NONE = 0x00000000, - DISPELABLE = 0x00000001, - ERASABLE = 0x00000002, - ATTACK = 0x00000004, - EMPATHY = 0x00000008, - DAMAGE = 0x00000010, - DEATH = 0x00000020, - MAGIC_BEGIN = 0x00000040, - MAGIC_END = 0x00000080, - ON_ZONE = 0x00000100, - NO_LOSS_MESSAGE = 0x00000200, - INVISIBLE = 0x00000400, - DETECTABLE = 0x00000800, - NO_REST = 0x00001000, - PREVENT_ACTION = 0x00002000, - WALTZABLE = 0x00004000, - FOOD = 0x00008000, - SONG = 0x00010000, - ROLL = 0x00020000, - SYNTH_SUPPORT = 0x00040000, - CONFRONTATION = 0x00080000, - LOGOUT = 0x00100000, - BLOODPACT = 0x00200000, - ON_JOBCHANGE = 0x00400000, - NO_CANCEL = 0x00800000, - INFLUENCE = 0x01000000, - OFFLINE_TICK = 0x02000000, - AURA = 0x04000000, - HIDE_TIMER = 0x08000000, - ON_ZONE_PATHOS = 0x10000000, - ALWAYS_EXPIRING = 0x20000000, -} diff --git a/scripts/enum/element.lua b/scripts/enum/element.lua deleted file mode 100644 index 0d69c87ffdb..00000000000 --- a/scripts/enum/element.lua +++ /dev/null @@ -1,15 +0,0 @@ -xi = xi or {} - ----@enum xi.element -xi.element = -{ - NONE = 0, - FIRE = 1, - ICE = 2, - WIND = 3, - EARTH = 4, - THUNDER = 5, - WATER = 6, - LIGHT = 7, - DARK = 8, -} diff --git a/sql/status_effects.sql b/sql/status_effects.sql deleted file mode 100644 index 6afaf18bc31..00000000000 --- a/sql/status_effects.sql +++ /dev/null @@ -1,749 +0,0 @@ -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - -SET @FLAG_DISPELABLE = 1; -- 0x00000001 -SET @FLAG_ERASABLE = 2; -- 0x00000002 -SET @FLAG_ATTACK = 4; -- 0x00000004 -SET @FLAG_EMPATHY = 8; -- 0x00000008 -SET @FLAG_DAMAGE = 16; -- 0x00000010 -SET @FLAG_DEATH = 32; -- 0x00000020 -SET @FLAG_MAGIC_BEGIN = 64; -- 0x00000040 -SET @FLAG_MAGIC_END = 128; -- 0x00000080 -SET @FLAG_ON_ZONE = 256; -- 0x00000100 -SET @FLAG_NO_LOSS_MESSAGE = 512; -- 0x00000200 -SET @FLAG_INVISIBLE = 1024; -- 0x00000400 -SET @FLAG_DETECTABLE = 2048; -- 0x00000800 -SET @FLAG_NO_REST = 4096; -- 0x00001000 -SET @FLAG_PREVENT_ACTION = 8192; -- 0x00002000 -SET @FLAG_WALTZABLE = 16384; -- 0x00004000 -SET @FLAG_FOOD = 32768; -- 0x00008000 -SET @FLAG_SONG = 65536; -- 0x00010000 -SET @FLAG_ROLL = 131072; -- 0x00020000 -SET @FLAG_SYNTH_SUPPORT = 262144; -- 0x00040000 -SET @FLAG_CONFRONTATION = 524288; -- 0x00080000 -SET @FLAG_LOGOUT = 1048576; -- 0x00100000 -SET @FLAG_BLOODPACT = 2097152; -- 0x00200000 -SET @FLAG_ON_JOBCHANGE = 4194304; -- 0x00400000 -SET @FLAG_NO_CANCEL = 8388608; -- 0x00800000 -SET @FLAG_INFLUENCE = 16777216; -- 0x01000000 -SET @FLAG_OFFLINE_TICK = 33554432; -- 0x02000000 -SET @FLAG_AURA = 67108864; -- 0x04000000 -SET @FLAG_HIDE_TIMER = 134217728; -- 0x08000000 -SET @FLAG_ON_ZONE_PATHOS = 268435456; -- 0x10000000 -SET @FLAG_ALWAYS_EXPIRING = 536870912; -- 0x20000000 -SET @FLAG_ON_ATTACK = 1073741824; -- 0x40000000 - --- --- Table structure for table `status_effects` --- - -DROP TABLE IF EXISTS `status_effects`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `status_effects` ( - `id` smallint(5) unsigned NOT NULL, - `name` varchar(50) NOT NULL, - `flags` int(8) unsigned NOT NULL DEFAULT 0, - `type` smallint(5) unsigned NOT NULL DEFAULT 0, -- This needs renamed eventually. See struct EffectParams_t in status_effect_container.cpp - `negative_id` smallint(5) unsigned DEFAULT 0, - `overwrite` smallint(5) unsigned NOT NULL DEFAULT 0, - `block_id` smallint(5) unsigned DEFAULT 0, - `remove_id` smallint(5) unsigned NOT NULL DEFAULT 0, - `element` smallint(5) unsigned NOT NULL DEFAULT 0, - `min_duration` smallint(5) unsigned NOT NULL DEFAULT 0, - `sort_key` smallint(5) unsigned NOT NULL DEFAULT 0, - `wear_off_message_id` smallint(5) unsigned DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=Aria TRANSACTIONAL=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `status_effects` --- - -LOCK TABLES `status_effects` WRITE; -/*!40000 ALTER TABLE `status_effects` DISABLE KEYS */; -INSERT INTO `status_effects` VALUES (0,'ko',@FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (1,'weakness',@FLAG_NO_CANCEL,0,0,3,0,0,0,1,0,204); -INSERT INTO `status_effects` VALUES (2,'sleep',@FLAG_DAMAGE | @FLAG_DEATH | @FLAG_NO_CANCEL,2,19,1,193,0,8,1,0,204); -INSERT INTO `status_effects` VALUES (3,'poison',@FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,2,0,0,6,1,0,204); -INSERT INTO `status_effects` VALUES (4,'paralysis',@FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,1,0,0,2,1,0,204); -INSERT INTO `status_effects` VALUES (5,'blindness',@FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,1,0,0,8,1,0,204); -INSERT INTO `status_effects` VALUES (6,'silence',@FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,2,0,0,3,1,0,204); -INSERT INTO `status_effects` VALUES (7,'petrification',@FLAG_DEATH | @FLAG_NO_CANCEL,7,0,2,10,0,4,1,0,204); -INSERT INTO `status_effects` VALUES (8,'disease',@FLAG_DEATH | @FLAG_NO_REST | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,8,0,2,0,0,1,1,0,204); -INSERT INTO `status_effects` VALUES (9,'curse',@FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,9,0,2,0,0,8,1,0,204); -INSERT INTO `status_effects` VALUES (10,'stun',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_NO_CANCEL,0,0,2,7,0,5,1,0,204); -INSERT INTO `status_effects` VALUES (11,'bind',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,2,0,0,2,1,0,204); -INSERT INTO `status_effects` VALUES (12,'weight',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,32,1,0,0,3,1,0,204); -INSERT INTO `status_effects` VALUES (13,'slow',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,33,1,0,0,4,1,0,NULL); -INSERT INTO `status_effects` VALUES (14,'charm',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,2,0,0,7,0,0,204); -INSERT INTO `status_effects` VALUES (15,'doom',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,2,0,0,8,1,0,204); -INSERT INTO `status_effects` VALUES (16,'amnesia',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,2,0,0,1,1,0,204); -INSERT INTO `status_effects` VALUES (17,'charm',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,2,0,0,7,0,0,204); -INSERT INTO `status_effects` VALUES (18,'gradual_petrification',@FLAG_DEATH | @FLAG_NO_CANCEL,7,0,2,0,0,4,1,0,204); -INSERT INTO `status_effects` VALUES (19,'sleep',@FLAG_DAMAGE | @FLAG_DEATH | @FLAG_NO_CANCEL,2,0,1,0,0,8,1,0,204); -INSERT INTO `status_effects` VALUES (20,'curse',@FLAG_DEATH | @FLAG_NO_REST | @FLAG_NO_CANCEL,9,0,2,0,0,8,1,0,204); -INSERT INTO `status_effects` VALUES (21,'addle',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,2,0,0,1,1,0,NULL); -INSERT INTO `status_effects` VALUES (22,'intimidate',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,2,0,0,0,1,0,204); -INSERT INTO `status_effects` VALUES (23,'kaustra',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,228,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (28,'terror',@FLAG_DEATH | @FLAG_NO_CANCEL,7,0,0,0,0,8,1,0,204); -INSERT INTO `status_effects` VALUES (29,'mute',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,2,0,6,3,1,0,204); -INSERT INTO `status_effects` VALUES (30,'bane',@FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,2,0,9,8,1,0,204); -INSERT INTO `status_effects` VALUES (31,'plague',@FLAG_DEATH | @FLAG_NO_REST | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,8,0,2,0,0,1,1,0,204); -INSERT INTO `status_effects` VALUES (32,'flee',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,12,0,0,0,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (33,'haste',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,13,0,0,0,3,0,100,NULL); -INSERT INTO `status_effects` VALUES (34,'blaze_spikes',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,34,0,0,0,0,1,0,800,NULL); -INSERT INTO `status_effects` VALUES (35,'ice_spikes',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,34,0,0,0,0,2,0,800,NULL); -INSERT INTO `status_effects` VALUES (36,'blink',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,36,0,0,66,0,3,0,50,NULL); -INSERT INTO `status_effects` VALUES (37,'stoneskin',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,5,0,0,4,0,600,NULL); -INSERT INTO `status_effects` VALUES (38,'shock_spikes',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,34,0,0,0,0,5,0,800,NULL); -INSERT INTO `status_effects` VALUES (39,'aquaveil',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,6,0,650,NULL); -INSERT INTO `status_effects` VALUES (40,'protect',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,7,0,200,NULL); -INSERT INTO `status_effects` VALUES (41,'shell',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,7,0,250,NULL); -INSERT INTO `status_effects` VALUES (42,'regen',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,7,0,700,NULL); -INSERT INTO `status_effects` VALUES (43,'refresh',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,7,0,750,NULL); -INSERT INTO `status_effects` VALUES (44,'mighty_strikes',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (45,'boost',@FLAG_ATTACK | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_JOBCHANGE,0,0,0,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (46,'hundred_fists',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (47,'manafont',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (48,'chainspell',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (49,'perfect_dodge',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (50,'invincible',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (51,'blood_weapon',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,94,0,0,0,0,8,0,0,NULL); -INSERT INTO `status_effects` VALUES (52,'soul_voice',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (53,'eagle_eye_shot',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (54,'meikyo_shisui',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (55,'astral_flow',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (56,'berserk',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (57,'defender',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (58,'aggressor',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (59,'focus',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (60,'dodge',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (61,'counterstance',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (62,'sentinel',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (63,'souleater',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (64,'last_resort',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (65,'sneak_attack',@FLAG_ATTACK | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (66,'copy_image',@FLAG_DISPELABLE | @FLAG_DEATH,0,0,0,0,36,3,0,50,NULL); -INSERT INTO `status_effects` VALUES (67,'third_eye',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (68,'warcry',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,460,0,0,400,NULL); -INSERT INTO `status_effects` VALUES (69,'invisible',@FLAG_DISPELABLE | @FLAG_ATTACK | @FLAG_DEATH | @FLAG_MAGIC_BEGIN | @FLAG_ON_ZONE | @FLAG_INVISIBLE | @FLAG_DETECTABLE | @FLAG_LOGOUT,0,0,2,0,0,3,0,850,NULL); -INSERT INTO `status_effects` VALUES (70,'deodorize',@FLAG_DISPELABLE | @FLAG_ATTACK | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_DETECTABLE | @FLAG_LOGOUT,0,0,2,0,0,3,0,1100,NULL); -INSERT INTO `status_effects` VALUES (71,'sneak',@FLAG_DISPELABLE | @FLAG_ATTACK | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_DETECTABLE | @FLAG_LOGOUT,0,0,2,0,0,3,0,1150,NULL); -INSERT INTO `status_effects` VALUES (72,'sharpshot',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (73,'barrage',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,73,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (74,'holy_circle',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (75,'arcane_circle',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (76,'hide',@FLAG_DISPELABLE | @FLAG_ATTACK | @FLAG_DEATH | @FLAG_MAGIC_BEGIN | @FLAG_ON_ZONE | @FLAG_INVISIBLE | @FLAG_DETECTABLE | @FLAG_LOGOUT,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (77,'camouflage',@FLAG_DISPELABLE | @FLAG_ATTACK | @FLAG_DEATH | @FLAG_MAGIC_BEGIN | @FLAG_ON_ZONE | @FLAG_INVISIBLE | @FLAG_DETECTABLE | @FLAG_LOGOUT,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (78,'divine_seal',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_MAGIC_END | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (79,'elemental_seal',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_MAGIC_END | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (80,'str_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,136,0,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (81,'dex_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,137,0,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (82,'vit_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,138,0,0,0,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (83,'agi_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,139,0,0,0,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (84,'int_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,140,0,0,0,2,0,0,NULL); -INSERT INTO `status_effects` VALUES (85,'mnd_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,141,0,0,0,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (86,'chr_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,142,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (87,'trick_attack',@FLAG_ATTACK | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (88,'max_hp_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,144,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (89,'max_mp_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,145,0,0,0,8,0,0,NULL); -INSERT INTO `status_effects` VALUES (90,'accuracy_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,146,0,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (91,'attack_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,147,0,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (92,'evasion_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,148,0,0,0,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (93,'defense_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,149,0,0,0,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (94,'enfire',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,1,0,1200,NULL); -INSERT INTO `status_effects` VALUES (95,'enblizzard',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,2,0,1200,NULL); -INSERT INTO `status_effects` VALUES (96,'enaero',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,3,0,1200,NULL); -INSERT INTO `status_effects` VALUES (97,'enstone',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,4,0,1200,NULL); -INSERT INTO `status_effects` VALUES (98,'enthunder',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,5,0,1200,NULL); -INSERT INTO `status_effects` VALUES (99,'enwater',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,6,0,1200,NULL); -INSERT INTO `status_effects` VALUES (100,'barfire',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,100,0,0,0,0,6,0,500,NULL); -INSERT INTO `status_effects` VALUES (101,'barblizzard',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,100,0,0,0,0,1,0,500,NULL); -INSERT INTO `status_effects` VALUES (102,'baraero',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,100,0,0,0,0,2,0,500,NULL); -INSERT INTO `status_effects` VALUES (103,'barstone',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,100,0,0,0,0,3,0,500,NULL); -INSERT INTO `status_effects` VALUES (104,'barthunder',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,100,0,0,0,0,4,0,500,NULL); -INSERT INTO `status_effects` VALUES (105,'barwater',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,100,0,0,0,0,5,0,500,NULL); -INSERT INTO `status_effects` VALUES (106,'barsleep',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,106,0,0,0,0,7,0,500,NULL); -INSERT INTO `status_effects` VALUES (107,'barpoison',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,106,0,0,0,0,5,0,500,NULL); -INSERT INTO `status_effects` VALUES (108,'barparalyze',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,106,0,0,0,0,1,0,500,NULL); -INSERT INTO `status_effects` VALUES (109,'barblind',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,106,0,0,0,0,7,0,500,NULL); -INSERT INTO `status_effects` VALUES (110,'barsilence',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,106,0,0,0,0,2,0,500,NULL); -INSERT INTO `status_effects` VALUES (111,'barpetrify',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,106,0,0,0,0,3,0,500,NULL); -INSERT INTO `status_effects` VALUES (112,'barvirus',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,106,0,0,0,0,6,0,500,NULL); -INSERT INTO `status_effects` VALUES (113,'reraise',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_JOBCHANGE,0,0,0,0,0,7,0,900,NULL); -INSERT INTO `status_effects` VALUES (114,'cover',@FLAG_DEATH | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (115,'unlimited_shot',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,73,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (116,'phalanx',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,7,0,1050,NULL); -INSERT INTO `status_effects` VALUES (117,'warding_circle',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (118,'ancient_circle',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (119,'str_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (120,'dex_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (121,'vit_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (122,'agi_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (123,'int_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,2,0,0,NULL); -INSERT INTO `status_effects` VALUES (124,'mnd_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (125,'chr_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (126,'spirit_surge',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (127,'costume',@FLAG_ATTACK | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_MAGIC_END,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (128,'burn',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,133,129,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (129,'frost',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,128,130,2,0,0,NULL); -INSERT INTO `status_effects` VALUES (130,'choke',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,129,131,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (131,'rasp',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,130,132,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (132,'shock',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,131,133,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (133,'drown',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,132,128,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (134,'dia',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,134,1,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (135,'bio',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,134,1,0,0,8,0,0,NULL); -INSERT INTO `status_effects` VALUES (136,'str_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,80,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (137,'dex_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,81,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (138,'vit_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,82,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (139,'agi_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,83,2,0,0,NULL); -INSERT INTO `status_effects` VALUES (140,'int_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,84,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (141,'mnd_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,85,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (142,'chr_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,86,8,0,0,NULL); -INSERT INTO `status_effects` VALUES (143,'level_restriction',@FLAG_NO_LOSS_MESSAGE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (144,'max_hp_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,88,8,0,0,NULL); -INSERT INTO `status_effects` VALUES (145,'max_mp_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,89,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (146,'accuracy_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,90,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (147,'attack_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,91,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (148,'evasion_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,92,2,0,0,NULL); -INSERT INTO `status_effects` VALUES (149,'defense_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,93,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (150,'physical_shield',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (151,'arrow_shield',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (152,'magic_shield',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (153,'damage_spikes',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_NO_CANCEL,34,0,0,0,0,0,0,800,NULL); -INSERT INTO `status_effects` VALUES (154,'shining_ruby',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (155,'medicine',@FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (156,'flash',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,1,0,0,7,0,0,204); -INSERT INTO `status_effects` VALUES (157,'sj_restriction',@FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (158,'provoke',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (159,'penalty',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (160,'preparations',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (161,'sprint',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (162,'enchantment',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (163,'azure_lore',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (164,'chain_affinity',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (165,'burst_affinity',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (166,'overdrive',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (167,'magic_def_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (168,'inhibit_tp',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,8,0,0,NULL); -INSERT INTO `status_effects` VALUES (169,'potency',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (170,'regain',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (171,'pax',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (172,'intension',@FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (173,'dread_spikes',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,34,0,0,0,0,0,0,800,NULL); -INSERT INTO `status_effects` VALUES (174,'magic_acc_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (175,'magic_atk_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,0,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (176,'quickening',@FLAG_ATTACK | @FLAG_EMPATHY | @FLAG_DAMAGE | @FLAG_DEATH | @FLAG_ON_JOBCHANGE | @FLAG_ON_ATTACK,0,0,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (177,'encumbrance',@FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (178,'firestorm',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (179,'hailstorm',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (180,'windstorm',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (181,'sandstorm',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (182,'thunderstorm',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (183,'rainstorm',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (184,'aurorastorm',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (185,'voidstorm',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (186,'helix',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (187,'sublimation_activated',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (188,'sublimation_complete',@FLAG_DEATH | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (189,'max_tp_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,0,8,0,0,NULL); -INSERT INTO `status_effects` VALUES (190,'magic_atk_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,2,0,0,NULL); -INSERT INTO `status_effects` VALUES (191,'magic_def_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (192,'requiem',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,1,0,0,7,0,2000,NULL); -INSERT INTO `status_effects` VALUES (193,'lullaby',@FLAG_DAMAGE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,2,19,2,2,0,7,1,2000,NULL); -INSERT INTO `status_effects` VALUES (194,'elegy',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,0,0,0,4,0,2000,NULL); -INSERT INTO `status_effects` VALUES (195,'paeon',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,7,0,2000,NULL); -INSERT INTO `status_effects` VALUES (196,'ballad',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,7,0,2000,NULL); -INSERT INTO `status_effects` VALUES (197,'minne',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,4,0,2000,NULL); -INSERT INTO `status_effects` VALUES (198,'minuet',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,1,0,2000,NULL); -INSERT INTO `status_effects` VALUES (199,'madrigal',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,5,0,2000,NULL); -INSERT INTO `status_effects` VALUES (200,'prelude',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (201,'mambo',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (202,'aubade',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (203,'pastoral',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (204,'hum',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (205,'fantasia',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (206,'operetta',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (207,'capriccio',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (208,'serenade',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (209,'round',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (210,'gavotte',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (211,'fugue',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (212,'rhapsody',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (213,'aria',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (214,'march',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (215,'etude',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (216,'carol',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (217,'threnody',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,1,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (218,'hymnus',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (219,'mazurka',@FLAG_DISPELABLE | @FLAG_ATTACK | @FLAG_DAMAGE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_ON_ATTACK | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (220,'sirvente',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (221,'dirge',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (222,'scherzo',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_SONG | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (223,'nocturne',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (227,'store_tp',@FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (228,'embrava',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,23,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (229,'manawell',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (230,'spontaneity',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (231,'marcato',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (233,'auto-regen',@FLAG_DEATH,0,0,4,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (234,'auto-refresh',@FLAG_DEATH,0,0,4,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (235,'fishing_imagery',@FLAG_DEATH | @FLAG_SYNTH_SUPPORT | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (236,'woodworking_imagery',@FLAG_DEATH | @FLAG_SYNTH_SUPPORT | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (237,'smithing_imagery',@FLAG_DEATH | @FLAG_SYNTH_SUPPORT | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (238,'goldsmithing_imagery',@FLAG_DEATH | @FLAG_SYNTH_SUPPORT | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (239,'clothcraft_imagery',@FLAG_DEATH | @FLAG_SYNTH_SUPPORT | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (240,'leathercraft_imagery',@FLAG_DEATH | @FLAG_SYNTH_SUPPORT | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (241,'bonecraft_imagery',@FLAG_DEATH | @FLAG_SYNTH_SUPPORT | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (242,'alchemy_imagery',@FLAG_DEATH | @FLAG_SYNTH_SUPPORT | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (243,'cooking_imagery',@FLAG_DEATH | @FLAG_SYNTH_SUPPORT | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (244,'imagery',@FLAG_DEATH | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (245,'imagery',@FLAG_DEATH | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (246,'imagery',@FLAG_DEATH | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (247,'imagery',@FLAG_DEATH | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (248,'imagery',@FLAG_DEATH | @FLAG_NO_CANCEL,244,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (249,'dedication',@FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (250,'ef_badge',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (251,'food',@FLAG_DEATH | @FLAG_FOOD | @FLAG_NO_CANCEL,0,0,2,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (252,'mounted',@FLAG_ATTACK | @FLAG_DEATH | @FLAG_MAGIC_END | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (253,'signet',@FLAG_INFLUENCE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,1000,NULL); -INSERT INTO `status_effects` VALUES (254,'battlefield',@FLAG_CONFRONTATION | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (256,'sanction',@FLAG_INFLUENCE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,1000,NULL); -INSERT INTO `status_effects` VALUES (257,'besieged',@FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (258,'illusion',@FLAG_ATTACK | @FLAG_DAMAGE | @FLAG_DEATH | @FLAG_MAGIC_END | @FLAG_ON_ZONE | @FLAG_NO_REST,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (259,'encumbrance',@FLAG_ON_ZONE_PATHOS | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (260,'obliviscence',@FLAG_ON_ZONE_PATHOS | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (261,'impairment',@FLAG_ON_ZONE_PATHOS | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (262,'omerta',@FLAG_ON_ZONE_PATHOS | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (263,'debilitation',@FLAG_ON_ZONE_PATHOS | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (264,'pathos',@FLAG_ON_ZONE_PATHOS | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (265,'flurry',@FLAG_DEATH | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (266,'concentration',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (267,'allied_tags',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_CONFRONTATION | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (268,'sigil',@FLAG_INFLUENCE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (269,'level_sync',@FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (270,'aftermath_lv1',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (271,'aftermath_lv2',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (272,'aftermath_lv3',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (273,'aftermath',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (274,'enlight',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (275,'auspice',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,94,51,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (276,'confrontation',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_CONFRONTATION | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (277,'enfire_ii',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (278,'enblizzard_ii',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,2,0,0,NULL); -INSERT INTO `status_effects` VALUES (279,'enaero_ii',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (280,'enstone_ii',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (281,'enthunder_ii',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (282,'enwater_ii',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (283,'perfect_defense',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (284,'egg',@FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (285,'visitant',@FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_OFFLINE_TICK,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (286,'baramnesia',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,106,0,0,0,0,0,0,500,NULL); -INSERT INTO `status_effects` VALUES (287,'atma',@FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,4,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (288,'endark',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,94,51,0,0,0,8,0,0,NULL); -INSERT INTO `status_effects` VALUES (289,'enmity_boost',@FLAG_DEATH,0,0,0,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (290,'subtle_blow_plus',@FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (291,'enmity_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE,0,0,0,0,0,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (292,'pennant',@FLAG_DEATH | @FLAG_CONFRONTATION | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (293,'negate_petrify',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,7,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (294,'negate_terror',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,28,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (295,'negate_amnesia',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,16,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (296,'negate_doom',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,15,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (297,'negate_poison',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,3,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (298,'critical_hit_evasion_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (299,'overload',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (300,'fire_maneuver',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,3000,NULL); -INSERT INTO `status_effects` VALUES (301,'ice_maneuver',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,3000,NULL); -INSERT INTO `status_effects` VALUES (302,'wind_maneuver',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,3000,NULL); -INSERT INTO `status_effects` VALUES (303,'earth_maneuver',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,3000,NULL); -INSERT INTO `status_effects` VALUES (304,'thunder_maneuver',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,3000,NULL); -INSERT INTO `status_effects` VALUES (305,'water_maneuver',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,3000,NULL); -INSERT INTO `status_effects` VALUES (306,'light_maneuver',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,3000,NULL); -INSERT INTO `status_effects` VALUES (307,'dark_maneuver',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,3000,NULL); -INSERT INTO `status_effects` VALUES (308,'double-up_chance',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2050,NULL); -INSERT INTO `status_effects` VALUES (309,'bust',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,4,0,0,0,0,2050,NULL); -INSERT INTO `status_effects` VALUES (310,'fighters_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (311,'monks_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (312,'healers_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (313,'wizards_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (314,'warlocks_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (315,'rogues_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (316,'gallants_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (317,'chaos_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (318,'beast_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (319,'choral_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (320,'hunters_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (321,'samurai_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (322,'ninja_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (323,'drachen_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (324,'evokers_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (325,'maguss_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (326,'corsairs_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (327,'puppet_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (328,'dancers_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (329,'scholars_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (330,'bolters_roll',@FLAG_DISPELABLE | @FLAG_ATTACK | @FLAG_EMPATHY | @FLAG_DAMAGE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_ON_ATTACK | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (331,'casters_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (332,'coursers_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (333,'blitzers_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (334,'tacticians_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (335,'allies_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (336,'misers_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (337,'companions_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (338,'avengers_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (339,'naturalists_roll',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,2000,NULL); -INSERT INTO `status_effects` VALUES (340,'warriors_charge',@FLAG_ATTACK | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (341,'formless_strikes',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (342,'assassins_charge',@FLAG_ATTACK | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (343,'feint',@FLAG_DEATH | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (344,'fealty',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (345,'dark_seal',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_MAGIC_END,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (346,'diabolic_eye',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (347,'nightingale',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (348,'troubadour',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (349,'killer_instinct',@FLAG_DEATH | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (350,'stealth_shot',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (351,'flashy_shot',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (352,'sange',@FLAG_DEATH | @FLAG_ON_ZONE,73,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (353,'hasso',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,353,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (354,'seigan',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE,353,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (355,'convergence',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (356,'diffusion',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (357,'snake_eye',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (358,'light_arts',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (359,'dark_arts',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (360,'penury',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (361,'parsimony',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (362,'celerity',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (363,'alacrity',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (364,'rapture',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (365,'ebullience',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (366,'accession',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (367,'manifestation',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (368,'drain_samba',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,368,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (369,'aspir_samba',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,368,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (370,'haste_samba',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,368,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (371,'velocity_shot',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (375,'building_flourish',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (376,'trance',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (377,'tabula_rasa',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (378,'drain_daze',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (379,'aspir_daze',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (380,'haste_daze',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (381,'finishing_move',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (382,'finishing_move',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (383,'finishing_move',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (384,'finishing_move',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (385,'finishing_move',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (386,'lethargic_daze_1',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (387,'lethargic_daze_2',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (388,'lethargic_daze_3',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (389,'lethargic_daze_4',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (390,'lethargic_daze_5',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (391,'sluggish_daze_1',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (392,'sluggish_daze_2',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (393,'sluggish_daze_3',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (394,'sluggish_daze_4',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (395,'sluggish_daze_5',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (396,'weakened_daze_1',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (397,'weakened_daze_2',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (398,'weakened_daze_3',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (399,'weakened_daze_4',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (400,'weakened_daze_5',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (401,'addendum_white',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (402,'addendum_black',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (403,'reprisal',@FLAG_DISPELABLE | @FLAG_DEATH,34,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (404,'magic_evasion_down',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_WALTZABLE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (405,'retaliation',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (406,'footwork',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (407,'klimaform',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (408,'sekkanoki',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (409,'pianissimo',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (410,'saber_dance',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (411,'fan_dance',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (412,'altruism',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (413,'focalization',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (414,'tranquility',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (415,'equanimity',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (416,'enlightenment',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (417,'afflatus_solace',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (418,'afflatus_misery',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (419,'composure',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (420,'yonin',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,420,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (421,'innin',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,420,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (422,'carbuncles_favor',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (423,'ifrits_favor',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (424,'shivas_favor',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (425,'garudas_favor',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (426,'titans_favor',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (427,'ramuhs_favor',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (428,'leviathans_favor',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (429,'fenrirs_favor',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (430,'diaboloss_favor',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (431,'avatars_favor',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_OFFLINE_TICK | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (432,'multi_strikes',@FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (433,'double_shot',@FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (434,'transcendency',@FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (435,'restraint',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (436,'perfect_counter',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (437,'mana_wall',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (438,'divine_emblem',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (439,'nether_void',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (440,'sengikori',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (441,'futae',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (442,'presto',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (443,'climactic_flourish',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (444,'copy_image',@FLAG_DEATH | @FLAG_ON_JOBCHANGE,36,0,0,0,0,0,0,50,NULL); -INSERT INTO `status_effects` VALUES (445,'copy_image',@FLAG_DEATH | @FLAG_ON_JOBCHANGE,36,0,0,0,0,0,0,50,NULL); -INSERT INTO `status_effects` VALUES (446,'copy_image',@FLAG_DEATH | @FLAG_ON_JOBCHANGE,36,0,0,0,0,0,0,50,NULL); -INSERT INTO `status_effects` VALUES (447,'multi_shots',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (448,'bewildered_daze_1',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (449,'bewildered_daze_2',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (450,'bewildered_daze_3',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (451,'bewildered_daze_4',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (452,'bewildered_daze_5',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (453,'divine_caress',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (454,'saboteur',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (455,'tenuto',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (456,'spur',@FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (457,'efflux',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (458,'earthen_armor',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (459,'divine_caress',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (460,'blood_rage',@FLAG_DEATH | @FLAG_ON_JOBCHANGE,0,0,0,0,68,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (461,'impetus',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (462,'conspirator',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (463,'sepulcher',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (464,'arcane_crest',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (465,'hamanoha',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (466,'dragon_breaker',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (467,'triple_shot',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (468,'striking_flourish',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (469,'perpetuance',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (470,'immanence',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (471,'migawari',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (472,'ternary_flourish',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (473,'muddle',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (474,'prowess',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (475,'voidwatcher',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (476,'ensphere',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (477,'sacrosanctity',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (478,'palisade',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (479,'scarlet_delirium',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (480,'scarlet_delirium',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (481,'abdhaljs_seal',@FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (482,'decoy_shot',@FLAG_DEATH | @FLAG_ON_JOBCHANGE,482,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (483,'hagakure',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (484,'issekigan',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (485,'unbridled_learning',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (486,'counter_boost',@FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (487,'endrain',@FLAG_DEATH | @FLAG_ON_ZONE,94,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (488,'enaspir',@FLAG_DEATH | @FLAG_ON_ZONE,94,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (489,'afterglow',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (490,'brazen_rush',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (491,'inner_strength',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (492,'asylum',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (493,'subtle_sorcery',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (494,'stymie',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (495,'macro_test',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_LOSS_MESSAGE | @FLAG_HIDE_TIMER | @FLAG_ALWAYS_EXPIRING,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (496,'intervene',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (497,'soul_enslavement',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (498,'unleash',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (499,'clarion_call',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (500,'overkill',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (501,'yaegasumi',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (502,'mikage',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (503,'fly_high',@FLAG_DEATH | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (504,'astral_conduit',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (505,'unbridled_wisdom',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (506,'grace',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (507,'grand_pas',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (508,'widened_compass',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (509,'odyllic_subterfuge',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (510,'ergon_might',@FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (511,'reive_mark',@FLAG_DEATH | @FLAG_CONFRONTATION | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (512,'ionis',@FLAG_INFLUENCE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (513,'bolster',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (515,'lasting_emanation',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (516,'ecliptic_attrition',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (517,'collimated_fervor',@FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (518,'dematerialize',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (519,'theurgic_focus',@FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (522,'elemental_sforzo',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (523,'ignis',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (524,'gelus',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,2,0,0,NULL); -INSERT INTO `status_effects` VALUES (525,'flabra',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (526,'tellus',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (527,'sulpor',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (528,'unda',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (529,'lux',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (530,'tenebrae',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,4,0,0,8,0,0,NULL); -INSERT INTO `status_effects` VALUES (531,'vallation',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (532,'swordplay',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (533,'pflug',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (534,'emboldened',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (535,'valiance',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,531,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (536,'gambit',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_NO_CANCEL,0,0,2,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (537,'liement',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (538,'one_for_all',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (539,'geo_regen',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (540,'geo_poison',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (541,'geo_refresh',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (542,'geo_str_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (543,'geo_dex_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (544,'geo_vit_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (545,'geo_agi_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (546,'geo_int_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,2,0,0,NULL); -INSERT INTO `status_effects` VALUES (547,'geo_mnd_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (548,'geo_chr_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (549,'geo_attack_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (550,'geo_defense_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (551,'geo_magic_atk_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,2,0,0,NULL); -INSERT INTO `status_effects` VALUES (552,'geo_magic_def_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (553,'geo_accuracy_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (554,'geo_evasion_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (555,'geo_magic_acc_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,8,0,0,NULL); -INSERT INTO `status_effects` VALUES (556,'geo_magic_evasion_boost',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (557,'geo_attack_down',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (558,'geo_defense_down',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (559,'geo_magic_atk_down',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (560,'geo_magic_def_down',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (561,'geo_accuracy_down',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (562,'geo_evasion_down',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,2,0,0,NULL); -INSERT INTO `status_effects` VALUES (563,'geo_magic_acc_down',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (564,'geo_magic_evasion_down',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,8,0,0,NULL); -INSERT INTO `status_effects` VALUES (565,'geo_slow',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (566,'geo_paralysis',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,2,0,0,NULL); -INSERT INTO `status_effects` VALUES (567,'geo_weight',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (568,'foil',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (569,'blaze_of_glory',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (570,'battuta',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (571,'rayke',@FLAG_ERASABLE | @FLAG_DEATH | @FLAG_NO_CANCEL,0,0,2,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (572,'avoidance_down',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (573,'deluge_spikes',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,34,0,0,0,0,6,0,800,NULL); -INSERT INTO `status_effects` VALUES (574,'fast_cast',@FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (575,'gestation',@FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (576,'doubt',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (577,'cait_siths_favor',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (578,'fishy_intuition',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (579,'commitment',@FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (580,'geo_haste',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (581,'flurry_ii',@FLAG_DEATH | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (582,'contradance',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (583,'apogee',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_BLOODPACT | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (584,'entrust',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (585,'costume',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,204); -INSERT INTO `status_effects` VALUES (586,'curing_conduit',@FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (587,'tp_bonus',@FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (588,'finishing_move',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (589,'firestorm_ii',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (590,'hailstorm_ii',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (591,'windstorm_ii',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (592,'sandstorm_ii',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (593,'thunderstorm_ii',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (594,'rainstorm_ii',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (595,'aurorastorm_ii',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (596,'voidstorm_ii',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (597,'inundation',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (598,'cascade',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (599,'consume_mana',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (600,'runeists_roll',@FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ROLL | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (601,'crooked_cards',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (602,'vorseal',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (603,'elvorseal',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (604,'mighty_guard',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (605,'gale_spikes',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,34,0,0,0,0,3,0,800,NULL); -INSERT INTO `status_effects` VALUES (606,'clod_spikes',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,34,0,0,0,0,4,0,800,NULL); -INSERT INTO `status_effects` VALUES (607,'glint_spikes',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,34,0,0,0,0,7,0,800,NULL); -INSERT INTO `status_effects` VALUES (608,'negate_virus',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (609,'negate_curse',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (610,'negate_charm',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (611,'magic_evasion_boost_ii',@FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (612,'colure_active',@FLAG_ON_ZONE | @FLAG_LOGOUT | @FLAG_NO_CANCEL,0,0,3,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (613,'mumors_radiance',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (614,'ullegores_gloom',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (615,'boost_ii',@FLAG_ATTACK | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (616,'artisanal_knowledge',@FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (617,'sacrifice',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (618,'emporoxs_gift',@FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (619,'spirit_bond',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (620,'awaken',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (621,'majesty',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (622,'guarding_rate_boost',@FLAG_DISPELABLE | @FLAG_EMPATHY | @FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (623,'rampart',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_LOGOUT | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (624,'winds_blessing',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (625,'sirens_favor',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (626,'negate_sleep',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (627,'mobilization',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_ON_JOBCHANGE | @FLAG_ON_ATTACK,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (628,'hover_shot',@FLAG_DISPELABLE | @FLAG_DEATH | @FLAG_ON_ZONE,482,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (629,'moogle_amplifier',@FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (630,'taint',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (631,'haunt',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (632,'black_sanctus',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (633,'animated',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (634,'serpents_guile',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (635,'resolved',@FLAG_ON_ZONE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -- TODO: flags need review -INSERT INTO `status_effects` VALUES (768,'abyssea_str',@FLAG_ON_ZONE,0,0,0,0,0,1,0,0,NULL); -INSERT INTO `status_effects` VALUES (769,'abyssea_dex',@FLAG_ON_ZONE,0,0,0,0,0,5,0,0,NULL); -INSERT INTO `status_effects` VALUES (770,'abyssea_vit',@FLAG_ON_ZONE,0,0,0,0,0,4,0,0,NULL); -INSERT INTO `status_effects` VALUES (771,'abyssea_agi',@FLAG_ON_ZONE,0,0,0,0,0,3,0,0,NULL); -INSERT INTO `status_effects` VALUES (772,'abyssea_int',@FLAG_ON_ZONE,0,0,0,0,0,2,0,0,NULL); -INSERT INTO `status_effects` VALUES (773,'abyssea_mnd',@FLAG_ON_ZONE,0,0,0,0,0,6,0,0,NULL); -INSERT INTO `status_effects` VALUES (774,'abyssea_chr',@FLAG_ON_ZONE,0,0,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (775,'abyssea_hp',@FLAG_ON_ZONE,0,0,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (776,'abyssea_mp',@FLAG_ON_ZONE,0,0,0,0,0,8,0,0,NULL); -INSERT INTO `status_effects` VALUES (777,'prowess_casket_rate',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (778,'prowess_skill_rate',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (779,'prowess_crystal_yeild',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (780,'prowess_th',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (781,'prowess_attack_speed',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (782,'prowess_hp_mp',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (783,'prowess_acc_racc',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (784,'prowess_att_ratt',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (785,'prowess_macc_matk',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (786,'prowess_cure_potency',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (787,'prowess_ws_dmg',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (788,'prowess_killer',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (790,'mark_of_seed',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (791,'all_miss',@FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (792,'super_buff',@FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (793,'ninjutsu_ele_debuff',@FLAG_DEATH | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (794,'healing',@FLAG_ATTACK | @FLAG_DAMAGE | @FLAG_DEATH | @FLAG_MAGIC_BEGIN | @FLAG_ON_ZONE | @FLAG_LOGOUT,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (795,'leavegame',@FLAG_ATTACK | @FLAG_DAMAGE | @FLAG_DEATH | @FLAG_MAGIC_BEGIN | @FLAG_ON_ZONE | @FLAG_LOGOUT,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (796,'haste_samba_haste',@FLAG_MAGIC_BEGIN | @FLAG_ON_ZONE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (797,'teleport',@FLAG_DEATH | @FLAG_ON_JOBCHANGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (798,'chainbound',@FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (799,'skillchain',@FLAG_DEATH,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (800,'dynamis',@FLAG_OFFLINE_TICK,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (801,'meditate',@FLAG_DEATH | @FLAG_ON_ZONE,0,0,0,0,0,7,0,0,NULL); -INSERT INTO `status_effects` VALUES (802,'elemental_resistance_down',@FLAG_DEATH | @FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (803,'full_speed_ahead',@FLAG_ON_ZONE | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (805,'tomahawk',@FLAG_DEATH | @FLAG_NO_LOSS_MESSAGE,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (807,'trust_aura_chr',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (808,'trust_aura_haste',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (809,'trust_aura_exp',@FLAG_DEATH | @FLAG_NO_CANCEL,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (810,'trust_aura_acc',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (811,'trust_aura_refresh',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (812,'trust_aura_regen',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); -INSERT INTO `status_effects` VALUES (813,'trust_aura_magic_attack',@FLAG_DEATH | @FLAG_NO_CANCEL | @FLAG_HIDE_TIMER,0,0,0,0,0,0,0,0,NULL); - -/*!40000 ALTER TABLE `status_effects` ENABLE KEYS */; -UNLOCK TABLES; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; diff --git a/src/map/CMakeLists.txt b/src/map/CMakeLists.txt index 19e3d24a43a..9f9e95cbb8e 100644 --- a/src/map/CMakeLists.txt +++ b/src/map/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(action) add_subdirectory(ai) +add_subdirectory(data) add_subdirectory(entities) add_subdirectory(enums) add_subdirectory(items) @@ -15,6 +16,7 @@ set(SOURCES ${COMMON_SOURCES} ${ACTION_SOURCES} ${AI_SOURCES} + ${DATA_SOURCES} ${ENTITY_SOURCES} ${ENUMS_SOURCES} ${ITEM_SOURCES} @@ -223,6 +225,8 @@ add_library(xi_map_lib STATIC ${MAP_LIB_SOURCES}) +add_dependencies(xi_map_lib data_codegen) + foreach(entry ${cmakelist_include_paths}) if (${entry} STREQUAL "") continue() diff --git a/src/map/data/CMakeLists.txt b/src/map/data/CMakeLists.txt new file mode 100644 index 00000000000..a1dd956eaa2 --- /dev/null +++ b/src/map/data/CMakeLists.txt @@ -0,0 +1,9 @@ +set(DATA_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/backends/yaml.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/backends/yaml.h + ${CMAKE_CURRENT_SOURCE_DIR}/enums/enum_traits.h + ${CMAKE_CURRENT_SOURCE_DIR}/load.h + ${CMAKE_CURRENT_SOURCE_DIR}/loader.h + ${CMAKE_CURRENT_SOURCE_DIR}/node.h + PARENT_SCOPE +) diff --git a/src/map/data/backends/yaml.cpp b/src/map/data/backends/yaml.cpp new file mode 100644 index 00000000000..bee43fe31e5 --- /dev/null +++ b/src/map/data/backends/yaml.cpp @@ -0,0 +1,189 @@ +/* +=========================================================================== + + Copyright (c) 2026 LandSandBoat Dev Teams + + 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 http://www.gnu.org/licenses/ + +=========================================================================== +*/ + +#include "data/backends/yaml.h" + +#include +#include + +#include +#include +#include +#include +#include + +namespace xi::data::backends +{ + +namespace +{ +// ryml can pass a null location name to the error callbacks. +auto toView(const ryml::csubstr s) -> std::string_view +{ + return s.str ? std::string_view(s.str, s.len) : std::string_view{}; +} +} // namespace + +void YAMLBackend::onErrorBasic(const ryml::csubstr msg, const ryml::ErrorDataBasic& errdata, void* /*ud*/) +{ + throw std::runtime_error(fmt::format("[ryml basic] {} at {}:{}", + toView(msg), + toView(errdata.location.name), + errdata.location.line)); +} + +void YAMLBackend::onErrorParse(const ryml::csubstr msg, const ryml::ErrorDataParse& errdata, void* /*ud*/) +{ + throw std::runtime_error(fmt::format("[ryml parse] {} at yaml line {} (from {}:{})", + toView(msg), + errdata.ymlloc.line, + toView(errdata.cpploc.name), + errdata.cpploc.line)); +} + +void YAMLBackend::onErrorVisit(const ryml::csubstr msg, const ryml::ErrorDataVisit& errdata, void* /*ud*/) +{ + std::string context = fmt::format("node={}", errdata.node); + if (errdata.tree && errdata.node != ryml::NONE) + { + const auto n = errdata.tree->cref(errdata.node); + if (n.has_key()) + { + context += fmt::format(" key='{}'", std::string_view(n.key().str, n.key().len)); + } + + if (n.has_val()) + { + context += fmt::format(" val='{}'", std::string_view(n.val().str, n.val().len)); + } + + if (n.has_parent()) + { + const auto p = n.parent(); + if (p.has_key()) + { + context += fmt::format(" parent_key='{}'", std::string_view(p.key().str, p.key().len)); + } + } + } + + throw std::runtime_error(fmt::format("[ryml visit] {} - {} (from {}:{})", + toView(msg), + context, + toView(errdata.cpploc.name), + errdata.cpploc.line)); +} + +void YAMLBackend::installCallbacks() +{ + // rapidyaml violently aborts out of the box. + // Install a few callbacks to attempt to log human-readable errors. + auto callbacks = ryml::get_callbacks(); + callbacks.set_error_basic(&YAMLBackend::onErrorBasic); + callbacks.set_error_parse(&YAMLBackend::onErrorParse); + callbacks.set_error_visit(&YAMLBackend::onErrorVisit); + ryml::set_callbacks(callbacks); +} + +YAMLBackend::Tree::Tree(std::string&& text) +{ + static std::once_flag installed; + std::call_once(installed, &YAMLBackend::installCallbacks); + + tree_ = ryml::parse_in_arena(ryml::csubstr{ text.data(), text.size() }); +} + +auto YAMLBackend::Tree::root() const -> node_t +{ + return tree_.rootref(); +} + +auto YAMLBackend::Tree::root() -> mutable_node_t +{ + return tree_.rootref(); +} + +auto YAMLBackend::isMap(const node_t& n) -> bool +{ + return n.is_map(); +} + +auto YAMLBackend::isSequence(const node_t& n) -> bool +{ + return n.is_seq(); +} + +auto YAMLBackend::hasValue(const node_t& n) -> bool +{ + return n.has_val(); +} + +auto YAMLBackend::hasChild(const node_t& n, std::string_view k) -> bool +{ + return n.has_child(ryml::csubstr{ k.data(), k.size() }); +} + +auto YAMLBackend::child(const node_t& n, std::string_view k) -> node_t +{ + return n[ryml::csubstr{ k.data(), k.size() }]; +} + +auto YAMLBackend::key(const node_t& n) -> std::string_view +{ + return { n.key().str, n.key().len }; +} + +// Modules: Any list redeclared has its core values dropped to enforce replace-only semantics on lists +void YAMLBackend::clearReplacedLists(ryml::NodeRef dst, const ryml::ConstNodeRef src) +{ + if (!src.is_map() || !dst.is_map()) + { + return; + } + + for (const auto srcChild : src.children()) + { + const auto key = srcChild.key(); + if (!dst.has_child(key)) + { + continue; + } + + auto dstChild = dst[key]; + if (srcChild.is_seq() && dstChild.is_seq()) + { + dst.tree()->remove_children(dstChild.id()); + } + else if (srcChild.is_map() && dstChild.is_map()) + { + clearReplacedLists(dstChild, srcChild); + } + } +} + +// Modules: Clear redeclared lists and hand off to rapidyaml for deep merge into core tree +void YAMLBackend::mergeInto(ryml::NodeRef dst, const ryml::ConstNodeRef src) +{ + clearReplacedLists(dst, src); + dst.tree()->merge_with(src.tree(), src.id(), dst.id()); +} + +} // namespace xi::data::backends diff --git a/src/map/data/backends/yaml.h b/src/map/data/backends/yaml.h new file mode 100644 index 00000000000..d8cc6b049c9 --- /dev/null +++ b/src/map/data/backends/yaml.h @@ -0,0 +1,87 @@ +/* +=========================================================================== + + Copyright (c) 2026 LandSandBoat Dev Teams + + 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 http://www.gnu.org/licenses/ + +=========================================================================== +*/ + +#pragma once + +#include "common/cbasetypes.h" + +#include +#include +#include + +#include +#include + +namespace xi::data::backends +{ + +class YAMLBackend +{ +public: + using node_t = ryml::ConstNodeRef; + using mutable_node_t = ryml::NodeRef; + + static constexpr std::string_view kExtension{ ".yaml" }; + + class Tree + { + public: + explicit Tree(std::string&& text); + + auto root() const -> node_t; + auto root() -> mutable_node_t; + + private: + ryml::Tree tree_; + }; + + static auto isMap(const node_t& n) -> bool; + static auto isSequence(const node_t& n) -> bool; + static auto hasValue(const node_t& n) -> bool; + static auto hasChild(const node_t& n, std::string_view k) -> bool; + static auto child(const node_t& n, std::string_view k) -> node_t; + static auto key(const node_t& n) -> std::string_view; + + static auto children(const node_t& n) + { + return n.children(); + } + + template + static auto scalarAs(const node_t& n) -> T + { + T out{}; + n >> out; + return out; + } + + static void mergeInto(mutable_node_t dst, node_t src); + static void installCallbacks(); + +private: + static void clearReplacedLists(mutable_node_t dst, node_t src); + + [[noreturn]] static void onErrorBasic(ryml::csubstr msg, const ryml::ErrorDataBasic& errdata, void* ud); + [[noreturn]] static void onErrorParse(ryml::csubstr msg, const ryml::ErrorDataParse& errdata, void* ud); + [[noreturn]] static void onErrorVisit(ryml::csubstr msg, const ryml::ErrorDataVisit& errdata, void* ud); +}; + +} // namespace xi::data::backends diff --git a/src/map/data/enums/enum_traits.h b/src/map/data/enums/enum_traits.h new file mode 100644 index 00000000000..f5b186bae26 --- /dev/null +++ b/src/map/data/enums/enum_traits.h @@ -0,0 +1,91 @@ +/* +=========================================================================== + + Copyright (c) 2026 LandSandBoat Dev Teams + + 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 http://www.gnu.org/licenses/ + +=========================================================================== +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace xi::data +{ + +// Codegen emits an EnumTraits specialization per enum. +template +struct EnumTraits; + +template +concept Nameable = requires(E e, std::string_view sv) { + { EnumTraits::fromName(sv) } -> std::same_as; + { EnumTraits::toName(e) } -> std::same_as; + { EnumTraits::kTypeName } -> std::convertible_to; +}; + +// Codegen sets this true for enums declaring `meta.flags: true`. +template +inline constexpr bool isFlagEnum = false; + +namespace enum_detail +{ +// Slug -> enum. Throws on miss; typeName goes in the message. +template +auto fromName(const std::string_view name, const std::span> entries, const std::string_view typeName) -> E +{ + // Lazy-init on first call, reused after. + static const std::unordered_map table{ entries.begin(), entries.end() }; + + const auto it = table.find(name); + if (it == table.end()) + { + throw std::runtime_error(fmt::format("'{}' is not a valid {} enum value", name, typeName)); + } + + return it->second; +} + +template +auto toName(const E value, const std::span> entries) -> std::string_view +{ + // Reverse map. Lazy-init on first call, reused after. + static const auto table = [entries] + { + std::unordered_map m; + m.reserve(entries.size()); + for (const auto& p : entries) + { + m.emplace(p.second, p.first); + } + + return m; + }(); + + const auto it = table.find(value); + return it != table.end() ? it->second : std::string_view{ "" }; +} +} // namespace enum_detail + +} // namespace xi::data diff --git a/src/map/data/load.h b/src/map/data/load.h new file mode 100644 index 00000000000..fa3af030445 --- /dev/null +++ b/src/map/data/load.h @@ -0,0 +1,153 @@ +/* +=========================================================================== + + Copyright (c) 2026 LandSandBoat Dev Teams + + 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 http://www.gnu.org/licenses/ + +=========================================================================== +*/ + +#pragma once + +#include "common/cbasetypes.h" +#include "common/logging.h" + +#include "data/node.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace xi::data +{ + +// Describe where the "primary key" of the object is located. +enum class IdSource +{ + YAMLField, // The `id:` field is used as PK + YAMLKey, // The map key itself is the PK +}; + +// Shared body for codegen'd populateMaps; per-type bits go in populateOne. +// Data backend is provided at compilation time, we just want something that deals with a tree-like structure +template +auto populateMapDriver(const Node root, const std::string_view sectionName, const IdSource idSource, const std::string_view source, PopulateOne populateOne) -> std::unordered_map +{ + using KeyT = decltype(T::Id); + + std::unordered_map result; + + // Section is the top level key where the records are stored + if (!root.has(sectionName)) + { + return result; + } + + const auto section = root.child(sectionName); + if (!section.isMap()) + { + return result; + } + + // Iterate every record and hand off the final parsing to the codegen'd specialization. + for (const auto child : section.children()) + { + // First figure out where the primary key is stored + KeyT id{}; + if (idSource == IdSource::YAMLField) + { + // Nested id property is the primary key + // + // weakness: + // id: 1 < HERE + id = child.template read("id"); + } + else + { + // Map key IS the primary key + // + // 16555: < HERE + // name: { en: ridill } + const std::string_view keyStr = child.key(); + const auto ec = std::from_chars(keyStr.data(), keyStr.data() + keyStr.size(), id).ec; + if (ec != std::errc{}) + { + throw std::runtime_error(fmt::format("{}: bad integer key '{}' in section '{}'", source, keyStr, sectionName)); + } + } + + T data = populateOne(child, id); // Ask the specialized function to parse the record + if (!result.try_emplace(data.Id, std::move(data)).second) // Any duplicate is a hard fail + { + throw std::runtime_error(fmt::format("{}: duplicate id {} in section '{}'", source, data.Id, sectionName)); + } + } + + return result; +} + +// Must be specialized by codegen, else it's a compile-time failure +template +auto populateMap(Node root, std::type_identity) -> std::unordered_map = delete; + +// Parse core, merge each module over it in init.txt order, populate. +// Module trees stay alive until populate ends; backend's merge references them. +template +auto loadAllOf(const std::string_view corePath, const std::span modulePaths) -> std::unordered_map +{ + const auto slurp = [](std::string_view path) -> std::string + { + std::ifstream in(std::string{ path }, std::ios::binary); + if (!in.is_open()) + { + throw std::runtime_error(fmt::format("cannot open {}", path)); + } + + std::stringstream buf; + buf << in.rdbuf(); + return buf.str(); + }; + + try + { + typename B::Tree coreTree{ slurp(corePath) }; + std::vector moduleTrees; + moduleTrees.reserve(modulePaths.size()); + + for (const auto& path : modulePaths) + { + moduleTrees.emplace_back(slurp(path)); + B::mergeInto(coreTree.root(), moduleTrees.back().root()); + } + + return populateMap(Node{ coreTree.root() }, std::type_identity{}); + } + catch (const std::exception& e) + { + ShowErrorFmt("loadAllOf({}) failed: {}", corePath, e.what()); + throw; + } +} + +} // namespace xi::data diff --git a/src/map/data/loader.h b/src/map/data/loader.h new file mode 100644 index 00000000000..fd410a79927 --- /dev/null +++ b/src/map/data/loader.h @@ -0,0 +1,64 @@ +/* +=========================================================================== + + Copyright (c) 2026 LandSandBoat Dev Teams + + 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 http://www.gnu.org/licenses/ + +=========================================================================== +*/ + +#pragma once + +#include "common/logging.h" + +#include "data/all.h" // Automatically generated manifest with every struct/populators +#include "data/backends/yaml.h" +#include "utils/moduleutils.h" + +#include +#include +#include +#include + +namespace xi::data +{ +// Load `data/` dataset. +// Enabled modules with matching filenames get loaded and deep merged into the dataset +template +auto loadDataSet(std::string_view dataPath) -> std::unordered_map +{ + const auto start = std::chrono::steady_clock::now(); + const auto corePath = fmt::format("data/{}{}", dataPath, B::kExtension); + const auto modules = moduleutils::GetDataModules(dataPath, B::kExtension); // Collect all module files matching EXACTLY the same dataPath + auto result = loadAllOf(corePath, modules); // Load main dataset with modules patches applied + const auto ms = std::chrono::duration_cast(std::chrono::steady_clock::now() - start).count(); + + const auto moduleSuffix = modules.empty() + ? std::string{} + : fmt::format(" +{} module{}", modules.size(), modules.size() == 1 ? "" : "s"); + + ShowInfoFmt("[data] {} {} entries loaded in {}ms{}", + dataPath, + result.size(), + ms, + moduleSuffix); + return result; +} +} // namespace xi::data + +inline auto LoadStatusEffects() +{ + return xi::data::loadDataSet("status_effects"); +} diff --git a/src/map/data/node.h b/src/map/data/node.h new file mode 100644 index 00000000000..2a114221deb --- /dev/null +++ b/src/map/data/node.h @@ -0,0 +1,235 @@ +/* +=========================================================================== + + Copyright (c) 2026 LandSandBoat Dev Teams + + 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 http://www.gnu.org/licenses/ + +=========================================================================== +*/ + +#pragma once + +#include "data/enums/enum_traits.h" + +#include +#include +#include +#include +#include + +namespace xi::data +{ + +template +inline constexpr bool isVector = false; + +template +inline constexpr bool isVector> = true; + +template +inline constexpr bool alwaysFalse = false; + +// All data backends must implement this. +template +concept NodeBackend = std::constructible_from && + std::convertible_to && + requires(const typename B::node_t& node, + typename B::mutable_node_t mutableNode, + const typename B::Tree& constTree, + typename B::Tree& mutableTree, + std::string_view key) { + typename B::node_t; + typename B::mutable_node_t; + typename B::Tree; + + { B::kExtension } -> std::convertible_to; + + { constTree.root() } -> std::convertible_to; + { mutableTree.root() } -> std::same_as; + + { B::isMap(node) } -> std::same_as; + { B::isSequence(node) } -> std::same_as; + { B::hasValue(node) } -> std::same_as; + { B::hasChild(node, key) } -> std::same_as; + { B::child(node, key) } -> std::same_as; + { B::key(node) } -> std::convertible_to; + B::children(node); + + { B::template scalarAs(node) } -> std::same_as; + { B::template scalarAs(node) } -> std::same_as; + { B::template scalarAs(node) } -> std::same_as; + { B::template scalarAs(node) } -> std::same_as; + + { B::mergeInto(mutableNode, node) } -> std::same_as; + }; + +template +class Node; + +// T has a codegen'd `populate(Node, type_identity) -> T`. +template +concept Populatable = requires(Node n) { + { populate(n, std::type_identity{}) } -> std::same_as; +}; + +template +class Node +{ +public: + explicit Node(const B::node_t node) + : node_(node) + { + } + + auto raw() const + { + return node_; + } + + auto has(const std::string_view k) const + { + return B::hasChild(node_, k); + } + + auto child(const std::string_view k) const + { + return Node{ B::child(node_, k) }; + } + + auto key() const -> std::string_view + { + return B::key(node_); + } + + auto isMap() const + { + return B::isMap(node_); + } + + auto isSequence() const + { + return B::isSequence(node_); + } + + auto children() const -> std::vector + { + std::vector> out; + for (const auto raw : B::children(node_)) + { + out.emplace_back(raw); + } + + return out; + } + + template + auto read(const std::string_view key) const -> T + { + if (!has(key)) + { + return T{}; + } + + return Node{ B::child(node_, key) }.template as(); + } + + template + auto as() const -> T + { + if constexpr (std::is_arithmetic_v || std::is_same_v) + { + // Scalar leaf. + // + // base_sell: 39 < HERE + if (!B::hasValue(node_)) + { + return T{}; + } + + return B::template scalarAs(node_); + } + else if constexpr (Nameable && isFlagEnum) + { + // Flag enum: sequence of names, OR'd together. + // + // flags: [mystery_box, inscribable] < HERE + if (!B::isSequence(node_)) + { + return T{}; + } + + using U = std::underlying_type_t; + U acc{}; + for (const auto child : children()) + { + acc |= static_cast(EnumTraits::fromName(child.template as())); + } + + return static_cast(acc); + } + else if constexpr (Nameable) + { + // Scalar enum: single name. + // + // type: weapon < HERE + if (!B::hasValue(node_)) + { + return T{}; + } + + return EnumTraits::fromName(B::template scalarAs(node_)); + } + else if constexpr (isVector) + { + // Sequence of records. + // + // mods: + // - { id: attack, value: 10 } < HERE + // - { id: defense, value: 5 } + using V = typename T::value_type; + T out; + if (!B::isSequence(node_)) + { + return out; + } + + for (const auto child : children()) + { + out.push_back(child.template as()); + } + + return out; + } + else if constexpr (Populatable) + { + // Nested record. Hand off to the codegen'd populate. + // + // weapon: < HERE + // skill: dagger + // damage: 3 + return B::isMap(node_) ? populate(*this, std::type_identity{}) : T{}; + } + else + { + static_assert(alwaysFalse, "Node::as: unsupported T"); + return T{}; // unreachable + } + } + +private: + B::node_t node_; +}; + +} // namespace xi::data diff --git a/src/map/status_effect_container.cpp b/src/map/status_effect_container.cpp index c6418bd5a47..b957603f379 100644 --- a/src/map/status_effect_container.cpp +++ b/src/map/status_effect_container.cpp @@ -35,6 +35,7 @@ When a status effect is gained twice on a player. It can do one or more of the f #include #include +#include "data/loader.h" #include "lua/luautils.h" #include "ai/ai_container.h" @@ -88,30 +89,26 @@ void LoadEffectsParameters() EffectsParams[i].Flag = 0; } - const auto rset = db::preparedStmt("SELECT id, name, flags, type, " - "negative_id, overwrite, block_id, remove_id, " - "element, min_duration, sort_key, wear_off_message_id " - "FROM status_effects " - "WHERE id < ?", - MAX_EFFECTID); - FOR_DB_MULTIPLE_RESULTS(rset) + for (const auto& [id, data] : LoadStatusEffects()) { - const auto EffectID = rset->get("id"); - - EffectsParams[EffectID].Name = rset->get("name"); - EffectsParams[EffectID].Flag = rset->get("flags"); - EffectsParams[EffectID].Type = rset->get("type"); - EffectsParams[EffectID].NegativeId = rset->get("negative_id"); - EffectsParams[EffectID].Overwrite = rset->get("overwrite"); - EffectsParams[EffectID].BlockId = rset->get("block_id"); - EffectsParams[EffectID].RemoveId = rset->get("remove_id"); - EffectsParams[EffectID].Element = rset->get("element"); - EffectsParams[EffectID].MinDuration = std::chrono::seconds(rset->get("min_duration")); - const auto sortKey = rset->get("sort_key"); - EffectsParams[EffectID].SortKey = sortKey == 0 ? 10000 : sortKey; // default to high number to such that effects without a sort key aren't first - EffectsParams[EffectID].WearOffMessageId = rset->getOrDefault("wear_off_message_id", MsgStd::EffectWearsOff); - - auto filename = fmt::format("./scripts/effects/{}.lua", EffectsParams[EffectID].Name); + if (id >= MAX_EFFECTID) + { + continue; + } + + EffectsParams[id].Name = data.Name; + EffectsParams[id].Flag = static_cast(data.Flags); + EffectsParams[id].Type = static_cast(data.ExclusionGroup); + EffectsParams[id].NegativeId = static_cast(data.Negative); + EffectsParams[id].Overwrite = static_cast(data.Overwrite); + EffectsParams[id].BlockId = static_cast(data.Block); + EffectsParams[id].RemoveId = static_cast(data.Remove); + EffectsParams[id].Element = static_cast(data.Element); + EffectsParams[id].MinDuration = std::chrono::seconds(data.MinDuration); + EffectsParams[id].SortKey = data.SortKey == 0 ? 10000 : data.SortKey; + EffectsParams[id].WearOffMessageId = data.WearOffMessageId == 0 ? MsgStd::EffectWearsOff : static_cast(data.WearOffMessageId); + + auto filename = fmt::format("./scripts/effects/{}.lua", EffectsParams[id].Name); luautils::CacheLuaObjectFromFile(filename); } } diff --git a/src/map/utils/moduleutils.cpp b/src/map/utils/moduleutils.cpp index 7b2feb3dc01..faaffd6de1c 100644 --- a/src/map/utils/moduleutils.cpp +++ b/src/map/utils/moduleutils.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include namespace @@ -333,6 +334,46 @@ void CleanupLuaModules() overrides.clear(); } +auto GetDataModules(const std::string_view name, const std::string_view extension) -> std::vector +{ + std::vector modules; + std::ifstream file("./modules/init.txt", std::ios_base::in); + if (!file) + { + return modules; + } + + std::unordered_set seenModules; + std::string line; + while (std::getline(file, line)) + { + const auto trimmed = trim(line, " \t\r\n"); + if (trimmed.empty() || trimmed[0] == '#') + { + continue; + } + + std::string moduleName = trimmed; + if (const auto slash = moduleName.find('/'); slash != std::string::npos) + { + moduleName.resize(slash); + } + + if (!seenModules.insert(moduleName).second) + { + continue; + } + + const auto modulePath = fmt::format("./modules/{}/data/{}{}", moduleName, name, extension); + if (std::filesystem::exists(modulePath)) + { + modules.emplace_back(modulePath); + } + } + + return modules; +} + void TryApplyLuaModules(const std::vector& parts, bool isReload) { if (parts.empty()) diff --git a/src/map/utils/moduleutils.h b/src/map/utils/moduleutils.h index cba7a172a9f..9d54d9301bd 100644 --- a/src/map/utils/moduleutils.h +++ b/src/map/utils/moduleutils.h @@ -27,6 +27,7 @@ #include "lua/luautils.h" #include +#include #include // Forward declare @@ -112,6 +113,7 @@ void LoadLuaModules(IPP mapIPP); void CleanupLuaModules(); void TryApplyLuaModules(const std::vector& parts, bool isReload = false); void TryApplyRemainingLuaModules(); +auto GetDataModules(const std::string_view name, const std::string_view extension) -> std::vector; void ReportLuaModuleUsage(); }; // namespace moduleutils diff --git a/tools/codegen/__init__.py b/tools/codegen/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tools/codegen/__main__.py b/tools/codegen/__main__.py new file mode 100644 index 00000000000..9ae637f13cd --- /dev/null +++ b/tools/codegen/__main__.py @@ -0,0 +1,4 @@ +from .cli import main + +if __name__ == "__main__": + main() diff --git a/tools/codegen/cli.py b/tools/codegen/cli.py new file mode 100644 index 00000000000..b23ea236b5f --- /dev/null +++ b/tools/codegen/cli.py @@ -0,0 +1,102 @@ +import argparse +import json +from pathlib import Path + +from .common import ENUMS_DIR, ROOT, TEMPLATES_DIR, write_if_changed +from .data_codegen import SchemaWalker +from .enum_codegen import emit_pure_enum, emit_table_enum +from .validate import validate_data_yamls + + +def inputs_newer_than(stamp: Path) -> bool: + if not stamp.exists(): + return True + stamp_mtime = stamp.stat().st_mtime + schemas_dir = ROOT / "data" / "schemas" + inputs = [ + *Path(__file__).parent.glob("*.py"), + *TEMPLATES_DIR.glob("*.j2"), + *ENUMS_DIR.glob("*.yaml"), + *schemas_dir.glob("*.schema.json"), + *(schemas_dir / "enums").glob("*.codegen.json"), + *(ROOT / "data").glob("*.yaml"), + ] + return any(p.stat().st_mtime > stamp_mtime for p in inputs) + + +def main(): + """No-op if stamp is newer than input files and `--validate` wasn't passed.""" + parser = argparse.ArgumentParser() + parser.add_argument("build_dir") + parser.add_argument( + "--validate", + action="store_true", + help="Also run schema validation.", + ) + args = parser.parse_args() + + build_root = Path(args.build_dir) + stamp = build_root / "generated" / ".codegen.stamp" + if not inputs_newer_than(stamp) and not args.validate: + return + + out_dir = build_root / "generated" / "data" / "enums" + data_out_dir = build_root / "generated" / "data" + lua_out_dir = ROOT / "scripts" / "enum" + keyset_dir = ROOT / "data" / "schemas" / "enums" + for d in (out_dir, data_out_dir, lua_out_dir, keyset_dir): + d.mkdir(parents=True, exist_ok=True) + + # Enums: pure (data/enums/*.yaml) + table-derived (meta.enum: inside a data file). + enums: list[dict] = [] + for p in sorted(ENUMS_DIR.glob("*.yaml")): + enums.append(emit_pure_enum(p)) + for p in sorted((ROOT / "data").rglob("*.yaml")): + if p.is_relative_to(ENUMS_DIR): + continue + print(f"scanning {p.relative_to(ROOT).as_posix()} for embedded enum ...", flush=True) + result = emit_table_enum(p) + if result is not None: + enums.append(result) + + for e in enums: + write_if_changed(out_dir / (e["name"] + ".h"), e["header"]) + if e["lua"]: + write_if_changed(lua_out_dir / (e["lua"]["name"] + ".codegen.lua"), e["lua"]["content"]) + # Keyset schema lets other schemas $ref the list of valid values for IDE completion + CI checks. + keyset = { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": f"enums/{e['name']}.codegen.json", + "description": f"GENERATED from {e['source_name']}. Do not edit.", + "type": "string", + "enum": list(e["values"].keys()), + } + write_if_changed(keyset_dir / (e["name"] + ".codegen.json"), json.dumps(keyset, indent=2) + "\n") + + schemas_dir = ROOT / "data" / "schemas" + walker = SchemaWalker() + data_names: list[str] = [] + for schema_path in sorted(schemas_dir.glob("*.schema.json")): + print(f"rendering {schema_path.relative_to(ROOT).as_posix()} ...", flush=True) + result = walker.emit(schema_path) + if result is None: + continue + write_if_changed(data_out_dir / (result["name"] + ".h"), result["pod"]) + write_if_changed(data_out_dir / (result["name"] + "_populator.h"), result["populator"]) + data_names.append(result["name"]) + + manifest_lines = ["// GENERATED by tools/codegen. Do not edit.", "#pragma once", ""] + for name in sorted(data_names): + manifest_lines.append(f'#include "data/{name}.h"') + manifest_lines.append(f'#include "data/{name}_populator.h"') + write_if_changed(data_out_dir / "all.h", "\n".join(manifest_lines) + "\n") + + stamp.parent.mkdir(parents=True, exist_ok=True) + stamp.touch() + + if args.validate: + validate_data_yamls(schemas_dir, keyset_dir, build_root) + + +if __name__ == "__main__": + main() diff --git a/tools/codegen/common.py b/tools/codegen/common.py new file mode 100644 index 00000000000..2f609558dce --- /dev/null +++ b/tools/codegen/common.py @@ -0,0 +1,70 @@ +import re +from pathlib import Path +from typing import Any, Callable + +from jinja2 import Environment, FileSystemLoader, StrictUndefined + +ROOT: Path = Path(__file__).resolve().parents[2] +ENUMS_DIR: Path = ROOT / "data" / "enums" +TEMPLATES_DIR: Path = Path(__file__).resolve().parent / "templates" + +ENV: Environment = Environment( + loader=FileSystemLoader(TEMPLATES_DIR), + undefined=StrictUndefined, + trim_blocks=True, + lstrip_blocks=True, + keep_trailing_newline=True, +) + + +def snake_to_pascal(s: str) -> str: + """status_effect_flag -> StatusEffectFlag""" + return "".join(part.capitalize() for part in s.split("_") if part) + + +def pascal_to_snake(s: str) -> str: + """StatusEffectFlag -> status_effect_flag""" + return re.sub(r"(? str: + s = s.lower() + s = _SLUG_PLUS.sub(r"p\1", s) + s = _SLUG_MINUS.sub(r"m\1", s) + s = _SLUG_STRIP.sub("", s) + s = _SLUG_SEP.sub("_", s) + s = _SLUG_REST.sub("", s) + s = re.sub(r"__+", "_", s).strip("_") + if s and s[0].isdigit(): + s = "i_" + s + return s + + +def dotpath_get(d: dict[str, Any], path: str) -> Any: + """`name.en` -> d["name"]["en"]""" + cur: Any = d + for part in path.split("."): + cur = cur.get(part) if isinstance(cur, dict) else None + if cur is None: + return None + return cur + + +def write_if_changed(path: Path, content: str) -> None: + if path.exists() and path.read_text(encoding="utf-8") == content: + return + path.write_text(content, encoding="utf-8") + print(f"wrote {path}") + diff --git a/tools/codegen/data_codegen.py b/tools/codegen/data_codegen.py new file mode 100644 index 00000000000..bf73e7eb748 --- /dev/null +++ b/tools/codegen/data_codegen.py @@ -0,0 +1,264 @@ +import json +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Literal + +import yaml +from jsonschema import Draft202012Validator, exceptions as jsonschema_exceptions + +from .common import CASE_FNS, ENUMS_DIR, ENV, ROOT, snake_to_pascal +from .yaml_loaders import FastLoader + + +PopulatorKind = Literal["scalar", "enum_ref", "bitflags", "enum_list", "record", "record_list"] + + +@dataclass(slots=True) +class Field: + """`populator` drives the template dispatch. enum_* set on enum_ref/bitflags/enum_list; defs_*/struct_* on record/record_list.""" + + yaml_name: str + cpp_name: str + cpp_type: str + populator: PopulatorKind + enum_name: str = "" + enum_class: str = "" + defs_name: str = "" + struct_name: str = "" + default: str = "" # C++-literal form of schema `default`, empty when not declared. + + +class SchemaWalker: + """One instance per codegen run; caches each enum YAML lookup so we open the file at most once.""" + + def __init__(self) -> None: + self.enum_cls_cache: dict[str, str] = {} + self.enum_flags_cache: dict[str, bool] = {} + self.enum_case_cache: dict[str, str] = {} + + def _load_enum_meta(self, name: str) -> dict[str, Any]: + yaml_path = ENUMS_DIR / f"{name}.yaml" + if not yaml_path.exists(): + return {} + with yaml_path.open(encoding="utf-8") as f: + return (yaml.load(f, Loader=FastLoader) or {}).get("meta") or {} + + def enum_is_flags(self, name: str) -> bool: + if name not in self.enum_flags_cache: + self.enum_flags_cache[name] = bool(self._load_enum_meta(name).get("flags", False)) + return self.enum_flags_cache[name] + + def enum_case(self, name: str) -> str: + if name not in self.enum_case_cache: + self.enum_case_cache[name] = (self._load_enum_meta(name).get("cpp") or {}).get("case", "pascal") + return self.enum_case_cache[name] + + def enum_default(self, enum_name: str, cls: str, value: str) -> str: + case_fn = CASE_FNS.get(self.enum_case(enum_name), snake_to_pascal) + return f"xi::{cls}::{case_fn(value)}" + + def enum_ref_to_class(self, ref: str) -> tuple[str, str]: + """`enums/item_flag.codegen.json` -> `("item_flag", "ItemFlag")`. Honors meta.cpp.class when set.""" + enum_name = ref.rsplit("/", 1)[-1].replace(".codegen.json", "") + if enum_name not in self.enum_cls_cache: + yaml_path = ENUMS_DIR / f"{enum_name}.yaml" + cls: str | None = None + if yaml_path.exists(): + with yaml_path.open(encoding="utf-8") as f: + doc = yaml.load(f, Loader=FastLoader) or {} + cls = ((doc.get("meta") or {}).get("cpp") or {}).get("class") + self.enum_cls_cache[enum_name] = cls or snake_to_pascal(enum_name) + return enum_name, self.enum_cls_cache[enum_name] + + @staticmethod + def defs_ref_to_struct(ref: str) -> tuple[str, str]: + """`#/$defs/item_weapon` -> `("item_weapon", "ItemWeaponData")`""" + defs_name = ref.rsplit("/", 1)[-1] + return defs_name, snake_to_pascal(defs_name) + "Data" + + @staticmethod + def int_cpp_type(schema: dict[str, Any]) -> str: + """Narrowest C++ int type that covers [minimum, maximum].""" + lo, hi = schema.get("minimum"), schema.get("maximum") + if lo is not None and lo < 0: + if lo >= -128 and hi is not None and hi <= 127: + return "int8" + if lo >= -32768 and hi is not None and hi <= 32767: + return "int16" + return "int32" + if hi is not None and hi <= 255: + return "uint8" + if hi is not None and hi <= 65535: + return "uint16" + return "uint32" + + @staticmethod + def scalar_default(schema: dict[str, Any]) -> str: + """Format the schema's `default` as a C++ literal. Empty string when no default is declared.""" + if "default" not in schema: + return "" + v = schema["default"] + if isinstance(v, bool): + return "true" if v else "false" + if isinstance(v, (int, float)): + return str(v) + if isinstance(v, str): + return f'"{v}"' + return "" + + def field_from_schema(self, name: str, schema: dict[str, Any]) -> Field: + cpp_name = snake_to_pascal(name) + + ref = schema.get("$ref") + if ref and ref.startswith("enums/"): + enum_name, cls = self.enum_ref_to_class(ref) + default = self.enum_default(enum_name, cls, schema["default"]) if isinstance(schema.get("default"), str) else "" + return Field(yaml_name=name, cpp_name=cpp_name, cpp_type=f"xi::{cls}", + populator="enum_ref", enum_name=enum_name, enum_class=cls, default=default) + if ref and ref.startswith("#/$defs/"): + defs_name, struct = self.defs_ref_to_struct(ref) + return Field(yaml_name=name, cpp_name=cpp_name, cpp_type=struct, + populator="record", defs_name=defs_name, struct_name=struct) + + items = schema.get("items") if schema.get("type") == "array" else None + if isinstance(items, dict) and "$ref" in items: + iref = items["$ref"] + if iref.startswith("enums/"): + enum_name, cls = self.enum_ref_to_class(iref) + if self.enum_is_flags(enum_name): + # Flag enums collapse to a single OR'd value, not a list. + default = self.enum_default(enum_name, cls, schema["default"]) if isinstance(schema.get("default"), str) else "" + return Field(yaml_name=name, cpp_name=cpp_name, cpp_type=f"xi::{cls}", + populator="bitflags", enum_name=enum_name, enum_class=cls, default=default) + return Field(yaml_name=name, cpp_name=cpp_name, cpp_type=f"std::vector", + populator="enum_list", enum_name=enum_name, enum_class=cls) + if iref.startswith("#/$defs/"): + defs_name, struct = self.defs_ref_to_struct(iref) + return Field(yaml_name=name, cpp_name=cpp_name, cpp_type=f"std::vector<{struct}>", + populator="record_list", defs_name=defs_name, struct_name=struct) + + t = schema.get("type") + default = self.scalar_default(schema) + if t == "integer": + return Field(yaml_name=name, cpp_name=cpp_name, cpp_type=self.int_cpp_type(schema), populator="scalar", default=default) + if t == "number": + return Field(yaml_name=name, cpp_name=cpp_name, cpp_type="float", populator="scalar", default=default) + if t == "boolean": + return Field(yaml_name=name, cpp_name=cpp_name, cpp_type="bool", populator="scalar", default=default) + if t == "string": + return Field(yaml_name=name, cpp_name=cpp_name, cpp_type="std::string", populator="scalar", default=default) + + raise ValueError(f"unsupported property '{name}' schema: {schema}") + + def variant_arms_from_oneof(self, one_of: list[dict[str, Any]]) -> list[dict[str, Any]]: + """Bodyless arm when the branch has no `required`; otherwise `required[0]` names the body field whose `$ref` points at the subtype `$defs`.""" + arms: list[dict[str, Any]] = [] + for branch in one_of: + props = branch.get("properties") or {} + type_prop = props.get("type") or {} + required = branch.get("required") or [] + type_values = [type_prop["const"]] if "const" in type_prop else type_prop.get("enum", []) + + if not required: + for tv in type_values: + arms.append( + {"type_value": tv, "cpp_name": snake_to_pascal(tv), "yaml_key": None, "struct_name": None, + "defs_name": None}) + continue + + yaml_key = required[0] + body_schema = props.get(yaml_key) or {} + if "$ref" not in body_schema: + raise ValueError(f"oneOf branch's '{yaml_key}' is not a $ref to $defs") + defs_name, struct = self.defs_ref_to_struct(body_schema["$ref"]) + for tv in type_values: + arms.append( + {"type_value": tv, "cpp_name": snake_to_pascal(tv), "yaml_key": yaml_key, "struct_name": struct, + "defs_name": defs_name}) + return arms + + @staticmethod + def find_main_defs(schema: dict[str, Any]) -> str | None: + """The main record's `$defs` key: the section's `additionalProperties.$ref`, or the lone `$defs` entry if there's only one.""" + section_schema = next( + (s for s in (schema.get("properties") or {}).values() if + isinstance(s, dict) and "additionalProperties" in s), + None, + ) + if section_schema: + addl = section_schema["additionalProperties"] + if isinstance(addl, dict) and "$ref" in addl: + return SchemaWalker.defs_ref_to_struct(addl["$ref"])[0] + defs = schema.get("$defs") or {} + return next(iter(defs.keys())) if len(defs) == 1 else None + + def emit(self, schema_path: Path) -> dict[str, Any] | None: + """Returns None when the schema has no main `$defs` (e.g. shared _meta). Sub-PODs emit before the main one so it can reference them.""" + with schema_path.open(encoding="utf-8") as f: + schema = json.load(f) + + try: + Draft202012Validator.check_schema(schema) + except jsonschema_exceptions.SchemaError as e: + raise SystemExit(f"{schema_path.relative_to(ROOT)}: not a valid JSON Schema 2020-12: {e.message}") + + defs = schema.get("$defs") or {} + main_name = self.find_main_defs(schema) if defs else None + if not main_name or main_name not in defs: + return None + + name = schema_path.stem.replace(".schema", "") + source = str(schema_path.relative_to(ROOT)).replace("\\", "/") + + pods: list[dict[str, Any]] = [] + main_pod: dict[str, Any] | None = None + for defs_name in [n for n in defs if n != main_name] + [main_name]: + props = defs[defs_name].get("properties") or {} + fields = [self.field_from_schema(name, fs) for name, fs in props.items()] + pod = { + "struct_name": snake_to_pascal(defs_name) + "Data", + "fields": fields, + "required": set(defs[defs_name].get("required") or []), + "cpp_type_width": max((len(f.cpp_type) for f in fields), default=0), + "is_main": defs_name == main_name, + "variant_arms": [], + "discriminator_field": None, + "discriminator_enum": None, + } + if pod["is_main"]: + main_pod = pod + pods.append(pod) + + one_of = defs[main_name].get("oneOf") + if one_of and main_pod is not None: + main_pod["variant_arms"] = self.variant_arms_from_oneof(one_of) + disc = next((f for f in main_pod["fields"] if f.populator == "enum_ref"), None) + if disc is not None: + main_pod["discriminator_field"] = disc.cpp_name + main_pod["discriminator_enum"] = disc.enum_class + + # id: on the record => driver reads it; otherwise the YAML key is the integer id. + has_id_field = any(f.yaml_name == "id" for f in main_pod["fields"]) + main_pod["key_source"] = "yaml_field" if has_id_field else "yaml_key" + if main_pod["key_source"] == "yaml_key": + main_pod["fields"].insert(0, Field(yaml_name="id", cpp_name="Id", cpp_type="uint16", populator="scalar")) + main_pod["cpp_type_width"] = max(len(f.cpp_type) for f in main_pod["fields"]) + + main_pod["name_default_from_key"] = main_pod["key_source"] == "yaml_field" and any( + f.yaml_name == "name" for f in main_pod["fields"]) + + enum_includes = {f.enum_name for pod in pods for f in pod["fields"] if f.enum_name} + + ctx = dict( + source=source, + name=name, + section_name=name, + main_pod=main_pod, + pods=pods, + enum_includes=sorted(enum_includes), + ) + return { + "name": name, + "pod": ENV.get_template("data_pod.h.j2").render(**ctx), + "populator": ENV.get_template("data_populator.h.j2").render(**ctx), + } diff --git a/tools/codegen/enum_codegen.py b/tools/codegen/enum_codegen.py new file mode 100644 index 00000000000..b2658c4a472 --- /dev/null +++ b/tools/codegen/enum_codegen.py @@ -0,0 +1,160 @@ +from pathlib import Path +from typing import Any + +import yaml + +from .common import ( + CASE_FNS, + ENUMS_DIR, + ENV, + dotpath_get, + pascal_to_snake, + slug, + snake_to_pascal, +) +from .yaml_loaders import FastLoader + + +def render_header(*, source_name: str, cls_name: str, underlying: str, is_flags: bool, case: str, values: dict[str, int]) -> str: + if case not in CASE_FNS: + raise ValueError(f"unknown enum case {case!r}; expected one of {sorted(CASE_FNS)}") + cpp_names = {k: CASE_FNS[case](k) for k in values} + return ENV.get_template("enum.h.j2").render( + source_name=source_name, + cls_name=cls_name, + underlying=underlying, + is_flags=is_flags, + values=values, + cpp_names=cpp_names, + enum_width=max(len(n) for n in cpp_names.values()), + quote_width=max(len(k) for k in values) + 2, + ) + + +def render_lua(*, source_name: str, lua_table: str, is_flags: bool, values: dict[str, int]) -> str: + """Identifiers are the YAML key uppercased: `no_erase` -> `NO_ERASE`.""" + lua_names = {k: k.upper() for k in values} + return ENV.get_template("enum.lua.j2").render( + source_name=source_name, + lua_table=lua_table, + is_flags=is_flags, + values=values, + lua_names=lua_names, + name_width=max(len(n) for n in lua_names.values()), + ) + + +def lua_block(lua_meta: dict[str, Any] | None, source_name: str, is_flags: bool, values: dict[str, int]) -> dict[str, str] | None: + if not lua_meta or "table" not in lua_meta: + return None + table = lua_meta["table"] + return { + "name": pascal_to_snake(table.removeprefix("xi.")), + "content": render_lua(source_name=source_name, lua_table=table, is_flags=is_flags, values=values), + } + + +def emit_pure_enum(yaml_path: Path) -> dict[str, Any]: + with yaml_path.open(encoding="utf-8") as f: + doc = yaml.load(f, Loader=FastLoader) + + meta = doc.get("meta") or {} + values = doc.get("values") or {} + if not values: + raise ValueError(f"{yaml_path.name}: no values: block") + + cpp = meta.get("cpp") or {} + cls_name = cpp.get("class") or snake_to_pascal(yaml_path.stem) + source_name = f"data/enums/{yaml_path.name}" + is_flags = bool(meta.get("flags", False)) + return { + "name": yaml_path.stem, + "values": values, + "source_name": source_name, + "header": render_header( + source_name=source_name, + cls_name=cls_name, + underlying=cpp.get("underlying", "uint32_t"), + is_flags=is_flags, + case=cpp.get("case", "pascal"), + values=values, + ), + "lua": lua_block(meta.get("lua"), source_name, is_flags, values), + } + + +def emit_table_enum(yaml_path: Path) -> dict[str, Any] | None: + """Same return shape as `emit_pure_enum`. Returns None when the file has no `meta.enum:` block.""" + with yaml_path.open(encoding="utf-8") as f: + doc = yaml.load(f, Loader=FastLoader) + + if not isinstance(doc, dict): + return None + meta_enum = (doc.get("meta") or {}).get("enum") + if not meta_enum: + return None + + section_name = meta_enum.get("section") or yaml_path.stem + section = doc.get(section_name) or {} + if not section: + raise ValueError(f"{yaml_path}: no '{section_name}' section to derive enum from") + + values = derive_values(yaml_path, section, meta_enum.get("name_from")) + + cpp = meta_enum.get("cpp") or {} + cls_name = cpp["class"] + source_name = str(yaml_path.relative_to(ENUMS_DIR.parents[1])).replace("\\", "/") + return { + "name": pascal_to_snake(cls_name), + "values": values, + "source_name": source_name, + "header": render_header( + source_name=source_name, + cls_name=cls_name, + underlying=cpp.get("underlying", "uint32_t"), + is_flags=False, + case=cpp.get("case", "pascal"), + values=values, + ), + "lua": lua_block(meta_enum.get("lua"), source_name, False, values), + } + + +def derive_values(yaml_path: Path, section: dict[str, Any], name_from: str | None) -> dict[str, int]: + """ + Returns {enum_name: int_value} from a YAML section. + + If `name_from` is set, YAML keys are the int ids and the enum name is slugged from the + string at that dotpath (e.g. `name.en`). Otherwise the YAML key is the enum name and the + int comes from the entry's `id:` field, or from the key itself if it's already an integer. + """ + if not name_from: + values: dict[str, int] = {} + for key, entry in section.items(): + if isinstance(entry, dict) and "id" in entry: + values[str(key)] = int(entry["id"]) + continue + try: + values[str(key)] = int(key) + except (TypeError, ValueError): + raise ValueError(f"{yaml_path}: entry '{key}' has no id: field and the key is not an integer") + return values + + slug_to_ids: dict[str, list[int]] = {} + for key, entry in section.items(): + raw = dotpath_get(entry, name_from) if isinstance(entry, dict) else None + if not isinstance(raw, str): + raise ValueError(f"{yaml_path}: entry {key!r} has no string at {name_from}") + s = slug(raw) + if not s: + raise ValueError(f"{yaml_path}: entry {key!r} slugged to empty from {raw!r}") + slug_to_ids.setdefault(s, []).append(int(key)) + + out: dict[str, int] = {} + for s, ids in slug_to_ids.items(): + if len(ids) == 1: + out[s] = ids[0] + else: + for i in ids: + out[f"{s}_{i}"] = i + return out diff --git a/tools/codegen/templates/data_pod.h.j2 b/tools/codegen/templates/data_pod.h.j2 new file mode 100644 index 00000000000..8167c6d5c37 --- /dev/null +++ b/tools/codegen/templates/data_pod.h.j2 @@ -0,0 +1,45 @@ +// GENERATED from {{ source }}. Do not edit. +#pragma once + +#include "common/cbasetypes.h" +{% for inc in enum_includes %} +#include "data/enums/{{ inc }}.h" +{% endfor %} + +#include +#include +{% if main_pod.variant_arms %} +#include +{% endif %} + +namespace xi::data +{ + +{% for pod in pods if not pod.is_main %} +struct {{ pod.struct_name }} +{ +{% for f in pod.fields %} + {{ "%-*s"|format(pod.cpp_type_width, f.cpp_type) }} {{ f.cpp_name }}{ {{- f.default -}} }; +{% endfor %} +}; + +{% endfor %} +{% if main_pod.variant_arms %} +using {{ main_pod.struct_name }}Payload = std::variant; + +{% endif %} +struct {{ main_pod.struct_name }} +{ +{% for f in main_pod.fields %} + {{ "%-*s"|format(main_pod.cpp_type_width, f.cpp_type) }} {{ f.cpp_name }}{ {{- f.default -}} }; +{% endfor %} +{% if main_pod.variant_arms %} + {{ "%-*s"|format(main_pod.cpp_type_width, main_pod.struct_name + "Payload") }} Payload{}; +{% endif %} +}; + +} // namespace xi::data diff --git a/tools/codegen/templates/data_populator.h.j2 b/tools/codegen/templates/data_populator.h.j2 new file mode 100644 index 00000000000..d0c85b2e5c8 --- /dev/null +++ b/tools/codegen/templates/data_populator.h.j2 @@ -0,0 +1,90 @@ +// GENERATED from {{ source }}. Do not edit. +#pragma once + +#include "data/{{ name }}.h" +#include "data/load.h" +#include "data/node.h" +{% for inc in enum_includes %} +#include "data/enums/{{ inc }}.h" +{% endfor %} + +#include +#include +#include +#include + +namespace xi::data +{ + +{% for pod in pods if not pod.is_main %} +template +auto populate(const Node node, std::type_identity<{{ pod.struct_name }}>) -> {{ pod.struct_name }} +{ + return {{ pod.struct_name }}{ +{% for f in pod.fields %} +{% if f.default %} + .{{ f.cpp_name }} = node.has("{{ f.yaml_name }}") ? node.template read<{{ f.cpp_type }}>("{{ f.yaml_name }}") : {{ f.cpp_type }}{ {{- f.default -}} }, +{% else %} + .{{ f.cpp_name }} = node.template read<{{ f.cpp_type }}>("{{ f.yaml_name }}"), +{% endif %} +{% endfor %} + }; +} + +{% endfor %} +template +auto populate(const Node node, std::type_identity<{{ main_pod.struct_name }}>) -> {{ main_pod.struct_name }} +{ + return {{ main_pod.struct_name }}{ +{% for f in main_pod.fields %} +{% if f.yaml_name == "id" %} +{% elif f.yaml_name == "name" and main_pod.name_default_from_key %} + .Name = node.has("name") ? node.template read("name") : std::string(node.key()), +{% elif f.default %} + .{{ f.cpp_name }} = node.has("{{ f.yaml_name }}") ? node.template read<{{ f.cpp_type }}>("{{ f.yaml_name }}") : {{ f.cpp_type }}{ {{- f.default -}} }, +{% else %} + .{{ f.cpp_name }} = node.template read<{{ f.cpp_type }}>("{{ f.yaml_name }}"), +{% endif %} +{% endfor %} + }; +} + +template +auto populateMap(const Node root, std::type_identity<{{ main_pod.struct_name }}>) -> std::unordered_map +{ + return populateMapDriver<{{ main_pod.struct_name }}, B>( + root, + "{{ section_name }}", +{% if main_pod.key_source == "yaml_field" %} + IdSource::YAMLField, +{% else %} + IdSource::YAMLKey, +{% endif %} + "{{ source }}", + [](const Node child, const auto id) { + auto data = populate(child, std::type_identity<{{ main_pod.struct_name }}>{}); + data.Id = id; +{% if main_pod.variant_arms %} + switch (data.{{ main_pod.discriminator_field }}) + { +{% for arm in main_pod.variant_arms if arm.struct_name %} + case xi::{{ main_pod.discriminator_enum }}::{{ arm.cpp_name }}: + data.Payload = child.template read<{{ arm.struct_name }}>("{{ arm.yaml_key }}"); + break; +{% endfor %} +{% for arm in main_pod.variant_arms if not arm.struct_name %} + case xi::{{ main_pod.discriminator_enum }}::{{ arm.cpp_name }}: + break; +{% endfor %} + default: + throw std::runtime_error(fmt::format( + "{{ main_pod.struct_name }}: unhandled discriminator '{}' for id {}", + EnumTraits::toName(data.{{ main_pod.discriminator_field }}), + data.Id)); + } +{% endif %} + return data; + }); +} + +} // namespace xi::data diff --git a/tools/codegen/templates/enum.h.j2 b/tools/codegen/templates/enum.h.j2 new file mode 100644 index 00000000000..7c963719b33 --- /dev/null +++ b/tools/codegen/templates/enum.h.j2 @@ -0,0 +1,58 @@ +// GENERATED from {{ source_name }}. Do not edit. +#pragma once + +#include +#include +#include +#include +{% if is_flags %} +#include +{% endif %} + +#include "data/enums/enum_traits.h" + +namespace xi +{ +enum class {{ cls_name }} : {{ underlying }} +{ +{% for key, val in values.items() %} + {{ "%-*s"|format(enum_width, cpp_names[key]) }} = {{ "0x%08x"|format(val) if is_flags else val }}, +{% endfor %} +}; +{% if is_flags %} + +using namespace magic_enum::bitwise_operators; +{% endif %} +} // namespace xi + +namespace xi::data +{ + +template <> +struct EnumTraits +{ + static constexpr std::string_view kTypeName{ "{{ cls_name }}" }; + + static constexpr std::array, {{ values|length }}> kEntries{ { +{% for key in values %} + std::pair{ std::string_view{ {{ "%-*s"|format(quote_width, '"' + key + '"') }} }, xi::{{ cls_name }}::{{ cpp_names[key] }} }, +{% endfor %} + } }; + + static auto fromName(const std::string_view name) -> xi::{{ cls_name }} + { + return enum_detail::fromName(name, kEntries, kTypeName); + } + + static auto toName(const xi::{{ cls_name }} value) -> std::string_view + { + return enum_detail::toName(value, kEntries); + } +}; +{% if is_flags %} + +template <> +inline constexpr bool isFlagEnum = true; +{% endif %} + +} // namespace xi::data diff --git a/tools/codegen/templates/enum.lua.j2 b/tools/codegen/templates/enum.lua.j2 new file mode 100644 index 00000000000..0c5bfa40844 --- /dev/null +++ b/tools/codegen/templates/enum.lua.j2 @@ -0,0 +1,10 @@ +-- GENERATED from {{ source_name }}. Do not edit. +xi = xi or {} + +---@enum {{ lua_table }} +{{ lua_table }} = +{ +{% for key, val in values.items() %} + {{ "%-*s"|format(name_width, lua_names[key]) }} = {{ "0x%08x"|format(val) if is_flags else val }}, +{% endfor %} +} diff --git a/tools/codegen/validate.py b/tools/codegen/validate.py new file mode 100644 index 00000000000..ae129a54b4a --- /dev/null +++ b/tools/codegen/validate.py @@ -0,0 +1,208 @@ +import json +import re +import sys +import time +from collections import defaultdict +from pathlib import Path +from typing import Any + +import yaml +from jsonschema import Draft202012Validator + +from .common import ROOT +from .yaml_loaders import LineLoader, node_line + + +def validate_data_yamls(schemas_dir: Path, keyset_dir: Path, build_root: Path) -> None: + """Per-file stamps under /generated/.validated..stamp skip yamls that haven't changed.""" + registry = build_registry(schemas_dir, keyset_dir) + schema_side_mtime = max( + ( + p.stat().st_mtime + for p in [ + Path(__file__), + *schemas_dir.glob("*.schema.json"), + *schemas_dir.glob("_*.schema.json"), + *keyset_dir.glob("*.codegen.json"), + ] + ), + default=0.0, + ) + + all_errors: list[tuple[Path, int, Any]] = [] + root_by_file: dict[Path, Any] = {} + for schema_path in sorted(schemas_dir.glob("*.schema.json")): + data_path = ROOT / "data" / f"{schema_path.stem.removesuffix('.schema')}.yaml" + if not data_path.exists(): + continue + stamp = build_root / "generated" / f".validated.{data_path.stem}.stamp" + if stamp.exists() and data_path.stat().st_mtime <= stamp.stat().st_mtime and schema_side_mtime <= stamp.stat().st_mtime: + continue + + rel = data_path.relative_to(ROOT).as_posix() + print(f"validating {rel} ...", end="", flush=True) + with schema_path.open(encoding="utf-8") as f: + schema = json.load(f) + with data_path.open(encoding="utf-8") as f: + data = yaml.load(f, Loader=LineLoader) + root_by_file[data_path] = data + + start = time.monotonic() + validator = Draft202012Validator(schema, registry=registry) + errs = [(data_path, node_line(data, list(e.absolute_path)), e) for e in validator.iter_errors(data)] + elapsed_ms = int((time.monotonic() - start) * 1000) + if errs: + print(f" {len(errs)} errors ({elapsed_ms} ms)", flush=True) + all_errors.extend(errs) + else: + print(f" ok ({elapsed_ms} ms)", flush=True) + stamp.parent.mkdir(parents=True, exist_ok=True) + stamp.touch() + + if all_errors: + print_errors(all_errors, root_by_file) + sys.exit(1) + + +def build_registry(schemas_dir: Path, keyset_dir: Path) -> Any: + from referencing import Registry, Resource + from referencing.jsonschema import DRAFT202012 + + reg = Registry() + for p in keyset_dir.glob("*.codegen.json"): + with p.open(encoding="utf-8") as f: + doc = json.load(f) + reg = reg.with_resource(uri=f"enums/{p.name}", resource=Resource(contents=doc, specification=DRAFT202012)) + for p in schemas_dir.glob("_*.schema.json"): + with p.open(encoding="utf-8") as f: + doc = json.load(f) + reg = reg.with_resource(uri=p.name, resource=Resource(contents=doc, specification=DRAFT202012)) + return reg + + +def entity_context(root: Any, absolute_path: list[Any]) -> str | None: + if not isinstance(root, dict) or len(absolute_path) < 2: + return None + section, key = str(absolute_path[0]), absolute_path[1] + section_node = root.get(section) + if not isinstance(section_node, dict): + return None + label = f"{section}[{key}]" if isinstance(key, int) else f"{section}.{key}" + entity = section_node.get(key) + if isinstance(entity, dict): + name = entity.get("name") + if isinstance(name, dict): + name = name.get("en") + if isinstance(name, str) and name: + label += f" {name}" + return label + + +def norm_path(absolute_path: list[Any]) -> str: + """List indices collapse to [*] so identical errors across 14k rows group into one.""" + parts: list[str] = [] + for p in absolute_path: + if isinstance(p, int): + parts.append("[*]") + else: + if parts: + parts.append(".") + parts.append(str(p)) + return "".join(parts) or "" + + +_REQUIRED_RE = re.compile(r"'([^']+)' is a required property") + + +def short_error(err: Any) -> str: + v = err.validator + if v == "enum": + sid = err.schema.get("$id", "") if isinstance(err.schema, dict) else "" + if sid.startswith("enums/") and sid.endswith(".codegen.json"): + return f"value {err.instance!r} is not a valid {sid[len('enums/'):-len('.codegen.json')]}" + return f"value {err.instance!r} not in enum" + if v == "type": + got = "null" if err.instance is None else type(err.instance).__name__ + return f"expected {err.validator_value}, got {got}" + if v == "required": + m = _REQUIRED_RE.search(err.message) + return f"missing required field {m.group(1)!r}" if m else err.message + if v == "oneOf": + return explain_oneof(err) + if v == "unevaluatedProperties": + return err.message + return err.message if len(err.message) <= 160 else err.message[:160] + " ..." + + +def explain_oneof(err: Any) -> str: + inst = err.instance if isinstance(err.instance, dict) else None + type_value = inst.get("type") if inst else None + if not type_value: + return "no oneOf branch matched (missing 'type' field)" + + branch_idx = None + for i, branch in enumerate(err.schema.get("oneOf", [])): + tp = branch.get("properties", {}).get("type", {}) + if tp.get("const") == type_value or type_value in (tp.get("enum") or []): + branch_idx = i + break + if branch_idx is None: + return f"type={type_value!r} not allowed by any oneOf branch" + + branch_errs = [e for e in err.context if e.schema_path and e.schema_path[0] == branch_idx] + if not branch_errs: + return f"type={type_value!r}: matched but no detail" + + deepest = max(branch_errs, key=lambda e: len(e.absolute_path)) + if deepest.validator == "type" and deepest.instance is None and deepest.absolute_path: + return f"type={type_value!r} but '{deepest.absolute_path[-1]}:' block is null (expected fields)" + if deepest.validator == "required": + m = _REQUIRED_RE.search(deepest.message) + if m: + return f"type={type_value!r} but '{m.group(1)}:' block is missing" + return f"type={type_value!r}: {short_error(deepest)}" + + +def print_errors(all_errors: list[tuple[Path, int, Any]], root_by_file: dict[Path, Any]) -> None: + """Suppress type errors paired with an enum error (same cause); same for unevaluatedProperties paired with oneOf.""" + suppress_type: set[tuple[Path, tuple[Any, ...]]] = set() + suppress_uneval: set[tuple[Path, tuple[Any, ...]]] = set() + for fpath, _line, err in all_errors: + loc = (fpath, tuple(err.absolute_path)) + if err.validator == "enum": + suppress_type.add(loc) + elif err.validator == "oneOf": + suppress_uneval.add(loc) + + groups: dict[tuple[Path, str, str], list[tuple[int, Any]]] = defaultdict(list) + for fpath, line, err in all_errors: + loc = (fpath, tuple(err.absolute_path)) + if err.validator == "type" and loc in suppress_type: + continue + if err.validator == "unevaluatedProperties" and loc in suppress_uneval: + continue + groups[(fpath, norm_path(err.absolute_path), err.validator)].append((line, err)) + + total = sum(len(v) for v in groups.values()) + by_file: dict[Path, list[tuple[str, str, list[tuple[int, Any]]]]] = defaultdict(list) + for (fpath, npath, validator), items in groups.items(): + by_file[fpath].append((npath, validator, items)) + + print(f"\n{total} errors, {len(groups)} patterns", file=sys.stderr) + + for fpath, entries in sorted(by_file.items(), key=lambda kv: kv[0].name): + abs_path = str(fpath.resolve()) + root = root_by_file.get(fpath) + print(f"\n {abs_path}", file=sys.stderr) + entries.sort(key=lambda e: (e[0], e[1])) + for npath, _validator, items in entries: + lead_line, lead_err = items[0] + print(f"\n [{len(items):>4}] {npath}", file=sys.stderr) + print(f" {short_error(lead_err)}", file=sys.stderr) + ctx = entity_context(root, list(lead_err.absolute_path)) or "" + print(f" {abs_path}:{lead_line}:1 {ctx}", file=sys.stderr) + for ln, err2 in items[1:3]: + ctx2 = entity_context(root, list(err2.absolute_path)) or "" + print(f" {abs_path}:{ln}:1 {ctx2}", file=sys.stderr) + if len(items) > 3: + print(f" ... and {len(items) - 3} more", file=sys.stderr) diff --git a/tools/codegen/yaml_loaders.py b/tools/codegen/yaml_loaders.py new file mode 100644 index 00000000000..02747ae9a27 --- /dev/null +++ b/tools/codegen/yaml_loaders.py @@ -0,0 +1,39 @@ +from typing import Any + +import yaml + +try: + from yaml import CSafeLoader as FastLoader +except ImportError: + from yaml import SafeLoader as FastLoader + + +class LinedDict(dict): + __line__: int = 0 + + +class LineLoader(yaml.SafeLoader): + """SafeLoader variant that materializes mappings as LinedDict.""" + + +def construct_lined_mapping(loader: yaml.Loader, node: yaml.MappingNode) -> LinedDict: + m = LinedDict(loader.construct_mapping(node, deep=True)) + m.__line__ = node.start_mark.line + 1 + return m + + +LineLoader.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_lined_mapping) + + +def node_line(root: Any, path: list[str | int]) -> int: + """Returns the deepest source line we reached; if the path drops out, the last LinedDict we passed through.""" + node = root + last_lined = root + for step in path: + try: + node = node[step] + except (TypeError, KeyError, IndexError): + break + if hasattr(node, "__line__"): + last_lined = node + return getattr(last_lined, "__line__", 1) diff --git a/tools/dbtool.py b/tools/dbtool.py index 2b8cd682418..8401edce882 100644 --- a/tools/dbtool.py +++ b/tools/dbtool.py @@ -1276,6 +1276,19 @@ def dump_all_tables(silent=False): print_green(f"Replaced values in all .sql files with data from the database.") +def validate_yaml_data(): + import tempfile + with tempfile.TemporaryDirectory() as tmp: + rc = subprocess.call( + [sys.executable, "-m", "tools.codegen", tmp, "--validate"], + cwd=server_dir_path, + ) + if rc == 0: + print_green("YAML data validates clean.") + else: + print_red("YAML validation failed.") + + def tasks_menu(): present_menu( "Maintenance Tasks", @@ -1288,6 +1301,7 @@ def tasks_menu(): # "Offload historical auction data to auction_house_history", # offload_to_auction_house_history, # ], + "v": ["Validate YAML data", validate_yaml_data], "l": [ "Configure single-process server", configure_single_process, diff --git a/tools/requirements.txt b/tools/requirements.txt index 2f6d1307b68..073cf68fbf0 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -9,3 +9,5 @@ regex argparse requests bcrypt +jinja2 +jsonschema>=4.18