Compare commits

..

No commits in common. "base" and "speed_up_module_loading" have entirely different histories.

5632 changed files with 167076 additions and 200907 deletions

View file

@ -1,7 +1,7 @@
---
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
# We base things of WebKit + Allman braces
# Compatible with clang-format-22 (enforced by tools/run_clang_format.py)
# Compatible with clang-format-20
Language: Cpp
# Access modifiers
@ -28,7 +28,8 @@ AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: None
AllowShortLoopsOnASingleLine: false
LambdaBodyIndentation: Signature
# Note: LambdaBodyIndentation not available in clang-format-20
# Template declarations
AlwaysBreakTemplateDeclarations: Yes
@ -70,8 +71,6 @@ BinPackParameters: false
# Namespaces
CompactNamespaces: false
NamespaceIndentation: None
WrapNamespaceBodyWithEmptyLines: Always
SeparateDefinitionBlocks: Always
# Braced lists and initializers
Cpp11BracedListStyle: false
@ -90,7 +89,8 @@ MaxEmptyLinesToKeep: 1
# Pointer and reference alignment
PointerAlignment: Left
ReferenceAlignment: Pointer
QualifierAlignment: Left # West Const
# Note: QualifierAlignment not available in clang-format-20, use manual const placement
# Comments
ReflowComments: Always

View file

@ -11,9 +11,7 @@
"remoteUser": "xiadmin",
"remoteEnv": { "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" },
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {
"moby": false
}
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
},
"customizations": {
"vscode": {

View file

@ -80,18 +80,6 @@ indent_brace_style = allman # This is unfortunately ignored in Visual Studio
[Makefile]
indent_style = tab
[*.{yml,yaml}]
[*.yml]
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

2
.gitattributes vendored
View file

@ -12,8 +12,6 @@
*.h text eol=lf
*.sql text eol=lf
*.sh text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
# Retaining CRLF line ends in the documentation dir (for now..)
*.txt text eol=crlf

View file

@ -15,9 +15,9 @@ jobs:
name: Clang Tidy
uses: ./.github/workflows/runner_build.yml
with:
runner: ubuntu-26.04
runner: ubuntu-24.04
compiler: clang
compiler_version: 22
compiler_version: 20
build_type: Debug
tracy: false
build_modules: false
@ -64,9 +64,9 @@ jobs:
upload_artifact: false
clang_tidy: false
- build_type: Debug
runner: ubuntu-26.04
runner: ubuntu-24.04
compiler: gcc
compiler_version: 15
compiler_version: 14
tracy: false
build_modules: false
save_cache: true
@ -93,8 +93,8 @@ jobs:
- build_type: Release
os: ubuntu
compiler: gcc
compiler_version: 15
clang_format_version: 22
compiler_version: 14
clang_format_version: 20
tracy: false
build_modules: false
save_cache: false
@ -110,8 +110,8 @@ jobs:
- build_type: Release
os: alpine
compiler: clang
compiler_version: 22
clang_format_version: 22
compiler_version: 20
clang_format_version: 20
tracy: false
build_modules: false
save_cache: false

View file

@ -9,15 +9,14 @@ on:
jobs:
Publish_Changelog:
name: Generate and Publish Changelog
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- run: git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
- run: git config --global user.name "github-actions[bot]"
- uses: actions/checkout@v1
- uses: fregante/setup-git-user@v1
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y python3
sudo apt-get install -y python3.7
pip3 install requests
- name: Generate changelog
run: |

View file

@ -13,7 +13,7 @@ jobs:
permissions: write-all
steps:
- name: Comment on unchecked boxes in template
uses: actions/github-script@v9
uses: actions/github-script@v7
with:
script: |
function count_instances(string, word)

View file

@ -36,16 +36,16 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v3
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y software-properties-common cmake libmariadb-dev-compat libluajit-5.1-dev libzmq3-dev zlib1g-dev libssl-dev binutils-dev libzstd-dev libdwarf-dev
sudo apt-get install -y software-properties-common cmake libmariadb-dev-compat libluajit-5.1-dev libzmq3-dev zlib1g-dev libssl-dev binutils-dev
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
uses: github/codeql-action/init@v2
with:
trap-caching: false
languages: ${{ matrix.language }}
@ -57,7 +57,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
# - name: Autobuild
# uses: github/codeql-action/autobuild@v4
# uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@ -73,7 +73,7 @@ jobs:
cmake --build build -j4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
uses: github/codeql-action/analyze@v2
with:
# https://josh-ops.com/posts/github-codeql-ignore-files/
upload: false # disable the upload here - we will upload in a different action
@ -89,6 +89,6 @@ jobs:
output: sarif-results/${{ matrix.language }}.sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v4
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: sarif-results/${{ matrix.language }}.sarif

View file

@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Comment on keywords in Discussion
uses: actions/github-script@v9
uses: actions/github-script@v6
with:
script: |
// Define the keywords to check (all lower-case for case-insensitive matching)

View file

@ -67,13 +67,13 @@ jobs:
echo "REPO_OWNER=${GITHUB_REPOSITORY_OWNER,,}" >>${GITHUB_ENV}
echo "REPO=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV}
- uses: docker/login-action@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v6
- uses: actions/checkout@v4
with:
fetch-depth: 1
@ -88,12 +88,12 @@ jobs:
f.write("renamer\n")
EOF
- uses: docker/setup-buildx-action@v4
- uses: docker/setup-buildx-action@v3
id: setup_buildx
- name: Restore build cache
if: ${{ !inputs.save_cache }}
uses: actions/cache/restore@v5
uses: actions/cache/restore@v4
env:
cmake_hash: ${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}
source_hash: ${{ hashFiles('src/**/*', 'ext/**/*') }}
@ -108,7 +108,7 @@ jobs:
- name: Cache build
id: cache_build
if: ${{ inputs.save_cache }}
uses: actions/cache@v5
uses: actions/cache@v4
env:
cmake_hash: ${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}
source_hash: ${{ hashFiles('src/**/*', 'ext/**/*') }}
@ -121,7 +121,7 @@ jobs:
${{ format('buildcache-docker-{0}-{1}{2}-{3}-{4}-', inputs.os, inputs.compiler, inputs.compiler_version, inputs.build_type, env.cmake_hash) }}
- name: Inject cache into container
uses: reproducible-containers/buildkit-cache-dance@v3.4.0
uses: reproducible-containers/buildkit-cache-dance@v3.2.0
with:
builder: ${{ steps.setup_buildx.outputs.name }}
cache-map: |
@ -145,7 +145,7 @@ jobs:
- name: Docker meta
id: docker-meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ env.REPO }}
tags: |
@ -161,7 +161,7 @@ jobs:
- name: Build devtools image
if: ${{ inputs.publish && vars.PUBLISH_DOCKER != '' }}
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
context: .
file: ${{ format('./docker/{0}.Dockerfile', inputs.os) }}
@ -173,7 +173,7 @@ jobs:
tags: ${{ format('ghcr.io/{0}/devtools:{1}', env.REPO_OWNER, inputs.os) }}
- name: Docker build and push
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
context: .
file: ${{ format('./docker/{0}.Dockerfile', inputs.os) }}
@ -194,7 +194,7 @@ jobs:
- name: Archive image
if: ${{ inputs.upload_artifact || (inputs.publish && vars.PUBLISH_DOCKER == '') }}
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v4
with:
name: ${{ format('LSB_{0}_image_{1}', inputs.os, github.sha) }}
path: ${{ format('{0}/LSB_{1}_image_{2}.tar', runner.temp, inputs.os, github.sha) }}

View file

@ -57,21 +57,21 @@ jobs:
echo "REPO_OWNER=${GITHUB_REPOSITORY_OWNER,,}" >>${GITHUB_ENV}
echo "REPO=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV}
- uses: actions/checkout@v6
- uses: actions/checkout@v4
with:
fetch-depth: 1
submodules: recursive # For navmeshes
- name: Download artifact
if: ${{ github.event_name == 'pull_request' }}
uses: actions/download-artifact@v8
uses: actions/download-artifact@v4
with:
name: ${{ env.artifact_name }}
path: ${{ runner.temp }}
- name: Download previous artifact
if: ${{ (github.event_name == 'workflow_run' || github.event_name == 'workflow_dispatch') && vars.PUBLISH_DOCKER == ''}}
uses: dawidd6/action-download-artifact@v21
uses: dawidd6/action-download-artifact@v3
with:
run_id: ${{ github.event.workflow_run.id }}
name: ${{ env.artifact_name }}
@ -119,7 +119,7 @@ jobs:
- name: Run xi_test
id: xi_test
continue-on-error: true
run: docker exec test-server /bin/bash -c './xi_test --keep-going --retry 5 --output log/tests.ctrf.json'
run: docker exec test-server /bin/bash -c './xi_test --keep-going --output log/tests.ctrf.json'
- name: Publish Test Report
if: ${{ !cancelled() }}

View file

@ -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@v6
- uses: actions/checkout@v4
with:
fetch-depth: 0
@ -46,7 +46,7 @@ jobs:
run: tr -d '\r' < sanity_checks_summary.md >> $GITHUB_STEP_SUMMARY
- name: Upload changed files as artifact
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v4
with:
name: changed-files
path: changed-files.txt
@ -63,7 +63,7 @@ jobs:
shell: bash
steps:
- name: Download Changed Files
uses: actions/download-artifact@v8
uses: actions/download-artifact@v4
with:
name: changed-files
@ -82,7 +82,7 @@ jobs:
- run: git config --global --add safe.directory $GITHUB_WORKSPACE
- uses: actions/checkout@v6
- uses: actions/checkout@v4
if: ${{ steps.check-changes.outputs.lua_changes == 'true' }}
with:
fetch-depth: 0
@ -93,10 +93,6 @@ 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' }}
@ -133,137 +129,14 @@ 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@v8
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@v8
with:
name: changed-files
- name: Filter data/ changed files
id: changed
run: |
mapfile -t changed_files < changed-files.txt
yaml_files=()
other_files=()
for f in "${changed_files[@]}"; do
if [[ $f == data/*.yaml || $f == data/*.yml ]]; then
yaml_files+=("$f")
elif [[ $f == data/* ]]; then
other_files+=("$f")
fi
done
echo "yaml=${yaml_files[*]}" >> "$GITHUB_OUTPUT"
echo "other=${other_files[*]}" >> "$GITHUB_OUTPUT"
echo "Changed YAML: ${yaml_files[*]}"
echo "Changed other: ${other_files[*]}"
- uses: actions/checkout@v6
if: steps.changed.outputs.yaml != '' || steps.changed.outputs.other != ''
- name: Setup Python
if: steps.changed.outputs.yaml != ''
uses: actions/setup-python@v6
with:
python-version: "3.14"
- name: Install Python dependencies
if: steps.changed.outputs.yaml != ''
run: python -m pip install pyyaml ruamel.yaml
- name: Check YAML formatting
if: steps.changed.outputs.yaml != ''
run: python tools/yaml/format.py ${{ steps.changed.outputs.yaml }} --check
- name: Cache prettier results
if: steps.changed.outputs.other != ''
uses: actions/cache@v5
with:
path: /tmp/prettier-cache
key: prettier-cache-${{ hashFiles('data/**/*.json') }}
restore-keys: prettier-cache-
- name: Run prettier
if: steps.changed.outputs.other != ''
run: |
set +e
FAILED=$(npx --yes prettier@3 --cache --cache-strategy content --cache-location /tmp/prettier-cache --list-different ${{ steps.changed.outputs.other }})
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
uses: ./.github/workflows/runner_build.yml
with:
runner: ubuntu-26.04
runner: ubuntu-24.04
compiler: clang
compiler_version: 22
compiler_version: 20
build_type: Debug
build_modules: false
tracy: false
@ -287,9 +160,9 @@ jobs:
compiler: appleClang
build_modules: false
- build_type: Debug
runner: ubuntu-26.04
runner: ubuntu-24.04
compiler: gcc
compiler_version: 15
compiler_version: 14
build_modules: false
uses: ./.github/workflows/runner_build.yml
with:
@ -316,9 +189,9 @@ jobs:
- runner: macos-26
test_modules: false
multi_process: false
xi_test: true
xi_test: false
startup_checks: true
- runner: ubuntu-26.04
- runner: ubuntu-24.04
test_modules: false
multi_process: false
xi_test: true

View file

@ -16,7 +16,7 @@ jobs:
permissions: write-all
steps:
- name: Check for blocking labels
uses: actions/github-script@v9
uses: actions/github-script@v7
with:
script: |
const response = await github.rest.issues.listLabelsOnIssue({

View file

@ -23,23 +23,23 @@ jobs:
echo "REPO_OWNER=${GITHUB_REPOSITORY_OWNER,,}" >>${GITHUB_ENV}
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
submodules: true
- name: Login to GHCR
uses: docker/login-action@v4
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ env.REPO_OWNER }}/ximeshes
tags: |
@ -50,7 +50,7 @@ jobs:
org.opencontainers.image.description=Line-of-sight and navigation meshes for use with LandSandBoat server.
- name: Build and push
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
env:
BUILDX_NO_DEFAULT_ATTESTATIONS: 1
with:

View file

@ -64,7 +64,7 @@ jobs:
steps:
- name: Download changed files artifact
if: ${{ inputs.optional_build }}
uses: actions/download-artifact@v8
uses: actions/download-artifact@v4
with:
name: changed-files
@ -92,14 +92,14 @@ jobs:
- name: Checkout
if: ${{ env.SKIP_BUILD != 'true' }}
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install dependencies (macOS)
if: ${{ runner.os == 'macOS' && env.SKIP_BUILD != 'true' }}
run: |
brew install --quiet \
brew update && brew install --quiet \
mariadb \
zeromq \
luajit \
@ -108,7 +108,7 @@ jobs:
- name: Setup LLVM Clang (macOS)
if: ${{ runner.os == 'macOS' && startsWith(inputs.compiler, 'clang') && env.SKIP_BUILD != 'true' }}
run: |
brew install --quiet \
brew update && brew install --quiet \
llvm@${{ inputs.compiler_version }} \
lld@${{ inputs.compiler_version }}
@ -128,7 +128,7 @@ jobs:
- name: Setup GCC (macOS)
if: ${{ runner.os == 'macOS' && startsWith(inputs.compiler, 'gcc') && env.SKIP_BUILD != 'true' }}
run: |
brew install --quiet gcc@${{ inputs.compiler_version }}
brew update && brew install --quiet gcc@${{ inputs.compiler_version }}
GCC_PREFIX=$(brew --prefix gcc@${{ inputs.compiler_version }})
echo "PATH=$GCC_PREFIX/bin:$PATH" >> $GITHUB_ENV
echo "CC=$GCC_PREFIX/bin/gcc-${{ inputs.compiler_version }}" >> $GITHUB_ENV
@ -139,7 +139,6 @@ jobs:
run: |
sudo apt-get update && sudo apt-get install --assume-yes --no-install-recommends --quiet \
binutils-dev \
libdwarf-dev \
libluajit-5.1-dev \
libmariadb-dev-compat \
libssl-dev \
@ -147,8 +146,7 @@ jobs:
luajit \
mariadb-client \
tzdata \
zlib1g-dev \
libzstd-dev
zlib1g-dev
- name: Setup GCC (Linux)
if: ${{ runner.os == 'Linux' && startsWith(inputs.compiler, 'gcc') && env.SKIP_BUILD != 'true' }}
@ -175,25 +173,21 @@ jobs:
- name: Setup MSVC
if: ${{ runner.os == 'Windows' && env.SKIP_BUILD != 'true' }}
uses: TheMrMilchmann/setup-msvc-dev@v4
uses: TheMrMilchmann/setup-msvc-dev@v3
with:
arch: x64
- name: Setup sccache
if: ${{ env.SKIP_BUILD != 'true' }}
uses: mozilla-actions/sccache-action@v0.0.10
uses: mozilla-actions/sccache-action@v0.0.9
with:
disable_annotations: ${{ !inputs.save_cache }}
- name: Setup Python
if: ${{ env.SKIP_BUILD != 'true' }}
uses: actions/setup-python@v6
uses: actions/setup-python@v5
with:
python-version: '3.14'
- name: Install Python codegen deps
if: ${{ env.SKIP_BUILD != 'true' }}
run: python -m pip install jinja2 jsonschema pyyaml
python-version: '3.12'
- name: Enable modules
if: ${{ inputs.build_modules && env.SKIP_BUILD != 'true' }}
@ -209,7 +203,7 @@ jobs:
- name: Restore build cache
if: ${{ env.SKIP_BUILD != 'true' }}
id: restore_build
uses: actions/cache/restore@v5
uses: actions/cache/restore@v4
env:
cmake_hash: ${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}
source_hash: ${{ hashFiles('src/**/*', 'ext/**/*') }}
@ -236,25 +230,16 @@ jobs:
- name: Upload artifact
if: ${{ inputs.upload_artifact && env.SKIP_BUILD != 'true' }}
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v4
with:
name: ${{ format('LSB_{0}_{1}_{2}', runner.os, inputs.build_type, github.sha) }}
path: |
xi_*
tracy.tar.gz
- name: Remove exes from build cache
if: ${{ inputs.save_cache && env.SKIP_BUILD != 'true' && steps.restore_build.outputs.cache-hit != 'true' }}
run: |
rm -f build/src/login/xi_connect*
rm -f build/src/map/xi_map*
rm -f build/src/search/xi_search*
rm -f build/src/test/xi_test*
rm -f build/src/world/xi_world*
- name: Cache build
if: ${{ inputs.save_cache && env.SKIP_BUILD != 'true' && steps.restore_build.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v5
uses: actions/cache/save@v4
with:
path: build
key: ${{ steps.restore_build.outputs.cache-primary-key }}

View file

@ -53,7 +53,7 @@ jobs:
XI_NETWORK_SQL_LOGIN: xiadmin
XI_NETWORK_SQL_PASSWORD: 'password'
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
with:
fetch-depth: 1
submodules: recursive # For navmeshes
@ -80,7 +80,6 @@ jobs:
sudo apt-get update && sudo apt-get install --assume-yes --no-install-recommends --quiet \
binutils \
git \
libdwarf1 \
libmariadb-dev-compat \
libzmq5 \
lua5.1 \
@ -110,10 +109,10 @@ jobs:
${{ env.MYSQL_CMD }} -e "GRANT ALL PRIVILEGES ON ${{ env.XI_NETWORK_SQL_DATABASE }}.* TO '${{ env.XI_NETWORK_SQL_LOGIN }}'@'%';"
${{ env.MYSQL_CMD }} -e "FLUSH PRIVILEGES;"
- uses: actions/setup-python@v6
- uses: actions/setup-python@v5
id: setup_python
with:
python-version: '3.14'
python-version: '3.12'
- name: Install Python dependencies
run: |
@ -127,19 +126,16 @@ 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@v8
uses: actions/download-artifact@v4
with:
name: ${{ format('LSB_{0}_{1}_{2}', runner.os, inputs.build_type, github.sha) }}
path: .
- name: Download previous artifact
if: ${{ github.event_name == 'workflow_run' || github.event_name == 'workflow_dispatch' }}
uses: dawidd6/action-download-artifact@v21
uses: dawidd6/action-download-artifact@v3
with:
run_id: ${{ github.event.workflow_run.id }}
name: ${{ format('LSB_{0}_{1}_{2}', runner.os, inputs.build_type, github.sha) }}
@ -168,7 +164,7 @@ jobs:
if: ${{ inputs.xi_test }}
id: xi_test
continue-on-error: true
run: ./xi_test --keep-going --retry 5 --output tests.ctrf.json
run: ./xi_test --keep-going --output tests.ctrf.json
- name: Publish Test Report
if: ${{ !cancelled() && inputs.xi_test }}
@ -189,7 +185,7 @@ jobs:
- name: Startup checks
if: ${{ inputs.startup_checks }}
id: startup_checks
uses: nick-fields/retry@v4
uses: nick-fields/retry@v3
with:
timeout_minutes: 10
max_attempts: 3

View file

@ -25,7 +25,7 @@ jobs:
shell: bash
steps:
- run: git config --global --add safe.directory $GITHUB_WORKSPACE
- uses: actions/checkout@v6
- uses: actions/checkout@v4
with:
fetch-depth: 0
@ -47,13 +47,10 @@ jobs:
shell: bash
steps:
- run: git config --global --add safe.directory $GITHUB_WORKSPACE
- uses: actions/checkout@v6
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate codegen Lua enums
run: python -m tools.codegen "$RUNNER_TEMP/codegen-out"
- name: Run Lua Language Server
id: run_lls
run: python ./tools/ci/lua_lang_server.py
@ -101,7 +98,7 @@ jobs:
build_type: Release
test_modules: false
multi_process: true
xi_test: true
xi_test: ${{ !startsWith(matrix.runner, 'macos') }}
startup_checks: true
Docker_Test:

7
.gitignore vendored
View file

@ -14,7 +14,6 @@
# Build results
build/
build*/
.cpm-cache/
lbuild/
build_mariadb_32/
build_mariadb_64/
@ -219,8 +218,6 @@ ip.txt
# Tracy download
ext/tracy/
tracy.tar.gz
tracy*
**/*.tracy
# Valgrind
*.memcheck.log
@ -269,7 +266,3 @@ __pycache__
sanity_checks_summary.md
changed-files.txt
clang_tidy_summary.md
# YAML codegen
*.codegen.json
*.codegen.lua

View file

@ -1,11 +0,0 @@
*.codegen.json
*.codegen.lua
# YAML is formatted by tools/yaml/format.py
*.yaml
*.yml
build/
build*/
cmake-*/
out/

View file

@ -1,6 +0,0 @@
{
"tabWidth": 2,
"useTabs": false,
"printWidth": 120,
"endOfLine": "lf"
}

View file

@ -11,9 +11,6 @@
"ms-vscode.cpptools-extension-pack",
"ms-vscode.cpptools",
"jeff-hykin.better-cpp-syntax",
"bierner.github-markdown-preview",
"esbenp.prettier-vscode",
"redhat.vscode-yaml",
"jkillian.custom-local-formatters"
"bierner.github-markdown-preview"
]
}

14
.vscode/settings.json vendored
View file

@ -355,20 +355,6 @@
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.formatOnSave": true
},
"[yaml]": {
"editor.defaultFormatter": "jkillian.custom-local-formatters",
"editor.formatOnSave": true
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"yaml.format.enable": false,
"customLocalFormatters.formatters": [
{
"command": "python tools/yaml/format.py --stdin",
"languages": ["yaml"]
}
],
"files.associations": {
"algorithm": "cpp",
"any": "cpp",

View file

@ -4,35 +4,15 @@ cmake_minimum_required(VERSION 3.25)
cmake_policy(SET CMP0141 NEW)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)
# On macOS, pin the deployment target to the host OS version (must happen before
# project()). Without this, some compilers infer it from the Darwin kernel version
# using the pre-macOS-26 numbering scheme (e.g. Homebrew LLVM 20 maps Darwin 25 to
# "macOS 16.0" instead of 26), and every link against a Homebrew dylib stamped with
# the real version warns:
# ld: warning: building for macOS-16.0, but linking with dylib built for newer version 26.0
# Overridable as usual via -DCMAKE_OSX_DEPLOYMENT_TARGET or MACOSX_DEPLOYMENT_TARGET.
if(CMAKE_HOST_APPLE AND "${CMAKE_OSX_DEPLOYMENT_TARGET}" STREQUAL "" AND "$ENV{MACOSX_DEPLOYMENT_TARGET}" STREQUAL "")
execute_process(
COMMAND sw_vers -productVersion
OUTPUT_VARIABLE host_macos_version
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REGEX MATCH "^[0-9]+" host_macos_major "${host_macos_version}")
if(host_macos_major)
set(CMAKE_OSX_DEPLOYMENT_TARGET "${host_macos_major}.0")
endif()
endif()
project(server C CXX)
# https://cmake.org/cmake/help/latest/policy/CMP0069.html
cmake_policy(SET CMP0069 NEW)
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_SCAN_FOR_MODULES OFF)
set(LINKER_LANGUAGE CXX)
set(USE_FOLDERS ON)
@ -118,6 +98,7 @@ endif()
# Find MariaDB
find_package(MariaDB REQUIRED)
find_package(MariaDBCPP REQUIRED)
# Find ZMQ
find_package(ZeroMQ REQUIRED)
@ -132,39 +113,29 @@ find_package(OpenSSLlibcrypto REQUIRED)
find_package(OpenSSLlibssl REQUIRED)
if(UNIX AND NOT APPLE)
# zstd is sometimes a prereq for binutils
# zstd is sometimes a prereq for binutils
find_package(Zstd REQUIRED)
find_package(Binutils REQUIRED)
endif()
# Link this 'library' to set the c++ standard / compile-time options requested
add_library(project_options INTERFACE)
target_compile_features(project_options INTERFACE cxx_std_23)
# Windows-only preprocessor defines for our first-party code ONLY.
if(WIN32)
target_compile_definitions(project_options INTERFACE
NOMINMAX
WIN32_LEAN_AND_MEAN
_CRT_SECURE_NO_WARNINGS
)
endif()
target_compile_features(project_options INTERFACE cxx_std_17)
# Link this 'library' to use the warnings specified in CompilerWarnings.cmake
add_library(project_warnings INTERFACE)
set_project_warnings(project_warnings)
add_compile_definitions(
# Globally define SOL_ALL_SAFETIES_ON so sol can be included anywhere.
SOL_ALL_SAFETIES_ON=1
# If SOL_NO_CHECK_NUMBER_PRECISION is defined, turns off number precision and integer
# precision fitting when pushing numbers into sol.
SOL_NO_CHECK_NUMBER_PRECISION=1
SOL_DEFAULT_PASS_ON_ERROR=1
SOL_PRINT_ERRORS=0
SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_DEBUG
XI_CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}"
XI_BUILD_TYPE="$<CONFIG>"
# Globally define SOL_ALL_SAFETIES_ON so sol can be included anywhere
# If SOL_NO_CHECK_NUMBER_PRECISION is defined, turns off number precision and integer
# precision fitting when pushing numbers into sol
# add_compile_definitions() comes with CMake 3.12
add_definitions(
-DSOL_ALL_SAFETIES_ON=1
-DSOL_NO_CHECK_NUMBER_PRECISION=1
-DSOL_DEFAULT_PASS_ON_ERROR=1
-DSOL_PRINT_ERRORS=0
-DSPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_DEBUG
)
# For external libs
@ -206,45 +177,6 @@ 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
"Codegen requires the Python packages jinja2, jsonschema, and pyyaml, "
"but they are not installed for the interpreter CMake selected:\n"
" ${Python_EXECUTABLE}\n"
"Install them by running this command exactly as shown (the interpreter path "
"matters, so the packages land in the environment this build uses):\n"
" ${Python_EXECUTABLE} -m pip install -r ${CMAKE_SOURCE_DIR}/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)

View file

@ -1,42 +0,0 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 21,
"patch": 0
},
"configurePresets": [
{
"name": "default",
"displayName": "Default (RelWithDebInfo)",
"description": "Optimized build with debug info. The standard configuration.",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
}
},
{
"name": "debug",
"displayName": "Debug",
"description": "Unoptimized build with full debug info.",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
}
],
"buildPresets": [
{
"name": "default",
"displayName": "Default (RelWithDebInfo)",
"configurePreset": "default",
"configuration": "RelWithDebInfo"
},
{
"name": "debug",
"displayName": "Debug",
"configurePreset": "debug",
"configuration": "Debug"
}
]
}

View file

@ -81,7 +81,6 @@ function(set_project_warnings project_name)
CLANG_WARNINGS
-Wno-nan-infinity-disabled # TODO: fmt triggers this, a combination of the fast-math flag and `isfinite`
-Wunused-private-field # warn on unused private fields
-Wno-nontrivial-memcall # recastnavigation memsets non-trivially-copyable types (e.g. dtMeshTile)
)
endif()

275
cmake/FindMariaDBCPP.cmake Normal file
View file

@ -0,0 +1,275 @@
if(NOT WIN32)
message(STATUS "Building MariaDB Connector/C++ from source")
CPMAddPackage(
NAME mariadb-connector-cpp
GITHUB_REPOSITORY zach2good/mariadb-connector-cpp
GIT_TAG efffd81c9c9cd806703b84ee7f0913d4de93e2ee
DOWNLOAD_ONLY YES
)
if(mariadb-connector-cpp_ADDED)
set(PROJECT_VERSION_MAJOR 0)
set(PROJECT_VERSION_MINOR 0)
set(PROJECT_VERSION_PATCH 0)
configure_file(
${mariadb-connector-cpp_SOURCE_DIR}/src/Version.h.in
${mariadb-connector-cpp_SOURCE_DIR}/src/Version.h
)
configure_file(
${mariadb-connector-cpp_SOURCE_DIR}/src/maconncpp.def.in
${mariadb-connector-cpp_SOURCE_DIR}/src/maconncpp.def
)
set(MACPP_SOURCES
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbDriver.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/DriverManager.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/UrlParser.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbDatabaseMetaData.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/HostAddress.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/Consts.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/SQLString.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbConnection.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbStatement.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDBException.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDBWarning.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/Identifier.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbSavepoint.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/SqlStates.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/Results.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/ColumnType.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/ColumnDefinition.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/protocol/MasterProtocol.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/protocol/capi/QueryProtocol.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/protocol/capi/ConnectProtocol.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/com/capi/ColumnDefinitionCapi.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/cache/CallableStatementCache.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/cache/CallableStatementCacheKey.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/util/Value.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/util/Utils.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/util/String.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/logger/NoLogger.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/logger/LoggerFactory.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/logger/ProtocolLoggingProxy.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/ParameterHolder.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/options/Options.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/options/DefaultOptions.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/pool/GlobalStateInfo.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/pool/Pools.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/failover/FailoverProxy.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/credential/CredentialPluginLoader.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/SelectResultSet.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/com/capi/SelectResultSetCapi.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/com/ColumnNameMap.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/io/StandardPacketInputStream.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/Charset.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/ClientSidePreparedStatement.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/BasePrepareStatement.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbFunctionStatement.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbProcedureStatement.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/ServerSidePreparedStatement.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/BigDecimalParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/BooleanParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/ByteArrayParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/ByteParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/DateParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/DefaultParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/DoubleParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/FloatParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/IntParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/LongParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/ULongParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/NullParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/ParameterHolder.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/ReaderParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/ShortParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/StreamParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/TimeParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/TimestampParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/StringParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbPooledConnection.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbParameterMetaData.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbResultSetMetaData.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/CallParameter.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/CallableParameterMetaData.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/com/Packet.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/credential/Credential.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/util/LogQueryTool.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/util/ClientPrepareResult.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/util/ServerPrepareResult.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/util/ServerPrepareStatementCache.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/com/CmdInformationSingle.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/com/CmdInformationBatch.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/com/CmdInformationMultiple.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/com/RowProtocol.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/protocol/capi/BinRowProtocolCapi.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/protocol/capi/TextRowProtocolCapi.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/ExceptionFactory.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/StringImp.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/CArray.cpp
${mariadb-connector-cpp_SOURCE_DIR}/src/SimpleParameterMetaData.cpp
)
# NOTE: Keep this around if we ever want to rebuild the mariadb-connector-cpp library
if(WIN32)
set(MACPP_SOURCES
${MACPP_SOURCES}
${mariadb-connector-cpp_SOURCE_DIR}/src/Dll.c
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDBConnCpp.h
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbDriver.h
${mariadb-connector-cpp_SOURCE_DIR}/src/UrlParser.h
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbDatabaseMetaData.h
${mariadb-connector-cpp_SOURCE_DIR}/src/HostAddress.h
${mariadb-connector-cpp_SOURCE_DIR}/src/Version.h
${mariadb-connector-cpp_SOURCE_DIR}/src/Consts.h
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbConnection.h
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbStatement.h
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDBWarning.h
${mariadb-connector-cpp_SOURCE_DIR}/src/Protocol.h
${mariadb-connector-cpp_SOURCE_DIR}/src/Identifier.h
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbSavepoint.h
${mariadb-connector-cpp_SOURCE_DIR}/src/SqlStates.h
${mariadb-connector-cpp_SOURCE_DIR}/src/Results.h
${mariadb-connector-cpp_SOURCE_DIR}/src/ColumnDefinition.h
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbServerCapabilities.h
${mariadb-connector-cpp_SOURCE_DIR}/src/protocol/MasterProtocol.h
${mariadb-connector-cpp_SOURCE_DIR}/src/protocol/capi/QueryProtocol.h
${mariadb-connector-cpp_SOURCE_DIR}/src/protocol/capi/ConnectProtocol.h
${mariadb-connector-cpp_SOURCE_DIR}/src/com/capi/ColumnDefinitionCapi.h
${mariadb-connector-cpp_SOURCE_DIR}/src/cache/CallableStatementCache.h
${mariadb-connector-cpp_SOURCE_DIR}/src/cache/CallableStatementCacheKey.h
${mariadb-connector-cpp_SOURCE_DIR}/src/util/Value.h
${mariadb-connector-cpp_SOURCE_DIR}/src/util/ClassField.h
${mariadb-connector-cpp_SOURCE_DIR}/src/util/Utils.h
${mariadb-connector-cpp_SOURCE_DIR}/src/util/StateChange.h
${mariadb-connector-cpp_SOURCE_DIR}/src/util/String.h
${mariadb-connector-cpp_SOURCE_DIR}/src/logger/NoLogger.h
${mariadb-connector-cpp_SOURCE_DIR}/src/logger/LoggerFactory.h
${mariadb-connector-cpp_SOURCE_DIR}/src/logger/Logger.h
${mariadb-connector-cpp_SOURCE_DIR}/src/logger/ProtocolLoggingProxy.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/ParameterHolder.h
${mariadb-connector-cpp_SOURCE_DIR}/src/options/Options.h
${mariadb-connector-cpp_SOURCE_DIR}/src/options/DefaultOptions.h
${mariadb-connector-cpp_SOURCE_DIR}/src/options/DriverPropertyInfo.h
${mariadb-connector-cpp_SOURCE_DIR}/src/io/PacketOutputStream.h
${mariadb-connector-cpp_SOURCE_DIR}/src/io/PacketInputStream.h
${mariadb-connector-cpp_SOURCE_DIR}/src/io/StandardPacketInputStream.h
${mariadb-connector-cpp_SOURCE_DIR}/src/credential/CredentialPlugin.h
${mariadb-connector-cpp_SOURCE_DIR}/src/credential/CredentialPluginLoader.h
${mariadb-connector-cpp_SOURCE_DIR}/src/pool/GlobalStateInfo.h
${mariadb-connector-cpp_SOURCE_DIR}/src/pool/Pools.h
${mariadb-connector-cpp_SOURCE_DIR}/src/pool/Pool.h
${mariadb-connector-cpp_SOURCE_DIR}/src/failover/FailoverProxy.h
${mariadb-connector-cpp_SOURCE_DIR}/src/Listener.h
${mariadb-connector-cpp_SOURCE_DIR}/src/com/CmdInformation.h
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/Connection.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/Statement.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/ResultSet.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/PreparedStatement.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/ParameterMetaData.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/ResultSetMetaData.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/DatabaseMetaData.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/CallableStatement.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/SQLString.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/Warning.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/Exception.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/jdbccompat.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/Driver.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/DriverManager.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/Types.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/buildconf.hpp
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp/CArray.hpp
${mariadb-connector-cpp_SOURCE_DIR}/src/SelectResultSet.h
${mariadb-connector-cpp_SOURCE_DIR}/src/com/capi/SelectResultSetCapi.h
${mariadb-connector-cpp_SOURCE_DIR}/src/com/SelectResultSetPacket.h
${mariadb-connector-cpp_SOURCE_DIR}/src/ColumnType.h
${mariadb-connector-cpp_SOURCE_DIR}/src/com/ColumnDefinitionPacket.h
${mariadb-connector-cpp_SOURCE_DIR}/src/com/ColumnNameMap.h
${mariadb-connector-cpp_SOURCE_DIR}/src/Charset.h
${mariadb-connector-cpp_SOURCE_DIR}/src/ClientSidePreparedStatement.h
${mariadb-connector-cpp_SOURCE_DIR}/src/BasePrepareStatement.h
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbFunctionStatement.h
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbProcedureStatement.h
${mariadb-connector-cpp_SOURCE_DIR}/src/ServerSidePreparedStatement.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/BigDecimalParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/BooleanParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/ByteArrayParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/ByteParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/DateParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/DefaultParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/DoubleParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/FloatParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/IntParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/LongParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/ULongParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/NullParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/ReaderParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/ShortParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/StreamParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/TimeParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/TimestampParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/parameters/StringParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/Parameters.h
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbPooledConnection.h
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbParameterMetaData.h
${mariadb-connector-cpp_SOURCE_DIR}/src/CallParameter.h
${mariadb-connector-cpp_SOURCE_DIR}/src/CallableParameterMetaData.h
${mariadb-connector-cpp_SOURCE_DIR}/src/MariaDbResultSetMetaData.h
${mariadb-connector-cpp_SOURCE_DIR}/src/com/Packet.h
${mariadb-connector-cpp_SOURCE_DIR}/src/util/ServerStatus.h
${mariadb-connector-cpp_SOURCE_DIR}/src/credential/Credential.h
${mariadb-connector-cpp_SOURCE_DIR}/src/util/LogQueryTool.h
${mariadb-connector-cpp_SOURCE_DIR}/src/PrepareResult.h
${mariadb-connector-cpp_SOURCE_DIR}/src/util/ClientPrepareResult.h
${mariadb-connector-cpp_SOURCE_DIR}/src/util/ServerPrepareResult.h
${mariadb-connector-cpp_SOURCE_DIR}/src/util/ServerPrepareStatementCache.h
${mariadb-connector-cpp_SOURCE_DIR}/src/com/CmdInformationSingle.h
${mariadb-connector-cpp_SOURCE_DIR}/src/com/CmdInformationBatch.h
${mariadb-connector-cpp_SOURCE_DIR}/src/com/CmdInformationMultiple.h
${mariadb-connector-cpp_SOURCE_DIR}/src/com/RowProtocol.h
${mariadb-connector-cpp_SOURCE_DIR}/src/protocol/capi/BinRowProtocolCapi.h
${mariadb-connector-cpp_SOURCE_DIR}/src/protocol/capi/TextRowProtocolCapi.h
${mariadb-connector-cpp_SOURCE_DIR}/src/ExceptionFactory.h
${mariadb-connector-cpp_SOURCE_DIR}/src/StringImp.h
${mariadb-connector-cpp_SOURCE_DIR}/src/CArrayImp.h
${mariadb-connector-cpp_SOURCE_DIR}/src/SimpleParameterMetaData.h
${mariadb-connector-cpp_SOURCE_DIR}/src/maconncpp.def
)
endif()
add_library(mariadbclientcpp STATIC ${MACPP_SOURCES})
target_include_directories(mariadbclientcpp
PUBLIC
${mariadb-connector-cpp_SOURCE_DIR}/include
PRIVATE
${mariadb-connector-cpp_SOURCE_DIR}/include/conncpp
${mariadb-connector-cpp_SOURCE_DIR}/src/
)
target_link_libraries(mariadbclientcpp PRIVATE mariadbclient)
set(MARIADBCPP_FOUND TRUE)
set(MARIADBCPP_LIBRARY mariadbclientcpp)
set(MARIADBCPP_INCLUDE_DIR ${mariadb-connector-cpp_SOURCE_DIR}/include)
endif()
else() # WIN32
message(STATUS "Looking for prebuilt MariaDB Connector/C++")
find_library(MARIADBCPP_LIBRARY
NAMES
mariadbcpp
PATHS
${PROJECT_SOURCE_DIR}/ext/mariadbcpp/${lib_dir}/
)
set(MARIADBCPP_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/ext/mariadbcpp/include/) # Only look internally
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MariaDBCPP DEFAULT_MSG MARIADBCPP_LIBRARY MARIADBCPP_INCLUDE_DIR)
endif()
message(STATUS "MARIADBCPP_FOUND: ${MARIADBCPP_FOUND}")
message(STATUS "MARIADBCPP_LIBRARY: ${MARIADBCPP_LIBRARY}")
message(STATUS "MARIADBCPP_INCLUDE_DIR: ${MARIADBCPP_INCLUDE_DIR}")
add_library(mariadbcpp INTERFACE)
target_link_libraries(mariadbcpp INTERFACE ${MARIADBCPP_LIBRARY})
target_include_directories(mariadbcpp SYSTEM INTERFACE ${MARIADBCPP_INCLUDE_DIR})

View file

@ -1,12 +1,12 @@
message(STATUS "CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}")
if(${CMAKE_SOURCE_DIR} MATCHES " +")
set(STRIPPED_PATH "")
STRING(REGEX REPLACE " +" "_" STRIPPED_PATH "${CMAKE_SOURCE_DIR}")
set(STRIPPED_PATH "")
STRING(REGEX REPLACE " +" "_" STRIPPED_PATH "${CMAKE_SOURCE_DIR}")
message(STATUS
"Current path: ${CMAKE_SOURCE_DIR}\n"
"Suggested path: ${STRIPPED_PATH}\n"
"Your path contains spaces, this is not recommended.")
message(STATUS
"Current path: ${CMAKE_SOURCE_DIR}\n"
"Suggested path: ${STRIPPED_PATH}\n"
"Your path contains spaces, this is not recommended.")
endif()
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
@ -33,15 +33,3 @@ set(libpath "lib${platform_suffix}")
if(WIN32)
set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF)
endif()
if(APPLE)
# The modern Apple linker (ld_prime, Xcode 15+) warns when the same library
# appears more than once on the link line. CMake's dependency propagation
# legitimately repeats static libs (historically required by classic ld64),
# so the warning is pure noise: silence it where the linker supports the flag.
include(CheckLinkerFlag)
check_linker_flag(CXX "-Wl,-no_warn_duplicate_libraries" LINKER_SUPPORTS_NO_WARN_DUPLICATE_LIBRARIES)
if(LINKER_SUPPORTS_NO_WARN_DUPLICATE_LIBRARIES)
add_link_options("-Wl,-no_warn_duplicate_libraries")
endif()
endif()

View file

@ -1,14 +1,5 @@
# Set a default build type if none was specified
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(isMultiConfig)
set(CMAKE_CONFIGURATION_TYPES
"RelWithDebInfo;Debug;Release;MinSizeRel"
CACHE STRING "Available build configurations" FORCE)
if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
set(CMAKE_DEFAULT_BUILD_TYPE "RelWithDebInfo")
endif()
elseif(NOT CMAKE_BUILD_TYPE)
if(NOT CMAKE_BUILD_TYPE)
message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.")
set(CMAKE_BUILD_TYPE
"RelWithDebInfo"
@ -17,11 +8,10 @@ elseif(NOT CMAKE_BUILD_TYPE)
set_property(
CACHE CMAKE_BUILD_TYPE
PROPERTY STRINGS
"RelWithDebInfo"
"Debug"
"Release"
"MinSizeRel"
)
"Debug"
"Release"
"MinSizeRel"
"RelWithDebInfo")
endif()
option(ENABLE_IPO "Enable Interprocedural Optimization, aka Link Time Optimization (LTO)" ON)
@ -51,6 +41,8 @@ if(MSVC)
list(APPEND FLAGS_AND_DEFINES
-D_CONSOLE
-D_MBCS
-DNOMINMAX
-D_CRT_SECURE_NO_WARNINGS
-D_CRT_NONSTDC_NO_DEPRECATE
# TODO: This is being overwritten by /Ob0
# /Ob2 # Inline Function Expansion
@ -76,7 +68,7 @@ if(MSVC)
)
endif()
link_libraries(ws2_32 dbghelp shlwapi winmm shell32 user32)
link_libraries(WS2_32 dbghelp Shlwapi)
endif()
if(UNIX)
@ -95,48 +87,33 @@ string(REPLACE ";" " " FLAGS_AND_DEFINES_STR "${FLAGS_AND_DEFINES}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS_AND_DEFINES_STR}")
function(set_target_output_directory target)
# Run from the repo root: data, scripts, settings and the runtime DLLs all live there.
# DEBUGGER_WORKING_DIRECTORY (CMake 4.0+): Ninja and other non-VS generators.
# VS_DEBUGGER_WORKING_DIRECTORY: Visual Studio generator (takes precedence there).
message(STATUS "Setting output directory for ${target} to ${CMAKE_SOURCE_DIR}")
set_target_properties(${target} PROPERTIES
DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
message(STATUS "${target}: staging build artifact to ${CMAKE_SOURCE_DIR} after build")
add_custom_command(TARGET ${target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_FILE:${target}>"
"${CMAKE_SOURCE_DIR}/$<TARGET_FILE_NAME:${target}>"
VERBATIM)
if(MSVC)
add_custom_command(TARGET ${target} POST_BUILD
COMMAND "$<$<CONFIG:Debug,RelWithDebInfo>:${CMAKE_COMMAND};-E;copy_if_different;$<TARGET_PDB_FILE:${target}>;${CMAKE_SOURCE_DIR}/$<TARGET_PDB_FILE_NAME:${target}>>"
COMMAND_EXPAND_LISTS
VERBATIM)
endif()
if(APPLE)
# Under LTO the linker merges codegen objects into temp files and deletes after linking.
# We need to preserve those for the next step!
# -object_path_lto persists those codegen objects to a real, per-target directory so
# dsymutil can gather their DWARF into the .dSYM.
if(CMAKE_INTERPROCEDURAL_OPTIMIZATION)
set(lto_object_dir "${CMAKE_BINARY_DIR}/lto-objects/${target}")
file(MAKE_DIRECTORY "${lto_object_dir}")
target_link_options(${target} PRIVATE "-Wl,-object_path_lto,${lto_object_dir}")
endif()
# dsymutil consolidates the DWARF into a self-contained .dSYM that travels with the
# binary, and atos picks it up automatically.
add_custom_command(TARGET ${target} POST_BUILD
COMMAND "$<$<CONFIG:Debug,RelWithDebInfo>:dsymutil;$<TARGET_FILE:${target}>;-o;${CMAKE_SOURCE_DIR}/$<TARGET_FILE_NAME:${target}>.dSYM>"
COMMAND_EXPAND_LISTS
VERBATIM)
endif()
VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY_ASAN "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY_UBSAN "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY_TSAN "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY_MSAN "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY_LSAN "${CMAKE_SOURCE_DIR}"
)
endfunction()
function(disable_lto target)
target_compile_options(${target} PRIVATE -fno-lto)
target_link_options(${target} PRIVATE -fno-lto)
endfunction()
# If we're on Unix and the system is 32-bit (void* is 4-bytes wide),
# then there's a good chance we're compiling for Raspberry Pi.
# Currently, CMake doesn't detect this properly and needs some help
# to link libatomic.
# Source: https://gitlab.kitware.com/cmake/cmake/-/issues/21174
#
# TODO: Use include(CheckCXXSourceCompiles) to make this check better.
if(UNIX AND CMAKE_SIZEOF_VOID_P EQUAL 4)
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -latomic")
endif()

View file

@ -1,16 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
cpp:
underlying: uint8_t
lua:
table: xi.allegiance
values:
mob: 0
player: 1
san_doria: 2
bastok: 3
windurst: 4
wyverns: 5
griffons: 6

View file

@ -1,53 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
cpp:
underlying: uint8_t
lua:
table: xi.animation
values:
none: 0
attack: 1
despawn: 2
death: 3
event: 4
chocobo: 5
fishing: 6
open_door: 8
close_door: 9
elevator_up: 10
elevator_down: 11
fishing_npc: 32
healing: 33
fishing_fish: 38
fishing_caught: 39
fishing_rod_break: 40
fishing_line_break: 41
fishing_monster: 42
fishing_stop: 43
synth: 44
sit: 47
ranged: 48
fishing_start: 50
new_fishing_start: 56
new_fishing_fish: 57
new_fishing_caught: 58
new_fishing_rod_break: 59
new_fishing_line_break: 60
new_fishing_monster: 61
new_fishing_stop: 62
# 63 through 73 are used with /sitchair
sitchair_0: 63
sitchair_1: 64
sitchair_2: 65
sitchair_3: 66
sitchair_4: 67
sitchair_5: 68
sitchair_6: 69
sitchair_7: 70
sitchair_8: 71
sitchair_9: 72
sitchair_10: 73
mount: 85
trust: 90 # trust NPC spawn-in animation

View file

@ -1,15 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
cpp:
underlying: uint8_t
lua:
table: xi.attackType
values:
none: 0
physical: 1
magical: 2
ranged: 3
breath: 4
special: 5

View file

@ -1,17 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
flags: true
cpp:
underlying: uint16_t
lua:
table: xi.behavior
values:
none: 0x000
no_despawn: 0x001 # mob does not despawn on death
standback: 0x002 # mob will standback forever
raisable: 0x004 # mob can be raised via Raise spells
no_assist: 0x008 # mob can not be targeted by helpful magic from players (cure, protect, etc)
aggro_ambush: 0x200 # mob aggroes by ambush
no_turn: 0x400 # mob does not turn to face target

View file

@ -1,12 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
cpp:
underlying: uint8_t
lua:
table: xi.claimType
values:
exclusive: 0 # Regular exclusive claim behavior. Only one entity and related group can attack.
non_exclusive: 1 # Regular claim behavior but multiple unrelated entities can attack and compete for claim. Rewards distributed to last claiming entity.
unclaimable: 2 # Mob cannot be claimed. Multiple unrelated entities can attack. Rewards will not be distributed.

View file

@ -1,23 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
cpp:
underlying: uint16_t
lua:
table: xi.damageType
values:
none: 0
piercing: 1
slashing: 2
blunt: 3
hand_to_hand: 4
elemental: 5
fire: 6
ice: 7
wind: 8
earth: 9
thunder: 10
water: 11
light: 12
dark: 13

View file

@ -1,21 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
flags: true
cpp:
underlying: uint16_t
lua:
table: xi.detects
values:
none: 0x000
sight: 0x001
hearing: 0x002
sight_and_hearing: 0x003
lowhp: 0x004
none1: 0x008
none2: 0x010
magic: 0x020
weaponskill: 0x040
jobability: 0x080
scent: 0x100

View file

@ -1,32 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
cpp:
underlying: uint8_t
lua:
table: xi.ecosystem
values:
unclassified: 0
amorph: 1
aquan: 2
arcana: 3
archaic_machine: 4
beast: 5
beastmen: 6
bird: 7
demon: 8
dragon: 9
elemental: 10
empty: 11
humanoid: 12
lizard: 13
luminian: 14
luminion: 15
plantoid: 16
supreme_beings: 17
undead: 18
vermin: 19
voragean: 20
structures: 21
weapons: 22

View file

@ -1,15 +0,0 @@
# 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 higher (tier, power)
never: 2 # never overwrite
always: 3 # always overwrite no matter
ignore_duplicate: 4 # ignore dupes
tier_higher: 5 # only overwrite if tier is higher (regardless of power)

View file

@ -1,18 +0,0 @@
# 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

View file

@ -1,21 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
flags: true
cpp:
underlying: uint32_t
lua:
table: xi.entityFlags
values:
none: 0x000
info_icon: 0x001 # (I) Icon next to name
# TODO: Flags 0x002, 0x004 and 0x008 do different things for different entities.
# : It isn't one-size-fits-all, and different combinations may do different things.
# : It'll need to be researched more.
# alt_appearance: 0x002
hide_name: 0x008
call_for_help: 0x020
hide_model: 0x080
hide_hp: 0x100
untargetable: 0x800

View file

@ -1,29 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
flags: true
cpp:
underlying: uint32_t
lua:
table: xi.immunity
values:
none: 0x00000000
addle: 0x00000001
gravity: 0x00000002
bind: 0x00000004
stun: 0x00000008
silence: 0x00000010
paralyze: 0x00000020
blind: 0x00000040
slow: 0x00000080
poison: 0x00000100
elegy: 0x00000200
requiem: 0x00000400
light_sleep: 0x00000800
dark_sleep: 0x00001000
aspir: 0x00002000
terror: 0x00004000
dispel: 0x00008000
petrify: 0x00010000
plague: 0x00020000

View file

@ -1,34 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
cpp:
underlying: uint8_t
case: screaming
lua:
table: xi.job
values:
none: 0
war: 1
mnk: 2
whm: 3
blm: 4
rdm: 5
thf: 6
pld: 7
drk: 8
bst: 9
brd: 10
rng: 11
sam: 12
nin: 13
drg: 14
smn: 15
blu: 16
cor: 17
pup: 18
dnc: 19
sch: 20
geo: 21
run: 22
mon: 23 # NOTE: MON is not a full job

View file

@ -1,75 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
cpp:
underlying: uint16_t
lua:
table: xi.latent
values:
hp_under_percent: 0 # hp less than or equal to % - PARAM: HP PERCENT
hp_over_percent: 1 # hp more than % - PARAM: HP PERCENT
hp_under_tp_under_100: 2 # hp less than or equal to %, tp under 100 - PARAM: HP PERCENT
hp_over_tp_under_100: 3 # hp more than %, tp over 100 - PARAM: HP PERCENT
mp_under_percent: 4 # mp less than or equal to % - PARAM: MP PERCENT
mp_under: 5 # mp less than # - PARAM: MP #
tp_under: 6 # tp under # and during WS - PARAM: TP VALUE
tp_over: 7 # tp over # - PARAM: TP VALUE
subjob: 8 # subjob - PARAM: JOBTYPE
pet_id: 9 # pettype - PARAM: PETID
weapon_drawn: 10 # weapon drawn
weapon_sheathed: 11 # weapon sheathed
signet_bonus: 12 # While in conquest region and engaged to an even match or less target
status_effect_active: 13 # status effect on player - PARAM: EFFECTID
no_food_active: 14 # no food effects active on player
party_members: 15 # party size # - PARAM: # OF MEMBERS
party_members_in_zone: 16 # party size # and members in zone - PARAM: # OF MEMBERS
sanction_regen_bonus: 17 # While in besieged region and HP is less than PARAM%
sanction_refresh_bonus: 18 # While in besieged region and MP is less than PARAM%
sigil_regen_bonus: 19 # While in campaign region and HP is less than PARAM%
sigil_refresh_bonus: 20 # While in campaign region and MP is less than PARAM%
avatar_in_party: 21 # party has a specific avatar - PARAM: same as globals/pets.lua (21 for any avatar)
job_in_party: 22 # party has job - PARAM: JOBTYPE
zone: 23 # in zone - PARAM: zoneid
synth_trainee: 24 # synth skill under 40 + no support: PARAM: 48: FISH, 49: WOOD, 50: SMITH, 51: GOLDSMITH, 52: CLOTH, 53: LEATHER, 54: BONE, 55: ALCHEMY, 56: COOKING
song_roll_active: 25 # any song or roll active
time_of_day: 26 # PARAM: 0: DAYTIME 1: NIGHTTIME 2: DUSK-DAWN
hour_of_day: 27 # PARAM: 1: NEW DAY, 2: DAWN, 3: DAY, 4: DUSK, 5: EVENING, 6: DEAD OF NIGHT
firesday: 28
earthsday: 29
watersday: 30
windsday: 31
darksday: 32
iceday: 34
lightningsday: 35
lightsday: 36
moon_phase: 37 # PARAM: 0: New Moon, 1: Waxing Crescent, 2: First Quarter, 3: Waxing Gibbous, 4: Full Moon, 5: Waning Gibbous, 6: Last Quarter, 7: Waning Crescent
job_multiple: 38 # PARAM: 0: ODD, 2: EVEN, 3-X: DIVISOR
job_multiple_at_night: 39 # PARAM: 0: ODD, 2: EVEN, 3-X: DIVISOR
equipped_in_slot: 40 # When item is equipped in the specified slot (e.g. Dweomer Knife, Erlking's Sword, etc.) PARAM: slotID
during_ws: 41 # During WS
weather_condition: 42 # See Weather.h for WEATHER enum
weapon_drawn_hp_under: 43 # PARAM: HP PERCENT
nation_citizen: 44 # Triggered by player being citizen of nation matching param: 0 San d'Oria, 1 Bastok, 2 Windurst
mp_under_visible_gear: 45 # mp less than or equal to %, calculated using MP bonuses from visible gear only
hp_over_visible_gear: 46 # hp more than or equal to %, calculated using HP bonuses from visible gear only
weapon_broken: 47
in_dynamis: 48
food_active: 49 # food effect (foodId) active - PARAM: FOOD ITEMID
job_level_below: 50 # PARAM: level
job_level_above: 51 # PARAM: level
weather_element: 52 # PARAM: 0: NONE, 1: FIRE, 2: ICE, 3: WIND 4: EARTH, 5: THUNDER, 6: WATER, 7: LIGHT, 8: DARK
nation_control: 53 # checks if player region is under nation's control - PARAM: 0: Under own nation's control, 1: Outside own nation's control
zone_home_nation: 54 # in zone and citizen of nation (aketons)
mp_over: 55 # mp greater than # - PARAM: MP #
weapon_drawn_mp_over: 56 # while weapon is drawn and mp greater than # - PARAM: MP #
eleven_roll_active: 57 # corsair roll of 11 active
in_assault: 58 # is in an Instance battle in a TOAU zone
vs_ecosystem: 59 # Vs. Specific Ecosystem ID (e.g. Vs. Plantoid: Accuracy+3)
vs_species: 60 # Vs. Specific Species ID (e.g. Vs. Korrigan: Accuracy+3)
vs_family: 61 # Vs. Specific Family ID (e.g. Vs. Mandragora: Accuracy+3)
mainjob: 62 # mainjob - PARAM: JOBTYPE
in_adoulin: 63
in_garrison: 64 # while in an active Garrison
sanction_food_bonus: 65 # While in besieged region
sigil_food_bonus: 66 # While in campaign region

View file

@ -1,107 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
cpp:
underlying: uint16_t
lua:
table: xi.mobMod
values:
none: 0
gil_min: 1 # minimum gil drop -- spawn mod only
gil_max: 2 # maximum gil drop -- spawn mod only
mp_base: 3 # Give mob mp. Used for mobs that are not mages, wyverns, avatars
sight_range: 4 # sight range
sound_range: 5 # sound range
buff_chance: 6 # % chance to buff (combat only)
ga_chance: 7 # % chance to use -ga spell
heal_chance: 8 # % chance to use heal
hp_heal_chance: 9 # can cast cures below this HP %
sublink: 10 # Sub link group. Enables mobs from different families to link if they share a SUBLINK value.
link_radius: 11 # link radius
sees_through_illusion: 12 # Mob can see through the Illusion effect that grants effects similar to Sneak & Invisible without this mod and allows aggro (see Viscious Liquid in mamook)
severe_spell_chance: 13 # % chance to use a severe spell like death or impact
skill_list: 14 # uses given mob skill list
mug_gil: 15 # amount gil carried for mugging
detection: 16 # Overrides mob family's detection method. In order to set to override to none an unused bit must be set such as xi::Detects::None1.
no_despawn: 17 # do not despawn when too far from spawn. Gob Diggers have this.
var: 18 # temp var for whatever. Gets cleared on spawn
can_shield_block: 19 # toggle shield use for mobs without physical shields (trusts)
no_h2h_penalty: 20 # Disables H2H penalty in base damage calculation when set to non-zero
pet_spell_list: 21 # set pet spell list
na_chance: 22 # % chance to cast -na
immunity: 23 # immune to set status effects. This only works from the db, not scripts
gradual_rage: 24 # (!) TODO: NOT YET IMPLEMENTED -- gradually rages
build_resist: 25 # (!) TODO: NOT YET IMPLEMENTED -- builds resistance to given effects
superlink: 26 # super link group. Only use this in scripts! Must be defined in onMobInitialize if relevant mobs are different families
spell_list: 27 # set spell list
exp_bonus: 28 # bonus exp (bonus / 100) negative values reduce exp.
assist: 29 # mobs will assist me
special_skill: 30 # give special skill
roam_distance: 31 # distance allowed to roam from spawn
dont_roam_home: 32 # Allow mobs to roam any distance from spawn. Useful for mobs with scripted roaming behavior.
special_cool: 33 # cool down for special
magic_cool: 34 # cool down for magic
standback_cool: 35 # cool down time for standing back (casting spell while not in attack range)
roam_cool: 36 # cool down time in seconds after roaming
always_aggro: 37 # aggro regardless of level. Spheroids
no_drops: 38 # If set monster cannot drop any items, not even seals.
share_pos: 39 # share a pos with another mob (eald'narche exoplates)
teleport_cd: 40 # cooldown for teleport abilities (tarutaru AA, angra mainyu, eald'narche)
teleport_start: 41 # mobskill ID to begin teleport
teleport_end: 42 # mobskill ID to end teleport
teleport_type: 43 # teleport type - 1: on cooldown, 2 - to close distance
dual_wield: 44 # enables a mob to use their offhand in attacks
add_effect: 45 # enables additional effect script to process on mobs attacks
auto_spikes: 46 # enables additional effect script to process when mob is attacked
spawn_leash: 47 # forces a mob to not move farther from its spawn than its leash distance
share_target: 48 # mob always targets same target as ID in this var
check_as_nm: 49 # If set , mob will check as a NM
roam_reset_facing: 50 # Resume facing the default spawn rotation after roaming home.
roam_turns: 51 # Maximum amount of turns during a roam
roam_rate: 52 # Roaming frequency. roam_cool - rand(roam_cool / (roam_rate / 10))
behavior: 53 # Add behaviors to mob
gil_bonus: 54 # Allow mob to drop gil. Multiplier to gil dropped by mob (bonus / 100) * total
idle_despawn: 55 # Time (in seconds) to despawn after being idle
hp_standback: 56 # mob will always standback with hp % higher to value
magic_delay: 57 # Amount of seconds mob waits before casting first spell
special_delay: 58 # Amount of seconds mob waits before using first special
base_damage_modifier: 59 # Add a flat modifer mob a mob's base damage. This is subject to multiplication by MOBMOD_BASE_DAMAGE_MULTIPLIER.
spawn_animationsub: 60 # reset animationsub to this on spawn
hp_scale: 61 # Scale the mobs max HP. ( hp_scale / 100 ) * maxhp
no_standback: 62 # Mob will never standback
attack_skill_list: 63 # skill list to use in place of regular attacks
charmable: 64 # mob is charmable
no_move: 65 # Mob will not be able to move
multi_hit: 66 # Mob will have as many swings as defined.
no_aggro: 67 # If set, mob cannot aggro until unset.
alli_hate: 68 # Range around target to add alliance member to enmity list.
no_link: 69 # If set, mob cannot link until unset.
no_rest: 70 # Mob cannot regain hp (e.g. re-burrowing antlions during ENM).
leader: 71 # Used for mob following. Positive number is how many followers a leader has. A negative number is the distance from this mob ID to the leader ID.
magic_range: 72 # magic aggro range
target_distance_offset: 73 # Adjusts how close a mob will move to it's target. 12 = 1.2 yalm. Positive values to go closer, negative farther.
one_way_linking: 74 # Will link with other mobs in its party (typically the same mob family) while roaming, but will not let others link with it once engaged
can_parry: 75 # Check if a mob is allowed to have parry rank (Rank Value 1-5)
no_widescan: 76 # Disables widescan for a specific mob
trust_distance: 77 # TRUSTS ONLY: Set movement type/distance. See trust.lua for details.
standback_range: 78 # Applies a specific standback range for the mob
cannot_guard: 79 # Check if the mob does not guard(despite being a MNK or PUP mob)
skip_allegiance_check: 80 # Skip the allegiance check for valid target (allows for example a mob to cast a TARGET_ENEMY spell on itself)
ability_response: 81 # Mob can respond to player ability use with onPlayerAbilityUse()
run_speed_mult: 82 # Multiplier for the speed of a mob while running (generally when the target is out of range) 100 = 1.00x
claim_type: 83 # Changes the claim behavior of the mob. See xi::ClaimType enum.
no_spell_cost: 84 # Mob does not use MP when casting spells
astral_pet_offset: 85 # If non-zero, defines the offset from main mob's ID for astral flow (if zero, will assume offset of 2)
base_damage_multiplier: 86 # Multiplies the mob's base damage. Example: 150 = x1.5. MOBMOD_DAMAGE_OFFSET/MOBMOD_RANGED_DAMAGE_OFFSET are not subject to multiplication.
damage_offset: 87 # Adds or subtracts the mob's base damage offset.
ranged_damage_offset: 88 # Adds or subtracts the mob's ranged base damage offset.
avatar_petid: 89 # A value from xi.petId to select model/ability from when owner uses astral flow
avatar_astral_delay: 90 # Number of milliseconds to delay AF after avatar spawn
h2h_single_swing: 91 # Mob will have only one swing per attack even as MNK with H2H skill
aoe_hit_all: 92 # Mob AoE can hit any player regardless of enmity
ranged_attack_range: 93 # Max range for ranged auto attacks. Mob will move closer if target is beyond this range.
follow_leash_range: 94 # Distance the leader can walk before their followers start moving. Applied to followers.
follow_stop_range: 95 # Distance the followers attempt to stop at once their leader stops moving. Applied to followers.
trust_shield_size: 96 # TRUSTS ONLY: Set the size of the mob's shield. 3 = Default size, only used for trusts that use shields.
bodyguard: 97 # Charmed mob defends its master similar to an avatar. (Maiden's Virelai)

View file

@ -1,17 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
flags: true
cpp:
underlying: uint8_t
lua:
table: xi.mobType
values:
normal: 0x00
unused: 0x01 # available for use
notorious: 0x02
fished: 0x04
called: 0x08
battlefield: 0x10
event: 0x20

File diff suppressed because it is too large Load diff

View file

@ -1,14 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
flags: true
cpp:
underlying: uint8_t
lua:
table: xi.nameVis
values:
none: 0x00
icon: 0x01 # (I) Icon next to name
hide_name: 0x08
ghost_phase: 0x80

View file

@ -1,23 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
flags: true
cpp:
underlying: uint16_t
lua:
table: xi.roamFlag
values:
none: 0x000
none0: 0x001
none1: 0x002
none2: 0x004
none3: 0x008
none4: 0x010
none5: 0x020
worm: 0x040 # pop up and down when moving
ambush: 0x080 # stays hidden until someone comes close (antlion)
scripted: 0x100 # calls lua method for roaming logic
ignore: 0x200 # ignore all hate, except linking hate
stealth: 0x400 # stays name hidden and untargetable until someone comes close (chigoe)
follow: 0x800 # follows a player when sighted for a little while

View file

@ -1,65 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
cpp:
underlying: uint8_t
lua:
table: xi.skill
values:
# Combat Skills
none: 0
hand_to_hand: 1
dagger: 2
sword: 3
great_sword: 4
axe: 5
great_axe: 6
scythe: 7
polearm: 8
katana: 9
great_katana: 10
club: 11
staff: 12
# 13-21 unused
automaton_melee: 22
automaton_ranged: 23
automaton_magic: 24
archery: 25
marksmanship: 26
throwing: 27
# Defensive Skills
guard: 28
evasion: 29
shield: 30
parry: 31
# Magic Skills
divine_magic: 32
healing_magic: 33
enhancing_magic: 34
enfeebling_magic: 35
elemental_magic: 36
dark_magic: 37
summoning_magic: 38
ninjutsu: 39
singing: 40
string_instrument: 41
wind_instrument: 42
blue_magic: 43
geomancy: 44
handbell: 45
# 46-47 unused
# Crafting Skills
fishing: 48
woodworking: 49
smithing: 50
goldsmithing: 51
clothcraft: 52
leathercraft: 53
bonecraft: 54
alchemy: 55
cooking: 56
synergy: 57
# Other Skills
rid: 58
dig: 59

View file

@ -1,11 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
cpp:
underlying: uint8_t
lua:
table: xi.spawnAnimation
values:
normal: 0
special: 1

View file

@ -1,19 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
flags: true
cpp:
underlying: uint8_t
lua:
table: xi.spawnType
values:
normal: 0x00 # 00:00-24:00
at_night: 0x01 # 20:00-04:00
at_evening: 0x02 # 18:00-06:00
weather: 0x04
fog: 0x08 # 02:00-07:00
moonphase: 0x10
lottery: 0x20
windowed: 0x40
scripted: 0x80 # scripted spawn

View file

@ -1,17 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
cpp:
underlying: uint8_t
lua:
table: xi.status
values:
normal: 0
update: 1
disappear: 2
invisible: 3
status_4: 4
cutscene_only: 6
status_18: 18
shutdown: 20

View file

@ -1,42 +0,0 @@
# 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

View file

@ -1,29 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
cpp:
underlying: uint16_t
lua:
table: xi.weather
values:
none: 0
sunshine: 1
clouds: 2
fog: 3
hot_spell: 4
heat_wave: 5
rain: 6
squall: 7
dust_storm: 8
sand_storm: 9
wind: 10
gales: 11
snow: 12
blizzards: 13
thunder: 14
thunderstorms: 15
auroras: 16
stellar_glare: 17
gloom: 18
darkness: 19

View file

@ -1,26 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
flags: true
cpp:
underlying: uint16_t
lua:
table: xi.zoneMisc
values:
none: 0x0000 # Able to be used in any area
escape: 0x0001 # Ability to use Escape Spell
fellow: 0x0002 # Ability to summon Fellow NPC
mount: 0x0004 # Ability to use Chocobos and mounts
mazurka: 0x0008 # Ability to use Mazurka Spell
tractor: 0x0010 # Ability to use Tractor Spell
mogmenu: 0x0020 # Ability to communicate with Nomad Moogle (menu access mog house)
costume: 0x0040 # Ability to use a Costumes
pet: 0x0080 # Ability to summon Pets
treasure: 0x0100 # Presence in the global zone TreasurePool
auction_house: 0x0200 # Ability to use the auction house
yell: 0x0400 # Send and receive /yell commands
trust: 0x0800 # Ability to summon Trust NPC
los_player_block: 0x1000 # Players can't use magic/JAs through walls if this is set
los_off: 0x2000 # Zone should not have LoS checks
assist: 0x4000 # Send and receive /assiste, /assistj commands

View file

@ -1,20 +0,0 @@
# yaml-language-server: $schema=../schemas/enums/_enum.schema.json
meta:
flags: true
cpp:
underlying: uint16_t
lua:
table: xi.zoneType
values:
unknown: 0x0000
city: 0x0001
outdoors: 0x0002
dungeon: 0x0004
signet: 0x0008
sanction: 0x0010
sigil: 0x0020
ionis: 0x0040
dynamis: 0x0080
instanced: 0x0100

View file

@ -1,43 +0,0 @@
{
"$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."
}
}
}
}
}

View file

@ -1,65 +0,0 @@
{
"$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" }
}
}
}

View file

@ -1,52 +0,0 @@
{
"$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 }
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@
########
# Base #
########
ARG BASE_TAG=3.24
ARG BASE_TAG=3.22
FROM --platform=$BUILDPLATFORM alpine:$BASE_TAG AS base
# Install runtime dependencies.
@ -12,7 +12,6 @@ apk --update-cache add \
bash \
binutils \
git \
libdwarf \
lua5.1-dev \
luajit \
mariadb-client \
@ -57,7 +56,7 @@ SHELL ["/bin/bash", "-c"]
###########
FROM base AS staging
ARG LLVM_VERSION=22
ARG LLVM_VERSION=20
# Install build dependencies.
RUN --mount=type=cache,target=/var/cache/apk,id=cache-apk,sharing=locked <<EOF
@ -66,18 +65,15 @@ apk --update-cache add \
ccache \
cmake \
g++ \
libdwarf-dev \
linux-headers \
luajit-dev \
make \
mariadb-dev \
ninja-build \
ninja-is-really-ninja \
openssl-dev \
python3-dev \
samurai \
zeromq-dev \
zlib-dev \
zstd-dev
zlib-dev
EOF
# Install secondary dependencies as user.
@ -142,6 +138,7 @@ COPY --chown=$UNAME:$UGROUP \
--exclude=.git \
--exclude=navmeshes/** \
--exclude=ximeshes/** \
--exclude=scripts \
--exclude=sql \
. /server
@ -154,6 +151,7 @@ ENV CCACHE_DIR=/xiadmin/.ccache
RUN --mount=type=cache,target=/xiadmin/build,uid=$UID,gid=$GID,id=build-alpine-$COMPILER-$CMAKE_BUILD_TYPE-tracy$TRACY_ENABLE-pch$PCH_ENABLE \
--mount=type=cache,target=/xiadmin/.ccache,uid=$UID,gid=$GID,id=ccache-alpine-$COMPILER-$CMAKE_BUILD_TYPE-tracy$TRACY_ENABLE-pch$PCH_ENABLE \
--mount=type=bind,source=.git,target=/server/.git \
--mount=type=bind,source=scripts,target=/server/scripts \
--mount=type=bind,source=sql,target=/server/sql <<EOF
set -eo pipefail
cp -p /xiadmin/build/version.cpp /server/src/common/ 2> /dev/null || true
@ -189,14 +187,13 @@ USER $UNAME
COPY --chown=$UNAME:$UGROUP LICENSE /server/LICENSE
COPY --chown=$UNAME:$UGROUP res/compress.dat res/decompress.dat /server/res/
COPY --chown=$UNAME:$UGROUP scripts /server/scripts
COPY --chown=$UNAME:$UGROUP sql /server/sql
COPY --chown=$UNAME:$UGROUP tools /server/tools
COPY --chown=$UNAME:$UGROUP modules /server/modules
COPY --chown=$UNAME:$UGROUP settings /server/settings
COPY --chown=$UNAME:$UGROUP --from=staging $VIRTUAL_ENV $VIRTUAL_ENV
COPY --chown=$UNAME:$UGROUP --from=build /server/data /server/data
COPY --chown=$UNAME:$UGROUP --from=build /server/scripts /server/scripts
COPY --chown=$UNAME:$UGROUP --from=build /server/xi_* /server/
COPY --chown=$UNAME:$UGROUP --from=build /server/build.log /server/build.log

View file

@ -3,7 +3,7 @@
########
# Base #
########
ARG BASE_TAG=26.04
ARG BASE_TAG=24.04
FROM --platform=$BUILDPLATFORM ubuntu:$BASE_TAG AS base
ARG DEBIAN_FRONTEND=noninteractive
@ -19,7 +19,6 @@ apt-get update && apt-get install --assume-yes --no-install-recommends --quiet \
binutils \
ca-certificates \
git \
libdwarf1 \
libzmq5 \
lua5.1 \
luajit \
@ -64,8 +63,8 @@ SHELL ["/bin/bash", "-c"]
###########
FROM base AS staging
ARG GCC_VERSION=15
ARG LLVM_VERSION=22
ARG GCC_VERSION=14
ARG LLVM_VERSION=20
# Install build dependencies.
RUN --mount=type=cache,target=/var/cache/apt,id=cache-apt,sharing=locked \
@ -75,18 +74,15 @@ apt-get update && apt-get install --assume-yes --no-install-recommends --quiet \
ccache \
cmake \
g++-$GCC_VERSION \
libdwarf-dev \
libluajit-5.1-dev \
libmariadb-dev-compat \
libssl-dev \
libzmq3-dev \
make \
ninja-build \
pkg-config \
python3-dev \
python3-venv \
zlib1g-dev \
libzstd-dev
zlib1g-dev
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-$GCC_VERSION 100
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-$GCC_VERSION 100
EOF
@ -154,6 +150,7 @@ COPY --chown=$UNAME:$UGROUP \
--exclude=.git \
--exclude=navmeshes/** \
--exclude=ximeshes/** \
--exclude=scripts \
--exclude=sql \
. /server
@ -166,6 +163,7 @@ ENV CCACHE_DIR=/xiadmin/.ccache
RUN --mount=type=cache,target=/xiadmin/build,uid=$UID,gid=$GID,id=build-ubuntu-$COMPILER-$CMAKE_BUILD_TYPE-tracy$TRACY_ENABLE-pch$PCH_ENABLE \
--mount=type=cache,target=/xiadmin/.ccache,uid=$UID,gid=$GID,id=ccache-ubuntu-$COMPILER-$CMAKE_BUILD_TYPE-tracy$TRACY_ENABLE-pch$PCH_ENABLE \
--mount=type=bind,source=.git,target=/server/.git \
--mount=type=bind,source=scripts,target=/server/scripts \
--mount=type=bind,source=sql,target=/server/sql <<EOF
set -eo pipefail
cp -p /xiadmin/build/version.cpp /server/src/common/ 2> /dev/null || true
@ -201,14 +199,13 @@ USER $UNAME
COPY --chown=$UNAME:$UGROUP LICENSE /server/LICENSE
COPY --chown=$UNAME:$UGROUP res/compress.dat res/decompress.dat /server/res/
COPY --chown=$UNAME:$UGROUP scripts /server/scripts
COPY --chown=$UNAME:$UGROUP sql /server/sql
COPY --chown=$UNAME:$UGROUP tools /server/tools
COPY --chown=$UNAME:$UGROUP modules /server/modules
COPY --chown=$UNAME:$UGROUP settings /server/settings
COPY --chown=$UNAME:$UGROUP --from=staging $VIRTUAL_ENV $VIRTUAL_ENV
COPY --chown=$UNAME:$UGROUP --from=build /server/data /server/data
COPY --chown=$UNAME:$UGROUP --from=build /server/scripts /server/scripts
COPY --chown=$UNAME:$UGROUP --from=build /server/xi_* /server/
COPY --chown=$UNAME:$UGROUP --from=build /server/build.log /server/build.log

View file

@ -554,7 +554,7 @@
ALL_WSDMG_FIRST_HIT = 841, // Generic (all Weaponskills) damage, first hit only.
AUTO_DECISION_DELAY = 842, // Reduces the Automaton's global decision delay
AUTO_SHIELD_BASH_DELAY = 843, // Reduces the Automaton's global shield bash delay
AUTO_MAGIC_COOLDOWN = 844, // Adjusts the Automaton's global magic cooldown. (negative value reduces cooldown, positive value increases cooldown)
AUTO_MAGIC_DELAY = 844, // Reduces the Automaton's global magic delay
AUTO_HEALING_DELAY = 845, // Reduces the Automaton's global healing delay
AUTO_HEALING_THRESHOLD = 846, // Increases the healing trigger threshold
BURDEN_DECAY = 847, // Increases amount of burden removed per tick
@ -653,8 +653,8 @@
// SPARE ID 936
FOOD_DURATION = 937, // Percentage to increase food duration
// SPARE ID 938
AUTO_STEAM_JACKET_REDUCTION = 939, // Percent damage reduction from Steam Jacket
AUTO_STEAM_JACKET = 938, // Causes the Automaton to mitigate damage from successive attacks of the same type
AUTO_STEAM_JACKET_REDUCTION = 939, // Amount of damage reduced with Steam Jacket
AUTO_SCHURZEN = 940, // Prevents fatal damage leaving the automaton at 1HP and consumes an Earth manuever
AUTO_EQUALIZER = 941, // Reduces damage received according to damage taken
AUTO_PERFORMANCE_BOOST = 942, // Increases the performance of other attachments by a percentage
@ -770,3 +770,4 @@
// For example, +10% damage to Chant du Cygne would be ID 570 + 225 (795)
// SPARE = 1077,

View file

@ -1,9 +1,9 @@
# add_subdirectory(lua) # Handled globally
# add_subdirectory(mariadb) # Handled globally
# add_subdirectory(mariadbcpp) # Handled globally
# add_subdirectory(zmq) # Handled globally
# add_subdirectory(openssl) # Handled globally
add_subdirectory(concurrentqueue)
add_subdirectory(SPSCQueue)
add_subdirectory(sol)
# CPM Modules
@ -42,55 +42,31 @@ if(TRACY_ENABLE)
tar xvf "${CMAKE_SOURCE_DIR}/tracy.tar.gz"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/
)
else() # UNIX (Linux / macOS)
include(ExternalProject)
else() # UNIX
# TODO: Auto-build Tracy and capture executables on Linux
# sudo apt-get -y install libglfw3-dev libdbus-1-dev libcapstone-dev libtbb-dev libdebuginfod-dev libfreetype-dev
# target name:source subdirectory
set(TRACY_TOOLS
"tracy-capture:capture"
"tracy-csvexport:csvexport"
)
# execute_process(COMMAND "make"
# WORKING_DIRECTORY ${tracy_SOURCE_DIR}/profiler/build/unix
# )
foreach(_tracy_tool ${TRACY_TOOLS})
string(REPLACE ":" ";" _tracy_tool "${_tracy_tool}")
list(GET _tracy_tool 0 _tracy_tool_name)
list(GET _tracy_tool 1 _tracy_tool_dir)
message(STATUS "Configuring Tracy tool: ${_tracy_tool_name}")
set(_tracy_tool_bindir ${CMAKE_BINARY_DIR}/tracy-tools/${_tracy_tool_name})
ExternalProject_Add(${_tracy_tool_name}
SOURCE_DIR ${TracyClient_SOURCE_DIR}/${_tracy_tool_dir}
BINARY_DIR ${_tracy_tool_bindir}
CMAKE_ARGS
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}
-DCMAKE_OSX_SYSROOT=${CMAKE_OSX_SYSROOT}
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${_tracy_tool_bindir}
BUILD_ALWAYS TRUE
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_if_different
${_tracy_tool_bindir}/${_tracy_tool_name}
${CMAKE_SOURCE_DIR}/${_tracy_tool_name}
)
endforeach()
# execute_process(COMMAND "make"
# WORKING_DIRECTORY ${tracy_SOURCE_DIR}/capture/build/unix
# )
endif()
endif(TRACY_ENABLE)
CPMAddPackage(
NAME fmt
GITHUB_REPOSITORY fmtlib/fmt
GIT_TAG 12.2.0
GIT_TAG 11.2.0
SYSTEM ON
) # defines: fmt::fmt
CPMAddPackage(
NAME spdlog
GITHUB_REPOSITORY gabime/spdlog
GIT_TAG v1.17.0
GIT_TAG v1.15.3
SYSTEM ON
OPTIONS
"SPDLOG_ENABLE_PCH ON"
@ -100,9 +76,11 @@ CPMAddPackage(
CPMAddPackage(
NAME recastnavigation
GITHUB_REPOSITORY recastnavigation/recastnavigation
GIT_TAG 1078bfe346d9bb560faa748c8fde2e7aae73a3ab
GIT_TAG bd98d84c274ee06842bf51a4088ca82ac71f8c2d
SYSTEM ON
OPTIONS
# TODO: Remove this once recast is updated to use CMake 3.5+, it's currently set to what we use in the root CMakeLists.txt
"CMAKE_POLICY_VERSION_MINIMUM 3.20"
"RECASTNAVIGATION_DEMO OFF"
"RECASTNAVIGATION_TESTS OFF"
"RECASTNAVIGATION_EXAMPLES OFF"
@ -132,7 +110,7 @@ endif()
CPMAddPackage(
NAME rapidyaml
GITHUB_REPOSITORY biojppm/rapidyaml
GIT_TAG v0.15.2
GIT_TAG v0.12.0
SYSTEM ON
OPTIONS
"RYML_BUILD_TOOLS OFF"
@ -149,8 +127,8 @@ CPMAddPackage(
CPMAddPackage(
NAME efsw
GITHUB_REPOSITORY SpartanJ/efsw
GIT_TAG 22f17a0bcdf3a4edf61f8b14328391463389e548 # master
GITHUB_REPOSITORY zach2good/efsw
GIT_TAG c37c7e0fc6bbd63659edeba458273c35a51513da # master
SYSTEM ON
OPTIONS
"VERBOSE OFF"
@ -171,7 +149,7 @@ CPMAddPackage(
CPMAddPackage(
NAME cpp-httplib
GITHUB_REPOSITORY yhirose/cpp-httplib
GIT_TAG v0.49.0
GIT_TAG v0.18.3
SYSTEM ON
OPTIONS
"HTTPLIB_REQUIRE_ZLIB OFF"
@ -181,7 +159,7 @@ CPMAddPackage(
CPMAddPackage(
NAME json
GITHUB_REPOSITORY nlohmann/json
GIT_TAG v3.12.0
GIT_TAG 9f60e855576bb1e95f39ab23b3821982cccb0bab
SYSTEM ON
) # defines: nlohmann_json::nlohmann_json
@ -197,9 +175,9 @@ endif()
CPMAddPackage(
NAME asio
VERSION 1.38.0
VERSION 1.36.0
GITHUB_REPOSITORY chriskohlhoff/asio
GIT_TAG asio-1-38-0 # asio uses non-standard version tag, we must specify GIT_TAG
GIT_TAG asio-1-36-0 # asio uses non-standard version tag, we must specify GIT_TAG
) #defines asio
# ASIO doesn't use CMake, we have to configure it manually. Extra notes for using on Windows:
@ -209,7 +187,7 @@ CPMAddPackage(
if(asio_ADDED)
add_library(asio INTERFACE)
target_include_directories(asio SYSTEM INTERFACE ${asio_SOURCE_DIR}/include)
target_include_directories(asio SYSTEM INTERFACE ${asio_SOURCE_DIR}/asio/include)
target_compile_definitions(asio INTERFACE ASIO_STANDALONE ASIO_NO_DEPRECATED)
@ -281,7 +259,7 @@ CPMAddPackage(
CPMAddPackage(
NAME magic_enum
GITHUB_REPOSITORY Neargye/magic_enum
GIT_TAG v0.9.8
GIT_TAG 1a1824df7ac798177a521eed952720681b0bf482
SYSTEM ON
) # defines: magic_enum
@ -292,56 +270,12 @@ CPMAddPackage(
SYSTEM ON
) # defines: termcolor::termcolor
CPMAddPackage(
NAME unordered_dense
GITHUB_REPOSITORY martinus/unordered_dense
GIT_TAG v4.8.1
SYSTEM ON
) # defines: unordered_dense::unordered_dense (aliased to FlatHashMap, see src/common/flat_hash_map.h)
# TODO: std::move_only_function lands in C++23, but libc++ (macOS) has not implemented
# : it yet. Remove this once all compilers for all platforms implement.
CPMAddPackage(
NAME function2
GITHUB_REPOSITORY Naios/function2
GIT_TAG 4.2.4
SYSTEM ON
) # defines: function2 (aliased to Fn, see src/common/types/fn.h)
# How cpptrace turns a crash address into function + file:line, per platform:
set(CPPTRACE_SYMBOL_OPTIONS "")
if(APPLE)
# macOS binaries carry a "debug map" pointing at the .o files rather than embedded DWARF;
# atos resolves against the staged .dSYM (see set_target_output_directory) and is fast.
list(APPEND CPPTRACE_SYMBOL_OPTIONS
"CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF OFF"
"CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE ON"
)
elseif(UNIX)
# Linux: resolve in-process with libdwarf.
list(APPEND CPPTRACE_SYMBOL_OPTIONS
"CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE OFF"
"CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF ON"
"CPPTRACE_USE_EXTERNAL_LIBDWARF ON"
"CPPTRACE_FIND_LIBDWARF_WITH_PKGCONFIG ON"
)
endif()
CPMAddPackage(
NAME cpptrace
GITHUB_REPOSITORY jeremy-rifkin/cpptrace
GIT_TAG v1.0.4
SYSTEM ON
OPTIONS
${CPPTRACE_SYMBOL_OPTIONS}
) # defines: cpptrace::cpptrace
set(SHARED_EXTERNAL_LIBS
fmt::fmt
spdlog
concurrentqueue
spscqueue
mariadbclient
mariadbcpp
sol2_single
argparse
efsw
@ -351,16 +285,25 @@ set(SHARED_EXTERNAL_LIBS
alpaca
magic_enum
utf8cpp
unordered_dense::unordered_dense
function2
cpptrace::cpptrace
)
if(APPLE)
if(WIN32)
# add wepoll for epoll support on windows
add_subdirectory(wepoll)
list(APPEND SHARED_EXTERNAL_LIBS
wepoll
)
# backwards needs these to add to linker
elseif(APPLE)
# MacOS has bfd built in clang
list(APPEND SHARED_EXTERNAL_LIBS
dl
)
elseif(UNIX)
# Linux needs bfd as it's not native like MacOS
# bfd may link zstd
list(APPEND SHARED_EXTERNAL_LIBS
bfd
dl

View file

@ -1,3 +0,0 @@
add_library(spscqueue INTERFACE)
target_sources(spscqueue INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include/rigtorp/SPSCQueue.h)
target_include_directories(spscqueue SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include/)

View file

@ -1,237 +0,0 @@
/*
Copyright (c) 2020 Erik Rigtorp <erik@rigtorp.se>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <atomic>
#include <cassert>
#include <cstddef>
#include <memory> // std::allocator
#include <new> // std::hardware_destructive_interference_size
#include <stdexcept>
#include <type_traits> // std::enable_if, std::is_*_constructible
#ifdef __has_cpp_attribute
#if __has_cpp_attribute(nodiscard)
#define RIGTORP_NODISCARD [[nodiscard]]
#endif
#endif
#ifndef RIGTORP_NODISCARD
#define RIGTORP_NODISCARD
#endif
namespace rigtorp {
template <typename T, typename Allocator = std::allocator<T>> class SPSCQueue {
#if defined(__cpp_if_constexpr) && defined(__cpp_lib_void_t)
template <typename Alloc2, typename = void>
struct has_allocate_at_least : std::false_type {};
template <typename Alloc2>
struct has_allocate_at_least<
Alloc2, std::void_t<typename Alloc2::value_type,
decltype(std::declval<Alloc2 &>().allocate_at_least(
size_t{}))>> : std::true_type {};
#endif
public:
explicit SPSCQueue(const size_t capacity,
const Allocator &allocator = Allocator())
: capacity_(capacity), allocator_(allocator) {
// The queue needs at least one element
if (capacity_ < 1) {
capacity_ = 1;
}
capacity_++; // Needs one slack element
// Prevent overflowing size_t
if (capacity_ > SIZE_MAX - 2 * kPadding) {
capacity_ = SIZE_MAX - 2 * kPadding;
}
#if defined(__cpp_if_constexpr) && defined(__cpp_lib_void_t)
if constexpr (has_allocate_at_least<Allocator>::value) {
auto res = allocator_.allocate_at_least(capacity_ + 2 * kPadding);
slots_ = res.ptr;
capacity_ = res.count - 2 * kPadding;
} else {
slots_ = std::allocator_traits<Allocator>::allocate(
allocator_, capacity_ + 2 * kPadding);
}
#else
slots_ = std::allocator_traits<Allocator>::allocate(
allocator_, capacity_ + 2 * kPadding);
#endif
static_assert(alignof(SPSCQueue<T>) == kCacheLineSize, "");
static_assert(sizeof(SPSCQueue<T>) >= 3 * kCacheLineSize, "");
assert(reinterpret_cast<char *>(&readIdx_) -
reinterpret_cast<char *>(&writeIdx_) >=
static_cast<std::ptrdiff_t>(kCacheLineSize));
}
~SPSCQueue() {
while (front()) {
pop();
}
std::allocator_traits<Allocator>::deallocate(allocator_, slots_,
capacity_ + 2 * kPadding);
}
// non-copyable and non-movable
SPSCQueue(const SPSCQueue &) = delete;
SPSCQueue &operator=(const SPSCQueue &) = delete;
template <typename... Args>
void emplace(Args &&...args) noexcept(
std::is_nothrow_constructible<T, Args &&...>::value) {
static_assert(std::is_constructible<T, Args &&...>::value,
"T must be constructible with Args&&...");
auto const writeIdx = writeIdx_.load(std::memory_order_relaxed);
auto nextWriteIdx = writeIdx + 1;
if (nextWriteIdx == capacity_) {
nextWriteIdx = 0;
}
while (nextWriteIdx == readIdxCache_) {
readIdxCache_ = readIdx_.load(std::memory_order_acquire);
}
new (&slots_[writeIdx + kPadding]) T(std::forward<Args>(args)...);
writeIdx_.store(nextWriteIdx, std::memory_order_release);
}
template <typename... Args>
RIGTORP_NODISCARD bool try_emplace(Args &&...args) noexcept(
std::is_nothrow_constructible<T, Args &&...>::value) {
static_assert(std::is_constructible<T, Args &&...>::value,
"T must be constructible with Args&&...");
auto const writeIdx = writeIdx_.load(std::memory_order_relaxed);
auto nextWriteIdx = writeIdx + 1;
if (nextWriteIdx == capacity_) {
nextWriteIdx = 0;
}
if (nextWriteIdx == readIdxCache_) {
readIdxCache_ = readIdx_.load(std::memory_order_acquire);
if (nextWriteIdx == readIdxCache_) {
return false;
}
}
new (&slots_[writeIdx + kPadding]) T(std::forward<Args>(args)...);
writeIdx_.store(nextWriteIdx, std::memory_order_release);
return true;
}
void push(const T &v) noexcept(std::is_nothrow_copy_constructible<T>::value) {
static_assert(std::is_copy_constructible<T>::value,
"T must be copy constructible");
emplace(v);
}
template <typename P, typename = typename std::enable_if<
std::is_constructible<T, P &&>::value>::type>
void push(P &&v) noexcept(std::is_nothrow_constructible<T, P &&>::value) {
emplace(std::forward<P>(v));
}
RIGTORP_NODISCARD bool
try_push(const T &v) noexcept(std::is_nothrow_copy_constructible<T>::value) {
static_assert(std::is_copy_constructible<T>::value,
"T must be copy constructible");
return try_emplace(v);
}
template <typename P, typename = typename std::enable_if<
std::is_constructible<T, P &&>::value>::type>
RIGTORP_NODISCARD bool
try_push(P &&v) noexcept(std::is_nothrow_constructible<T, P &&>::value) {
return try_emplace(std::forward<P>(v));
}
RIGTORP_NODISCARD T *front() noexcept {
auto const readIdx = readIdx_.load(std::memory_order_relaxed);
if (readIdx == writeIdxCache_) {
writeIdxCache_ = writeIdx_.load(std::memory_order_acquire);
if (writeIdxCache_ == readIdx) {
return nullptr;
}
}
return &slots_[readIdx + kPadding];
}
void pop() noexcept {
static_assert(std::is_nothrow_destructible<T>::value,
"T must be nothrow destructible");
auto const readIdx = readIdx_.load(std::memory_order_relaxed);
assert(writeIdx_.load(std::memory_order_acquire) != readIdx &&
"Can only call pop() after front() has returned a non-nullptr");
slots_[readIdx + kPadding].~T();
auto nextReadIdx = readIdx + 1;
if (nextReadIdx == capacity_) {
nextReadIdx = 0;
}
readIdx_.store(nextReadIdx, std::memory_order_release);
}
RIGTORP_NODISCARD size_t size() const noexcept {
std::ptrdiff_t diff = writeIdx_.load(std::memory_order_acquire) -
readIdx_.load(std::memory_order_acquire);
if (diff < 0) {
diff += capacity_;
}
return static_cast<size_t>(diff);
}
RIGTORP_NODISCARD bool empty() const noexcept {
return writeIdx_.load(std::memory_order_acquire) ==
readIdx_.load(std::memory_order_acquire);
}
RIGTORP_NODISCARD size_t capacity() const noexcept { return capacity_ - 1; }
private:
#ifdef __cpp_lib_hardware_interference_size
static constexpr size_t kCacheLineSize =
std::hardware_destructive_interference_size;
#else
static constexpr size_t kCacheLineSize = 64;
#endif
// Padding to avoid false sharing between slots_ and adjacent allocations
static constexpr size_t kPadding = (kCacheLineSize - 1) / sizeof(T) + 1;
private:
size_t capacity_;
T *slots_;
#if defined(__has_cpp_attribute) && __has_cpp_attribute(no_unique_address)
Allocator allocator_ [[no_unique_address]];
#else
Allocator allocator_;
#endif
// Align to cache line size in order to avoid false sharing
// readIdxCache_ and writeIdxCache_ is used to reduce the amount of cache
// coherency traffic
alignas(kCacheLineSize) std::atomic<size_t> writeIdx_ = {0};
alignas(kCacheLineSize) size_t readIdxCache_ = 0;
alignas(kCacheLineSize) std::atomic<size_t> readIdx_ = {0};
alignas(kCacheLineSize) size_t writeIdxCache_ = 0;
};
} // namespace rigtorp

21
ext/backward/LICENSE.txt Normal file
View file

@ -0,0 +1,21 @@
Copyright 2013 Google Inc. All Rights Reserved.
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

42
ext/backward/backward.cpp Normal file
View file

@ -0,0 +1,42 @@
// Pick your poison.
//
// On GNU/Linux, you have few choices to get the most out of your stack trace.
//
// By default you get:
// - object filename
// - function name
//
// In order to add:
// - source filename
// - line and column numbers
// - source code snippet (assuming the file is accessible)
// Install one of the following libraries then uncomment one of the macro (or
// better, add the detection of the lib and the macro definition in your build
// system)
// - apt-get install libdw-dev ...
// - g++/clang++ -ldw ...
// #define BACKWARD_HAS_DW 1
// - apt-get install binutils-dev ...
// - g++/clang++ -lbfd ...
// #define BACKWARD_HAS_BFD 1
// - apt-get install libdwarf-dev ...
// - g++/clang++ -ldwarf ...
// #define BACKWARD_HAS_DWARF 1
// Regardless of the library you choose to read the debug information,
// for potentially more detailed stack traces you can use libunwind
// - apt-get install libunwind-dev
// - g++/clang++ -lunwind
// #define BACKWARD_HAS_LIBUNWIND 1
#include "backward.hpp"
namespace backward {
backward::SignalHandling sh;
} // namespace backward

4514
ext/backward/backward.hpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,9 @@
set(SOURCES
wepoll.c
wepoll.h
)
add_library(wepoll STATIC ${SOURCES})
target_include_directories(wepoll SYSTEM PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

28
ext/wepoll/LICENSE Normal file
View file

@ -0,0 +1,28 @@
wepoll - epoll for Windows
https://github.com/piscisaureus/wepoll
Copyright 2012-2020, Bert Belder <bertbelder@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

202
ext/wepoll/README.md Normal file
View file

@ -0,0 +1,202 @@
# wepoll - epoll for windows
[![][ci status badge]][ci status link]
This library implements the [epoll][man epoll] API for Windows
applications. It is fast and scalable, and it closely resembles the API
and behavior of Linux' epoll.
## Rationale
Unlike Linux, OS X, and many other operating systems, Windows doesn't
have a good API for receiving socket state notifications. It only
supports the `select` and `WSAPoll` APIs, but they
[don't scale][select scale] and suffer from
[other issues][wsapoll broken].
Using I/O completion ports isn't always practical when software is
designed to be cross-platform. Wepoll offers an alternative that is
much closer to a drop-in replacement for software that was designed
to run on Linux.
## Features
* Can poll 100000s of sockets efficiently.
* Fully thread-safe.
* Multiple threads can poll the same epoll port.
* Sockets can be added to multiple epoll sets.
* All epoll events (`EPOLLIN`, `EPOLLOUT`, `EPOLLPRI`, `EPOLLRDHUP`)
are supported.
* Level-triggered and one-shot (`EPOLLONESTHOT`) modes are supported
* Trivial to embed: you need [only two files][dist].
## Limitations
* Only works with sockets.
* Edge-triggered (`EPOLLET`) mode isn't supported.
## How to use
The library is [distributed][dist] as a single source file
([wepoll.c][wepoll.c]) and a single header file ([wepoll.h][wepoll.h]).<br>
Compile the .c file as part of your project, and include the header wherever
needed.
## Compatibility
* Requires Windows Vista or higher.
* Can be compiled with recent versions of MSVC, Clang, and GCC.
## API
### General remarks
* The epoll port is a `HANDLE`, not a file descriptor.
* All functions set both `errno` and `GetLastError()` on failure.
* For more extensive documentation, see the [epoll(7) man page][man epoll],
and the per-function man pages that are linked below.
### epoll_create/epoll_create1
```c
HANDLE epoll_create(int size);
HANDLE epoll_create1(int flags);
```
* Create a new epoll instance (port).
* `size` is ignored but most be greater than zero.
* `flags` must be zero as there are no supported flags.
* Returns `NULL` on failure.
* [Linux man page][man epoll_create]
### epoll_close
```c
int epoll_close(HANDLE ephnd);
```
* Close an epoll port.
* Do not attempt to close the epoll port with `close()`,
`CloseHandle()` or `closesocket()`.
### epoll_ctl
```c
int epoll_ctl(HANDLE ephnd,
int op,
SOCKET sock,
struct epoll_event* event);
```
* Control which socket events are monitored by an epoll port.
* `ephnd` must be a HANDLE created by
[`epoll_create()`](#epoll_createepoll_create1) or
[`epoll_create1()`](#epoll_createepoll_create1).
* `op` must be one of `EPOLL_CTL_ADD`, `EPOLL_CTL_MOD`, `EPOLL_CTL_DEL`.
* `sock` must be a valid socket created by [`socket()`][msdn socket],
[`WSASocket()`][msdn wsasocket], or [`accept()`][msdn accept].
* `event` should be a pointer to a [`struct epoll_event`](#struct-epoll_event).<br>
If `op` is `EPOLL_CTL_DEL` then the `event` parameter is ignored, and it
may be `NULL`.
* Returns 0 on success, -1 on failure.
* It is recommended to always explicitly remove a socket from its epoll
set using `EPOLL_CTL_DEL` *before* closing it.<br>
As on Linux, closed sockets are automatically removed from the epoll set, but
wepoll may not be able to detect that a socket was closed until the next call
to [`epoll_wait()`](#epoll_wait).
* [Linux man page][man epoll_ctl]
### epoll_wait
```c
int epoll_wait(HANDLE ephnd,
struct epoll_event* events,
int maxevents,
int timeout);
```
* Receive socket events from an epoll port.
* `events` should point to a caller-allocated array of
[`epoll_event`](#struct-epoll_event) structs, which will receive the
reported events.
* `maxevents` is the maximum number of events that will be written to the
`events` array, and must be greater than zero.
* `timeout` specifies whether to block when no events are immediately available.
- `<0` block indefinitely
- `0` report any events that are already waiting, but don't block
- `≥1` block for at most N milliseconds
* Return value:
- `-1` an error occurred
- `0` timed out without any events to report
- `≥1` the number of events stored in the `events` buffer
* [Linux man page][man epoll_wait]
### struct epoll_event
```c
typedef union epoll_data {
void* ptr;
int fd;
uint32_t u32;
uint64_t u64;
SOCKET sock; /* Windows specific */
HANDLE hnd; /* Windows specific */
} epoll_data_t;
```
```c
struct epoll_event {
uint32_t events; /* Epoll events and flags */
epoll_data_t data; /* User data variable */
};
```
* The `events` field is a bit mask containing the events being
monitored/reported, and optional flags.<br>
Flags are accepted by [`epoll_ctl()`](#epoll_ctl), but they are not reported
back by [`epoll_wait()`](#epoll_wait).
* The `data` field can be used to associate application-specific information
with a socket; its value will be returned unmodified by
[`epoll_wait()`](#epoll_wait).
* [Linux man page][man epoll_ctl]
| Event | Description |
|---------------|----------------------------------------------------------------------|
| `EPOLLIN` | incoming data available, or incoming connection ready to be accepted |
| `EPOLLOUT` | ready to send data, or outgoing connection successfully established |
| `EPOLLRDHUP` | remote peer initiated graceful socket shutdown |
| `EPOLLPRI` | out-of-band data available for reading |
| `EPOLLERR` | socket error<sup>1</sup> |
| `EPOLLHUP` | socket hang-up<sup>1</sup> |
| `EPOLLRDNORM` | same as `EPOLLIN` |
| `EPOLLRDBAND` | same as `EPOLLPRI` |
| `EPOLLWRNORM` | same as `EPOLLOUT` |
| `EPOLLWRBAND` | same as `EPOLLOUT` |
| `EPOLLMSG` | never reported |
| Flag | Description |
|------------------|---------------------------|
| `EPOLLONESHOT` | report event(s) only once |
| `EPOLLET` | not supported by wepoll |
| `EPOLLEXCLUSIVE` | not supported by wepoll |
| `EPOLLWAKEUP` | not supported by wepoll |
<sup>1</sup>: the `EPOLLERR` and `EPOLLHUP` events may always be reported by
[`epoll_wait()`](#epoll_wait), regardless of the event mask that was passed to
[`epoll_ctl()`](#epoll_ctl).
[ci status badge]: https://ci.appveyor.com/api/projects/status/github/piscisaureus/wepoll?branch=master&svg=true
[ci status link]: https://ci.appveyor.com/project/piscisaureus/wepoll/branch/master
[dist]: https://github.com/piscisaureus/wepoll/tree/dist
[man epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
[man epoll_create]: http://man7.org/linux/man-pages/man2/epoll_create.2.html
[man epoll_ctl]: http://man7.org/linux/man-pages/man2/epoll_ctl.2.html
[man epoll_wait]: http://man7.org/linux/man-pages/man2/epoll_wait.2.html
[msdn accept]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms737526(v=vs.85).aspx
[msdn socket]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740506(v=vs.85).aspx
[msdn wsasocket]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms742212(v=vs.85).aspx
[select scale]: https://daniel.haxx.se/docs/poll-vs-select.html
[wsapoll broken]: https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/
[wepoll.c]: https://github.com/piscisaureus/wepoll/blob/dist/wepoll.c
[wepoll.h]: https://github.com/piscisaureus/wepoll/blob/dist/wepoll.h

2253
ext/wepoll/wepoll.c Normal file

File diff suppressed because it is too large Load diff

113
ext/wepoll/wepoll.h Normal file
View file

@ -0,0 +1,113 @@
/*
* wepoll - epoll for Windows
* https://github.com/piscisaureus/wepoll
*
* Copyright 2012-2020, Bert Belder <bertbelder@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WEPOLL_H_
#define WEPOLL_H_
#ifndef WEPOLL_EXPORT
#define WEPOLL_EXPORT
#endif
#include <stdint.h>
enum EPOLL_EVENTS {
EPOLLIN = (int) (1U << 0),
EPOLLPRI = (int) (1U << 1),
EPOLLOUT = (int) (1U << 2),
EPOLLERR = (int) (1U << 3),
EPOLLHUP = (int) (1U << 4),
EPOLLRDNORM = (int) (1U << 6),
EPOLLRDBAND = (int) (1U << 7),
EPOLLWRNORM = (int) (1U << 8),
EPOLLWRBAND = (int) (1U << 9),
EPOLLMSG = (int) (1U << 10), /* Never reported. */
EPOLLRDHUP = (int) (1U << 13),
EPOLLONESHOT = (int) (1U << 31)
};
#define EPOLLIN (1U << 0)
#define EPOLLPRI (1U << 1)
#define EPOLLOUT (1U << 2)
#define EPOLLERR (1U << 3)
#define EPOLLHUP (1U << 4)
#define EPOLLRDNORM (1U << 6)
#define EPOLLRDBAND (1U << 7)
#define EPOLLWRNORM (1U << 8)
#define EPOLLWRBAND (1U << 9)
#define EPOLLMSG (1U << 10)
#define EPOLLRDHUP (1U << 13)
#define EPOLLONESHOT (1U << 31)
#define EPOLL_CTL_ADD 1
#define EPOLL_CTL_MOD 2
#define EPOLL_CTL_DEL 3
typedef void* HANDLE;
typedef uintptr_t SOCKET;
typedef union epoll_data {
void* ptr;
int fd;
uint32_t u32;
uint64_t u64;
SOCKET sock; /* Windows specific */
HANDLE hnd; /* Windows specific */
} epoll_data_t;
struct epoll_event {
uint32_t events; /* Epoll events and flags */
epoll_data_t data; /* User data variable */
};
#ifdef __cplusplus
extern "C" {
#endif
WEPOLL_EXPORT HANDLE epoll_create(int size);
WEPOLL_EXPORT HANDLE epoll_create1(int flags);
WEPOLL_EXPORT int epoll_close(HANDLE ephnd);
WEPOLL_EXPORT int epoll_ctl(HANDLE ephnd,
int op,
SOCKET sock,
struct epoll_event* event);
WEPOLL_EXPORT int epoll_wait(HANDLE ephnd,
struct epoll_event* events,
int maxevents,
int timeout);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* WEPOLL_H_ */

BIN
mariadbcpp.dll Normal file

Binary file not shown.

View file

@ -6,16 +6,14 @@ Please see [the module guide on the wiki](https://github.com/LandSandBoat/server
## Era Accuracy Modules
Lua era-accuracy modules live under `era/lua/` and mirror the main `scripts/` tree where practical. These modules should use `xi.module.isContentEnabled(contentTag)` to decide whether an era override should register. If the relevant content is enabled, return a data-only table such as `{ name = moduleName }`.
When creating modules to revert or adjust content for era accuracy, place them in the folder corresponding to the expansion when the change was introduced:
Common content tags are:
- cop/ : Chains of Promathia (September 2004 - March 2006)
- toau/ : Treasures of Aht Urhgan (April 2006 - October 2007)
- wotg/ : Wings of the Goddess (November 2007 - May 2010)
- abyssea/ : Abyssea Add-ons (June 2010 - February 2013)
- soa/ : Seekers of Adoulin (March 2013 - April 2015)
- rov/ : Rhapsodies of Vana'diel (May 2015 - July 2020)
- tvr/ : The Voracious Resurgence (August 2020 - Present)
- COP : Chains of Promathia (September 2004 - March 2006)
- TOAU : Treasures of Aht Urhgan (April 2006 - October 2007)
- WOTG : Wings of the Goddess (November 2007 - May 2010)
- ABYSSEA : Abyssea Add-ons (June 2010 - February 2013)
- SOA : Seekers of Adoulin (March 2013 - April 2015)
- ROV : Rhapsodies of Vana'diel (May 2015 - July 2020)
- TVR : The Voracious Resurgence (August 2020 - Present)
For example, if a Lua module reverts a December 2010 change, place it in the matching mirrored path under `era/lua/` and guard its override with `not xi.module.isContentEnabled('ABYSSEA')`.
For example, if a change occurred in December 2010 and you want a module to revert it, place it in the abyssea/ folder.

View file

@ -4,15 +4,7 @@
-----------------------------------
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(06/21/2010)
-----------------------------------
require('modules/module_utils')
-----------------------------------
local moduleName = 'cop_level_caps'
if xi.module.isContentEnabled('ABYSSEA') then
return { name = moduleName }
end
local m = Module:new(moduleName)
local m = Module:new('cop_level_caps')
-- Apply level caps after server initialization when all battlefields are loaded
m:addOverride('xi.server.onServerStart', function()

View file

@ -89,7 +89,7 @@ hnmSystem:addOverride('xi.zones.Dragons_Aery.Zone.onInitialize', function(zone)
-- First-time setup.
if hnmPopTime == 0 then
hnmPopTime = currentTime + math.randomInt(1, 48) * 1800
hnmPopTime = currentTime + math.random(1, 48) * 1800
SetServerVariable('[HNM]Fafnir', hnmPopTime) -- Save pop time.
end
@ -99,7 +99,7 @@ hnmSystem:addOverride('xi.zones.Dragons_Aery.Zone.onInitialize', function(zone)
if
hnmKillCount > 3 and
(math.randomInt(1, 5) == 3 or hnmKillCount > 6)
(math.random(1, 5) == 3 or hnmKillCount > 6)
then
monster = dragonsAeryID.mob.NIDHOGG
end
@ -122,7 +122,7 @@ hnmSystem:addOverride('xi.zones.Dragons_Aery.mobs.Fafnir.onMobDespawn', function
super(mob)
-- Server Variable work.
local randomPopTime = 75600 + math.randomInt(0, 6) * 1800
local randomPopTime = 75600 + math.random(0, 6) * 1800
local hnmKillCount = GetServerVariable('[HNM]Fafnir_C') + 1
SetServerVariable('[HNM]Fafnir', GetSystemTime() + randomPopTime) -- Save next pop time.
@ -133,7 +133,7 @@ hnmSystem:addOverride('xi.zones.Dragons_Aery.mobs.Fafnir.onMobDespawn', function
if
hnmKillCount > 3 and
(math.randomInt(1, 5) == 3 or hnmKillCount > 6)
(math.random(1, 5) == 3 or hnmKillCount > 6)
then
monster = dragonsAeryID.mob.NIDHOGG
end
@ -146,7 +146,7 @@ hnmSystem:addOverride('xi.zones.Dragons_Aery.mobs.Nidhogg.onMobDespawn', functio
super(mob)
-- Server Variable work.
local randomPopTime = 75600 + math.randomInt(0, 6) * 1800
local randomPopTime = 75600 + math.random(0, 6) * 1800
SetServerVariable('[HNM]Fafnir', GetSystemTime() + randomPopTime) -- Save next pop time.
SetServerVariable('[HNM]Fafnir_C', 0) -- Save kill count.
@ -222,7 +222,7 @@ hnmSystem:addOverride('xi.zones.Valley_of_Sorrows.Zone.onInitialize', function(z
-- First-time setup.
if hnmPopTime == 0 then
hnmPopTime = currentTime + math.randomInt(1, 48) * 1800
hnmPopTime = currentTime + math.random(1, 48) * 1800
SetServerVariable('[HNM]Adamantoise', hnmPopTime) -- Save pop time.
end
@ -232,7 +232,7 @@ hnmSystem:addOverride('xi.zones.Valley_of_Sorrows.Zone.onInitialize', function(z
if
hnmKillCount > 3 and
(math.randomInt(1, 5) == 3 or hnmKillCount > 6)
(math.random(1, 5) == 3 or hnmKillCount > 6)
then
monster = valleySorrowsID.mob.ASPIDOCHELONE
end
@ -255,7 +255,7 @@ hnmSystem:addOverride('xi.zones.Valley_of_Sorrows.mobs.Adamantoise.onMobDespawn'
super(mob)
-- Server Variable work.
local randomPopTime = 75600 + math.randomInt(0, 6) * 1800
local randomPopTime = 75600 + math.random(0, 6) * 1800
local hnmKillCount = GetServerVariable('[HNM]Adamantoise_C') + 1
SetServerVariable('[HNM]Adamantoise', GetSystemTime() + randomPopTime) -- Save next pop time.
@ -266,7 +266,7 @@ hnmSystem:addOverride('xi.zones.Valley_of_Sorrows.mobs.Adamantoise.onMobDespawn'
if
hnmKillCount > 3 and
(math.randomInt(1, 5) == 3 or hnmKillCount > 6)
(math.random(1, 5) == 3 or hnmKillCount > 6)
then
monster = valleySorrowsID.mob.ASPIDOCHELONE
end
@ -279,7 +279,7 @@ hnmSystem:addOverride('xi.zones.Valley_of_Sorrows.mobs.Aspidochelone.onMobDespaw
super(mob)
-- Server Variable work.
local randomPopTime = 75600 + math.randomInt(0, 6) * 1800
local randomPopTime = 75600 + math.random(0, 6) * 1800
SetServerVariable('[HNM]Adamantoise', GetSystemTime() + randomPopTime) -- Save next pop time.
SetServerVariable('[HNM]Adamantoise_C', 0) -- Save kill count.
@ -355,7 +355,7 @@ hnmSystem:addOverride('xi.zones.Behemoths_Dominion.Zone.onInitialize', function(
-- First-time setup.
if hnmPopTime == 0 then
hnmPopTime = currentTime + math.randomInt(1, 48) * 1800
hnmPopTime = currentTime + math.random(1, 48) * 1800
SetServerVariable('[HNM]Behemoth', hnmPopTime) -- Save pop time.
end
@ -365,7 +365,7 @@ hnmSystem:addOverride('xi.zones.Behemoths_Dominion.Zone.onInitialize', function(
if
hnmKillCount > 3 and
(math.randomInt(1, 5) == 3 or hnmKillCount > 6)
(math.random(1, 5) == 3 or hnmKillCount > 6)
then
monster = behemothDomID.mob.KING_BEHEMOTH
end
@ -388,7 +388,7 @@ hnmSystem:addOverride('xi.zones.Behemoths_Dominion.mobs.Behemoth.onMobDespawn',
super(mob)
-- Server Variable work.
local randomPopTime = 75600 + math.randomInt(0, 6) * 1800
local randomPopTime = 75600 + math.random(0, 6) * 1800
local hnmKillCount = GetServerVariable('[HNM]Behemoth_C') + 1
SetServerVariable('[HNM]Behemoth', GetSystemTime() + randomPopTime) -- Save next pop time.
@ -399,7 +399,7 @@ hnmSystem:addOverride('xi.zones.Behemoths_Dominion.mobs.Behemoth.onMobDespawn',
if
hnmKillCount > 3 and
(math.randomInt(1, 5) == 3 or hnmKillCount > 6)
(math.random(1, 5) == 3 or hnmKillCount > 6)
then
monster = behemothDomID.mob.KING_BEHEMOTH
end
@ -412,7 +412,7 @@ hnmSystem:addOverride('xi.zones.Behemoths_Dominion.mobs.King_Behemoth.onMobDespa
super(mob)
-- Server Variable work.
local randomPopTime = 75600 + math.randomInt(0, 6) * 1800
local randomPopTime = 75600 + math.random(0, 6) * 1800
SetServerVariable('[HNM]Behemoth', GetSystemTime() + randomPopTime) -- Save next pop time.
SetServerVariable('[HNM]Behemoth_C', 0) -- Save kill count.

View file

@ -5,13 +5,7 @@
-----------------------------------
require('modules/module_utils')
-----------------------------------
local moduleName = 'lamian_fang_key_tally_timer'
if xi.module.isContentEnabled('ABYSSEA') then
return { name = moduleName }
end
local m = Module:new(moduleName)
local m = Module:new('lamian_fang_key_tally_timer')
m:addOverride('xi.zones.Caedarva_Mire.npcs.qm8.onTrigger', function(player, npc)
local ID = zones[xi.zone.CAEDARVA_MIRE]

View file

@ -0,0 +1,59 @@
-----------------------------------
-- Module: HELM Adjustments (Abyssea Era)
-- Desc: Removes items that were added to existing zone HELM rewards during the Abyssea era
-- Source:
-- Aquilaria Log: https://www.bg-wiki.com/ffxi/September_2010_Version_Update_Changes#Usable_Items
-- Butterpear and Kapor Log: https://www.bg-wiki.com/ffxi/September_2011_Version_Update_Changes#Wings_of_the_Goddess_Quests
-----------------------------------
require('modules/module_utils')
-----------------------------------
local m = Module:new('abyssea_helm_adjustments')
local removals =
{
[xi.helmType.LOGGING] =
{
[xi.zone.YHOATOR_JUNGLE] =
{
xi.item.BUTTERPEAR,
xi.item.AQUILARIA_LOG,
xi.item.KAPOR_LOG,
},
[xi.zone.YUHTUNGA_JUNGLE] =
{
xi.item.AQUILARIA_LOG,
},
},
}
local removeItems = function(drops, itemsToRemove)
local removeSet = {}
for _, itemId in ipairs(itemsToRemove) do
removeSet[itemId] = true
end
local filtered = {}
for _, entry in ipairs(drops) do
if not removeSet[entry[2]] then
filtered[#filtered + 1] = entry
end
end
return filtered
end
-- Apply removals to xi.helm.dataTable.
for helmType, zones in pairs(removals) do
local helmData = xi.helm.dataTable[helmType]
if helmData then
for zoneId, itemsToRemove in pairs(zones) do
local zoneData = helmData.zone[zoneId]
if zoneData and zoneData.drops then
zoneData.drops = removeItems(zoneData.drops, itemsToRemove)
end
end
end
end
return m

View file

@ -0,0 +1,596 @@
-----------------------------------
-- Module: Job Adjustments (Abyssea Era)
-- Desc: Removes traits/abilities/effects that were added to jobs during the Abyssea era
-----------------------------------
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(03/26/2012)
-----------------------------------
require('modules/module_utils')
-----------------------------------
local m = Module:new('abyssea_job_adjustments')
-----------------------------------
-- Warrior
-----------------------------------
-- Warrior's Charge: Remove Triple Attack bonus
m:addOverride('xi.effects.warriors_charge.onEffectGain', function(target, effect)
effect:addMod(xi.mod.DOUBLE_ATTACK, 100)
end)
-- Warrior's Charge: Apply merit recast reduction
m:addOverride('xi.job_utils.warrior.useWarriorsCharge', function(player, target, ability, action)
local recastReduction = player:getMerit(xi.merit.WARRIORS_CHARGE) - 150
action:setRecast(action:getRecast() - recastReduction)
player:addStatusEffect(xi.effect.WARRIORS_CHARGE, { power = 1, duration = 60, origin = player })
return xi.effect.WARRIORS_CHARGE
end)
-----------------------------------
-- White Mage
-----------------------------------
-- Martyr: Apply merit recast reduction, remove merit healing bonus
m:addOverride('xi.job_utils.white_mage.useMartyr', function(player, target, ability, action)
local recastReduction = player:getMerit(xi.merit.MARTYR) - 150
action:setRecast(action:getRecast() - recastReduction)
local damageHP = math.floor(player:getHP() * 0.25)
local healHP = damageHP * 2
healHP = utils.clamp(healHP, 0, target:getMaxHP() - target:getHP())
-- If stoneskin is present, it should absorb damage
damageHP = utils.handleStoneskin(player, damageHP)
player:delHP(damageHP)
target:addHP(healHP)
return healHP
end)
-- Devotion: Apply merit recast reduction, remove merit MP bonus
m:addOverride('xi.job_utils.white_mage.useDevotion', function(player, target, ability, action)
local recastReduction = player:getMerit(xi.merit.DEVOTION) - 150
action:setRecast(action:getRecast() - recastReduction)
local damageHP = math.floor(player:getHP() * 0.25)
local healMP = damageHP
healMP = utils.clamp(healMP, 0, target:getMaxMP() - target:getMP())
-- If stoneskin is present, it should absorb damage
damageHP = utils.handleStoneskin(player, damageHP)
player:delHP(damageHP)
target:addMP(healMP)
return healMP
end)
-----------------------------------
-- Thief
-----------------------------------
-- Assassin's Charge: Remove Quadruple Attack
m:addOverride('xi.effects.assassins_charge.onEffectGain', function(target, effect)
effect:addMod(xi.mod.TRIPLE_ATTACK, 100)
end)
-- Assassin's Charge: Reduce cooldown by merit count
m:addOverride('xi.job_utils.thief.useAssassinsCharge', function(player, target, ability, action)
local recastReduction = player:getMerit(xi.merit.ASSASSINS_CHARGE) - 150
action:setRecast(action:getRecast() - recastReduction)
player:addStatusEffect(xi.effect.ASSASSINS_CHARGE, { power = 1, duration = 60, origin = player })
return xi.effect.ASSASSINS_CHARGE
end)
-- Feint: Remove Treasure Hunter rate and reduce cooldown by merit count
m:addOverride('xi.job_utils.thief.useFeint', function(player, target, ability, action)
local recastReduction = player:getMerit(xi.merit.FEINT) - 120
action:setRecast(action:getRecast() - recastReduction)
player:addStatusEffect(xi.effect.FEINT, { power = 150, duration = 60, origin = player })
end)
-----------------------------------
-- Dark Knight
-----------------------------------
-- Arcane Circle: Revert duration from 3 minutes to 1 minute
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(02/13/2012)
m:addOverride('xi.job_utils.dark_knight.useArcaneCircle', function(player, target, ability)
local duration = 60 + player:getMod(xi.mod.ARCANE_CIRCLE_DURATION)
local power = 15
if player:getMainJob() ~= xi.job.DRK then
power = 5
end
power = power + player:getMod(xi.mod.ARCANE_CIRCLE_POTENCY)
target:addStatusEffect(xi.effect.ARCANE_CIRCLE, { power = power, duration = duration, origin = player })
return xi.effect.ARCANE_CIRCLE
end)
-- Last Resort: Revert duration from 3 minutes to 30 seconds
m:addOverride('xi.job_utils.dark_knight.useLastResort', function(player, target, ability)
player:addStatusEffect(xi.effect.LAST_RESORT, { duration = 30, origin = player })
return xi.effect.LAST_RESORT
end)
-- Dark Seal: Remove extra duration and cast speed from merits
m:addOverride('xi.effects.dark_seal.onEffectGain', function(target, effect)
-- Overwrites
target:delStatusEffectSilent(xi.effect.DIVINE_EMBLEM)
target:delStatusEffectSilent(xi.effect.DIVINE_SEAL)
target:delStatusEffectSilent(xi.effect.ELEMENTAL_SEAL)
end)
-- Dark Seal: Apply merit recast reduction
m:addOverride('xi.job_utils.dark_knight.useDarkSeal', function(player, target, ability, action)
local recastReduction = player:getMerit(xi.merit.DARK_SEAL) - 150
action:setRecast(action:getRecast() - recastReduction)
player:addStatusEffect(xi.effect.DARK_SEAL, { power = 1, duration = 60, origin = player })
return xi.effect.DARK_SEAL
end)
-- Diabolic Eye: Remove extra duration and potency from merits and apply merit recast reduction
m:addOverride('xi.job_utils.dark_knight.useDiabolicEye', function(player, target, ability, action)
local recastReduction = player:getMerit(xi.merit.DIABOLIC_EYE) - 150
action:setRecast(action:getRecast() - recastReduction)
player:addStatusEffect(xi.effect.DIABOLIC_EYE, { power = 20, duration = 180, origin = player })
return xi.effect.DIABOLIC_EYE
end)
-----------------------------------
-- Beastmaster
-----------------------------------
-- Reward: Override pet food healing values to pre-Abyssea values
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(09/08/2010)
xi.job_utils.beastmaster.petFoodData =
{
[xi.item.PET_FOOD_ALPHA_BISCUIT] = { minHealing = 25, regen = 1, mndMult = 2, mndThreshold = 10 },
[xi.item.PET_FOOD_BETA_BISCUIT] = { minHealing = 50, regen = 3, mndMult = 1, mndThreshold = 33 },
[xi.item.PET_FOOD_GAMMA_BISCUIT] = { minHealing = 100, regen = 5, mndMult = 1, mndThreshold = 35 },
[xi.item.PET_FOOD_DELTA_BISCUIT] = { minHealing = 150, regen = 8, mndMult = 2, mndThreshold = 40 },
[xi.item.PET_FOOD_EPSILON_BISCUIT] = { minHealing = 300, regen = 11, mndMult = 2, mndThreshold = 45 },
[xi.item.PET_FOOD_ZETA_BISCUIT] = { minHealing = 350, regen = 14, mndMult = 3, mndThreshold = 45 },
}
-- Feral Howl: Apply merit recast reduction, remove extra accuracy from merits
m:addOverride('xi.job_utils.beastmaster.useFeralHowl', function(player, target, ability, action)
local recastReduction = player:getMerit(xi.merit.FERAL_HOWL) - 150
action:setRecast(action:getRecast() - recastReduction)
if
not xi.data.statusEffect.isTargetImmune(target, xi.effect.TERROR, xi.element.DARK) and
not xi.data.statusEffect.isTargetResistant(player, target, xi.effect.TERROR) and
not xi.data.statusEffect.isEffectNullified(target, xi.effect.TERROR, 0)
then
local resistanceRate = xi.combat.magicHitRate.calculateResistRate(player, target, 0, 0, xi.skillRank.B_MINUS, xi.element.DARK, xi.mod.CHR, xi.effect.TERROR)
if xi.data.statusEffect.isResistRateSuccessfull(xi.effect.TERROR, resistanceRate, 0) then
target:addStatusEffect(xi.effect.TERROR, { power = 1, duration = 10 * resistanceRate, origin = player })
end
end
return xi.effect.TERROR
end)
-- Killer Insinct: Apply merit recast reduction, remove extra duration from merits
m:addOverride('xi.job_utils.beastmaster.useKillerInstinct', function(player, target, ability, action)
local recastReduction = player:getMerit(xi.merit.KILLER_INSTINCT) - 150
action:setRecast(action:getRecast() - recastReduction)
-- Notes: Pet ecosystem is assigned to the subPower, then mapped to the correct killer mod in the effect script.
local pet = player:getPet()
local petEcosystem = pet:getEcosystem()
local power = 10
target:addStatusEffect(xi.effect.KILLER_INSTINCT, { power = power, duration = 60, origin = player, subPower = petEcosystem })
return xi.effect.KILLER_INSTINCT
end)
-----------------------------------
-- Samurai
-----------------------------------
-- Warding Circle: Revert duration from 3 minutes to 1 minute
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(02/13/2012)
m:addOverride('xi.job_utils.samurai.useWardingCircle', function(player, target, ability)
local duration = 60 + player:getMod(xi.mod.WARDING_CIRCLE_DURATION)
local power = 15
if player:getMainJob() ~= xi.job.SAM then
power = 5
end
power = power + player:getMod(xi.mod.WARDING_CIRCLE_POTENCY)
target:addStatusEffect(xi.effect.WARDING_CIRCLE, { power = power, duration = duration, origin = player })
return xi.effect.WARDING_CIRCLE
end)
-- Blade Bash: Apply merit recast reduction, remove extra plague duration from merits
m:addOverride('xi.job_utils.samurai.useBladeBash', function(player, target, ability, action)
local recastReduction = player:getMerit(xi.merit.BLADE_BASH) - 150
action:setRecast(action:getRecast() - recastReduction)
-- Damage
-- TODO: Verify damage formula and DRK interaction
local jobLevel = utils.getActiveJobLevel(player, xi.job.DRK)
local damage = math.floor((jobLevel + 11) / 4 + player:getMod(xi.mod.WEAPON_BASH))
damage = utils.handleStoneskin(target, damage)
target:takeDamage(damage, player, xi.attackType.PHYSICAL, xi.damageType.BLUNT)
target:updateEnmityFromDamage(player, damage)
-- Stun
if
not xi.data.statusEffect.isTargetImmune(target, xi.effect.STUN, xi.element.THUNDER) and
not xi.data.statusEffect.isTargetResistant(player, target, xi.effect.STUN) and
not xi.data.statusEffect.isEffectNullified(target, xi.effect.STUN, 0)
then
local resistanceRate = xi.combat.magicHitRate.calculateResistRate(player, target, 0, 0, xi.skillRank.A_PLUS, xi.element.THUNDER, xi.mod.INT, xi.effect.STUN, 0)
if xi.data.statusEffect.isResistRateSuccessfull(xi.effect.STUN, resistanceRate, 0) then
target:addStatusEffect(xi.effect.STUN, { power = 1, duration = 6 * resistanceRate, origin = player })
end
end
-- Plague
if
not xi.data.statusEffect.isTargetImmune(target, xi.effect.PLAGUE, xi.element.FIRE) and
not xi.data.statusEffect.isTargetResistant(player, target, xi.effect.PLAGUE) and
not xi.data.statusEffect.isEffectNullified(target, xi.effect.PLAGUE, 0)
then
local resistanceRate = xi.combat.magicHitRate.calculateResistRate(player, target, 0, 0, xi.skillRank.A_PLUS, xi.element.FIRE, xi.mod.INT, xi.effect.PLAGUE, 0)
if xi.data.statusEffect.isResistRateSuccessfull(xi.effect.PLAGUE, resistanceRate, 0) then
target:addStatusEffect(xi.effect.PLAGUE, { power = 5, duration = 15 * resistanceRate, origin = player })
end
end
-- Animation
local animationTable =
{
-- [weapon type] = animation ID
[xi.skill.GREAT_SWORD ] = 201,
[xi.skill.GREAT_KATANA] = 201,
[xi.skill.GREAT_AXE ] = 202,
[xi.skill.SCYTHE ] = 202,
[xi.skill.STAFF ] = 202,
[xi.skill.POLEARM ] = 203,
}
local animation = animationTable[player:getWeaponSkillType(xi.slot.MAIN)] or 0
action:setAnimation(target:getID(), animation)
ability:setMsg(xi.msg.basic.JA_DAMAGE)
return damage
end)
-- Shikikoyo: Apply merit recast reduction, remove extra TP sharing from merits
m:addOverride('xi.job_utils.samurai.useShikikoyo', function(player, target, ability, action)
local recastReduction = player:getMerit(xi.merit.SHIKIKOYO) - 150
action:setRecast(action:getRecast() - recastReduction)
local pTP = player:getTP() - 1000
pTP = utils.clamp(pTP, 0, 3000 - target:getTP())
player:setTP(1000)
target:setTP(target:getTP() + pTP)
return pTP
end)
-- Hasso: Remove Zanshin bonus
m:addOverride('xi.effects.hasso.onEffectGain', function(target, effect)
effect:addMod(xi.mod.TWOHAND_STR, effect:getPower())
effect:addMod(xi.mod.TWOHAND_HASTE_ABILITY, 1000)
effect:addMod(xi.mod.TWOHAND_ACC, 10)
end)
-- Seigan: Remove Zanshin-based counter bonus
m:addOverride('xi.effects.seigan.onEffectGain', function(target, effect)
local jpValue = target:getJobPointLevel(xi.jp.SEIGAN_EFFECT)
effect:addMod(xi.mod.DEF, jpValue * 3)
end)
-----------------------------------
-- Ranger
-----------------------------------
-- Flashy Shot: Apply merit recast reduction
m:addOverride('xi.job_utils.ranger.useFlashyShot', function(player, target, ability, action)
local recastReduction = player:getMerit(xi.merit.FLASHY_SHOT) - 150
action:setRecast(action:getRecast() - recastReduction)
player:addStatusEffect(xi.effect.FLASHY_SHOT, { power = 1, duration = 60, origin = player })
return xi.effect.FLASHY_SHOT
end)
-- Flashy Shot Effect: Add level correction bypass
m:addOverride('xi.effects.flashy_shot.onEffectGain', function(target, effect)
effect:addMod(xi.mod.ENMITY, 50)
effect:addMod(xi.mod.RA_IGNORE_LVL_DIFF, 1)
end)
-----------------------------------
-- Dragoon
-----------------------------------
-- Ancient Circle: Revert duration from 3 minutes to 1 minute
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(02/13/2012)
m:addOverride('xi.job_utils.dragoon.useAncientCircle', function(player, target, ability)
local duration = 60 + player:getMod(xi.mod.ANCIENT_CIRCLE_DURATION)
local power = 15
if player:getMainJob() ~= xi.job.DRG then
power = 5
end
power = power + player:getMod(xi.mod.ANCIENT_CIRCLE_POTENCY)
ability:setMsg(xi.msg.basic.USES_ABILITY_FORTIFIED_DRAGONS)
target:addStatusEffect(xi.effect.ANCIENT_CIRCLE, { power = power, duration = duration, origin = player })
return xi.effect.ANCIENT_CIRCLE
end)
-- Spirit Surge: Revert haste to be HASTE_MAGIC instead of HASTE_ABILITY
-- Also removes ATK and DEF bonuses which are removed in SoA module
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(02/13/2012)
m:addOverride('xi.effects.spirit_surge.onEffectGain', function(target, effect)
effect:addMod(xi.mod.HP, effect:getPower())
target:updateHealth()
effect:addMod(xi.mod.STR, effect:getSubPower())
effect:addMod(xi.mod.ACC, 50)
effect:addMod(xi.mod.HASTE_MAGIC, 2500)
effect:addMod(xi.mod.MAIN_DMG_RATING, target:getJobPointLevel(xi.jp.SPIRIT_SURGE_EFFECT))
end)
-- Spirit Surge + Super Jump: Revert enmity reduction from 100% to 50%
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(03/26/2012)
m:addOverride('xi.job_utils.dragoon.superJumpSurgeEffect', function(player, target)
if player:hasStatusEffect(xi.effect.SPIRIT_SURGE) then
local minDistance = 9999
local closestPartyMember = nil
-- Find the closest party member
local party = player:getPartyWithTrusts()
for _, member in pairs(party) do
local distance = member:checkDistance(player)
if
member:getID() ~= player:getID() and
not member:isDead() and
(distance < minDistance or closestPartyMember == nil)
then
closestPartyMember = member
minDistance = distance
end
end
-- TODO: verify conditions for how close the dragoon needs to be to the mob, if at all
if
closestPartyMember and
closestPartyMember:isBehind(player) and
(player:checkDistance(target) < closestPartyMember:checkDistance(target))
then
if target:isMob() then
target:lowerEnmity(closestPartyMember, 50)
end
end
end
end)
-- Deep Breathing: Apply merit recast reduction instead of breath power bonus
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(03/26/2012)
m:addOverride('xi.job_utils.dragoon.useDeepBreathing', function(player, target, ability, action)
local recastReduction = player:getMerit(xi.merit.DEEP_BREATHING) - 150
action:setRecast(action:getRecast() - recastReduction)
local wyvern = player:getPet()
if wyvern and wyvern:getPetID() == xi.petId.WYVERN then
wyvern:addStatusEffect(xi.effect.MAGIC_ATK_BOOST, { duration = 180, origin = player })
end
end)
-- Deep Breathing Bonus: Remove merit scaling, use flat base bonus only
m:addOverride('xi.job_utils.dragoon.getDeepBreathingBonus', function(wyvern, master, isHealing)
local bonus = 0
local hadEffect = wyvern:hasStatusEffect(xi.effect.MAGIC_ATK_BOOST)
if hadEffect then
bonus = isHealing and 37.5 or 0.75
wyvern:delStatusEffect(xi.effect.MAGIC_ATK_BOOST)
end
return bonus
end)
-- Spirit Link: Revert TP transfer from wyvern to master and removes regen
-- TP Transfer Source: https://www.bg-wiki.com/ffxi/Version_Update_(06/21/2010)
-- Regen Source: https://www.bg-wiki.com/ffxi/Version_Update_(03/26/2012)
m:addOverride('xi.job_utils.dragoon.useSpiritLink', function(player, target, ability, action)
local wyvern = player:getPet()
local playerHP = player:getHP()
xi.job_utils.dragoon.checkForRemovableEffectsOnSpiritLink(player, wyvern)
-- Empathy: copy status effects and grant wyvern EXP
xi.job_utils.dragoon.applyEmpathyBonus(player, wyvern)
-- Pre-Abyssea: No TP transfer from wyvern to master
-- Calculate drain amount.
local drainAmount = 0
if wyvern:getHP() ~= wyvern:getMaxHP() then
drainAmount = (math.random(25, 35) / 100) * playerHP
drainAmount = drainAmount * (1 - (0.01 * player:getJobPointLevel(xi.jp.SPIRIT_LINK_EFFECT)))
end
-- Handle Stoneskin.
local stoneskinPower = 0
if player:hasStatusEffect(xi.effect.STONESKIN) then
stoneskinPower = player:getMod(xi.mod.STONESKIN)
-- If stoneskin is more powerfull than the amount to be drained.
if stoneskinPower > drainAmount then
local effect = player:getStatusEffect(xi.effect.STONESKIN)
effect:setPower(effect:getPower() - drainAmount) -- Fixes the status effect so when it ends it uses the new power instead of old.
player:delMod(xi.mod.STONESKIN, drainAmount) -- Removes the amount from the mod.
-- If stoneskin is as powerful or less than the amount to be drained.
else
player:delStatusEffect(xi.effect.STONESKIN)
end
end
-- Handle master damage and pet healing.
player:takeDamage(drainAmount - stoneskinPower)
-- Pre-September 2015: Healing formula includes MND and wyvern level components.
-- Source: https://wiki.ffo.jp/html/1897.html https://www.bg-wiki.com/ffxi/Spirit_Link
local playerMND = player:getStat(xi.mod.MND)
local alpha = wyvern:getMainLvl() * 0.7
local healPet = (drainAmount + playerMND + alpha) * 2
if player:getEquipID(xi.slot.HEAD) == xi.item.DRACHEN_ARMET_P1 then
healPet = healPet + 15
end
-- Spirit Link is self target but reports effect on Wyvern.
action:ID(player:getID(), wyvern:getID())
return wyvern:addHP(healPet) -- add the hp to wyvern
end)
-- Empathy: Revert Spirit Link granting wyvern 200 EXP per Empathy merit level
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(05/15/2012)
m:addOverride('xi.job_utils.dragoon.applyEmpathyBonus', function(player, wyvern)
local empathyTotal = player:getMerit(xi.merit.EMPATHY)
if empathyTotal > 0 then
local validEffects = {}
local i = 0
local effects = player:getStatusEffects()
local copyi = 0
for _, effect in pairs(effects) do
if effect:hasEffectFlag(xi.effectFlag.EMPATHY) then
validEffects[i + 1] = effect
i = i + 1
end
end
if i < empathyTotal then
empathyTotal = i
elseif i > empathyTotal then
validEffects = xi.job_utils.dragoon.cutEmpathyEffectTable(validEffects, i, empathyTotal)
end
local copyEffect = nil
while copyi < empathyTotal do
copyEffect = validEffects[copyi + 1]
if wyvern:hasStatusEffect(copyEffect:getEffectType()) then
wyvern:delStatusEffectSilent(copyEffect:getEffectType())
end
wyvern:copyStatusEffect(copyEffect)
copyi = copyi + 1
end
end
end)
-- Wyvern Spawn: Revert innate -40% DT and reduce status breath table
-- DT Source: https://www.bg-wiki.com/ffxi/Version_Update_(09/19/2011)
-- Status Breath Source: https://www.bg-wiki.com/ffxi/Version_Update_(02/13/2012)
m:addOverride('xi.pets.wyvern.onMobSpawn', function(mob)
super(mob)
local master = mob:getMaster()
-- Revert innate -40% DT
mob:addMod(xi.mod.DMG, 4000)
-- Determine if wyvern is DEFENSIVE type (status breath on WS)
local defensiveJobs =
{
[xi.job.WHM] = true,
[xi.job.BLM] = true,
[xi.job.RDM] = true,
[xi.job.SMN] = true,
[xi.job.BLU] = true,
[xi.job.SCH] = true,
[xi.job.GEO] = true,
}
if defensiveJobs[master:getSubJob()] then
-- Replace WS listener with pre-2012 status breath table
master:removeListener('PET_WYVERN_WS')
local removeBreathTable =
{
{ 40, xi.jobAbility.REMOVE_PARALYSIS, { xi.effect.PARALYSIS } },
{ 20, xi.jobAbility.REMOVE_BLINDNESS, { xi.effect.BLINDNESS } },
{ 1, xi.jobAbility.REMOVE_POISON, { xi.effect.POISON } },
}
local breathRange = 14
local function doStatusBreath(target, player)
local wyvern = player:getPet()
for _, v in pairs(removeBreathTable) do
local minLevel = v[1]
local ability = v[2]
local statuses = v[3]
if wyvern:getMainLvl() >= minLevel then
for _, effect in pairs(statuses) do
if
target:hasStatusEffect(effect) and
wyvern:checkDistance(target) <= breathRange
then
wyvern:usePetAbility(ability, target)
return true
end
end
end
end
return false
end
master:addListener('WEAPONSKILL_USE', 'PET_WYVERN_WS', function(player, target, skillid)
if not doStatusBreath(player, player) then
local party = player:getParty()
for _, member in pairs(party) do
if doStatusBreath(member, player) then
break
end
end
end
end)
end
end)
return m

View file

@ -0,0 +1,104 @@
-----------------------------------
-- Analyzer (Pre 2012)
-- Reduces damage taken from repeated TP moves by 10%, with an additional 10% per Earth Maneuver.
-- Resets after a new skill is used.
-- Was changed March 27th, 2012 to analyze multiple TP moves based off earth maneuvers, with a 40% damage reduction.
-- NOTE: This module touches both the attachment, and the combat utility. Both are needed for this attachment to function correctly.
-- https://wiki.ffo.jp/html/10746.html
-----------------------------------
require('modules/module_utils')
-----------------------------------
local m = Module:new('era_analyzer')
-----------------------------------
-- Attachment Module
-----------------------------------
m:addOverride('xi.actions.abilities.pets.attachments.analyzer.onEquip', function(pet, attachment)
-- Analyzed skills do not carry over between zones, onEquip is called when rebuilding the automaton after zoning.
pet:setLocalVar('analyzedSkill1', 0)
pet:addListener('WEAPONSKILL_TAKE', 'ANALYZER_WEAPONSKILL_TAKE', function(mob, target, skill, tp, action)
local analyzerModifier = target:getMod(xi.mod.AUTO_ANALYZER)
local incomingSkill = skill:getID()
-- If Analyzer modifier is 0, return. (Should be impossible since the attachment wouldn't be equipped, but just in case.)
if analyzerModifier <= 0 then
return
end
local analyzedSkill = target:getLocalVar('analyzedSkill1')
-- If the incoming skill is the one we have already analyzed, return.
if incomingSkill == analyzedSkill then
return
end
-- If the incoming skill is different from the analyzed skill, update the analyzed skill ID.
if incomingSkill ~= analyzedSkill then
target:setLocalVar('analyzedSkill1', incomingSkill)
end
end)
xi.automaton.onAttachmentEquip(pet, attachment)
end)
m:addOverride('xi.actions.abilities.pets.attachments.analyzer.onUnequip', function(pet, attachment)
-- Clear analyzed skill on unequip, and remove the listener.
pet:setLocalVar('analyzedSkill1', 0)
pet:removeListener('ANALYZER_WEAPONSKILL_TAKE')
xi.automaton.onAttachmentUnequip(pet, attachment)
end)
m:addOverride('xi.actions.abilities.pets.attachments.analyzer.onManeuverGain', function(pet, attachment, maneuvers)
end)
m:addOverride('xi.actions.abilities.pets.attachments.analyzer.onManeuverLose', function(pet, attachment, maneuvers)
end)
m:addOverride('xi.actions.abilities.pets.attachments.analyzer.onUpdate', function(pet, attachment, maneuvers)
end)
-----------------------------------
-- Combat Utility Override
-----------------------------------
m:addOverride('utils.handleAutomatonAutoAnalyzer', function(actor, skill, damage)
local analyzerModifier = actor:getMod(xi.mod.AUTO_ANALYZER)
-- If no Analyzer equipped, return unmodified damage.
if analyzerModifier <= 0 then
return damage
end
local automatonId = actor:getID()
-- If we can't track this automaton, return unmodified damage.
if not automatonId then
return damage
end
local automatonMaster = actor:getMaster()
-- If we can't get the master of this automaton, return unmodified damage.
if not automatonMaster then
return damage
end
local incomingSkill = skill:getID()
local analyzedSkill = actor:getLocalVar('analyzedSkill1')
-- If the incoming skill is the same ID as the analyzed skill, apply the Analyzer damage reduction and return.
if incomingSkill == analyzedSkill then
local earthManeuvers = automatonMaster:countEffect(xi.effect.EARTH_MANEUVER)
local damageReduction = 10 + 10 * earthManeuvers
return math.floor(damage * (100 - damageReduction) / 100)
end
-- If we somehow make it here, return unmodified damage.
return damage
end)
return m

View file

@ -0,0 +1,123 @@
-----------------------------------
-- Eraser (Pre-2011)
-- Removes up to 3 status effects from the Automaton or its Master based on the number of Light Maneuvers active.
-- Consumes all maneuvers on use.
-- Eraser cannot remove Venom, Death Sentence, Charm or Gradual Petrification.
-- Prioritizes removing effects from the Automaton over the Master.
-- Updated to consume only Light Maneuvers on December 15th, 2011.
-- Updated to consume no maneuvers on March 11th, 2019.
-- https://wiki.ffo.jp/html/5365.html
-----------------------------------
require('modules/module_utils')
-----------------------------------
local m = Module:new('era_eraser')
local maneuvers =
{
xi.effect.FIRE_MANEUVER,
xi.effect.ICE_MANEUVER,
xi.effect.WIND_MANEUVER,
xi.effect.EARTH_MANEUVER,
xi.effect.THUNDER_MANEUVER,
xi.effect.WATER_MANEUVER,
xi.effect.LIGHT_MANEUVER,
xi.effect.DARK_MANEUVER,
}
local removables =
{
-- Songs
xi.effect.ELEGY,
xi.effect.REQUIEM,
xi.effect.THRENODY,
-- Enfeebling
xi.effect.BLINDNESS,
xi.effect.PARALYSIS,
xi.effect.SILENCE,
xi.effect.POISON,
xi.effect.CURSE_I,
xi.effect.CURSE_II,
xi.effect.DISEASE,
xi.effect.PLAGUE,
xi.effect.WEIGHT,
xi.effect.BIND,
xi.effect.ADDLE,
xi.effect.SLOW,
xi.effect.PETRIFICATION,
-- DoTs
xi.effect.BIO,
xi.effect.DIA,
xi.effect.BURN,
xi.effect.FROST,
xi.effect.CHOKE,
xi.effect.RASP,
xi.effect.SHOCK,
xi.effect.DROWN,
-- Main Stat Downs
xi.effect.STR_DOWN,
xi.effect.DEX_DOWN,
xi.effect.VIT_DOWN,
xi.effect.AGI_DOWN,
xi.effect.INT_DOWN,
xi.effect.MND_DOWN,
xi.effect.CHR_DOWN,
-- Combat Stat Downs
xi.effect.ACCURACY_DOWN,
xi.effect.ATTACK_DOWN,
xi.effect.EVASION_DOWN,
xi.effect.DEFENSE_DOWN,
-- Magic Stat Downs
xi.effect.MAGIC_ACC_DOWN,
xi.effect.MAGIC_ATK_DOWN,
xi.effect.MAGIC_EVASION_DOWN,
xi.effect.MAGIC_DEF_DOWN,
-- HP/MP/TP Stat Downs
xi.effect.MAX_TP_DOWN,
xi.effect.MAX_MP_DOWN,
xi.effect.MAX_HP_DOWN,
}
m:addOverride('xi.actions.abilities.pets.automaton.eraser.onAutomatonAbilityCheck', function(target, automaton, skill)
return 0
end)
m:addOverride('xi.actions.abilities.pets.automaton.eraser.onAutomatonAbility', function(target, automaton, skill, master, action)
automaton:addRecast(xi.recast.ABILITY, skill:getID(), 30)
local lightManeuvers = master:countEffect(xi.effect.LIGHT_MANEUVER)
local effectsRemoved = 0
for _, effectId in ipairs(removables) do
if target:hasStatusEffect(effectId) then
target:delStatusEffectSilent(effectId)
effectsRemoved = effectsRemoved + 1
if effectsRemoved >= lightManeuvers then
break
end
end
end
for _, maneuverId in ipairs(maneuvers) do
for _ = 1, master:countEffect(maneuverId) do
master:delStatusEffectSilent(maneuverId)
end
end
if effectsRemoved > 0 then
skill:setMsg(xi.msg.basic.DISAPPEAR_NUM)
else
skill:setMsg(xi.msg.basic.USES)
end
return effectsRemoved
end)
return m

View file

@ -0,0 +1,45 @@
-----------------------------------
-- Replicator (Pre-2011)
-- Description : Applies Blink based on Wind Maneuvers when HP is below a certain threshold. Cooldown of 1 minute. Consumes all Wind Maneuvers on use.
-- If Automaton has a Damage Gauge equipped, activation threshold is increased to 75% HP.
-- Amount of images increased on December 15th, 2011.
-- Changed from Blink to Copy Image on August 5th, 2015.
-- Changed to not consume Wind Maneuvers on August 6th, 2019.
-- https://wiki.ffo.jp/html/12225.html
-----------------------------------
require('modules/module_utils')
-----------------------------------
local m = Module:new('era_replicator')
local shadowTable =
{
[1] = 2,
[2] = 3,
[3] = 4,
}
m:addOverride('xi.actions.abilities.pets.automaton.replicator.onAutomatonAbilityCheck', function(target, automaton, skill)
return 0
end)
m:addOverride('xi.actions.abilities.pets.automaton.replicator.onAutomatonAbility', function(target, automaton, skill, master, action)
local windManeuvers = master:countEffect(xi.effect.WIND_MANEUVER)
local shadows = shadowTable[windManeuvers]
automaton:addRecast(xi.recast.ABILITY, skill:getID(), 60)
for i = 1, windManeuvers do
master:delStatusEffectSilent(xi.effect.WIND_MANEUVER)
end
if target:addStatusEffect(xi.effect.BLINK, { power = shadows, duration = 300, origin = automaton }) then
skill:setMsg(xi.msg.basic.SKILL_GAIN_EFFECT)
else
skill:setMsg(xi.msg.basic.SKILL_NO_EFFECT)
end
return xi.effect.BLINK
end)
return m

View file

@ -7,13 +7,7 @@
-----------------------------------
require('modules/module_utils')
-----------------------------------
local moduleName = 'unlocking_a_myth'
if xi.module.isContentEnabled('ABYSSEA') then
return { name = moduleName }
end
local m = Module:new(moduleName)
local m = Module:new('unlocking_a_myth')
local weaponList =
{

View file

@ -1,19 +0,0 @@
-----------------------------------
-- NIN/DRG/SAM Quest Mobs Original Difficulty Module
-- Reverts the nerfs to the NIN/DRG/SAM quest mobs in the May 10, 2011 version update
-- Source: https://forum.square-enix.com/ffxi/threads/7257
-----------------------------------
-- Level: set all six spawns to level 32 (min == max => fixed level)
UPDATE mob_spawn_points SET minLevel = 32, maxLevel = 32 WHERE mobid = 17486187; -- Korroloka Leech (Korroloka Tunnel)
UPDATE mob_spawn_points SET minLevel = 32, maxLevel = 32 WHERE mobid = 17486188; -- Korroloka Leech (Korroloka Tunnel)
UPDATE mob_spawn_points SET minLevel = 32, maxLevel = 32 WHERE mobid = 17486189; -- Korroloka Leech (Korroloka Tunnel)
UPDATE mob_spawn_points SET minLevel = 32, maxLevel = 32 WHERE mobid = 17350928; -- Cyranuce M Cutauleon (Ghelsba Outpost)
UPDATE mob_spawn_points SET minLevel = 32, maxLevel = 32 WHERE mobid = 17219999; -- Forger (Konschtat Highlands)
UPDATE mob_spawn_points SET minLevel = 32, maxLevel = 32 WHERE mobid = 17272838; -- Guardian Treant (The Sanctuary of Zi'Tah)
-- HP: per-group override, keyed by (groupid, zoneid)
UPDATE mob_groups SET HP = 900 WHERE groupid = 28 AND zoneid = 173; -- Korroloka Leech x3 (Korroloka Tunnel)
UPDATE mob_groups SET HP = 2700 WHERE groupid = 26 AND zoneid = 140; -- Cyranuce M Cutauleon (Ghelsba Outpost)
UPDATE mob_groups SET HP = 2000 WHERE groupid = 33 AND zoneid = 108; -- Forger (Konschtat Highlands)
UPDATE mob_groups SET HP = 2000 WHERE groupid = 5 AND zoneid = 121; -- Guardian Treant (The Sanctuary of Zi'Tah)

View file

@ -32,12 +32,28 @@ UPDATE merits SET value = 150 WHERE name = 'martyr';
UPDATE merits SET value = 150 WHERE name = 'devotion';
-- Animus Solace: Disable merit upgrades
-- Source: https://forum.square-enix.com/ffxi/threads/55360?_ga=2.195400239.203489549.1557463710-808700183.1440009048
UPDATE merits SET upgrade = 0 WHERE name = 'animus_solace';
-- Animus Misery: Disable merit upgrades
UPDATE merits SET upgrade = 0 WHERE name = 'animus_misery';
------------------------------------
-- WHM Spell Cast Times
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(02/13/2012)
------------------------------------
-- Esuna: Revert cast time from 1 to 3 seconds
UPDATE spell_list SET castTime = 3000 WHERE name = 'esuna';
-- Sacrifice: Revert cast time from 1 to 1.5 seconds
UPDATE spell_list SET castTime = 1500 WHERE name = 'sacrifice';
-- Blindna: Revert cast time from 1 to 3 seconds
UPDATE spell_list SET castTime = 3000 WHERE name = 'blindna';
-- Cursna: Revert cast time from 1 to 3 seconds
UPDATE spell_list SET castTime = 3000 WHERE name = 'cursna';
------------------------------------
-- Thief
------------------------------------
@ -69,8 +85,7 @@ UPDATE merits SET value = 20 WHERE name = 'arcane_circle_recast';
UPDATE abilities SET recastTime = 300 WHERE name = 'weapon_bash';
-- Weapon Bash merit: Revert value to 10 seconds per level
-- Note: merit is named weapon_bash_effect (provides both recast reduction and effect)
UPDATE merits SET value = 10 WHERE name = 'weapon_bash_effect';
UPDATE merits SET value = 10 WHERE name = 'weapon_bash_recast';
-- Dark Seal: Revert recast from 5 to 15 minutes
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(03/26/2012)
@ -85,35 +100,6 @@ UPDATE abilities SET recastTime = 900 WHERE name = 'diabolic_eye';
-- Diabolic Eye merit: Revert value to 150 seconds per level
UPDATE merits SET value = 150 WHERE name = 'diabolic_eye';
------------------------------------
-- Paladin
------------------------------------
-- Holy Circle: Revert recast from 5 to 10 minutes
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(02/13/2012)
UPDATE abilities SET recastTime = 600 WHERE name = 'holy_circle';
-- Holy Circle merit: Revert value to 20 seconds per level
UPDATE merits SET value = 20 WHERE name = 'holy_circle_recast';
-- Chivalry: Revert recast from 10 to 20 minutes
UPDATE abilities SET recastTime = 1200 WHERE name = 'chivalry';
-- Fealty: Revert recast from 10 to 20 minutes
UPDATE abilities SET recastTime = 1200 WHERE name = 'fealty';
-- Chivalry merit: Revert value to 150 seconds per level
UPDATE merits SET value = 150 WHERE name = 'chivalry';
-- Fealty merit: Revert value to 150 seconds per level
UPDATE merits SET value = 150 WHERE name = 'fealty';
-- Shield Bash: Revert recast from 3 to 5 minutes
UPDATE abilities SET recastTime = 300 WHERE name = 'shield_bash';
-- Shield Bash merit: Revert value to 10 seconds per level
UPDATE merits SET value = 10 WHERE name = 'shield_bash_recast';
------------------------------------
-- Beastmaster
------------------------------------
@ -139,25 +125,6 @@ UPDATE abilities SET recastTime = 900 WHERE name = 'killer_instinct';
-- Killer Instinct merit: Revert value to 150 seconds per level
UPDATE merits SET value = 150 WHERE name = 'killer_instinct';
------------------------------------
-- Bard
------------------------------------
-- Mazurka: Revert to town/field only
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(09/08/2010)
SET @TYPE_CITY = 1;
SET @TYPE_OUTDOORS = 2;
SET @MISC_MAZURKA = 8;
-- Remove mazurka from all zones
UPDATE zone_settings
SET misc = misc & ~@MISC_MAZURKA;
-- Reapply to cities and outdoor zones
UPDATE zone_settings
SET misc = misc | @MISC_MAZURKA
WHERE (zonetype & (@TYPE_CITY | @TYPE_OUTDOORS)) <> 0;
------------------------------------
-- Samurai
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(02/13/2012)
@ -214,6 +181,13 @@ UPDATE abilities SET recastTime = 300 WHERE name = 'yonin';
-- Innin: Revert recast from 3 minutes to 5 minutes and add shared cooldown with Yonin
UPDATE abilities SET recastTime = 300, recastId = 146 WHERE name = 'innin';
-- Tonko: Ichi: Revert cast time from 1.5 to 4 seconds
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(02/13/2012)
UPDATE spell_list SET castTime = 4000 WHERE name = 'tonko_ichi';
-- Monomi: Ichi: Revert cast time from 1.5 to 4 seconds
UPDATE spell_list SET castTime = 4000 WHERE name = 'monomi_ichi';
-----------------------------------
-- Dragoon
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(02/13/2012)
@ -251,35 +225,3 @@ UPDATE abilities SET recastTime = 900 WHERE name = 'deep_breathing';
-- Deep Breathing merit: Revert value to 150 seconds per level
UPDATE merits SET value = 150 WHERE name = 'deep_breathing';
-----------------------------------
-- Summoner
-----------------------------------
-- Summoning Magic Casting Time Merit: Repurposed to Spirit MP cost merit. Revert merit value from 5 to 1 per level.
-- Source: https://forum.square-enix.com/ffxi/threads/22099-March-27-2012-%28JST%29-Version-Update
UPDATE merits SET value = 1 WHERE name = 'summoning_magic_cast_time';
-----------------------------------
-- Corsair
-----------------------------------
-- Double-Up: Revert recast from 5 to 7 seconds
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(09/19/2011)
UPDATE abilities SET recastTime = 7 WHERE name = 'double-up';
-- Snake Eye: Revert recast from 5 to 15 minutes
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(05/15/2012)
UPDATE abilities SET recastTime = 900 WHERE name = 'snake_eye';
-- Snake Eye merit: Revert value to 150 seconds per level
UPDATE merits SET value = 150 WHERE name = 'snake_eye';
-- Fold: Revert recast from 5 to 15 minutes
UPDATE abilities SET recastTime = 900 WHERE name = 'fold';
-- Fold merit: Revert value to 150 seconds per level
UPDATE merits SET value = 150 WHERE name = 'fold';
-- Quick Draw: Revert range from 22 to 15 yalms
UPDATE abilities SET `range` = 15 WHERE name = 'quick_draw';

View file

@ -1,74 +0,0 @@
------------------------------------
-- Abyssea Spell SQL Adjustments
-- This module reverts relevant spells to their pre-Abyssea values
------------------------------------
------------------------------------
-- Healing Magic
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(02/13/2012)
------------------------------------
-- Esuna: Revert cast time from 1 to 3 seconds
UPDATE spell_list SET castTime = 3000 WHERE name = 'esuna';
-- Sacrifice: Revert cast time from 1 to 1.5 seconds
UPDATE spell_list SET castTime = 1500 WHERE name = 'sacrifice';
-- Blindna: Revert cast time from 1 to 3 seconds
UPDATE spell_list SET castTime = 3000 WHERE name = 'blindna';
-- Cursna: Revert cast time from 1 to 3 seconds
UPDATE spell_list SET castTime = 3000 WHERE name = 'cursna';
------------------------------------
-- Enhancing Magic
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(12/14/2011)
------------------------------------
-- Regen: Revert cast time from 1.5 to 4 seconds
UPDATE spell_list SET castTime = 4000 WHERE name = 'regen';
-- Regen II: Revert cast time from 1.75 to 4.5 seconds
UPDATE spell_list SET castTime = 4500 WHERE name = 'regen_ii';
-- Regen III: Revert cast time from 2 to 5 seconds
UPDATE spell_list SET castTime = 5000 WHERE name = 'regen_iii';
------------------------------------
-- Singing
-- Source: https://forum.square-enix.com/ffxi/threads/29150-December-13-2012-%28JST%29-Version-Update
-- Source: https://forum.square-enix.com/ffxi/threads/27883-dev1138-Bard-Job-Adjustments
------------------------------------
-- Etudes / Prelude / Sirvente / Dirge: Revert from AoE to single target and cast time to 4 seconds
UPDATE spell_list SET validTargets = 3, AOE = 0, castTime = 4000 WHERE name IN (
'foe_sirvente',
'adventurers_dirge',
'hunters_prelude',
'archers_prelude',
'sinewy_etude',
'dextrous_etude',
'vivacious_etude',
'quick_etude',
'learned_etude',
'spirited_etude',
'enchanting_etude',
'herculean_etude',
'uncanny_etude',
'vital_etude',
'swift_etude',
'sage_etude',
'logical_etude',
'bewitching_etude'
);
------------------------------------
-- Ninjutsu
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(02/13/2012)
------------------------------------
-- Tonko: Ichi: Revert cast time from 1.5 to 4 seconds
UPDATE spell_list SET castTime = 4000 WHERE name = 'tonko_ichi';
-- Monomi: Ichi: Revert cast time from 1.5 to 4 seconds
UPDATE spell_list SET castTime = 4000 WHERE name = 'monomi_ichi';

View file

@ -7,13 +7,7 @@
require('modules/module_utils')
require('scripts/globals/treasure')
-----------------------------------
local moduleName = 'pre_rmt_drops'
if xi.module.isContentEnabled('COP') then
return { name = moduleName }
end
return { name = moduleName }
local m = Module:new('pre_rmt_drops')
--[[
-- This Module is disabled until the new treasure system is tested an appropiate amount of time.
@ -34,3 +28,5 @@ m:addOverride('xi.zones.Castle_Oztroja.Zone.onInitialize', function(zone)
end)
]]--
return m

View file

@ -45,7 +45,7 @@ class AHPaginationModule : public CPPModule
return false;
}
if (PChar->m_GMlevel == 0 && !PChar->loc.zone->CanUseMisc(xi::ZoneMisc::AuctionHouse))
if (PChar->m_GMlevel == 0 && !PChar->loc.zone->CanUseMisc(MISC_AH))
{
ShowWarning("[AH PAGES] %s is trying to use the auction house in a disallowed zone [%s]", PChar->getName(), PChar->loc.zone->getName());
return true;

View file

@ -35,7 +35,7 @@ hnmSystem:addOverride('xi.zones.Dragons_Aery.Zone.onInitialize', function(zone)
-- First-time setup.
if hnmPopTime == 0 then
hnmPopTime = currentTime + math.randomInt(1, 48) * 1800
hnmPopTime = currentTime + math.random(1, 48) * 1800
SetServerVariable('[HNM]Fafnir', hnmPopTime) -- Save pop time.
end
@ -54,7 +54,7 @@ hnmSystem:addOverride('xi.zones.Dragons_Aery.mobs.Fafnir.onMobDespawn', function
super(mob)
-- Server Variable work.
local randomPopTime = 75600 + math.randomInt(0, 6) * 1800
local randomPopTime = 75600 + math.random(0, 6) * 1800
SetServerVariable('[HNM]Fafnir', GetSystemTime() + randomPopTime) -- Save next pop time.
@ -85,7 +85,7 @@ hnmSystem:addOverride('xi.zones.Valley_of_Sorrows.Zone.onInitialize', function(z
-- First-time setup.
if hnmPopTime == 0 then
hnmPopTime = currentTime + math.randomInt(1, 48) * 1800
hnmPopTime = currentTime + math.random(1, 48) * 1800
SetServerVariable('[HNM]Adamantoise', hnmPopTime) -- Save pop time.
end
@ -104,7 +104,7 @@ hnmSystem:addOverride('xi.zones.Valley_of_Sorrows.mobs.Adamantoise.onMobDespawn'
super(mob)
-- Server Variable work.
local randomPopTime = 75600 + math.randomInt(0, 6) * 1800
local randomPopTime = 75600 + math.random(0, 6) * 1800
SetServerVariable('[HNM]Adamantoise', GetSystemTime() + randomPopTime) -- Save next pop time.
@ -135,7 +135,7 @@ hnmSystem:addOverride('xi.zones.Behemoths_Dominion.Zone.onInitialize', function(
-- First-time setup.
if hnmPopTime == 0 then
hnmPopTime = currentTime + math.randomInt(1, 48) * 1800
hnmPopTime = currentTime + math.random(1, 48) * 1800
SetServerVariable('[HNM]Behemoth', hnmPopTime) -- Save pop time.
end
@ -154,7 +154,7 @@ hnmSystem:addOverride('xi.zones.Behemoths_Dominion.mobs.Behemoth.onMobDespawn',
super(mob)
-- Server Variable work.
local randomPopTime = 75600 + math.randomInt(0, 6) * 1800
local randomPopTime = 75600 + math.random(0, 6) * 1800
SetServerVariable('[HNM]Behemoth', GetSystemTime() + randomPopTime) -- Save next pop time.

View file

@ -0,0 +1,20 @@
-----------------------------------
-- Module to make 'Mom the Adventurer?' quest missable.
-----------------------------------
require('modules/module_utils')
-----------------------------------
local m = Module:new('missable_mom_the_adventurer')
m:addOverride('xi.server.onServerStart', function()
super()
xi.module.modifyInteractionEntry('scripts/quests/bastok/Mom_the_Adventurer', function(quest)
quest.sections[1].check = function(player, status, vars)
return status ~= xi.questStatus.QUEST_ACCEPTED and
player:getFameLevel(xi.fameArea.BASTOK) < 2 and
vars.Prog == 0
end
end)
end)
return m

View file

@ -1,92 +0,0 @@
-----------------------------------
-- Mog House Exit Home Point Prompt Module
-----------------------------------
-- Restores the prompt to set your home point when exiting the Mog House after changing jobs.
-----------------------------------
require('modules/module_utils')
require('scripts/globals/moghouse')
-----------------------------------
local m = Module:new('moghouse_exit_homepoint')
-- Variable used for this module to store the job snapshot in the player's character variables.
local jobSnapshot = 'moghouseExitJobSnapshot'
-- The current event ID for the Mog House exit prompt. May change with future updates. If this module ever breaks, check here first.
local exitEventId = 30004
-- Zones to prompt players to set their home point upon exiting the Mog House.
local exitZones =
{
['Southern_San_dOria' ] = xi.zone.SOUTHERN_SAN_DORIA,
['Northern_San_dOria' ] = xi.zone.NORTHERN_SAN_DORIA,
['Port_San_dOria' ] = xi.zone.PORT_SAN_DORIA,
['Bastok_Mines' ] = xi.zone.BASTOK_MINES,
['Bastok_Markets' ] = xi.zone.BASTOK_MARKETS,
['Port_Bastok' ] = xi.zone.PORT_BASTOK,
['Windurst_Waters' ] = xi.zone.WINDURST_WATERS,
['Windurst_Walls' ] = xi.zone.WINDURST_WALLS,
['Port_Windurst' ] = xi.zone.PORT_WINDURST,
['Windurst_Woods' ] = xi.zone.WINDURST_WOODS,
['RuLude_Gardens' ] = xi.zone.RULUDE_GARDENS,
['Upper_Jeuno' ] = xi.zone.UPPER_JEUNO,
['Lower_Jeuno' ] = xi.zone.LOWER_JEUNO,
['Port_Jeuno' ] = xi.zone.PORT_JEUNO,
['Al_Zahbi' ] = xi.zone.AL_ZAHBI,
['Aht_Urhgan_Whitegate' ] = xi.zone.AHT_URHGAN_WHITEGATE,
['Southern_San_dOria_[S]'] = xi.zone.SOUTHERN_SAN_DORIA_S,
['Bastok_Markets_[S]' ] = xi.zone.BASTOK_MARKETS_S,
['Windurst_Waters_[S]' ] = xi.zone.WINDURST_WATERS_S,
}
local promptZoneIds = {}
for _, zoneId in pairs(exitZones) do
promptZoneIds[zoneId] = true
end
local currentJob = function(player)
return player:getMainJob() * 100 + player:getSubJob()
end
m:addOverride('xi.moghouse.onMoghouseZoneEvent', function(player, prevZone)
-- Create a snapshot of the players current job when entering the mog house.
if player:inMogHouse() then
player:setCharVar(jobSnapshot, currentJob(player))
return super(player, prevZone)
end
local moghouseExitPos = player:getXPos() == 0 and player:getYPos() == 0 and player:getZPos() == 0
local baseCsId = super(player, prevZone)
local storedJob = player:getCharVar(jobSnapshot)
if moghouseExitPos and storedJob > 0 then
player:setCharVar(jobSnapshot, 0)
if
baseCsId == -1 and
promptZoneIds[player:getZoneID()] and
storedJob ~= currentJob(player)
then
return exitEventId
end
end
return baseCsId
end)
for zoneName in pairs(exitZones) do
m:addOverride(string.format('xi.zones.%s.Zone.onEventFinish', zoneName), function(player, csid, option, npc)
if csid == exitEventId then
if option == 0 then
player:setHomePoint()
player:messageSpecial(zones[player:getZoneID()].text.HOMEPOINT_SET)
end
return
end
super(player, csid, option, npc)
end)
end
return m

View file

@ -20,7 +20,7 @@ local nmsToPersist =
'Behemoths_Dominion',
'Behemoth',
function()
return 75600 + math.randomInt(0, 6) * 1800
return 75600 + math.random(0, 6) * 1800
end
},
}

View file

@ -1,297 +0,0 @@
-----------------------------------
-- Reverts blood pacts to no longer have a duration based on summoning magic.
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(09/08/2010)
-----------------------------------
require('modules/module_utils')
-----------------------------------
local moduleName = 'abyssea_avatar_bloodpacts'
if xi.module.isContentEnabled('ABYSSEA') then
return { name = moduleName }
end
local m = Module:new(moduleName)
-----------------------------------
-- Shining Ruby
-----------------------------------
m:addOverride('xi.actions.abilities.pets.shining_ruby.onPetAbility', function(target, pet, petskill, summoner, action)
local duration = 180
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
target:delStatusEffect(xi.effect.SHINING_RUBY)
target:addStatusEffect(xi.effect.SHINING_RUBY, { power = 1, duration = duration, origin = pet })
if target:getID() == action:getPrimaryTargetID() then
petskill:setMsg(xi.msg.basic.SKILL_GAIN_EFFECT_2)
else
petskill:setMsg(xi.msg.basic.JA_GAIN_EFFECT)
end
return xi.effect.SHINING_RUBY
end)
-----------------------------------
-- Hastega
-----------------------------------
m:addOverride('xi.actions.abilities.pets.hastega.onPetAbility', function(target, pet, petskill, summoner, action)
local duration = 180
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
-- Reverts Garuda's Hastega to use 102/1024 or 9.96%
local typeEffect = xi.effect.HASTE
if target:addStatusEffect(typeEffect, { power = 996, duration = duration, origin = pet }) then
if target:getID() == action:getPrimaryTargetID() then
petskill:setMsg(xi.msg.basic.SKILL_GAIN_EFFECT_2)
else
petskill:setMsg(xi.msg.basic.JA_GAIN_EFFECT)
end
else
petskill:setMsg(xi.msg.basic.JA_NO_EFFECT_2)
return
end
return typeEffect
end)
-----------------------------------
-- Crimson Howl
-----------------------------------
m:addOverride('xi.actions.abilities.pets.crimson_howl.onPetAbility', function(target, pet, petskill, summoner, action)
local duration = 60
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local typeEffect = xi.effect.WARCRY
if target:addStatusEffect(typeEffect, { power = 9, duration = duration, origin = pet }) then
if target:getID() == action:getPrimaryTargetID() then
petskill:setMsg(xi.msg.basic.SKILL_GAIN_EFFECT_2)
else
petskill:setMsg(xi.msg.basic.JA_GAIN_EFFECT)
end
else
petskill:setMsg(xi.msg.basic.JA_NO_EFFECT_2)
return
end
return typeEffect
end)
-----------------------------------
-- Frost Armor
-----------------------------------
m:addOverride('xi.actions.abilities.pets.frost_armor.onPetAbility', function(target, pet, petskill, summoner, action)
local duration = 180
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local typeEffect = xi.effect.ICE_SPIKES
target:delStatusEffect(typeEffect)
if target:addStatusEffect(typeEffect, { power = 15, duration = duration, origin = pet }) then
if target:getID() == action:getPrimaryTargetID() then
petskill:setMsg(xi.msg.basic.SKILL_GAIN_EFFECT_2)
else
petskill:setMsg(xi.msg.basic.JA_GAIN_EFFECT)
end
else
petskill:setMsg(xi.msg.basic.JA_NO_EFFECT_2)
return
end
return typeEffect
end)
-----------------------------------
-- Rolling Thunder
-----------------------------------
m:addOverride('xi.actions.abilities.pets.rolling_thunder.onPetAbility', function(target, pet, petskill, summoner, action)
local duration = 120
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local magicskill = xi.data.skillLevel.getSkillCap(target:getMainLvl(), xi.skillRank.A_PLUS)
local potency = 3 + 6 * magicskill / 100
if magicskill > 200 then
potency = 5 + 5 * magicskill / 100
end
xi.mobskills.mobBuffMove(target, xi.effect.ENTHUNDER, potency, 0, duration)
if target:getID() == action:getPrimaryTargetID() then
petskill:setMsg(xi.msg.basic.JA_RECEIVES_EFFECT_2)
else
petskill:setMsg(xi.msg.basic.JA_RECEIVES_EFFECT)
end
return xi.effect.ENTHUNDER
end)
-----------------------------------
-- Lightning Armor
-----------------------------------
m:addOverride('xi.actions.abilities.pets.lightning_armor.onPetAbility', function(target, pet, petskill, summoner, action)
local duration = 180
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local typeEffect = xi.effect.SHOCK_SPIKES
target:delStatusEffect(typeEffect)
if target:addStatusEffect(typeEffect, { power = 15, duration = duration, origin = pet }) then
if target:getID() == action:getPrimaryTargetID() then
petskill:setMsg(xi.msg.basic.SKILL_GAIN_EFFECT_2)
else
petskill:setMsg(xi.msg.basic.JA_GAIN_EFFECT)
end
else
petskill:setMsg(xi.msg.basic.JA_NO_EFFECT_2)
return
end
return typeEffect
end)
-----------------------------------
-- Ecliptic Growl
-----------------------------------
m:addOverride('xi.actions.abilities.pets.ecliptic_growl.onPetAbility', function(target, pet, petskill, summoner, action)
local duration = 180
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local moonCycle = getVanadielMoonCycle()
local cycleBuffs =
{
[xi.moonCycle.NEW_MOON] = 1,
[xi.moonCycle.LESSER_WAXING_CRESCENT] = 2,
[xi.moonCycle.GREATER_WAXING_CRESCENT] = 3,
[xi.moonCycle.FIRST_QUARTER] = 4,
[xi.moonCycle.LESSER_WAXING_GIBBOUS] = 5,
[xi.moonCycle.GREATER_WAXING_GIBBOUS] = 6,
[xi.moonCycle.FULL_MOON] = 7,
[xi.moonCycle.GREATER_WANING_GIBBOUS] = 6,
[xi.moonCycle.LESSER_WANING_GIBBOUS] = 5,
[xi.moonCycle.THIRD_QUARTER] = 4,
[xi.moonCycle.GREATER_WANING_CRESCENT] = 3,
[xi.moonCycle.LESSER_WANING_CRESCENT] = 2,
}
local buffValue = cycleBuffs[moonCycle]
target:delStatusEffect(xi.effect.STR_BOOST)
target:delStatusEffect(xi.effect.DEX_BOOST)
target:delStatusEffect(xi.effect.VIT_BOOST)
target:delStatusEffect(xi.effect.AGI_BOOST)
target:delStatusEffect(xi.effect.MND_BOOST)
target:delStatusEffect(xi.effect.CHR_BOOST)
target:addStatusEffect(xi.effect.STR_BOOST, { power = buffValue, duration = duration, origin = pet })
target:addStatusEffect(xi.effect.DEX_BOOST, { power = buffValue, duration = duration, origin = pet })
target:addStatusEffect(xi.effect.VIT_BOOST, { power = buffValue, duration = duration, origin = pet })
target:addStatusEffect(xi.effect.AGI_BOOST, { power = 8 - buffValue, duration = duration, origin = pet })
target:addStatusEffect(xi.effect.INT_BOOST, { power = 8 - buffValue, duration = duration, origin = pet })
target:addStatusEffect(xi.effect.MND_BOOST, { power = 8 - buffValue, duration = duration, origin = pet })
target:addStatusEffect(xi.effect.CHR_BOOST, { power = 8 - buffValue, duration = duration, origin = pet })
if target:getID() == action:getPrimaryTargetID() then
petskill:setMsg(xi.msg.basic.STATUS_BOOST)
else
petskill:setMsg(xi.msg.basic.STATUS_BOOST_2)
end
return 0
end)
-----------------------------------
-- Ecliptic Howl
-----------------------------------
m:addOverride('xi.actions.abilities.pets.ecliptic_howl.onPetAbility', function(target, pet, petskill, summoner, action)
local duration = 180
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local moonCycle = getVanadielMoonCycle()
local cycleBuffs =
{
[xi.moonCycle.NEW_MOON] = 1,
[xi.moonCycle.LESSER_WAXING_CRESCENT] = 5,
[xi.moonCycle.GREATER_WAXING_CRESCENT] = 9,
[xi.moonCycle.FIRST_QUARTER] = 13,
[xi.moonCycle.LESSER_WAXING_GIBBOUS] = 17,
[xi.moonCycle.GREATER_WAXING_GIBBOUS] = 21,
[xi.moonCycle.FULL_MOON] = 25,
[xi.moonCycle.GREATER_WANING_GIBBOUS] = 21,
[xi.moonCycle.LESSER_WANING_GIBBOUS] = 17,
[xi.moonCycle.THIRD_QUARTER] = 13,
[xi.moonCycle.GREATER_WANING_CRESCENT] = 9,
[xi.moonCycle.LESSER_WANING_CRESCENT] = 5,
}
local buffValue = cycleBuffs[moonCycle]
target:delStatusEffect(xi.effect.ACCURACY_BOOST)
target:delStatusEffect(xi.effect.EVASION_BOOST)
target:addStatusEffect(xi.effect.ACCURACY_BOOST, { power = buffValue, duration = duration, origin = pet })
target:addStatusEffect(xi.effect.EVASION_BOOST, { power = 25 - buffValue, duration = duration, origin = pet })
if target:getID() == action:getPrimaryTargetID() then
petskill:setMsg(xi.msg.basic.ACC_EVA_BOOST)
else
petskill:setMsg(xi.msg.basic.ACC_EVA_BOOST_2)
end
return 0
end)
-----------------------------------
-- Noctoshield
-----------------------------------
m:addOverride('xi.actions.abilities.pets.noctoshield.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local duration = 180
if target:addStatusEffect(xi.effect.PHALANX, { power = 13, duration = duration, origin = pet }) then
if target:getID() == action:getPrimaryTargetID() then
petskill:setMsg(xi.msg.basic.SKILL_GAIN_EFFECT_2)
else
petskill:setMsg(xi.msg.basic.JA_GAIN_EFFECT)
end
else
petskill:setMsg(xi.msg.basic.JA_NO_EFFECT_2)
return
end
return xi.effect.PHALANX
end)
-----------------------------------
-- Dream Shroud
-----------------------------------
m:addOverride('xi.actions.abilities.pets.dream_shroud.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local duration = 180
local hour = VanadielHour()
local buffvalue = math.abs(12 - hour) + 1
target:delStatusEffect(xi.effect.MAGIC_ATK_BOOST)
target:delStatusEffect(xi.effect.MAGIC_DEF_BOOST)
target:addStatusEffect(xi.effect.MAGIC_ATK_BOOST, { power = buffvalue, duration = duration, origin = pet })
target:addStatusEffect(xi.effect.MAGIC_DEF_BOOST, { power = 14 - buffvalue, duration = duration, origin = pet })
if target:getID() == action:getPrimaryTargetID() then
petskill:setMsg(xi.msg.basic.JA_RECEIVES_MAB_MDB)
else
petskill:setMsg(xi.msg.basic.JA_RECEIVES_MAB_MDB_2)
end
return 0
end)
return m

View file

@ -1,552 +0,0 @@
-----------------------------------
-- Attachment module
-- Recreates attachment effects in the WoTG Era.
-----------------------------------
require('modules/module_utils')
require('scripts/globals/automaton')
-----------------------------------
local moduleName = 'attachments'
if xi.module.isContentEnabled('ABYSSEA') then
return { name = moduleName }
end
local m = Module:new(moduleName)
-- Reduces Enmity boost from Strobe : https://wiki.ffo.jp/html/8610.html
-- Reduces Store TP from Inhibitor : https://wiki.ffo.jp/html/8625.html
-- Changes Armor Plate and Armor Plate II to Defense instead of PDT : https://wiki.ffo.jp/html/9070.html
-- Adds a Ranged Attack Penalty to Drum Magazine. : https://wiki.ffo.jp/html/8882.html
-- Changes Turbo Charger Haste to Gear Haste instead of Magic : https://wiki.ffo.jp/html/8627.html
-- Adds Burden to Tactical Processor : https://wiki.ffo.jp/html/13527.html
-- Reduces scaling from Volt Gun : https://wiki.ffo.jp/html/8752.html
-- Reduces Burden Decay From Heatsink : https://wiki.ffo.jp/html/8629.html
-- Reduces the potency of Steam Jackets Damage Reduction : https://wiki.ffo.jp/html/15352.html
xi.automaton.attachmentModifiers['strobe' ] = { { modifier = xi.mod.ENMITY, values = { 5, 15, 25, 40 }, opticFiber = true }, }
xi.automaton.attachmentModifiers['inhibitor' ] = { { modifier = xi.mod.STORETP, values = { 5, 10, 15, 20 }, opticFiber = true }, }
xi.automaton.attachmentModifiers['armor_plate' ] = { { modifier = xi.mod.DEFP, values = { 10, 15, 20, 25 }, opticFiber = true }, }
xi.automaton.attachmentModifiers['armor_plate_ii' ] = { { modifier = xi.mod.DEFP, values = { 20, 25, 30, 35 }, opticFiber = true }, }
xi.automaton.attachmentModifiers['drum_magazine' ] = { { modifier = xi.mod.AUTO_RANGED_DELAY, values = { 2, 4, 6, 8 }, opticFiber = false },
{ modifier = xi.mod.RACC, values = { -15, -30, -50, -75 }, opticFiber = false }, }
xi.automaton.attachmentModifiers['flame_holder' ] = { { modifier = xi.mod.WEAPONSKILL_DAMAGE_BASE, values = { 0, 125, 150, 175 }, opticFiber = true }, }
xi.automaton.attachmentModifiers['ice_maker' ] = { { modifier = xi.mod.AUTO_MAB_COEFFICIENT, values = { 0, 20, 40, 60 }, opticFiber = true }, }
xi.automaton.attachmentModifiers['turbo_charger' ] = { { modifier = xi.mod.HASTE_GEAR, values = { 500, 1500, 2000, 2500 }, opticFiber = true }, }
xi.automaton.attachmentModifiers['tactical_processor'] = { { modifier = xi.mod.AUTO_DECISION_DELAY, values = { 50, 70, 85, 115 }, opticFiber = false },
{ modifier = xi.mod.OVERLOAD_THRESH, values = { -5, -5, -5, -5 }, opticFiber = false }, }
xi.automaton.attachmentModifiers['volt_gun' ] = { { modifier = xi.mod.VOLT_GUN_POTENCY, values = { 0, 0, 0, 0 }, opticFiber = false }, }
xi.automaton.attachmentModifiers['heatsink' ] = { { modifier = xi.mod.BURDEN_DECAY, values = { 1, 1, 1, 1 }, opticFiber = false }, }
xi.automaton.attachmentModifiers['steam_jacket' ] = { { modifier = xi.mod.AUTO_STEAM_JACKET_REDUCTION, values = { 25, 35, 40, 60 }, opticFiber = true }, }
-- Reduces potency of Auto Repair Kit II and removed level based scaling from Mana Tank : https://wiki.ffo.jp/html/19739.html
xi.automaton.repairKit.data['auto-repair_kit_ii' ] = { id = 196, hpBoost = 2, regenBase = { 0, 2, 3, 4 }, regenMultiplier = { 0, 0.4, 0.6, 0.8 } }
xi.automaton.manaTank.data ['mana_tank' ] = { id = 225, mpBoost = 1, refreshBase = { 0, 1, 2, 3 }, refreshMultiplier = { 0, 0.0, 0.0, 0.0 } }
xi.automaton.manaTank.data ['mana_tank_ii' ] = { id = 228, mpBoost = 2, refreshBase = { 0, 2, 3, 4 }, refreshMultiplier = { 0, 0.0, 0.0, 0.0 } }
-----------------------------------
-- Flame Holder - Reduces Flame Holder Scaling, and consumes all Fire Maneuvers on weaponskill execution. https://wiki.ffo.jp/html/11183.html
-----------------------------------
local validFlameHolderSkills = set
{
xi.mobSkill.ARCUBALLISTA_AUTOMATON,
xi.mobSkill.ARMOR_PIERCER_AUTOMATON,
xi.mobSkill.ARMOR_SHATTERER_AUTOMATON,
xi.mobSkill.BONE_CRUSHER_AUTOMATON,
xi.mobSkill.CANNIBAL_BLADE_AUTOMATON,
xi.mobSkill.CHIMERA_RIPPER_AUTOMATON,
xi.mobSkill.DAZE_AUTOMATON,
xi.mobSkill.KNOCKOUT_AUTOMATON,
xi.mobSkill.MAGIC_MORTAR_AUTOMATON,
xi.mobSkill.SLAPSTICK_AUTOMATON,
xi.mobSkill.STRING_CLIPPER_AUTOMATON,
xi.mobSkill.STRING_SHREDDER_AUTOMATON,
}
m:addOverride('xi.actions.abilities.pets.attachments.flame_holder.onEquip', function(pet, attachment)
pet:addListener('WEAPONSKILL_STATE_EXIT', 'AUTO_FLAME_HOLDER_END', function(automaton, skillId, wasExecuted)
if not validFlameHolderSkills[skillId] then
return
end
if not wasExecuted then
return
end
local master = automaton:getMaster()
if not master then
return
end
-- Consume all Fire Maneuvers on weaponskill execution.
local fireManeuvers = master:countEffect(xi.effect.FIRE_MANEUVER)
for i = 1, fireManeuvers do
master:delStatusEffectSilent(xi.effect.FIRE_MANEUVER)
end
master:updateAttachments()
end)
xi.automaton.onAttachmentEquip(pet, attachment)
end)
m:addOverride('xi.actions.abilities.pets.attachments.flame_holder.onUnequip', function(pet, attachment)
xi.automaton.onAttachmentUnequip(pet, attachment)
pet:removeListener('AUTO_FLAME_HOLDER_END')
end)
-----------------------------------
-- Ice Maker - Reduces Magic Attack Bonus from Ice Maker, and consumes all Ice Maneuvers on magic attack execution. https://wiki.ffo.jp/html/11198.html
-----------------------------------
local validIceMakerSpells = set
{
xi.magic.spell.FIRE,
xi.magic.spell.FIRE_II,
xi.magic.spell.FIRE_III,
xi.magic.spell.FIRE_IV,
xi.magic.spell.FIRE_V,
xi.magic.spell.BLIZZARD,
xi.magic.spell.BLIZZARD_II,
xi.magic.spell.BLIZZARD_III,
xi.magic.spell.BLIZZARD_IV,
xi.magic.spell.BLIZZARD_V,
xi.magic.spell.AERO,
xi.magic.spell.AERO_II,
xi.magic.spell.AERO_III,
xi.magic.spell.AERO_IV,
xi.magic.spell.AERO_V,
xi.magic.spell.STONE,
xi.magic.spell.STONE_II,
xi.magic.spell.STONE_III,
xi.magic.spell.STONE_IV,
xi.magic.spell.STONE_V,
xi.magic.spell.THUNDER,
xi.magic.spell.THUNDER_II,
xi.magic.spell.THUNDER_III,
xi.magic.spell.THUNDER_IV,
xi.magic.spell.THUNDER_V,
xi.magic.spell.WATER,
xi.magic.spell.WATER_II,
xi.magic.spell.WATER_III,
xi.magic.spell.WATER_IV,
xi.magic.spell.WATER_V,
}
m:addOverride('xi.actions.abilities.pets.attachments.ice_maker.onEquip', function(pet, attachment)
pet:addListener('MAGIC_USE', 'AUTO_ICE_MAKER_USE', function(automaton, target, spell, action)
if not validIceMakerSpells[spell:getID()] then
return
end
local master = automaton:getMaster()
if not master then
return
end
local iceManeuvers = master:countEffect(xi.effect.ICE_MANEUVER)
for i = 1, iceManeuvers do
master:delStatusEffectSilent(xi.effect.ICE_MANEUVER)
end
master:updateAttachments()
end)
xi.automaton.onAttachmentEquip(pet, attachment)
end)
m:addOverride('xi.actions.abilities.pets.attachments.ice_maker.onUnequip', function(pet, attachment)
xi.automaton.onAttachmentUnequip(pet, attachment)
pet:removeListener('AUTO_ICE_MAKER_USE')
end)
-----------------------------------
-- Replicator - Reduces amount of absorbs granted by Replicator, and changes them to Blink from Utsusemi. Also consumes Wind Maneuvers. https://wiki.ffo.jp/html/12225.html
-----------------------------------
local shadowTable =
{
[1] = 2,
[2] = 3,
[3] = 4,
}
m:addOverride('xi.actions.abilities.pets.automaton.replicator.onAutomatonAbilityCheck', function(target, automaton, skill)
return 0
end)
m:addOverride('xi.actions.abilities.pets.automaton.replicator.onAutomatonAbility', function(target, automaton, skill, master, action)
local windManeuvers = xi.automaton.getManeuverCount(master, master:countEffect(xi.effect.WIND_MANEUVER))
local shadows = shadowTable[windManeuvers]
automaton:addRecast(xi.recast.ABILITY, skill:getID(), 60)
for i = 1, windManeuvers do
master:delStatusEffectSilent(xi.effect.WIND_MANEUVER)
end
master:updateAttachments()
if
shadows and
target:addStatusEffect(xi.effect.BLINK, { power = shadows, duration = 300, origin = automaton })
then
skill:setMsg(xi.msg.basic.SKILL_GAIN_EFFECT)
else
skill:setMsg(xi.msg.basic.SKILL_NO_EFFECT)
end
return xi.effect.BLINK
end)
-----------------------------------
-- Shock Absorber - Reduces the potency of the stoneskin effect and removes scaling. https://wiki.ffo.jp/html/12927.html
-----------------------------------
m:addOverride('xi.actions.abilities.pets.automaton.shock_absorber.onAutomatonAbilityCheck', function(target, automaton, skill)
return 0
end)
m:addOverride('xi.actions.abilities.pets.automaton.shock_absorber.onAutomatonAbility', function(target, automaton, skill, master, action)
automaton:addRecast(xi.recast.ABILITY, skill:getID(), 180)
if target:addStatusEffect(xi.effect.STONESKIN, { power = 100, duration = 180, origin = automaton, tier = 4 }) then
skill:setMsg(xi.msg.basic.SKILL_GAIN_EFFECT)
else
skill:setMsg(xi.msg.basic.SKILL_NO_EFFECT)
end
return xi.effect.STONESKIN
end)
-----------------------------------
-- Shield Bash - Removes gaurunteed hit chance while Hammermill is equipped. https://wiki.ffo.jp/html/12156.html
-----------------------------------
local shieldBashSlowTable =
{
[1] = { tier = 4, duration = 30 },
[2] = { tier = 5, duration = 50 },
[3] = { tier = 6, duration = 70 },
}
local function applyHammermillSlow(automaton, target, skill, master)
local power = automaton:getMod(xi.mod.AUTO_SHIELD_BASH_SLOW) * 100
if power <= 0 then
return
end
local slowTier = shieldBashSlowTable[master and xi.automaton.getManeuverCount(master, master:countEffect(xi.effect.EARTH_MANEUVER)) or 0]
local params =
{
[1] = { effectId = xi.effect.SLOW, power = power, duration = slowTier.duration, tier = slowTier.tier },
}
xi.combat.action.executeMobskillStatusEffect(automaton, target, skill, params, { messageBypass = true })
end
m:addOverride('xi.actions.abilities.pets.automaton.shield_bash.onAutomatonAbilityCheck', function(target, automaton, skill)
return 0
end)
-----------------------------------
-- Hammermill
-----------------------------------
m:addOverride('xi.actions.abilities.pets.automaton.shield_bash.onAutomatonAbility', function(target, automaton, skill, master, action)
local params = {}
params.baseDamage = automaton:getWeaponDmg()
params.numHits = utils.clamp(1 + xi.automaton.getExtraHits(automaton, 1), 1, 8)
params.fTP = { 1.0, 1.0, 1.0 }
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = params.numHits
local hammermillEquipped = automaton:hasAttachmentSet(xi.item.HAMMERMILL_ATTACHMENT)
if hammermillEquipped then
local shieldBashBonus = 1.0 + automaton:getMod(xi.mod.SHIELD_BASH) / 100
params.fTP =
{
params.fTP[1] * shieldBashBonus,
params.fTP[2] * shieldBashBonus,
params.fTP[3] * shieldBashBonus,
}
end
local info = xi.mobskills.mobPhysicalMove(automaton, target, skill, action, params)
if xi.mobskills.processDamage(automaton, target, skill, action, info) then
target:takeDamage(info.damage, automaton, info.attackType, info.damageType)
xi.mobskills.mobStatusEffectMove(automaton, target, xi.effect.STUN, 1, 0, 6)
if hammermillEquipped then
applyHammermillSlow(automaton, target, skill, master)
end
end
return info.damage
end)
-----------------------------------
-- Analyzer - Caps the amount of skills that can be analyzed to 1. https://wiki.ffo.jp/html/10746.html
-----------------------------------
m:addOverride('xi.actions.abilities.pets.attachments.analyzer.onEquip', function(pet, attachment)
pet:setLocalVar('analyzedSkill1', 0)
pet:addListener('WEAPONSKILL_TAKE', 'ANALYZER_WEAPONSKILL_TAKE', function(mob, target, skill, tp, action)
local analyzerModifier = target:getMod(xi.mod.AUTO_ANALYZER)
local incomingSkill = skill:getID()
if analyzerModifier <= 0 then
return
end
local analyzedSkill = target:getLocalVar('analyzedSkill1')
if incomingSkill == analyzedSkill then
return
end
if incomingSkill ~= analyzedSkill then
target:setLocalVar('analyzedSkill1', incomingSkill)
end
end)
xi.automaton.onAttachmentEquip(pet, attachment)
end)
m:addOverride('xi.actions.abilities.pets.attachments.analyzer.onUnequip', function(pet, attachment)
pet:setLocalVar('analyzedSkill1', 0)
pet:removeListener('ANALYZER_WEAPONSKILL_TAKE')
xi.automaton.onAttachmentUnequip(pet, attachment)
end)
m:addOverride('xi.actions.abilities.pets.attachments.analyzer.onManeuverGain', function(pet, attachment, maneuvers)
end)
m:addOverride('xi.actions.abilities.pets.attachments.analyzer.onManeuverLose', function(pet, attachment, maneuvers)
end)
m:addOverride('xi.actions.abilities.pets.attachments.analyzer.onUpdate', function(pet, attachment, maneuvers)
end)
m:addOverride('utils.handleAutomatonAutoAnalyzer', function(actor, skill, damage)
local analyzerModifier = actor:getMod(xi.mod.AUTO_ANALYZER)
if analyzerModifier <= 0 then
return damage
end
local automatonId = actor:getID()
if not automatonId then
return damage
end
local automatonMaster = actor:getMaster()
if not automatonMaster then
return damage
end
local incomingSkill = skill:getID()
local analyzedSkill = actor:getLocalVar('analyzedSkill1')
if incomingSkill == analyzedSkill then
local earthManeuvers = xi.automaton.getManeuverCount(automatonMaster, automatonMaster:countEffect(xi.effect.EARTH_MANEUVER))
local damageReduction = 10 + 10 * earthManeuvers
return math.floor(damage * (100 - damageReduction) / 100)
end
return damage
end)
-----------------------------------
-- Eraser - Changes Eraser to consume all Maneuvers on activation. https://wiki.ffo.jp/html/5365.html
-----------------------------------
local maneuvers =
{
xi.effect.FIRE_MANEUVER,
xi.effect.ICE_MANEUVER,
xi.effect.WIND_MANEUVER,
xi.effect.EARTH_MANEUVER,
xi.effect.THUNDER_MANEUVER,
xi.effect.WATER_MANEUVER,
xi.effect.LIGHT_MANEUVER,
xi.effect.DARK_MANEUVER,
}
local function removeAllManeuvers(master)
-- Era Eraser consumes all active maneuvers, not just Light Maneuvers.
for _, maneuverId in ipairs(maneuvers) do
for _ = 1, master:countEffect(maneuverId) do
master:delStatusEffectSilent(maneuverId)
end
end
end
local removables =
{
-- Songs
xi.effect.ELEGY,
xi.effect.REQUIEM,
xi.effect.THRENODY,
-- Enfeebling
xi.effect.BLINDNESS,
xi.effect.PARALYSIS,
xi.effect.SILENCE,
xi.effect.POISON,
xi.effect.CURSE_I,
xi.effect.CURSE_II,
xi.effect.DISEASE,
xi.effect.PLAGUE,
xi.effect.WEIGHT,
xi.effect.BIND,
xi.effect.ADDLE,
xi.effect.SLOW,
xi.effect.PETRIFICATION,
-- DoTs
xi.effect.BIO,
xi.effect.DIA,
xi.effect.BURN,
xi.effect.FROST,
xi.effect.CHOKE,
xi.effect.RASP,
xi.effect.SHOCK,
xi.effect.DROWN,
-- Main Stat Downs
xi.effect.STR_DOWN,
xi.effect.DEX_DOWN,
xi.effect.VIT_DOWN,
xi.effect.AGI_DOWN,
xi.effect.INT_DOWN,
xi.effect.MND_DOWN,
xi.effect.CHR_DOWN,
-- Combat Stat Downs
xi.effect.ACCURACY_DOWN,
xi.effect.ATTACK_DOWN,
xi.effect.EVASION_DOWN,
xi.effect.DEFENSE_DOWN,
-- Magic Stat Downs
xi.effect.MAGIC_ACC_DOWN,
xi.effect.MAGIC_ATK_DOWN,
xi.effect.MAGIC_EVASION_DOWN,
xi.effect.MAGIC_DEF_DOWN,
-- HP/MP/TP Stat Downs
xi.effect.MAX_TP_DOWN,
xi.effect.MAX_MP_DOWN,
xi.effect.MAX_HP_DOWN,
}
m:addOverride('xi.actions.abilities.pets.automaton.eraser.onAutomatonAbilityCheck', function(target, automaton, skill)
return 0
end)
m:addOverride('xi.actions.abilities.pets.automaton.eraser.onAutomatonAbility', function(target, automaton, skill, master, action)
automaton:addRecast(xi.recast.ABILITY, skill:getID(), 30)
local lightManeuvers = xi.automaton.getManeuverCount(master, master:countEffect(xi.effect.LIGHT_MANEUVER))
local effectsRemoved = 0
for _, effectId in ipairs(removables) do
if target:hasStatusEffect(effectId) then
target:delStatusEffectSilent(effectId)
effectsRemoved = effectsRemoved + 1
if effectsRemoved >= lightManeuvers then
break
end
end
end
removeAllManeuvers(master)
master:updateAttachments()
if effectsRemoved > 0 then
skill:setMsg(xi.msg.basic.DISAPPEAR_NUM)
else
skill:setMsg(xi.msg.basic.USES)
end
return effectsRemoved
end)
-----------------------------------
-- Economizer - Changes Economizer to consume all Dark Maneuvers on activation. : https://wiki.ffo.jp/html/10435.html
-----------------------------------
local activationThresholds =
{
[0] = 30,
[1] = 40,
[2] = 50,
[3] = 60,
}
m:addOverride('xi.actions.abilities.pets.automaton.economizer.onEquip', function(pet)
pet:addListener('AUTOMATON_ATTACHMENT_CHECK', 'ATTACHMENT_ECONOMIZER', function(automaton, target)
-- If Economizer is still on cooldown, do nothing.
if automaton:hasRecast(xi.recast.ABILITY, xi.mobSkill.ECONOMIZER_AUTOMATON) then
return
end
local master = automaton:getMaster()
if not master then
return
end
local darkManeuvers = master:countEffect(xi.effect.DARK_MANEUVER)
if darkManeuvers == 0 then
return
end
local maxMP = automaton:getMaxMP()
-- If this automaton has no MP, do nothing.
if maxMP == 0 then
return
end
local mpPercent = automaton:getMPP()
local mpThreshold = activationThresholds[darkManeuvers] or 30
-- If the automaton's MP is above the threshold, do nothing.
if mpPercent > mpThreshold then
return
end
automaton:useMobAbility(xi.mobSkill.ECONOMIZER_AUTOMATON, automaton)
end)
end)
m:addOverride('xi.actions.abilities.pets.automaton.economizer.onAutomatonAbility', function(target, automaton, skill, master, action)
automaton:addRecast(xi.recast.ABILITY, skill:getID(), 180)
local darkManeuvers = master:countEffect(xi.effect.DARK_MANEUVER)
local mpRecovered = math.floor(automaton:getMaxMP() * 0.2 * darkManeuvers)
for _ = 1, darkManeuvers do
master:delStatusEffectSilent(xi.effect.DARK_MANEUVER)
end
master:updateAttachments()
skill:setMsg(xi.msg.basic.SKILL_RECOVERS_MP)
return automaton:addMP(mpRecovered)
end)
return m

View file

@ -1,37 +0,0 @@
-----------------------------------
-- Reverts Hastega to no longer have a duration based on summoning magic and reduces haste power
-- Source: https://www.bg-wiki.com/ffxi/Version_Update_(04/08/2009)
-----------------------------------
require('modules/module_utils')
-----------------------------------
local moduleName = 'hastega'
if xi.module.isContentEnabled('WOTG') then
return { name = moduleName }
end
local m = Module:new(moduleName)
m:addOverride('xi.actions.abilities.pets.hastega.onPetAbility', function(target, pet, petskill, summoner, action)
local duration = 180
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
-- Reverts Garuda's Hastega to use 102/1024 or 9.96%
local typeEffect = xi.effect.HASTE
if target:addStatusEffect(typeEffect, { power = 996, duration = duration, origin = pet }) then
if target:getID() == action:getPrimaryTargetID() then
petskill:setMsg(xi.msg.basic.SKILL_GAIN_EFFECT_2)
else
petskill:setMsg(xi.msg.basic.JA_GAIN_EFFECT)
end
else
petskill:setMsg(xi.msg.basic.JA_NO_EFFECT_2)
return
end
return typeEffect
end)
return m

View file

@ -1,838 +0,0 @@
-----------------------------------
-- Date : 2016 November 10th Patch
-- Notes: https://wiki.ffo.jp/html/35795.html
-- Multihit skills' fTPs were lowered but the first hit fTP carried over into subsequent hits.
-- In 75 era, the subsequent hits had a 1.0 multiplier.
-- Old fTPs might be lost to time unless there new data is uncovered through online documentation or client data.
-----------------------------------
require('modules/module_utils')
-----------------------------------
local moduleName = 'rov_avatar_bloodpacts'
if xi.module.isContentEnabled('ROV') then
return { name = moduleName }
end
local m = Module:new(moduleName)
-----------------------------------
-- Axe Kick
-----------------------------------
m:addOverride('xi.actions.abilities.pets.axe_kick.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 2.00, 2.00, 2.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.str_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.attackMultiplier = { 2.0, 2.0, 2.0 }
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Barracuda Dive
-----------------------------------
m:addOverride('xi.actions.abilities.pets.barracuda_dive.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 2.00, 2.00, 2.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.str_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.SLASHING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.attackMultiplier = { 2.0, 2.0, 2.0 }
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Blindside
-----------------------------------
m:addOverride('xi.actions.abilities.pets.blindside.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 2.00, 2.00, 2.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
-- params.str_wSC = 0.20 -- TODO: Capture wSCs
-- params.mnd_wSC = 0.20
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Burning Strike
-----------------------------------
m:addOverride('xi.actions.abilities.pets.burning_strike.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 2.75, 2.75, 2.75 }
params.fTPSubsequentHits = { 2.75, 2.75, 2.75 }
params.str_wSC = 0.20
params.int_wSC = 0.20
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.hybridSkill = true
params.hybridSkillElement = xi.element.FIRE
params.hybridAttackType = xi.attackType.MAGICAL
params.hybridDamageType = xi.damageType.FIRE
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
local totalDamage = 0
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
if info.damage > 0 then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
totalDamage = totalDamage + info.damage
end
if info.hybridDamage > 0 and target:getHP() > 0 then
target:takeDamage(info.hybridDamage, pet, info.hybridAttackType, info.hybridDamageType)
totalDamage = totalDamage + info.hybridDamage
end
end
return totalDamage
end)
-----------------------------------
-- Camisado
-----------------------------------
m:addOverride('xi.actions.abilities.pets.camisado.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 2.0, 2.0, 2.0 }
params.fTPSubsequentHits = { 2.0, 2.0, 2.0 }
params.str_wSC = 0.20
params.mnd_wSC = 0.20
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.attackMultiplier = { 2.0, 2.0, 2.0 }
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
-- TODO: Knockback may not yet be hooked up to abilities.
-- action:knockback(target:getID(), xi.action.knockback.LEVEL3)
-- TODO: Some equipment that reduces movement speed can reduce knockback distance. (Example: Plumb Boots)
-- https://discord.com/channels/392903136336936960/883227978002206751/1280243231635804262
-- https://discord.com/channels/443544205206355968/443893540922064896/1376405495845355661
end
return info.damage
end)
-----------------------------------
-- Chaotic Strike
-----------------------------------
m:addOverride('xi.actions.abilities.pets.chaotic_strike.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 3
params.fTP = { 10.00, 10.00, 10.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.str_wSC = 0.20
params.int_wSC = 0.20
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_3
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
local effectTable =
{
[1] = { effectId = xi.effect.STUN, power = 1, duration = 12, origin = pet },
}
xi.combat.action.executeMobskillStatusEffect(pet, target, petskill, effectTable, { messageBypass = true })
end
return info.damage
end)
-----------------------------------
-- Claw
-----------------------------------
m:addOverride('xi.actions.abilities.pets.claw.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 2.00, 2.00, 2.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.dex_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.PIERCING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.attackMultiplier = { 2.0, 2.0, 2.0 }
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Crag Throw
-----------------------------------
-- TODO: Not currently coded at time of this comment. Does not gain an accuracy bonus based on fTP.
-----------------------------------
-- Crescent Fang
-----------------------------------
m:addOverride('xi.actions.abilities.pets.crescent_fang.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 1.50, 1.50, 1.50 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.str_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.PIERCING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.attackMultiplier = { 2.0, 2.0, 2.0 }
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
local effectTable =
{
[1] = { effectId = xi.effect.PARALYSIS, power = 22, duration = 60, origin = pet }, -- TODO: Capture power
}
xi.combat.action.executeMobskillStatusEffect(pet, target, petskill, effectTable, { messageBypass = true })
end
return info.damage
end)
-----------------------------------
-- Double Punch
-----------------------------------
m:addOverride('xi.actions.abilities.pets.double_punch.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 2
params.fTP = { 5.00, 5.00, 5.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.str_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_2
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Double Slap
-----------------------------------
m:addOverride('xi.actions.abilities.pets.double_slap.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 2
params.fTP = { 6.328125, 6.328125, 6.328125 }
params.fTPSubsequentHits = { 1.000000, 1.000000, 1.000000 }
params.str_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_2
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Eclipse Bite
-----------------------------------
m:addOverride('xi.actions.abilities.pets.eclipse_bite.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 3
params.fTP = { 3.269531, 3.269531, 3.269531 }
params.fTPSubsequentHits = { 1.000000, 1.000000, 1.000000 }
params.dex_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.SLASHING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_3
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Flaming Crush
-----------------------------------
m:addOverride('xi.actions.abilities.pets.flaming_crush.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 2
params.fTP = { 6.00, 6.00, 6.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.str_wSC = 0.20
params.int_wSC = 0.20
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.hybridSkill = true
params.hybridSkillElement = xi.element.FIRE
params.hybridAttackType = xi.attackType.MAGICAL
params.hybridDamageType = xi.damageType.FIRE
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_2
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
local totalDamage = 0
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
if info.damage > 0 then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
totalDamage = totalDamage + info.damage
end
if info.hybridDamage > 0 and target:getHP() > 0 then
target:takeDamage(info.hybridDamage, pet, info.hybridAttackType, info.hybridDamageType)
totalDamage = totalDamage + info.hybridDamage
end
end
return totalDamage
end)
-----------------------------------
-- Megalith Throw
-----------------------------------
m:addOverride('xi.actions.abilities.pets.megalith_throw.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getRangedDmg()
params.numHits = 1
params.fTP = { 2.375, 2.375, 2.375 }
params.fTPSubsequentHits = { 1.000, 1.000, 1.000 }
params.str_wSC = 0.20
params.agi_wSC = 0.20
params.skipParry = true
params.skipGuard = true
params.skipBlock = true
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.SLASHING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobRangedMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
local effectTable =
{
[1] = { effectId = xi.effect.SLOW, power = 3000, duration = 120, tier = 8, origin = pet }, -- TODO: Capture Slow tier
}
xi.combat.action.executeMobskillStatusEffect(pet, target, petskill, effectTable, { messageBypass = true })
end
return info.damage
end)
-----------------------------------
-- Moonlit Charge
-----------------------------------
m:addOverride('xi.actions.abilities.pets.moonlit_charge.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 1.00, 1.00, 1.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.vit_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.attackMultiplier = { 2.0, 2.0, 2.0 }
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
local effectTable =
{
[1] = { effectId = xi.effect.BLINDNESS, power = 25, duration = 60, origin = pet },
}
xi.combat.action.executeMobskillStatusEffect(pet, target, petskill, effectTable, { messageBypass = true })
end
return info.damage
end)
-----------------------------------
-- Mountain Buster
-----------------------------------
m:addOverride('xi.actions.abilities.pets.mountain_buster.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 7.25, 7.25, 7.25 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.vit_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.attackMultiplier = { 2.0, 2.0, 2.0 }
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobRangedMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Poison Nails
-----------------------------------
m:addOverride('xi.actions.abilities.pets.poison_nails.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 2.00, 2.00, 2.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.dex_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.PIERCING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.attackMultiplier = { 2.0, 2.0, 2.0 }
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
local effectTable =
{
[1] = { effectId = xi.effect.POISON, power = 1, tick = 3, duration = 90, tier = 1, origin = pet },
}
xi.combat.action.executeMobskillStatusEffect(pet, target, petskill, effectTable, { messageBypass = true })
end
return info.damage
end)
-----------------------------------
-- Predator Claws
-----------------------------------
m:addOverride('xi.actions.abilities.pets.predator_claws.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 3
params.fTP = { 10.00, 10.00, 10.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.dex_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.SLASHING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_3
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Punch
-----------------------------------
m:addOverride('xi.actions.abilities.pets.punch.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 2.00, 2.00, 2.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.str_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.attackMultiplier = { 2.0, 2.0, 2.0 }
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Regal Gash
-----------------------------------
-- TODO: Not coded at time of this comment. Loses accuracy ftp scaling.
-----------------------------------
-- Regal Scratch
-----------------------------------
m:addOverride('xi.actions.abilities.pets.regal_scratch.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
-- https://wiki.ffo.jp/html/26384.html
-- JP Wiki states that this skill was excluded from carrying first hit fTP to subsequent hits.
-- (See Patch note history for November 10th, 2016 in above link.)
params.baseDamage = pet:getWeaponDmg()
params.numHits = 3
params.fTP = { 3.00, 3.00, 3.00 } -- TODO: Capture fTPs
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
-- params.dex_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.SLASHING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_3
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Rock Buster
-----------------------------------
m:addOverride('xi.actions.abilities.pets.rock_buster.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 2.25, 2.25, 2.25 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.vit_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.attackMultiplier = { 2.0, 2.0, 2.0 }
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
local effectTable =
{
[1] = { effectId = xi.effect.BIND, power = 1, duration = 120, origin = pet }, -- TODO: Capture duration
}
xi.combat.action.executeMobskillStatusEffect(pet, target, petskill, effectTable, { messageBypass = true })
end
return info.damage
end)
-----------------------------------
-- Rock Throw
-----------------------------------
m:addOverride('xi.actions.abilities.pets.rock_throw.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getRangedDmg()
params.numHits = 1
params.fTP = { 1.00, 1.00, 1.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.str_wSC = 0.20
params.agi_wSC = 0.20
params.skipParry = true
params.skipGuard = true
params.skipBlock = true
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.SLASHING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobRangedMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
local effectTable =
{
[1] = { effectId = xi.effect.SLOW, power = 3000, duration = 120, tier = 8, origin = pet }, -- TODO: Capture Slow tier
}
xi.combat.action.executeMobskillStatusEffect(pet, target, petskill, effectTable, { messageBypass = true })
end
return info.damage
end)
-----------------------------------
-- Rush
-----------------------------------
m:addOverride('xi.actions.abilities.pets.rush.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 5
params.fTP = { 3.50, 3.50, 3.50 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.str_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_5
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Shock Strike
-----------------------------------
m:addOverride('xi.actions.abilities.pets.shock_strike.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 2.00, 2.00, 2.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.str_wSC = 0.20
params.int_wSC = 0.20
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.attackMultiplier = { 2.0, 2.0, 2.0 }
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
local effectTable =
{
[1] = { effectId = xi.effect.STUN, power = 1, duration = 12, origin = pet },
}
xi.combat.action.executeMobskillStatusEffect(pet, target, petskill, effectTable, { messageBypass = true })
end
return info.damage
end)
-----------------------------------
-- Spinning Dive
-----------------------------------
m:addOverride('xi.actions.abilities.pets.spinning_dive.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 7.01171, 7.01171, 7.01171 }
params.fTPSubsequentHits = { 1.00000, 1.00000, 1.00000 }
params.str_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.SLASHING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.attackMultiplier = { 2.0, 2.0, 2.0 }
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Tail Whip
-----------------------------------
m:addOverride('xi.actions.abilities.pets.tail_whip.onPetAbility', function(target, pet, petskill, summoner, action)
xi.job_utils.summoner.onUseBloodPact(target, petskill, summoner, action)
local params = {}
params.baseDamage = pet:getWeaponDmg()
params.numHits = 1
params.fTP = { 3.00, 3.00, 3.00 }
params.fTPSubsequentHits = { 1.00, 1.00, 1.00 }
params.str_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.attackMultiplier = { 2.0, 2.0, 2.0 }
params.primaryMessage = xi.msg.basic.USES_JA_TAKE_DAMAGE
local info = xi.mobskills.mobPhysicalMove(pet, target, petskill, action, params)
if xi.mobskills.processDamage(pet, target, petskill, action, info) then
target:takeDamage(info.damage, pet, info.attackType, info.damageType)
local effectTable =
{
[1] = { effectId = xi.effect.WEIGHT, power = 50, duration = 120, tier = 1, origin = pet }, -- TODO: Capture power/duration/tier
}
xi.combat.action.executeMobskillStatusEffect(pet, target, petskill, effectTable, { messageBypass = true })
end
return info.damage
end)
-----------------------------------
-- Volt Strike
-----------------------------------
-- TODO: Volt Strike is not currently coded at time of this comment but should be set to 1.0 for fTPSubsequentHits. Loses Crit Scaling.
return m

View file

@ -1,204 +0,0 @@
-----------------------------------
-- Module: Spell Adjustments (Rhapsodies of Vana'diel Era)
-- Desc: Reverts spell changes introduced during the RoV era
-----------------------------------
require('modules/module_utils')
-----------------------------------
local moduleName = 'rov_spell_adjustments'
if xi.module.isContentEnabled('ROV') then
return { name = moduleName }
end
local m = Module:new(moduleName)
-----------------------------------
-- Enfeebling Magic
-----------------------------------
-- Dia family: Revert defense down values.
-- Source: https://forum.square-enix.com/ffxi/threads/55263-April.-3-2019-%28JST%29-Version-Update
local function castEraDia(caster, target, spell, tier, dotPower, duration, defenseDown)
local damage = xi.spells.damage.useDamageSpell(caster, target, spell)
-- Check for Bio.
local bio = target:getStatusEffect(xi.effect.BIO)
if
not bio or
(bio and bio:getTier() < tier)
then
target:delStatusEffect(xi.effect.BIO)
local power = dotPower + caster:getMod(xi.mod.DIA_DOT)
target:addStatusEffect(xi.effect.DIA, { power = power, duration = duration, origin = caster, tick = 3, subPower = defenseDown, tier = tier })
end
return damage
end
m:addOverride('xi.actions.spells.white.dia.onSpellCast', function(caster, target, spell)
return castEraDia(caster, target, spell, 1, 1, 60, 5)
end)
m:addOverride('xi.actions.spells.white.dia_ii.onSpellCast', function(caster, target, spell)
return castEraDia(caster, target, spell, 3, 2, 120, 10)
end)
m:addOverride('xi.actions.spells.white.dia_iii.onSpellCast', function(caster, target, spell)
return castEraDia(caster, target, spell, 5, 3, 180, 15)
end)
m:addOverride('xi.actions.spells.white.diaga.onSpellCast', function(caster, target, spell)
return castEraDia(caster, target, spell, 1, 1, 60, 5)
end)
-- TODO: Blind II / Blind
-- Source: https://forum.square-enix.com/ffxi/threads/46531-Mar-26-2015-%28JST%29-Version-Update
-- - Remove fixed 180 duration, revert to between 80 and 300 seconds
-- - Potency: Blind: (User INT - Opponent MND + 60)/4 Blind II: (User INT - Opponent MND + 100)/4
-- TODO: Paralyze / Paralyze II
-- - Remove fixed 120 duration, revert to between 30 and 120 seconds
-- TODO: Poison / Poison II / Poisonga
-- - Revert potencies to pre-RoV values
-----------------------------------
-- Dark Magic
-----------------------------------
-- Bio family: Revert attack down values.
-- Source: https://forum.square-enix.com/ffxi/threads/55263-April.-3-2019-%28JST%29-Version-Update
local function calculateBioPower(caster, tier)
local skillLevel = caster:getSkillLevel(xi.skill.DARK_MAGIC)
if tier == 2 then
return utils.clamp(math.ceil(skillLevel / 40), 1, 3)
elseif tier == 4 then
return utils.clamp(math.floor((skillLevel + 29) / 40), 3, 8)
end
local power = 0
if skillLevel > 291 then
power = 13 + math.floor((skillLevel - 291) / 27) -- 13 + 1 every 27 skill levels.
elseif skillLevel > 246 then
power = 9 + math.floor((skillLevel - 246) / 11) -- 9 + 1 every 11 skill levels.
else
power = 5 + math.floor((skillLevel - 106) / 35) -- 5 + 1 every 35 skill levels.
end
return utils.clamp(power, 5, 17)
end
local function castEraBio(caster, target, spell, tier, duration, attackDown)
local damage = xi.spells.damage.useDamageSpell(caster, target, spell)
-- Check for Dia.
local dia = target:getStatusEffect(xi.effect.DIA)
if
not dia or
(dia and dia:getTier() < tier)
then
target:delStatusEffect(xi.effect.DIA)
local power = calculateBioPower(caster, tier)
target:addStatusEffect(xi.effect.BIO, { power = power, duration = duration, origin = caster, tick = 3, subPower = attackDown, tier = tier })
end
return damage
end
m:addOverride('xi.actions.spells.black.bio.onSpellCast', function(caster, target, spell)
return castEraBio(caster, target, spell, 2, 60, 5)
end)
m:addOverride('xi.actions.spells.black.bio_ii.onSpellCast', function(caster, target, spell)
return castEraBio(caster, target, spell, 4, 120, 10)
end)
m:addOverride('xi.actions.spells.black.bio_iii.onSpellCast', function(caster, target, spell)
return castEraBio(caster, target, spell, 6, 180, 15)
end)
-- Dread Spikes: Revert duration from 3 minutes to 1 minute.
-- Source: https://forum.square-enix.com/ffxi/threads/48564-Sep-16-2015-%28JST%29-Version-Update
m:addOverride('xi.effects.dread_spikes.onEffectGain', function(target, effect)
super(target, effect)
effect:setDuration(60000)
end)
-- TODO Absorb-STAT: Add decay tick and set 90 second duration to boost effects
-- TODO Drain II: Set duration of max HP boost to 60 seconds.
-- Source:
-- Decay Removal: http://forum.square-enix.com/ffxi/threads/46531-Mar-26-2015-%28JST%29-Version-Update
-- Duration Change: https://forum.square-enix.com/ffxi/threads/48564-Sep-16-2015-%28JST%29-Version-Update
-----------------------------------
-- Singing
-----------------------------------
-- TODO (pending exposure of pTables in magic scripts):
-- Update scripts/globals/spells/enhancing_song.lua pTable entries:
-- Source: https://forum.square-enix.com/ffxi/threads/55899-September.-10-2019-%28JST%29-Version-Update?p=619588&viewfull=1#post619588
-- xi.magic.spell.FOE_SIRVENTE : MERIT_ID 0 -> xi.merit.FOE_SIRVENTE, POWER_BASE 35 -> 0
-- xi.magic.spell.ADVENTURERS_DIRGE : MERIT_ID 0 -> xi.merit.ADVENTURERS_DIRGE, POWER_BASE 32 -> 5
-- POWER_CAP value: current -> target:
-- Source: https://forum.square-enix.com/ffxi/threads/52095-Feb.-10-2017-%28JST%29-Version-Update
-- xi.magic.spell.FIRE_CAROL : POWER_CAP 80 -> 50, MULTIPLIER 8 -> 5
-- xi.magic.spell.ICE_CAROL : POWER_CAP 80 -> 50, MULTIPLIER 8 -> 5
-- xi.magic.spell.WIND_CAROL : POWER_CAP 80 -> 50, MULTIPLIER 8 -> 5
-- xi.magic.spell.EARTH_CAROL : POWER_CAP 80 -> 50, MULTIPLIER 8 -> 5
-- xi.magic.spell.LIGHTNING_CAROL : POWER_CAP 80 -> 50, MULTIPLIER 8 -> 5
-- xi.magic.spell.WATER_CAROL : POWER_CAP 80 -> 50, MULTIPLIER 8 -> 5
-- xi.magic.spell.LIGHT_CAROL : POWER_CAP 80 -> 50, MULTIPLIER 8 -> 5
-- xi.magic.spell.DARK_CAROL : POWER_CAP 80 -> 50, MULTIPLIER 8 -> 5
-- xi.magic.spell.SWORD_MADRIGAL : POWER_CAP 45 -> 15, MULTIPLIER 4.5 -> 2, DIVISOR 18 -> 23.25, SKILL_REQUIREMENT 85 -> 40
-- xi.magic.spell.BLADE_MADRIGAL : POWER_CAP 60 -> 30, MULTIPLIER 6 -> 2
-- xi.magic.spell.SHEEPFOE_MAMBO : POWER_CAP 48 -> 15, MULTIPLIER 5 -> 2.5
-- xi.magic.spell.DRAGONFOE_MAMBO : POWER_CAP 72 -> 23, MULTIPLIER 7 -> 2.5
-- xi.magic.spell.ADVANCING_MARCH : POWER_CAP 108 -> 64, MULTIPLIER 11 -> 16
-- xi.magic.spell.VICTORY_MARCH : POWER_CAP 163 -> 96, POWER_BASE 43 -> 53
-- xi.magic.spell.KNIGHTS_MINNE : POWER_CAP 30 -> 13, MULTIPLIER 3 -> 2.5, DIVISOR 10 -> 15, POWER_BASE 8 -> 5
-- xi.magic.spell.KNIGHTS_MINNE_II : POWER_CAP 69 -> 27, MULTIPLIER 7 -> 2.5, DIVISOR 10 -> 15, POWER_BASE 12 -> 6
-- xi.magic.spell.KNIGHTS_MINNE_III: POWER_CAP 108 -> 40, MULTIPLIER 11 -> 2.5, DIVISOR 10 -> 15, POWER_BASE 18 -> 10
-- xi.magic.spell.KNIGHTS_MINNE_IV : POWER_CAP 164 -> 48, MULTIPLIER 16 -> 2.5, DIVISOR 10 -> 15, POWER_BASE 30 -> 12
-- xi.magic.spell.VALOR_MINUET : POWER_CAP 30 -> 16, MULTIPLIER 3 -> 2.5, DIVISOR 4.3 -> 6
-- xi.magic.spell.VALOR_MINUET_II : POWER_CAP 69 -> 32, MULTIPLIER 6 -> 2.5, DIVISOR 3.9 -> 6, SKILL_REQUIREMENT 100 -> 85
-- xi.magic.spell.VALOR_MINUET_III : POWER_CAP 108 -> 48, MULTIPLIER 9 -> 2.5, DIVISOR 3.5 -> 6
-- xi.magic.spell.VALOR_MINUET_IV : POWER_CAP 164 -> 56, MULTIPLIER 11 -> 2.5, DIVISOR 3.3 -> 15, POWER_BASE 31 -> 29
-- xi.magic.spell.HUNTERS_PRELUDE : POWER_CAP 45 -> 15, MULTIPLIER 4.5 -> 2
-- xi.magic.spell.ARCHERS_PRELUDE : POWER_CAP 60 -> 30, MULTIPLIER 6 -> 2
-----------------------------------
-- Ninjutsu
-----------------------------------
-- San Spells: Add +5 Magic Attack and +5 Magic Accuracy per merit rank
-- Source: https://forum.square-enix.com/ffxi/threads/55525-June.-10-2019-%28JST%29-Version-Update
local sanSpellOverrides =
{
{ path = 'xi.actions.spells.ninjutsu.katon_san.onSpellCast', merit = xi.merit.KATON_SAN },
{ path = 'xi.actions.spells.ninjutsu.hyoton_san.onSpellCast', merit = xi.merit.HYOTON_SAN },
{ path = 'xi.actions.spells.ninjutsu.huton_san.onSpellCast', merit = xi.merit.HUTON_SAN },
{ path = 'xi.actions.spells.ninjutsu.doton_san.onSpellCast', merit = xi.merit.DOTON_SAN },
{ path = 'xi.actions.spells.ninjutsu.raiton_san.onSpellCast', merit = xi.merit.RAITON_SAN },
{ path = 'xi.actions.spells.ninjutsu.suiton_san.onSpellCast', merit = xi.merit.SUITON_SAN },
}
for _, entry in ipairs(sanSpellOverrides) do
m:addOverride(entry.path, function(caster, target, spell)
local meritBonus = caster:getMerit(entry.merit)
caster:addMod(xi.mod.MATT, meritBonus)
caster:addMod(xi.mod.MACC, meritBonus)
local damage = super(caster, target, spell)
caster:delMod(xi.mod.MATT, meritBonus)
caster:delMod(xi.mod.MACC, meritBonus)
return damage
end)
end
return m

View file

@ -1,305 +0,0 @@
-----------------------------------
-- WoTG Era Automaton Weaponskills
-----------------------------------
require('modules/module_utils')
-----------------------------------
local moduleName = 'wotg_automaton'
local m = Module:new(moduleName)
if xi.module.isContentEnabled('ABYSSEA') then
return { name = moduleName }
end
-----------------------------------
-- Arcuballista
-----------------------------------
m:addOverride('xi.actions.abilities.pets.automaton.arcuballista.onAutomatonAbility', function(target, automaton, skill, master, action)
local params = {}
params.baseDamage = xi.automaton.getRangedBaseDamage(automaton)
params.numHits = 1
params.fTP = { 2.5, 3.0, 4.0 }
params.dex_wSC = 0.30
params.accuracyModifier = { 100, 100, 100 }
params.attackType = xi.attackType.RANGED
params.damageType = xi.damageType.PIERCING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.skipParry = true
params.skipGuard = true
params.skipBlock = true
xi.automaton.applyFlameHolder(automaton, params.fTP)
local info = xi.mobskills.mobRangedMove(automaton, target, skill, action, params)
if xi.mobskills.processDamage(automaton, target, skill, action, info) then
target:takeDamage(info.damage, automaton, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Armor Piercer
-----------------------------------
m:addOverride('xi.actions.abilities.pets.automaton.armor_piercer.onAutomatonAbility', function(target, automaton, skill, master, action)
local params = {}
params.baseDamage = xi.automaton.getRangedBaseDamage(automaton)
params.numHits = 1
params.fTP = { 3.0, 3.5, 4.0 }
params.dex_wSC = 0.30
params.ignoreDefense = { 0.5, 0.5, 0.5 }
params.accuracyModifier = { 100, 100, 100 }
params.attackType = xi.attackType.RANGED
params.damageType = xi.damageType.PIERCING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.skipParry = true
params.skipGuard = true
params.skipBlock = true
xi.automaton.applyFlameHolder(automaton, params.fTP)
local info = xi.mobskills.mobRangedMove(automaton, target, skill, action, params)
if xi.mobskills.processDamage(automaton, target, skill, action, info) then
target:takeDamage(info.damage, automaton, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Bone Crusher
-----------------------------------
m:addOverride('xi.actions.abilities.pets.automaton.bone_crusher.onAutomatonAbility', function(target, automaton, skill, master, action)
local params = {}
params.baseDamage = automaton:getWeaponDmg()
params.numHits = utils.clamp(3 + xi.automaton.getExtraHits(automaton, 3), 1, 8)
params.fTP = { 1.5, 1.5, 1.5 }
params.vit_wSC = 0.30
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = params.numHits
if target:isUndead() then
params.fTP = { 2.5, 2.5, 2.5 }
end
xi.automaton.applyFlameHolder(automaton, params.fTP)
local info = xi.mobskills.mobPhysicalMove(automaton, target, skill, action, params)
if xi.mobskills.processDamage(automaton, target, skill, action, info) then
target:takeDamage(info.damage, automaton, info.attackType, info.damageType)
xi.mobskills.mobStatusEffectMove(automaton, target, xi.effect.STUN, 1, 0, 4)
end
return info.damage
end)
-----------------------------------
-- Cannibal Blade
-----------------------------------
m:addOverride('xi.actions.abilities.pets.automaton.cannibal_blade.onAutomatonAbility', function(target, automaton, skill, master, action)
local params = {}
params.baseDamage = automaton:getSkillLevel(xi.skill.AUTOMATON_MELEE) / 9.2
params.numHits = 1
params.fTP = { 11.0, 12.5, 14.0 }
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.SLASHING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.guaranteedFirstHit = true
params.skipFSTR = true
params.skipPDIF = true
xi.automaton.applyFlameHolder(automaton, params.fTP)
local info = xi.mobskills.mobPhysicalMove(automaton, target, skill, action, params)
if xi.mobskills.processDamage(automaton, target, skill, action, info) then
target:takeDamage(info.damage, automaton, info.attackType, info.damageType)
if not target:isUndead() then
automaton:addHP(info.damage)
end
end
-- Does not return TP.
automaton:setTP(0)
return info.damage
end)
-----------------------------------
-- Chimera Ripper
-----------------------------------
m:addOverride('xi.actions.abilities.pets.automaton.chimera_ripper.onAutomatonAbility', function(target, automaton, skill, master, action)
local params = {}
params.baseDamage = automaton:getWeaponDmg()
params.numHits = utils.clamp(1 + xi.automaton.getExtraHits(automaton, 1), 1, 8)
params.fTP = { 2.0, 2.5, 3.0 }
params.str_wSC = 0.30
params.accuracyModifier = { 100, 100, 100 }
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.SLASHING
params.shadowBehavior = params.numHits
xi.automaton.applyFlameHolder(automaton, params.fTP)
local info = xi.mobskills.mobPhysicalMove(automaton, target, skill, action, params)
if xi.mobskills.processDamage(automaton, target, skill, action, info) then
target:takeDamage(info.damage, automaton, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Daze
-----------------------------------
m:addOverride('xi.actions.abilities.pets.automaton.daze.onAutomatonAbility', function(target, automaton, skill, master, action)
local params = {}
params.baseDamage = xi.automaton.getRangedBaseDamage(automaton)
params.numHits = 1
params.fTP = { 5.0, 5.5, 6.0 }
params.dex_wSC = 0.30
params.accuracyModifier = { 150, 150, 150 }
params.attackType = xi.attackType.RANGED
params.damageType = xi.damageType.PIERCING
params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1
params.skipParry = true
params.skipGuard = true
params.skipBlock = true
xi.automaton.applyFlameHolder(automaton, params.fTP)
local info = xi.mobskills.mobRangedMove(automaton, target, skill, action, params)
if xi.mobskills.processDamage(automaton, target, skill, action, info) then
target:takeDamage(info.damage, automaton, info.attackType, info.damageType)
xi.mobskills.mobStatusEffectMove(automaton, target, xi.effect.STUN, 1, 0, 4)
end
return info.damage
end)
-----------------------------------
-- Knockout
-----------------------------------
m:addOverride('xi.actions.abilities.pets.automaton.knockout.onAutomatonAbility', function(target, automaton, skill, master, action)
local params = {}
params.numHits = utils.clamp(1 + xi.automaton.getExtraHits(automaton, 1), 1, 8)
params.fTP = { 4.0, 4.5, 5.0 }
params.agi_wSC = 0.40
params.accuracyModifier = { 50, 50, 50 }
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = params.numHits
xi.automaton.applyFlameHolder(automaton, params.fTP)
local info = xi.mobskills.mobPhysicalMove(automaton, target, skill, action, params)
if xi.mobskills.processDamage(automaton, target, skill, action, info) then
target:takeDamage(info.damage, automaton, info.attackType, info.damageType)
xi.mobskills.mobStatusEffectMove(automaton, target, xi.effect.EVASION_DOWN, 20, 0, 30)
end
return info.damage
end)
-----------------------------------
-- Magic Mortar
-----------------------------------
m:addOverride('xi.actions.abilities.pets.automaton.magic_mortar.onAutomatonAbility', function(target, automaton, skill, master, action)
local params = {}
params.baseDamage = automaton:getMaxHP() - automaton:getHP()
params.fTP = { 0.50, 0.75, 1.00 }
params.element = xi.element.NONE
params.attackType = xi.attackType.MAGICAL
params.damageType = xi.damageType.ELEMENTAL
params.shadowBehavior = xi.mobskills.shadowBehavior.IGNORE_SHADOWS
-- Flame Holder multiplies the base damage of Magic Mortar. Gives a 25% boost at 3 Fire Maneuvers.
local flameHolderModifier = 1.0 + (automaton:getMod(xi.mod.WEAPONSKILL_DAMAGE_BASE) - 100) / 1000
if flameHolderModifier > 1.0 then
params.baseDamage = math.floor(params.baseDamage * flameHolderModifier)
end
local info = xi.mobskills.mobMagicalMove(automaton, target, skill, action, params)
if xi.mobskills.processDamage(automaton, target, skill, action, info) then
target:takeDamage(info.damage, automaton, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- Slapstick
-----------------------------------
m:addOverride('xi.actions.abilities.pets.automaton.slapstick.onAutomatonAbility', function(target, automaton, skill, master, action)
local params = {}
params.numHits = utils.clamp(3 + xi.automaton.getExtraHits(automaton, 3), 1, 8)
params.fTP = { 1.0, 1.0, 1.0 }
params.str_wSC = 0.20
params.dex_wSC = 0.20
params.accuracyModifier = { 0, 30, 50 }
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.BLUNT
params.shadowBehavior = params.numHits
xi.automaton.applyFlameHolder(automaton, params.fTP)
local info = xi.mobskills.mobPhysicalMove(automaton, target, skill, action, params)
if xi.mobskills.processDamage(automaton, target, skill, action, info) then
target:takeDamage(info.damage, automaton, info.attackType, info.damageType)
end
return info.damage
end)
-----------------------------------
-- String Clipper
-----------------------------------
m:addOverride('xi.actions.abilities.pets.automaton.string_clipper.onAutomatonAbility', function(target, automaton, skill, master, action)
local params = {}
params.baseDamage = automaton:getWeaponDmg()
params.numHits = utils.clamp(2 + xi.automaton.getExtraHits(automaton, 2), 1, 8)
params.fTP = { 2.0, 2.0, 2.0 }
params.str_wSC = 0.15
params.dex_wSC = 0.15
params.attackMultiplier = { 1.5, 1.5, 1.5 }
params.accuracyModifier = { 0, 50, 100 }
params.attackType = xi.attackType.PHYSICAL
params.damageType = xi.damageType.SLASHING
params.shadowBehavior = params.numHits
xi.automaton.applyFlameHolder(automaton, params.fTP)
local info = xi.mobskills.mobPhysicalMove(automaton, target, skill, action, params)
if xi.mobskills.processDamage(automaton, target, skill, action, info) then
target:takeDamage(info.damage, automaton, info.attackType, info.damageType)
end
return info.damage
end)
return m

View file

@ -1,24 +0,0 @@
-----------------------------------
-- Pre-SoA Magic Burst Module
-- Restores the pre-2015 magic burst multiplier: 1.25 + 0.05 per skillchain step.
-- https://forum.square-enix.com/ffxi/threads/46531
-----------------------------------
require('modules/module_utils')
-----------------------------------
local moduleName = 'era_magic_burst'
if xi.module.isContentEnabled('SOA') then
return { name = moduleName }
end
local m = Module:new(moduleName)
m:addOverride('xi.spells.damage.calculateIfMagicBurst', function(caster, target, spellElement, magicBurstTier)
if spellElement <= xi.element.NONE then
return 1
end
return 1.25 + 0.05 * utils.clamp(magicBurstTier, 1, 5)
end)
return m

Some files were not shown because too many files have changed in this diff Show more