Compare commits
10 Commits
6219d00c06
...
d7701b5b98
| Author | SHA1 | Date | |
|---|---|---|---|
| d7701b5b98 | |||
| e1ccf30afc | |||
| 80a4a589f6 | |||
| 0bc9b016d6 | |||
| 3a4c6c01dd | |||
| b0b876b76b | |||
| fa7a543b94 | |||
| 5408eae697 | |||
| 995122dc78 | |||
| 0ac509e421 |
@@ -0,0 +1,8 @@
|
||||
.git
|
||||
.github
|
||||
build
|
||||
data
|
||||
docker/db-dumps
|
||||
*.log
|
||||
*.pid
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
DB_ROOT_PASSWORD=change-me
|
||||
DB_USER=sylvania
|
||||
DB_PASSWORD=sylvania
|
||||
EXTERNAL_ADDRESS=127.0.0.1
|
||||
REALM_NAME=Sylvania Solo
|
||||
REALM_ADDRESS=127.0.0.1
|
||||
REALM_PORT=8086
|
||||
BUILD_JOBS=2
|
||||
BUILD_TYPE=Release
|
||||
IMAGE_TAG=local
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copy to .env.production and replace both passwords before deployment.
|
||||
DB_ROOT_PASSWORD=GENERATE_A_LONG_RANDOM_ROOT_PASSWORD
|
||||
DB_USER=sylvania
|
||||
DB_PASSWORD=GENERATE_A_DIFFERENT_LONG_RANDOM_DB_PASSWORD
|
||||
|
||||
REALM_NAME=FelWell
|
||||
REALM_ADDRESS=legion.moon-well.online
|
||||
REALM_PORT=8085
|
||||
EXTERNAL_ADDRESS=legion.moon-well.online
|
||||
|
||||
BUILD_JOBS=8
|
||||
BUILD_TYPE=Release
|
||||
IMAGE_TAG=production
|
||||
@@ -9,6 +9,12 @@ build*/
|
||||
*.kdev*
|
||||
.DS_Store
|
||||
CMakeLists.txt.user
|
||||
.env
|
||||
.env.production
|
||||
/data/
|
||||
/docker/db-dumps/*.rar
|
||||
/docker/db-dumps/*.sql
|
||||
/docker/db-dumps/*.sql.gz
|
||||
*.bak
|
||||
*.patch
|
||||
*.diff
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
FROM ubuntu:24.04 AS builder
|
||||
|
||||
ARG BUILD_TYPE=Release
|
||||
ARG BUILD_JOBS=2
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
|
||||
apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
cmake \
|
||||
git \
|
||||
libboost-filesystem-dev \
|
||||
libboost-iostreams-dev \
|
||||
libboost-locale-dev \
|
||||
libboost-program-options-dev \
|
||||
libboost-regex-dev \
|
||||
libboost-system-dev \
|
||||
libboost-thread-dev \
|
||||
libbz2-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libmariadb-dev \
|
||||
libmariadb-dev-compat \
|
||||
libncurses-dev \
|
||||
libreadline-dev \
|
||||
libssl-dev \
|
||||
zlib1g-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /src
|
||||
COPY . .
|
||||
|
||||
RUN cmake -S . -B /build \
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
|
||||
-DCMAKE_INSTALL_PREFIX=/opt/sylvania \
|
||||
-DTOOLS=OFF \
|
||||
&& cmake --build /build --parallel "${BUILD_JOBS}" \
|
||||
&& cmake --install /build
|
||||
|
||||
FROM ubuntu:24.04 AS runtime
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
|
||||
apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
libboost-filesystem1.83.0 \
|
||||
libboost-iostreams1.83.0 \
|
||||
libboost-locale1.83.0 \
|
||||
libboost-program-options1.83.0 \
|
||||
libboost-regex1.83.0 \
|
||||
libboost-system1.83.0 \
|
||||
libboost-thread1.83.0 \
|
||||
libbz2-1.0 \
|
||||
libcurl4t64 \
|
||||
libmariadb3 \
|
||||
libncurses6 \
|
||||
libreadline8t64 \
|
||||
libssl3t64 \
|
||||
mariadb-client \
|
||||
zlib1g \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& useradd --system --uid 10001 --home /opt/sylvania --shell /usr/sbin/nologin sylvania
|
||||
|
||||
COPY --from=builder /opt/sylvania /opt/sylvania
|
||||
COPY docker/entrypoint.sh /usr/local/bin/sylvania-entrypoint
|
||||
|
||||
RUN chmod +x /usr/local/bin/sylvania-entrypoint \
|
||||
&& mkdir -p /opt/sylvania/data /opt/sylvania/logs \
|
||||
&& chown -R sylvania:sylvania /opt/sylvania
|
||||
|
||||
USER sylvania
|
||||
WORKDIR /opt/sylvania
|
||||
|
||||
EXPOSE 1119 8081 8085
|
||||
ENTRYPOINT ["sylvania-entrypoint"]
|
||||
CMD ["worldserver"]
|
||||
@@ -0,0 +1,58 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
FROM ubuntu:24.04 AS builder
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
|
||||
apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
cmake \
|
||||
git \
|
||||
libboost-filesystem-dev \
|
||||
libboost-iostreams-dev \
|
||||
libboost-locale-dev \
|
||||
libboost-program-options-dev \
|
||||
libboost-regex-dev \
|
||||
libboost-system-dev \
|
||||
libboost-thread-dev \
|
||||
libbz2-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libmariadb-dev \
|
||||
libmariadb-dev-compat \
|
||||
libncurses-dev \
|
||||
libreadline-dev \
|
||||
libssl-dev \
|
||||
zlib1g-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /src
|
||||
COPY . .
|
||||
|
||||
RUN cmake -S . -B /build \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=/opt/sylvania \
|
||||
-DSERVERS=OFF \
|
||||
-DTOOLS=ON \
|
||||
&& cmake --build /build --parallel 2 \
|
||||
&& cmake --install /build
|
||||
|
||||
FROM ubuntu:24.04
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
libboost-filesystem1.83.0 \
|
||||
libboost-iostreams1.83.0 \
|
||||
libboost-program-options1.83.0 \
|
||||
libboost-regex1.83.0 \
|
||||
libboost-system1.83.0 \
|
||||
libbz2-1.0 \
|
||||
libssl3t64 \
|
||||
zlib1g \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=builder /opt/sylvania/bin /opt/sylvania/bin
|
||||
WORKDIR /client
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
**Le core C++ du royaume [La Légion de Sylvania](https://legendesylvania.com)**
|
||||
Émulateur de serveur *World of Warcraft®* — Legion 7.3.5
|
||||
|
||||
[](https://github.com/BlaMacfly/SylvaniaCore/wiki)
|
||||
[](https://discord.gg/qmQBXbuXkx)
|
||||
[](./LICENSE)
|
||||
[](https://github.com/BlaMacfly/SylvaniaCore/stargazers)
|
||||
@@ -49,6 +50,23 @@ Au-delà du core amont, le royaume apporte ses propres systèmes :
|
||||
|
||||
---
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
Ce README suffit pour **installer et lancer** un serveur. Tout le reste vit dans le
|
||||
**[wiki du projet](https://github.com/BlaMacfly/SylvaniaCore/wiki)** :
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| 🔧 **[Corriger le contenu](https://github.com/BlaMacfly/SylvaniaCore/wiki/Corriger-le-contenu)** | Les classes de bugs récurrentes de ce core — scripts C++ non rattachés, hooks morts, quêtes sans objectif, butin, phases résiduelles — et comment les trouver. **Le meilleur point d'entrée pour une première contribution.** |
|
||||
| ⚙️ **[Configuration](https://github.com/BlaMacfly/SylvaniaCore/wiki/Configuration)** | Référence de toutes les clés de configuration propres au royaume |
|
||||
| 🧩 **[Architecture du core](https://github.com/BlaMacfly/SylvaniaCore/wiki/Architecture-du-core)** | Arborescence, lignée amont, pièges d'architecture |
|
||||
| 🤖 **Modules** | [PlayerBots](https://github.com/BlaMacfly/SylvaniaCore/wiki/Module-PlayerBots) · [Mercenaires](https://github.com/BlaMacfly/SylvaniaCore/wiki/Module-Mercenaires) · [Siège des Capitales](https://github.com/BlaMacfly/SylvaniaCore/wiki/Module-Siege-des-Capitales) · [Autres customs](https://github.com/BlaMacfly/SylvaniaCore/wiki/Autres-customs) |
|
||||
| 💥 **[Diagnostic des crashs](https://github.com/BlaMacfly/SylvaniaCore/wiki/Diagnostic-des-crashs)** | Core dumps, redzone jemalloc, faux crashs d'arrêt |
|
||||
| 🩺 **[FAQ Dépannage](https://github.com/BlaMacfly/SylvaniaCore/wiki/FAQ-Depannage)** | Écran de chargement, PNJ disparus, personnage bloqué, boss infaisable… |
|
||||
| 🚧 **[Chantiers en cours](https://github.com/BlaMacfly/SylvaniaCore/wiki/Chantiers-en-cours)** | Ce qui est ouvert, ce qui est clos, et les **impasses connues** |
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Prérequis
|
||||
|
||||
- **CMake 3.31+**
|
||||
@@ -59,6 +77,9 @@ Au-delà du core amont, le royaume apporte ses propres systèmes :
|
||||
|
||||
Plateformes supportées : **Linux, Windows, macOS**.
|
||||
|
||||
> 📖 Paquets à installer, extraction des données client et compilation sur une machine modeste :
|
||||
> **[Installation](https://github.com/BlaMacfly/SylvaniaCore/wiki/Installation)** sur le wiki.
|
||||
|
||||
---
|
||||
|
||||
## 📦 Compilation
|
||||
@@ -151,8 +172,8 @@ amont est livrée vide : c'est normal, tout l'historique est rejoué. Comptez pl
|
||||
`sql/sylvania/` est la trace versionnée des correctifs data appliqués à la base du royaume
|
||||
(artefacts, campagnes, donjons, modules Mercenaires et Siège des Capitales…). Ils sont indépendants
|
||||
du mécanisme de mise à jour automatique et s'importent à la main, dans l'ordre chronologique, une
|
||||
fois les étapes précédentes terminées. La base `world` de production du royaume n'est pas
|
||||
distribuée.
|
||||
fois les étapes précédentes terminées. **Chaque fichier annonce sa base cible dans son en-tête :
|
||||
le dossier n'en a pas une seule.** Détail et conventions : **[Bases de données](https://github.com/BlaMacfly/SylvaniaCore/wiki/Bases-de-donnees)**.
|
||||
|
||||
### 🩺 Bloqué sur l'écran de chargement ?
|
||||
|
||||
@@ -166,14 +187,12 @@ Received not handled opcode [CMSG_GET_ACCOUNT_CHARACTER_LIST ...]
|
||||
|
||||
`ResourceService` est un service Battle.net resté à l'état d'ébauche en amont, et
|
||||
`CMSG_GET_ACCOUNT_CHARACTER_LIST` (liste des personnages inter-royaumes) est délibérément déclaré
|
||||
`STATUS_UNHANDLED` dans `src/server/game/Server/Protocol/Opcodes.cpp`. Si le client reste bloqué au
|
||||
chargement, cherchez plutôt du côté :
|
||||
`STATUS_UNHANDLED` dans `src/server/game/Server/Protocol/Opcodes.cpp`.
|
||||
|
||||
- d'une base `world` ou `hotfixes` mal importée — voir l'avertissement sur `sql/base/dev/` ;
|
||||
- du cache du client : videz son dossier `Cache` ;
|
||||
- des données extraites — `dbc/`, `maps/`, `vmaps/`, `mmaps/`, `cameras/` et `gt/` doivent provenir
|
||||
d'un client **7.3.5 build 26972**, et `DataDir` doit pointer sur le dossier qui les contient ;
|
||||
- de `DBErrors.log` et des lignes de démarrage du worldserver, qui nomment la table fautive.
|
||||
La cause est presque toujours une base `world` ou `hotfixes` mal importée — relisez l'avertissement
|
||||
sur `sql/base/dev/` ci-dessus. Les autres pistes (cache client, données extraites, lecture de
|
||||
`DBErrors.log`) sont détaillées dans la **[FAQ Dépannage](https://github.com/BlaMacfly/SylvaniaCore/wiki/FAQ-Depannage)**, avec les autres
|
||||
symptômes fréquents.
|
||||
|
||||
---
|
||||
|
||||
@@ -191,7 +210,10 @@ ou nouvelle fonctionnalité :
|
||||
|
||||
1. Forkez le dépôt
|
||||
2. Créez une branche dédiée
|
||||
3. Ouvrez une pull request
|
||||
3. Ouvrez une pull request contre `sylvaniacore`
|
||||
|
||||
> 📖 Conventions du dépôt, style de commit, règles pour le SQL et doctrine de correction :
|
||||
> **[Contribuer](https://github.com/BlaMacfly/SylvaniaCore/wiki/Contribuer)** sur le wiki.
|
||||
|
||||
Un Discord est ouvert **aux contributeurs et aux personnes qui souhaitent participer au
|
||||
développement du core** : c'est l'endroit où discuter d'un correctif avant de se lancer, poser
|
||||
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
# FelWell — Legion 7.3.5
|
||||
|
||||
Production-сборка SylvaniaCore для realm **FelWell**. Сервер рассчитан на
|
||||
клиент World of Warcraft Legion **7.3.5 build 26972** и публикуется по адресу
|
||||
`legion.moon-well.online`.
|
||||
|
||||
## Что входит в сборку
|
||||
|
||||
- SylvaniaCore: `worldserver` и `bnetserver`;
|
||||
- MariaDB 11.4 с базами `auth`, `characters`, `world`, `hotfixes` и `shop`;
|
||||
- Docker Compose для сборки и запуска всего стека;
|
||||
- автоматическая настройка `auth.realmlist` из переменных окружения;
|
||||
- русская локализация дополнительных `broadcast_text`;
|
||||
- постоянные Docker volumes для базы данных и журналов.
|
||||
|
||||
## Требования к VPS
|
||||
|
||||
- Ubuntu 24.04;
|
||||
- Docker Engine с Compose plugin;
|
||||
- DNS-запись `legion.moon-well.online`, направленная на публичный IP VPS;
|
||||
- открытые входящие TCP-порты `1119`, `8081` и `8085`;
|
||||
- игровой порт MariaDB `3306` не должен быть открыт в Интернет.
|
||||
|
||||
В каталоге `data/` должны находиться данные, извлечённые из клиента
|
||||
7.3.5.26972: `dbc`, `maps`, `vmaps`, `mmaps`, `cameras` и `gt`.
|
||||
|
||||
## Первый запуск
|
||||
|
||||
Создайте production-конфигурацию:
|
||||
|
||||
```bash
|
||||
cp .env.production.example .env.production
|
||||
nano .env.production
|
||||
```
|
||||
|
||||
Обязательно замените `DB_ROOT_PASSWORD` и `DB_PASSWORD` на разные длинные
|
||||
случайные пароли. Затем положите полные дампы `world` и `hotfixes` в
|
||||
`docker/db-dumps/` и запустите сервер:
|
||||
|
||||
```bash
|
||||
docker compose --env-file .env.production up --build -d
|
||||
docker compose --env-file .env.production ps
|
||||
docker compose --env-file .env.production logs -f bnetserver worldserver
|
||||
```
|
||||
|
||||
При запуске запись realm автоматически получает следующие значения:
|
||||
|
||||
```text
|
||||
name = FelWell
|
||||
address = legion.moon-well.online
|
||||
port = 8085
|
||||
gamebuild = 26972
|
||||
```
|
||||
|
||||
## Русские переводы
|
||||
|
||||
Дополнительные переводы находятся в `sql/translations/ruRU/`. Их можно
|
||||
импортировать после инициализации базы:
|
||||
|
||||
```bash
|
||||
set -a
|
||||
. ./.env.production
|
||||
set +a
|
||||
|
||||
for file in sql/translations/ruRU/broadcast_text_locale_ruRU_part_*.sql; do
|
||||
docker compose --env-file .env.production exec -T database \
|
||||
mariadb --binary-mode -uroot "-p${DB_ROOT_PASSWORD}" hotfixes < "$file"
|
||||
done
|
||||
|
||||
docker compose --env-file .env.production restart worldserver
|
||||
```
|
||||
|
||||
Импорт идемпотентный: существующие строки не перезаписываются.
|
||||
|
||||
## Свой Git-сервер и обновления GitHub
|
||||
|
||||
Используется стандартная схема с двумя remote:
|
||||
|
||||
- `origin` — ваш собственный Git-сервер, основное место хранения;
|
||||
- `upstream` — публичный GitHub-репозиторий SylvaniaCore, только источник
|
||||
обновлений.
|
||||
|
||||
GitHub уже настроен как `upstream`. Добавьте свой сервер, подставив настоящий
|
||||
SSH URL:
|
||||
|
||||
```bash
|
||||
git remote add origin git@YOUR_GIT_SERVER:YOUR_GROUP/SylvaniaCore.git
|
||||
git push -u origin master
|
||||
git remote -v
|
||||
```
|
||||
|
||||
Рабочие изменения сначала коммитятся и отправляются только в ваш `origin`:
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Configure FelWell production deployment"
|
||||
git push origin master
|
||||
```
|
||||
|
||||
Для получения очередных обновлений GitHub:
|
||||
|
||||
```bash
|
||||
git status
|
||||
git fetch upstream --prune
|
||||
git switch master
|
||||
git branch "backup/before-upstream-$(date +%F-%H%M)"
|
||||
git merge upstream/sylvaniacore
|
||||
```
|
||||
|
||||
Если возникли конфликты, разрешите их, сохраняя FelWell-настройки в
|
||||
`compose.yaml`, `docker/`, `.env.production.example` и SQL-миграциях. После
|
||||
сборки и проверки отправьте результат на собственный сервер:
|
||||
|
||||
```bash
|
||||
docker compose --env-file .env.production build
|
||||
docker compose --env-file .env.production up -d
|
||||
docker compose --env-file .env.production logs --tail=200 worldserver bnetserver
|
||||
git push origin master
|
||||
```
|
||||
|
||||
Не выполняйте обновление при незакоммиченных изменениях. Файлы `.env`,
|
||||
`.env.production`, игровые данные и полные дампы БД исключены из Git.
|
||||
|
||||
## Резервное копирование базы
|
||||
|
||||
Перед обновлением создайте дамп всех игровых баз:
|
||||
|
||||
```bash
|
||||
set -a
|
||||
. ./.env.production
|
||||
set +a
|
||||
|
||||
docker compose --env-file .env.production exec -T database \
|
||||
mariadb-dump -uroot "-p${DB_ROOT_PASSWORD}" \
|
||||
--single-transaction --routines --events \
|
||||
--databases auth characters world hotfixes shop \
|
||||
| gzip > "felwell-$(date +%F-%H%M).sql.gz"
|
||||
```
|
||||
|
||||
Храните резервные копии вне VPS. Docker volume защищает данные при пересоздании
|
||||
контейнеров, но не заменяет внешнюю резервную копию.
|
||||
|
||||
## Полезные команды
|
||||
|
||||
```bash
|
||||
# Состояние контейнеров
|
||||
docker compose --env-file .env.production ps
|
||||
|
||||
# Последние журналы
|
||||
docker compose --env-file .env.production logs --tail=200 worldserver bnetserver
|
||||
|
||||
# Перезапуск серверов без удаления БД
|
||||
docker compose --env-file .env.production restart bnetserver worldserver
|
||||
|
||||
# Остановка стека с сохранением volumes
|
||||
docker compose --env-file .env.production down
|
||||
```
|
||||
|
||||
Не запускайте `docker compose down -v` на production: ключ `-v` удаляет volume
|
||||
MariaDB вместе с игровыми аккаунтами и персонажами.
|
||||
+309
@@ -0,0 +1,309 @@
|
||||
<div align="center">
|
||||
|
||||
<img src=".github/assets/sylvaniacore-logo.png" alt="SylvaniaCore" width="360">
|
||||
|
||||
# SylvaniaCore
|
||||
|
||||
**C++-ядро игрового мира [La Légion de Sylvania](https://legendesylvania.com)**<br>
|
||||
Эмулятор сервера *World of Warcraft®* — Legion 7.3.5
|
||||
|
||||
[](https://discord.gg/qmQBXbuXkx)
|
||||
[](./LICENSE)
|
||||
[](https://github.com/BlaMacfly/SylvaniaCore/stargazers)
|
||||
[](https://github.com/BlaMacfly/SylvaniaCore/network/members)
|
||||
[](https://github.com/slash-design/DestinyCore)
|
||||
|
||||
</div>
|
||||
|
||||
> Практическая инструкция по Docker, production-развёртыванию FelWell и
|
||||
> синхронизации с собственным Git-сервером: [README.ru.md](./README.ru.md).
|
||||
|
||||
---
|
||||
|
||||
## 📖 О проекте
|
||||
|
||||
**SylvaniaCore** — ядро франкоязычного игрового мира **La Légion de Sylvania**
|
||||
для *World of Warcraft® Legion 7.3.5*. Это форк
|
||||
[DestinyCore](https://github.com/slash-design/DestinyCore), который, в свою
|
||||
очередь, происходит из семейства TrinityCore. Проект постоянно развивается и
|
||||
поддерживается для нужд игрового мира.
|
||||
|
||||
Репозиторий одновременно служит **актуальной кодовой базой** и **резервной
|
||||
копией** production-сервера.
|
||||
|
||||
### Философия: «адаптивный blizzlike»
|
||||
|
||||
Это не *fun*-сервер и не сервер с *rates x∞*. Оригинальные значения Blizzard
|
||||
(урон, баланс и экономика) **сохраняются**. Основная работа направлена на
|
||||
**исправление отклонений от blizzlike**, а не на упрощение игры. Каждая
|
||||
обнаруженная ошибка исправляется в источнике — в данных или в ядре, — а не
|
||||
обходится командами игрового мастера.
|
||||
|
||||
---
|
||||
|
||||
## ✨ Дополнения SylvaniaCore
|
||||
|
||||
Помимо возможностей upstream-ядра, проект содержит собственные системы:
|
||||
|
||||
| Модуль | Описание |
|
||||
| --- | --- |
|
||||
| 🤖 **PlayerBots** | Управляемые боты-игроки (`src/server/game/PlayerBot`): групповые команды, роли танка и лекаря, управление экипировкой и автоматическое заполнение полей боя |
|
||||
| ⚔️ **Осада столиц** | Ежедневные нападения отрядов ботов на столицы с назначенным командиром и PvP-флагом игроков (`src/server/game/CapitalSiege`) |
|
||||
| 💰 **Наёмники** | Нанимаемые NPC-компаньоны: одиночный игрок может заключить с ними контракт за игровое золото (`src/server/game/Mercenary`) |
|
||||
| 🇫🇷 **Локализация frFR** | Восстановление официальных французских текстов из клиента 7.3.5 — заданий, диалогов и broadcast-текстов — и перевод отсутствующего сценарного контента |
|
||||
| 🐛 **Исправления контента** | Последовательное восстановление кампаний, подземелий и заданий по отдельным зонам: Мардум, Скитающийся остров, Вершина Смерча и другие |
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Требования
|
||||
|
||||
- **CMake 3.31+**
|
||||
- **Boost 1.84.0**
|
||||
- **MySQL 8.0** или **MariaDB 10.6+** — игровой мир использует MariaDB 11.4
|
||||
- **OpenSSL 3.x**
|
||||
- **GCC / Clang / MSVC** — рекомендуется Visual Studio 2022
|
||||
|
||||
Поддерживаемые платформы: **Linux, Windows и macOS**.
|
||||
|
||||
---
|
||||
|
||||
## 📦 Сборка
|
||||
|
||||
1. Клонируйте репозиторий:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/BlaMacfly/SylvaniaCore.git
|
||||
cd SylvaniaCore
|
||||
```
|
||||
|
||||
2. Настройте и соберите проект:
|
||||
|
||||
```bash
|
||||
cmake -S . -B build -DTOOLS=ON
|
||||
cmake --build build -j$(nproc)
|
||||
```
|
||||
|
||||
3. Установите базы данных согласно разделу
|
||||
[Установка базы данных](#-установка-базы-данных).
|
||||
|
||||
4. Запустите серверы:
|
||||
|
||||
```bash
|
||||
./bin/worldserver
|
||||
./bin/bnetserver
|
||||
```
|
||||
|
||||
> ℹ️ В исходном коде намеренно сохранены внутренние имена upstream-проекта:
|
||||
> `DestinyCore`, названия целей CMake и пути конфигурации. Это обеспечивает
|
||||
> совместимость с upstream-обновлениями и существующими сценариями
|
||||
> развёртывания.
|
||||
|
||||
### Docker Compose
|
||||
|
||||
Ядро, сервер Battle.net и MariaDB 11.4 можно собрать и запустить вместе:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# Поместите DB_world_*.sql и DB_hotfixes_*.sql (или .sql.gz) в docker/db-dumps/
|
||||
# Поместите dbc/, maps/, vmaps/, mmaps/, cameras/ и gt/ клиента 7.3.5 в data/
|
||||
docker compose up --build -d
|
||||
docker compose logs -f worldserver
|
||||
```
|
||||
|
||||
Схемы `auth`, `characters` и `shop` импортируются автоматически при первом
|
||||
запуске MariaDB. Полные дампы `world` и `hotfixes` также импортируются из
|
||||
`docker/db-dumps/`. Перед публикацией сервера обязательно замените пароли в
|
||||
`.env`. Объявляемый клиентам адрес задаётся переменной `EXTERNAL_ADDRESS`.
|
||||
|
||||
### Production-развёртывание FelWell
|
||||
|
||||
Production-шаблон настраивает игровой мир `FelWell` по адресу
|
||||
`legion.moon-well.online:8085`:
|
||||
|
||||
```bash
|
||||
cp .env.production.example .env.production
|
||||
# Обязательно замените оба пароля в .env.production
|
||||
docker compose --env-file .env.production up --build -d
|
||||
docker compose --env-file .env.production logs -f bnetserver worldserver
|
||||
```
|
||||
|
||||
При запуске запись `auth.realmlist` автоматически синхронизируется с
|
||||
`REALM_NAME`, `REALM_ADDRESS` и `REALM_PORT`. DNS-запись `A/AAAA` должна
|
||||
указывать на VPS, а брандмауэр должен разрешать TCP-порты `1119`, `8081` и
|
||||
`8085`. MariaDB должна оставаться только во внутренней сети Docker и не должна
|
||||
публиковаться в Интернет.
|
||||
|
||||
Volumes `database-data` и `sylvania-logs` сохраняют базу данных и журналы
|
||||
соответственно. Изменения в `docker/db-dumps/` не импортируются повторно, если
|
||||
база уже была инициализирована.
|
||||
|
||||
---
|
||||
|
||||
## 💾 Установка базы данных
|
||||
|
||||
Репозиторий содержит **только схемы** `auth`, `characters` и `shop`. Базы
|
||||
`world` и `hotfixes` слишком велики для хранения в Git; их необходимо загрузить
|
||||
из **релизов upstream-репозитория DestinyCore**.
|
||||
|
||||
> ⚠️ **Никогда не импортируйте файлы из `sql/base/dev/`.** Это **пустые**
|
||||
> структуры таблиц без игровых данных, предназначенные для разработчиков
|
||||
> upstream-проекта. После такого импорта `worldserver` может запуститься, но
|
||||
> клиент останется на экране загрузки из-за пустой базы `world`.
|
||||
|
||||
### 1. Загрузка upstream-базы
|
||||
|
||||
Загрузите последний релиз базы на странице
|
||||
[slash-design/DestinyCore/releases](https://github.com/slash-design/DestinyCore/releases).
|
||||
На момент написания это `DB735.02.rar` размером около 84 МБ. Архив содержит два
|
||||
дампа:
|
||||
|
||||
| Файл | База | Размер после распаковки |
|
||||
| --- | --- | --- |
|
||||
| `DB_world_735.02.sql` | `world` | около 375 МБ |
|
||||
| `DB_hotfixes_735.02.sql` | `hotfixes` | около 127 МБ |
|
||||
|
||||
Оба дампа самостоятельно выполняют `CREATE DATABASE`, а затем `USE` для баз
|
||||
`world` и `hotfixes`. Если нужны другие имена баз, измените эти две строки в
|
||||
начале соответствующего файла.
|
||||
|
||||
### 2. Создание и импорт баз
|
||||
|
||||
```bash
|
||||
# Базы auth / characters / world / hotfixes
|
||||
mysql -u root -p < sql/create/create_mysql.sql
|
||||
|
||||
# База shop не создаётся upstream-скриптом
|
||||
mysql -u root -p -e "CREATE DATABASE shop DEFAULT CHARACTER SET utf8;"
|
||||
|
||||
# Схемы из репозитория
|
||||
mysql -u trinity -p auth < sql/base/auth_database.sql
|
||||
mysql -u trinity -p characters < sql/base/characters_database.sql
|
||||
mysql -u trinity -p shop < sql/base/shop_database.sql
|
||||
|
||||
# Полные базы из upstream-релиза
|
||||
mysql -u trinity -p < DB_world_735.02.sql
|
||||
mysql -u trinity -p < DB_hotfixes_735.02.sql
|
||||
```
|
||||
|
||||
### 3. Автоматическое применение обновлений ядром
|
||||
|
||||
Не импортируйте файлы из `sql/updates/` вручную. В `worldserver.conf` должно
|
||||
быть указано:
|
||||
|
||||
```ini
|
||||
Updates.EnableDatabases = 31 # auth + characters + world + hotfixes + shop
|
||||
Updates.AutoSetup = 1
|
||||
```
|
||||
|
||||
При первом запуске `worldserver` самостоятельно применит около 330 файлов из
|
||||
`sql/updates/world`, а также обновления для `characters` и `hotfixes`. Таблица
|
||||
`updates` в upstream-дампах изначально пуста — это нормально: история
|
||||
обновлений будет применена целиком. Процесс может занять несколько минут.
|
||||
|
||||
### 4. Исправления контента игрового мира (необязательно)
|
||||
|
||||
В `sql/sylvania/` хранится версионируемая история исправлений игровых данных:
|
||||
артефактов, кампаний, подземелий, модулей «Наёмники» и «Осада столиц». Они не
|
||||
относятся к механизму автоматических обновлений и импортируются вручную в
|
||||
хронологическом порядке после завершения предыдущих этапов. Production-база
|
||||
`world` игрового мира не распространяется.
|
||||
|
||||
### 🩺 Клиент завис на экране загрузки?
|
||||
|
||||
Следующие два сообщения появляются при каждом подключении на **всех** серверах
|
||||
этого семейства и **не являются ошибками**:
|
||||
|
||||
```text
|
||||
Client tried to call not implemented method ResourceService.GetContentHandle
|
||||
Received not handled opcode [CMSG_GET_ACCOUNT_CHARACTER_LIST ...]
|
||||
```
|
||||
|
||||
`ResourceService` — незавершённая upstream-реализация сервиса Battle.net, а
|
||||
`CMSG_GET_ACCOUNT_CHARACTER_LIST`, то есть межсерверный список персонажей,
|
||||
намеренно объявлен как `STATUS_UNHANDLED` в
|
||||
`src/server/game/Server/Protocol/Opcodes.cpp`. Если клиент не проходит экран
|
||||
загрузки, проверьте:
|
||||
|
||||
- правильность импорта `world` и `hotfixes`, учитывая предупреждение о
|
||||
`sql/base/dev/`;
|
||||
- кеш клиента — очистите каталог `Cache`;
|
||||
- извлечённые данные: `dbc/`, `maps/`, `vmaps/`, `mmaps/`, `cameras/` и `gt/`
|
||||
должны происходить из клиента **7.3.5 build 26972**, а `DataDir` должен
|
||||
указывать на содержащий их каталог;
|
||||
- `DBErrors.log` и начальные строки журнала `worldserver`, где будет указана
|
||||
проблемная таблица.
|
||||
|
||||
---
|
||||
|
||||
## 🌍 Подключение к игровому миру
|
||||
|
||||
Игровой сервер открыт, а инструкции по подключению опубликованы на официальном
|
||||
сайте: **[legendesylvania.com](https://legendesylvania.com)**.
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Участие в разработке
|
||||
|
||||
Мы приветствуем исправления ошибок, улучшения документации и новые возможности:
|
||||
|
||||
1. Создайте форк репозитория.
|
||||
2. Создайте отдельную ветку для изменения.
|
||||
3. Откройте pull request.
|
||||
|
||||
Discord открыт **для разработчиков и всех желающих участвовать в развитии
|
||||
ядра**. Там можно обсудить исправление до начала работы, задать вопросы по
|
||||
архитектуре или попросить проверить pull request. Это не Discord игрового мира.
|
||||
|
||||
<a href="https://discord.gg/qmQBXbuXkx"><img src="https://img.shields.io/badge/Discord-Для%20разработчиков-5865F2?style=for-the-badge&logo=discord&logoColor=white" alt="Присоединиться к Discord разработчиков"></a>
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Сообщение об ошибке
|
||||
|
||||
Создайте обращение в [трекере задач](https://github.com/BlaMacfly/SylvaniaCore/issues).
|
||||
Перед этим убедитесь, что аналогичная проблема ещё не зарегистрирована.
|
||||
|
||||
---
|
||||
|
||||
## 🙏 Благодарности
|
||||
|
||||
SylvaniaCore не существовал бы без проектов, на основе которых он создан:
|
||||
|
||||
- [DestinyCore](https://github.com/slash-design/DestinyCore) — upstream-ядро,
|
||||
форком которого является этот репозиторий;
|
||||
- [TrinityCore](https://github.com/TrinityCore/TrinityCore) — исходное семейство
|
||||
проекта;
|
||||
- [**ArgusCore**](https://github.com/Trion-Control-Panel/ArgusCore), проект
|
||||
[FlyingPhoenix](https://github.com/fIyingPhoenix), — один из важнейших
|
||||
ориентиров для SylvaniaCore. В нём проделана огромная работа над движком,
|
||||
сетевым уровнем и механиками классов версии 7.3.5. Мы регулярно используем
|
||||
его как источник решений при восстановлении крупных частей ядра. Спасибо за
|
||||
открыто опубликованные наработки;
|
||||
- [mod-playerbots](https://github.com/liyunfan1223/mod-playerbots) — источник
|
||||
решений для логики ботов-игроков.
|
||||
|
||||
Состояние CI upstream-репозитория:
|
||||
[](https://github.com/slash-design/DestinyCore/actions/workflows/win-x64-build.yml)
|
||||
[](https://github.com/slash-design/DestinyCore/actions/workflows/gcc-build.yml)
|
||||
[](https://github.com/slash-design/DestinyCore/actions/workflows/clang-build.yml)
|
||||
|
||||
---
|
||||
|
||||
## 📜 Лицензия
|
||||
|
||||
Проект распространяется по лицензии **GPL v2.0**. См. файл
|
||||
[LICENSE](./LICENSE).
|
||||
|
||||
*World of Warcraft® и Blizzard Entertainment® являются зарегистрированными
|
||||
товарными знаками Blizzard Entertainment, Inc. Проект не связан с Blizzard
|
||||
Entertainment и не одобрен этой компанией.*
|
||||
|
||||
---
|
||||
|
||||
<div align="center">
|
||||
|
||||
<img src=".github/assets/sylvaniacore-logo.png" alt="SylvaniaCore" width="90">
|
||||
|
||||
⭐ Если вам нравится SylvaniaCore, поставьте проекту звезду!
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,100 @@
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=102702;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=97510;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=113054;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=113055;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=110617;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=102706;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=113058;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=90506;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=94191;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=113056;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=110616;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=113057;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=102696;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=113053;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=94190;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=91967;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=94189;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=91970;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=101667;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=102701;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=113059;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=90525;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105176;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105169;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105168;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105171;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105170;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111079;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=90688;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111154;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111089;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=91902;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105166;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105163;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=111165;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111153;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111152;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111149;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111148;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=92558;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105192;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105188;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105190;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105185;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105187;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105186;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105181;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105180;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105182;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105179;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=90677;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105203;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=90515;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=90516;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111167;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111156;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111088;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111087;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105197;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105189;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111173;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111175;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111174;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105183;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105175;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105174;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105165;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105164;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111157;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111155;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111085;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111171;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105206;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105196;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=105167;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105205;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105200;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105199;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=111074;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=105172;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=102698;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=92564;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=100621;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=110615;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=110614;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=102704;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=102703;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=102705;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=109591;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=113037;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=113036;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=109604;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=109592;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=113038;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=91588;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=109587;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=109586;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=93719;
|
||||
UPDATE `creature_template` SET `faction`=2780 WHERE `entry`=90705;
|
||||
UPDATE `creature_template` SET `faction`=1768 WHERE `entry`=101632;
|
||||
@@ -0,0 +1,53 @@
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105176;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105169;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105168;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105171;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105170;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111079;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=90688;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111154;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111089;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=91902;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105166;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105163;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111165;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111153;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111152;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111149;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111148;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=92558;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105192;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105188;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105190;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105185;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105187;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105186;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105181;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105180;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105182;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105179;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111167;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111156;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111088;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111087;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105197;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105189;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111173;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111175;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111174;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105183;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105175;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105174;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105165;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105164;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111157;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111155;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111085;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=111171;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105196;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105167;
|
||||
UPDATE `creature_template` SET `unit_flags`=33555200 WHERE `entry`=113129;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=90544;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=105172;
|
||||
UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=94276;
|
||||
UPDATE `creature_template` SET `unit_flags`=537166592 WHERE `entry`=101632;
|
||||
@@ -0,0 +1,67 @@
|
||||
UPDATE `creature_template` SET `unit_flags2`=2097152 WHERE `entry`=90686;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=97525;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=112920;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2097152 WHERE `entry`=100959;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=97527;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099201 WHERE `entry`=112977;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=113054;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=113055;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=102706;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=113058;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=97528;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=94191;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=113056;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=113057;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=113053;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=94190;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=94189;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=91970;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=102701;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=113059;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=105217;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=110941;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=94223;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=97502;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=102698;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=91949;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099201 WHERE `entry`=92122;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099201 WHERE `entry`=97503;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2097152 WHERE `entry`=92121;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099201 WHERE `entry`=94209;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=110615;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099201 WHERE `entry`=97526;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099201 WHERE `entry`=113290;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099201 WHERE `entry`=108990;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=112921;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099201 WHERE `entry`=97521;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=93704;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=110614;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=102704;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=102703;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=102705;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2097152 WHERE `entry`=109591;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=113036;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2097152 WHERE `entry`=109604;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2097152 WHERE `entry`=109592;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099201 WHERE `entry`=113291;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2131968 WHERE `entry`=113038;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=90711;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=90712;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=90708;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2131968 WHERE `entry`=91588;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2131968 WHERE `entry`=109587;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=91353;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=97486;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=92586;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2113536 WHERE `entry`=92061;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2131968 WHERE `entry`=109586;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=101056;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=90714;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=93219;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=90710;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=97496;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=101057;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=90717;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=90705;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=90713;
|
||||
UPDATE `creature_template` SET `unit_flags2`=2099200 WHERE `entry`=90709;
|
||||
@@ -0,0 +1,71 @@
|
||||
name: sylvania-core
|
||||
|
||||
x-core: &core
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
BUILD_JOBS: ${BUILD_JOBS:-2}
|
||||
BUILD_TYPE: ${BUILD_TYPE:-Release}
|
||||
image: sylvania-core:${IMAGE_TAG:-local}
|
||||
working_dir: /opt/sylvania/bin
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
database:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
DB_HOST: database
|
||||
DB_PORT: 3306
|
||||
DB_USER: ${DB_USER:-sylvania}
|
||||
DB_PASSWORD: ${DB_PASSWORD:-sylvania}
|
||||
REALM_NAME: ${REALM_NAME:-Sylvania Solo}
|
||||
REALM_ADDRESS: ${REALM_ADDRESS:-127.0.0.1}
|
||||
REALM_PORT: ${REALM_PORT:-8086}
|
||||
volumes:
|
||||
- ./data:/opt/sylvania/data:ro
|
||||
- ./sql:/src/sql:ro
|
||||
- sylvania-logs:/opt/sylvania/logs
|
||||
|
||||
services:
|
||||
database:
|
||||
image: mariadb:11.4
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-change-me}
|
||||
DB_USER: ${DB_USER:-sylvania}
|
||||
DB_PASSWORD: ${DB_PASSWORD:-sylvania}
|
||||
volumes:
|
||||
- database-data:/var/lib/mysql
|
||||
- ./docker/database/init.sh:/docker-entrypoint-initdb.d/00-sylvania-init.sh:ro
|
||||
- ./sql/base:/sylvania/base:ro
|
||||
- ./docker/db-dumps:/sylvania/dumps:ro
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "healthcheck.sh --connect --innodb_initialized"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 30
|
||||
start_period: 30s
|
||||
|
||||
bnetserver:
|
||||
<<: *core
|
||||
command: ["bnetserver"]
|
||||
environment:
|
||||
DB_HOST: database
|
||||
DB_PORT: 3306
|
||||
DB_USER: ${DB_USER:-sylvania}
|
||||
DB_PASSWORD: ${DB_PASSWORD:-sylvania}
|
||||
EXTERNAL_ADDRESS: ${EXTERNAL_ADDRESS:-127.0.0.1}
|
||||
ports:
|
||||
- "1119:1119"
|
||||
- "8081:8081"
|
||||
|
||||
worldserver:
|
||||
<<: *core
|
||||
command: ["worldserver"]
|
||||
stdin_open: true
|
||||
tty: true
|
||||
ports:
|
||||
- "${REALM_PORT:-8086}:8085"
|
||||
|
||||
volumes:
|
||||
database-data:
|
||||
sylvania-logs:
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
db_user="${DB_USER:-sylvania}"
|
||||
db_password="${DB_PASSWORD:-sylvania}"
|
||||
|
||||
# Identifiers are deliberately fixed; only the application login is configurable.
|
||||
mariadb --protocol=socket -uroot -p"${MARIADB_ROOT_PASSWORD}" <<SQL
|
||||
CREATE DATABASE IF NOT EXISTS auth CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
CREATE DATABASE IF NOT EXISTS characters CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
CREATE DATABASE IF NOT EXISTS world CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
CREATE DATABASE IF NOT EXISTS hotfixes CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
CREATE DATABASE IF NOT EXISTS shop CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
CREATE USER IF NOT EXISTS '${db_user}'@'%' IDENTIFIED BY '${db_password}';
|
||||
GRANT ALL PRIVILEGES ON auth.* TO '${db_user}'@'%';
|
||||
GRANT ALL PRIVILEGES ON characters.* TO '${db_user}'@'%';
|
||||
GRANT ALL PRIVILEGES ON world.* TO '${db_user}'@'%';
|
||||
GRANT ALL PRIVILEGES ON hotfixes.* TO '${db_user}'@'%';
|
||||
GRANT ALL PRIVILEGES ON shop.* TO '${db_user}'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
SQL
|
||||
|
||||
mariadb --protocol=socket -uroot -p"${MARIADB_ROOT_PASSWORD}" auth < /sylvania/base/auth_database.sql
|
||||
mariadb --protocol=socket -uroot -p"${MARIADB_ROOT_PASSWORD}" characters < /sylvania/base/characters_database.sql
|
||||
mariadb --protocol=socket -uroot -p"${MARIADB_ROOT_PASSWORD}" shop < /sylvania/base/shop_database.sql
|
||||
|
||||
shopt -s nullglob
|
||||
for dump in /sylvania/dumps/*.sql /sylvania/dumps/*.sql.gz; do
|
||||
echo "Importing game database dump: ${dump}"
|
||||
if [[ "${dump}" == *.gz ]]; then
|
||||
gzip -dc "${dump}" | mariadb --protocol=socket -uroot -p"${MARIADB_ROOT_PASSWORD}"
|
||||
else
|
||||
mariadb --protocol=socket -uroot -p"${MARIADB_ROOT_PASSWORD}" < "${dump}"
|
||||
fi
|
||||
done
|
||||
|
||||
# The published 7.3.5 dump uses a lowercase name, while the core queries this
|
||||
# one legacy table with its historical mixed-case identifier on Linux.
|
||||
mariadb --protocol=socket -uroot -p"${MARIADB_ROOT_PASSWORD}" \
|
||||
-e 'RENAME TABLE hotfixes.questv2clitask TO hotfixes.QuestV2CliTask;'
|
||||
@@ -0,0 +1,13 @@
|
||||
# Full game database dumps
|
||||
|
||||
Put the upstream `world` and `hotfixes` dumps here before the first
|
||||
`docker compose up`. Both plain `.sql` and `.sql.gz` files are imported.
|
||||
|
||||
The repository intentionally does not ship those datasets. Do not use
|
||||
`sql/base/dev`: those files contain empty developer schemas and are not a
|
||||
playable game database.
|
||||
|
||||
If the database volume has already been initialized, add the dumps manually or
|
||||
recreate the volume explicitly with `docker compose down -v` (this deletes all
|
||||
database data).
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
server="${1:-worldserver}"
|
||||
case "${server}" in
|
||||
worldserver|bnetserver) ;;
|
||||
*) exec "$@" ;;
|
||||
esac
|
||||
|
||||
db_host="${DB_HOST:-database}"
|
||||
db_port="${DB_PORT:-3306}"
|
||||
db_user="${DB_USER:-sylvania}"
|
||||
db_password="${DB_PASSWORD:-sylvania}"
|
||||
external_address="${EXTERNAL_ADDRESS:-127.0.0.1}"
|
||||
realm_name="${REALM_NAME:-Sylvania Solo}"
|
||||
realm_address="${REALM_ADDRESS:-127.0.0.1}"
|
||||
realm_port="${REALM_PORT:-8086}"
|
||||
|
||||
if [[ ! "${realm_name}" =~ ^[[:alnum:]А-Яа-яЁё._[:space:]-]{1,32}$ ]]; then
|
||||
echo "REALM_NAME contains unsupported characters or is longer than 32 characters" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "${realm_address}" =~ ^[A-Za-z0-9.-]+$ ]]; then
|
||||
echo "REALM_ADDRESS must be an IPv4 address or a DNS name" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "${realm_port}" =~ ^[0-9]+$ ]] || (( realm_port < 1 || realm_port > 65535 )); then
|
||||
echo "REALM_PORT must be an integer between 1 and 65535" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
config_dir=/opt/sylvania/etc
|
||||
template="${config_dir}/${server}.conf.dist"
|
||||
config="${config_dir}/${server}.conf"
|
||||
|
||||
cp "${template}" "${config}"
|
||||
sed -i -E \
|
||||
-e "s#^(LoginDatabaseInfo[[:space:]]*=).*#\\1 \"${db_host};${db_port};${db_user};${db_password};auth\"#" \
|
||||
"${config}"
|
||||
|
||||
# Keep the client-facing realm record in sync after restores and migrations.
|
||||
# Values are validated above before being interpolated into SQL.
|
||||
mariadb --protocol=tcp \
|
||||
-h "${db_host}" -P "${db_port}" -u "${db_user}" "-p${db_password}" auth <<SQL
|
||||
INSERT INTO realmlist
|
||||
(id, name, address, localAddress, localSubnetMask, port, icon, flag,
|
||||
timezone, allowedSecurityLevel, population, gamebuild, Region, Battlegroup)
|
||||
VALUES
|
||||
(1, '${realm_name}', '${realm_address}', '${realm_address}',
|
||||
'255.255.255.0', ${realm_port}, 0, 0, 1, 0, 0, 26972, 1, 1)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
name = VALUES(name),
|
||||
address = VALUES(address),
|
||||
localAddress = VALUES(localAddress),
|
||||
port = VALUES(port),
|
||||
gamebuild = VALUES(gamebuild);
|
||||
SQL
|
||||
|
||||
if [[ "${server}" == worldserver ]]; then
|
||||
sed -i -E \
|
||||
-e "s#^(WorldDatabaseInfo[[:space:]]*=).*#\\1 \"${db_host};${db_port};${db_user};${db_password};world\"#" \
|
||||
-e "s#^(CharacterDatabaseInfo[[:space:]]*=).*#\\1 \"${db_host};${db_port};${db_user};${db_password};characters\"#" \
|
||||
-e "s#^(HotfixDatabaseInfo[[:space:]]*=).*#\\1 \"${db_host};${db_port};${db_user};${db_password};hotfixes\"#" \
|
||||
-e "s#^(ShopDatabaseInfo[[:space:]]*=).*#\\1 \"${db_host};${db_port};${db_user};${db_password};shop\"#" \
|
||||
-e 's#^DataDir[[:space:]]*=.*#DataDir = "/opt/sylvania/data"#' \
|
||||
-e 's#^LogsDir[[:space:]]*=.*#LogsDir = "/opt/sylvania/logs"#' \
|
||||
"${config}"
|
||||
else
|
||||
sed -i -E \
|
||||
-e "s#^LoginREST.ExternalAddress=.*#LoginREST.ExternalAddress=${external_address}#" \
|
||||
-e "s#^LoginREST.LocalAddress=.*#LoginREST.LocalAddress=${external_address}#" \
|
||||
-e 's#^LogsDir[[:space:]]*=.*#LogsDir = "/opt/sylvania/logs"#' \
|
||||
"${config}"
|
||||
fi
|
||||
|
||||
exec "/opt/sylvania/bin/${server}" -c "${config}"
|
||||
@@ -0,0 +1,48 @@
|
||||
-- =====================================================================
|
||||
-- Rivage brisé (carte 1460) — factions démoniaques ramenées à 16
|
||||
--
|
||||
-- ÉTABLI PAR TEST A/B, pas par raisonnement.
|
||||
-- Une seule entrée a été basculée en faction 16 — le Molosse de l'effroi
|
||||
-- gangrené (90686) — toutes choses égales par ailleurs. Résultat en jeu :
|
||||
-- « les molosses sont maintenant attaquables », les autres non.
|
||||
--
|
||||
-- La sonde SPAWNDBG confirme que seule la faction distingue les deux :
|
||||
-- Felstalker Dreadhound faction=16 drapeaux=32768 drapeaux2=0 → OK
|
||||
-- Felguard Legionnaire faction=2780 drapeaux=32768 drapeaux2=0 → bloqué
|
||||
-- Mêmes drapeaux, même niveau, même vie, mêmes phases.
|
||||
--
|
||||
-- POURQUOI 2780 ÉCHOUE, ALORS QUE LA THÉORIE DIT L'INVERSE
|
||||
-- `FactionTemplate.db2` donne pour 2780 : Faction=1786, EnemyGroup=15,
|
||||
-- soit ennemi de tous les groupes, joueurs compris. Et 1786 (« Burning
|
||||
-- Legion Invaders ») a ReputationIndex=-1, donc aucune réputation
|
||||
-- n'intervient. Sur le papier, 2780 devrait être hostile.
|
||||
--
|
||||
-- Elle ne l'est pas dans les faits, et je n'ai pas élucidé pourquoi. Le
|
||||
-- refus vient du client, qui n'interroge jamais le serveur — aucune sonde
|
||||
-- côté serveur ne peut l'observer.
|
||||
--
|
||||
-- CHOIX ASSUMÉ : on retient la faction 16, qui fonctionne de façon
|
||||
-- démontrée dans ce scénario même — c'est celle qu'emploient les démons
|
||||
-- invoqués par le script. C'est un écart avec la donnée de référence,
|
||||
-- consenti parce qu'il rend le contenu jouable.
|
||||
--
|
||||
-- Effet secondaire bienvenu : les démons cessent de s'entretuer. La
|
||||
-- faction 16 les rend amis entre eux (Friend_0=14), ce qui met fin au
|
||||
-- « démons inattaquables qui se battent avec les attaquables ».
|
||||
--
|
||||
-- PORTÉE : uniquement les entrées exclusives à la carte 1460, comme pour
|
||||
-- les correctifs précédents. Les entrées partagées avec d'autres cartes
|
||||
-- sont écartées.
|
||||
--
|
||||
-- Retour arrière : chantiers/rivage_brise/retour_faction16_1460.sql
|
||||
-- =====================================================================
|
||||
|
||||
UPDATE `creature_template` ct
|
||||
JOIN (SELECT DISTINCT c.id
|
||||
FROM creature c
|
||||
JOIN creature_template t ON t.entry = c.id
|
||||
WHERE c.map = 1460
|
||||
AND t.faction IN (2780, 1768)
|
||||
AND c.id NOT IN (SELECT DISTINCT id FROM creature WHERE map <> 1460)) AS cible
|
||||
ON cible.id = ct.entry
|
||||
SET ct.faction = 16;
|
||||
@@ -0,0 +1,46 @@
|
||||
-- =====================================================================
|
||||
-- Rivage brisé (carte 1460) — retrait de l'immunité aux joueurs
|
||||
--
|
||||
-- Signalé en jeu : « les démons invoqués c'est ok mais pas les autres
|
||||
-- au fond ». Les créatures invoquées par le script étaient frappables,
|
||||
-- les placements statiques non.
|
||||
--
|
||||
-- LA CAUSE, et elle est de mon fait
|
||||
-- La transposition des modèles de créatures depuis le dump de référence
|
||||
-- a importé `unit_flags` sur 136 entrées. Parmi les valeurs reprises,
|
||||
-- 33536 et 537166592 contiennent le bit 256 — UNIT_FLAG_IMMUNE_TO_PC,
|
||||
-- qui empêche tout joueur d'attaquer la créature.
|
||||
--
|
||||
-- Dans le cœur de référence, un script retire vraisemblablement ce
|
||||
-- drapeau à l'instant voulu. Le nôtre ne gère aucun drapeau : les
|
||||
-- démons restaient donc immunisés en permanence.
|
||||
--
|
||||
-- Cela explique aussi pourquoi la sonde ATTDBG ne produisait plus rien :
|
||||
-- le client refusait de lui-même, sans jamais interroger le serveur.
|
||||
--
|
||||
-- PORTÉE : uniquement les factions HOSTILES —
|
||||
-- 2780 (30 entrées), 1768 (20 : Anetheron, Balnazzar, Brutallus…),
|
||||
-- 2878 (Krosus), 14 (Gul'dan), 2877 (Lave gangrenée).
|
||||
--
|
||||
-- Volontairement ÉPARGNÉS, car l'immunité y est légitime :
|
||||
-- 35, 2876, 2879, 1819 — alliés, prêtres, montures, vaisseaux.
|
||||
--
|
||||
-- UNE SIMPLIFICATION ASSUMÉE
|
||||
-- Krosus et Gul'dan perdent aussi leur immunité, alors qu'une
|
||||
-- implémentation fidèle la retirerait au début de leur étape. Notre
|
||||
-- script ne gère aucun drapeau : la conserver rendrait les étapes 7 et 8
|
||||
-- infranchissables. La progression reste pilotée par la machine à états
|
||||
-- du script.
|
||||
--
|
||||
-- Retour arrière : chantiers/rivage_brise/retour_immunite_1460.sql
|
||||
-- =====================================================================
|
||||
|
||||
UPDATE `creature_template` ct
|
||||
JOIN (SELECT DISTINCT c.id
|
||||
FROM creature c
|
||||
JOIN creature_template t ON t.entry = c.id
|
||||
WHERE c.map = 1460
|
||||
AND (t.unit_flags & 256)
|
||||
AND t.faction IN (2780, 1768, 2877, 2878, 14)) AS cible
|
||||
ON cible.id = ct.entry
|
||||
SET ct.unit_flags = ct.unit_flags & ~256;
|
||||
@@ -0,0 +1,42 @@
|
||||
-- =====================================================================
|
||||
-- Rivage brisé (carte 1460) — retrait du drapeau UNIT_FLAG2_UNK5
|
||||
--
|
||||
-- Signalé en jeu : « les démons invoqués c'est ok mais pas les autres au
|
||||
-- fond », puis « les fameux démons inattaquables se battent avec les
|
||||
-- démons attaquables ». Nommément : Gangreseigneur Rakkan, Légionnaire
|
||||
-- gangregarde, Molosse de l'effroi gangrené.
|
||||
--
|
||||
-- LA CAUSE, et elle est de mon fait
|
||||
-- La transposition des modèles depuis le dump de référence a importé
|
||||
-- `unit_flags2` sur 147 entrées. Ces trois-là valaient 0 avant ; elles
|
||||
-- ont reçu 2097152, soit 0x200000 — UNIT_FLAG2_UNK5 dans notre cœur.
|
||||
--
|
||||
-- CE QUI REND CE DRAPEAU PARTICULIER : notre serveur l'IGNORE
|
||||
-- totalement. Aucune de ses vérifications ne le consulte. Mais le client,
|
||||
-- lui, l'interprète et refuse de désigner la créature comme cible.
|
||||
--
|
||||
-- C'est ce qui explique le symptôme le plus déroutant de la série : une
|
||||
-- sonde posée dans `Unit::_IsValidAttackTarget` n'a JAMAIS produit la
|
||||
-- moindre ligne pour ces créatures. Le client refusait de lui-même, sans
|
||||
-- jamais interroger le serveur. L'absence de trace était l'information.
|
||||
--
|
||||
-- LA CORRÉLATION QUI TRANCHE
|
||||
-- démons INVOQUÉS par le script (attaquables) : unit_flags2 = 0
|
||||
-- démons STATIQUES (bloqués) : bit 0x200000 présent
|
||||
-- 67 entrées, 420 spawns concernés
|
||||
--
|
||||
-- On retire UNIQUEMENT ce bit, en préservant le reste de la colonne.
|
||||
-- Le serveur ne s'en sert pas : ce retrait ne peut rien casser côté
|
||||
-- logique, il lève seulement le refus du client.
|
||||
--
|
||||
-- Retour arrière : chantiers/rivage_brise/retour_unk5_1460.sql
|
||||
-- =====================================================================
|
||||
|
||||
UPDATE `creature_template` ct
|
||||
JOIN (SELECT DISTINCT c.id
|
||||
FROM creature c
|
||||
JOIN creature_template t ON t.entry = c.id
|
||||
WHERE c.map = 1460
|
||||
AND (t.unit_flags2 & 2097152)) AS cible
|
||||
ON cible.id = ct.entry
|
||||
SET ct.unit_flags2 = ct.unit_flags2 & ~2097152;
|
||||
@@ -0,0 +1,34 @@
|
||||
# Русская локализация Legion 7.3.5
|
||||
|
||||
Пакет добавляет 37 773 отсутствующие строки `ruRU` в таблицу
|
||||
`broadcast_text_locale`. Переводы взяты из ветки `legion` проекта
|
||||
AshamaneCore и адаптированы к текущей схеме SylvaniaCore:
|
||||
|
||||
- `MaleText_lang` → `Text_lang`
|
||||
- `FemaleText_lang` → `Text1_lang`
|
||||
|
||||
Файлы используют `INSERT IGNORE`: уже существующие строки не изменяются.
|
||||
Импортировать их нужно по порядку в базу `hotfixes`:
|
||||
|
||||
```bash
|
||||
set -a
|
||||
. ./.env
|
||||
set +a
|
||||
|
||||
for file in sql/translations/ruRU/broadcast_text_locale_ruRU_part_*.sql; do
|
||||
docker compose exec -T database \
|
||||
mariadb --binary-mode -uroot "-p${DB_ROOT_PASSWORD}" hotfixes < "$file"
|
||||
done
|
||||
```
|
||||
|
||||
После импорта перезапустите игровой сервер:
|
||||
|
||||
```bash
|
||||
docker compose restart worldserver
|
||||
```
|
||||
|
||||
Перед установкой на рабочий сервер рекомендуется сделать резервную копию БД.
|
||||
|
||||
Таблицы `creature_template_locale`, `quest_template_locale` и
|
||||
`quest_objectives_locale` уже содержат все русские строки из указанного
|
||||
источника, поэтому для них SQL-дельта не требуется.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
-- Production realm defaults. Docker startup keeps these values synchronized
|
||||
-- from REALM_NAME, REALM_ADDRESS and REALM_PORT after this migration runs.
|
||||
UPDATE `realmlist`
|
||||
SET `name` = 'FelWell',
|
||||
`address` = 'legion.moon-well.online',
|
||||
`localAddress` = 'legion.moon-well.online',
|
||||
`port` = 8085,
|
||||
`gamebuild` = 26972
|
||||
WHERE `id` = 1;
|
||||
@@ -1574,6 +1574,29 @@ bool Creature::LoadCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool ad
|
||||
|
||||
GetMap()->AddBattlePet(this);
|
||||
|
||||
// SONDE TEMPORAIRE - carte 1460. Etat REEL en memoire une fois la
|
||||
// creature entierement chargee depuis la base, pour le comparer a ce
|
||||
// que dit la table. Une sur dix : il y en a 757.
|
||||
//
|
||||
// La version precedente etait posee dans un bloc de rechargement que
|
||||
// ce chemin n'emprunte jamais -- elle n'a produit aucune ligne.
|
||||
if (GetMapId() == 1460)
|
||||
{
|
||||
static uint32 sondeSpawn = 0;
|
||||
if ((++sondeSpawn % 10) == 1)
|
||||
{
|
||||
TC_LOG_ERROR("misc",
|
||||
"SPAWNDBG %s (entree %u) | faction=%u niveau=%u | pv=" UI64FMTD "/" UI64FMTD
|
||||
" | vivante=%u | drapeaux=%u drapeaux2=%u dynamiques=%u | phases=%u",
|
||||
GetName().c_str(), GetEntry(), getFaction(), getLevel(),
|
||||
GetHealth(), GetMaxHealth(),
|
||||
uint32(IsAlive() ? 1 : 0),
|
||||
GetUInt32Value(UNIT_FIELD_FLAGS), GetUInt32Value(UNIT_FIELD_FLAGS_2),
|
||||
GetUInt32Value(OBJECT_DYNAMIC_FLAGS),
|
||||
uint32(GetPhaseShift().GetPhases().size()));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3336,6 +3359,7 @@ void Creature::ReLoad(bool skipDB)
|
||||
if (IsAIEnabled)
|
||||
AI()->EnterEvadeMode();
|
||||
|
||||
|
||||
TC_LOG_DEBUG("sql.sql", "Creature SpawnID (" SI64FMTD ") reloaded.", GetSpawnId());
|
||||
}
|
||||
|
||||
|
||||
@@ -8314,6 +8314,42 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
|
||||
{
|
||||
ASSERT(target);
|
||||
|
||||
// SONDE TEMPORAIRE - carte 1460 uniquement, et seulement quand un
|
||||
// JOUEUR vise une CREATURE. Volume borne : quelques lignes par seconde
|
||||
// au plus, et uniquement dans ce scenario.
|
||||
if (GetTypeId() == TYPEID_PLAYER && target->GetTypeId() == TYPEID_UNIT && GetMapId() == 1460)
|
||||
{
|
||||
// On ne veut QUE les demons statiques : factions 2780 et 1768.
|
||||
// Les invoques (faction 16) fonctionnent deja et polluaient le
|
||||
// releve.
|
||||
uint32 const factionCible = target->getFaction();
|
||||
static uint32 sondeAtt = 0;
|
||||
if ((factionCible == 2780 || factionCible == 1768) && (++sondeAtt % 5) == 1)
|
||||
{
|
||||
TC_LOG_ERROR("misc",
|
||||
"ATTDBG cible %s (entree %u) | vivante=%u etatInattaquable=%u | drapeaux=%u "
|
||||
"(NON_ATTACKABLE=%u NOT_ATTACKABLE_1=%u UNK_16=%u IMMUNE_PC=%u NOT_SELECTABLE=%u) "
|
||||
"| reaction=%d | jeLaVois=%u | mesPhases=%u sesPhases=%u "
|
||||
"| factionCible=%u maFaction=%u | elleMEstHostile=%u jeLuiSuisHostile=%u",
|
||||
target->GetName().c_str(), target->GetEntry(),
|
||||
uint32(target->IsAlive() ? 1 : 0),
|
||||
uint32(target->HasUnitState(UNIT_STATE_UNATTACKABLE) ? 1 : 0),
|
||||
target->GetUInt32Value(UNIT_FIELD_FLAGS),
|
||||
uint32(target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) ? 1 : 0),
|
||||
uint32(target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_1) ? 1 : 0),
|
||||
uint32(target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_16) ? 1 : 0),
|
||||
uint32(target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) ? 1 : 0),
|
||||
uint32(target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE) ? 1 : 0),
|
||||
int32(GetReactionTo(target)),
|
||||
uint32(CanSeeOrDetect(target, true) ? 1 : 0),
|
||||
uint32(GetPhaseShift().GetPhases().size()),
|
||||
uint32(target->GetPhaseShift().GetPhases().size()),
|
||||
factionCible, getFaction(),
|
||||
uint32(target->IsHostileTo(this) ? 1 : 0),
|
||||
uint32(IsHostileTo(target) ? 1 : 0));
|
||||
}
|
||||
}
|
||||
|
||||
// can't attack self
|
||||
if (this == target)
|
||||
return false;
|
||||
|
||||
@@ -350,7 +350,20 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
|
||||
|
||||
///- Before we process anything:
|
||||
/// If necessary, kick the player from the character select screen
|
||||
if (!IsBotSession() && IsConnectionIdle())
|
||||
//
|
||||
// SylvaniaCore : les comptes de niveau superieur a SEC_PLAYER --
|
||||
// maitres de jeu, testeurs, administration -- ne sont plus coupes
|
||||
// pour inactivite.
|
||||
//
|
||||
// Motif : ces comptes restent volontairement connectes de longues
|
||||
// minutes sans emettre de paquet, le temps d'observer une zone, de
|
||||
// suivre un evenement scripte ou d'attendre le resultat d'un test.
|
||||
// Le delai de SocketTimeOutTime (900 s) les deconnectait en plein
|
||||
// travail, parfois au milieu d'une instance.
|
||||
//
|
||||
// Les joueurs ordinaires restent soumis au delai : la protection
|
||||
// contre les sessions fantomes conserve tout son interet pour eux.
|
||||
if (!IsBotSession() && GetSecurity() <= SEC_PLAYER && IsConnectionIdle())
|
||||
m_Socket[CONNECTION_TYPE_REALM]->CloseSocket();
|
||||
|
||||
///- Retrieve packets from the receive queue and call the appropriate handlers
|
||||
|
||||
@@ -172,7 +172,30 @@ struct scenario_broken_shore_intro : public InstanceScript
|
||||
if (player->GetMapId() != 1460)
|
||||
return;
|
||||
|
||||
PhasingHandler::AddPhase(player, PHASE_NORMAL, true);
|
||||
// ==========================================================
|
||||
// SylvaniaCore : phasage retire.
|
||||
//
|
||||
// SIGNALE EN JEU : les creatures etaient visibles, hostiles, mais
|
||||
// impossibles a cibler. Une sonde posee dans _IsValidAttackTarget
|
||||
// a donne le verdict :
|
||||
// reaction=1 (hostile), aucun drapeau bloquant, vivante,
|
||||
// mesPhases=0 sesPhases=1
|
||||
//
|
||||
// Deux objets ne se voient que s'ils PARTAGENT une phase
|
||||
// (PhaseShift::CanSee, intersection des phases), et
|
||||
// UpdateUnphasedFlag retire le statut « non phase » des qu'un
|
||||
// objet en possede une. Le joueur n'en avait aucune : aucune
|
||||
// intersection possible.
|
||||
//
|
||||
// Le phasage etait de toute facon une invention locale : le dump
|
||||
// de reference laisse les 757 placements de cette carte SANS
|
||||
// phase (PhaseId vide). On revient donc a cette configuration --
|
||||
// tout le monde non phase, tout le monde se voit.
|
||||
//
|
||||
// La phase 169 n'existe d'ailleurs pas dans Phase.db2 du build
|
||||
// 7.3.5.26972, ce qui la rendait d'autant plus douteuse.
|
||||
// ==========================================================
|
||||
|
||||
// objectif « embarquement » (Alliance) : credite aussi ici au cas ou
|
||||
player->KilledMonsterCredit(NPC_CREDIT_SHIP);
|
||||
|
||||
@@ -207,10 +230,13 @@ struct scenario_broken_shore_intro : public InstanceScript
|
||||
// Toute invocation doit partager la phase des joueurs (OnPlayerEnter les met en 169),
|
||||
// sinon elle est invisible/intangible : cible de quete introuvable, vague intuable.
|
||||
// (defaut systemique detecte par le harnais bot le 26/07, deja corrige dans le runner d artefacts)
|
||||
// SylvaniaCore : ne phase plus rien. Laisser la phase 169 ici alors
|
||||
// que le joueur n'en a aucune rendrait les invocations invisibles --
|
||||
// le probleme meme qu'on vient de corriger, en sens inverse.
|
||||
// Conservee comme point de passage unique pour les invocations, au
|
||||
// cas ou un traitement commun redevienne necessaire.
|
||||
TempSummon* FinalizeSummon(TempSummon* summon) const
|
||||
{
|
||||
if (summon)
|
||||
PhasingHandler::AddPhase(summon, PHASE_NORMAL, true);
|
||||
return summon;
|
||||
}
|
||||
|
||||
@@ -337,6 +363,27 @@ struct scenario_broken_shore_intro : public InstanceScript
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// =====================================================
|
||||
// SylvaniaCore : tout demon compte pour l objectif.
|
||||
//
|
||||
// SIGNALE EN JEU : « les molosses sont maintenant
|
||||
// attaquables mais ne comptent pas dans l objectif du
|
||||
// scenario ».
|
||||
//
|
||||
// Le script ne reconnaissait que les CINQ entrees qu il
|
||||
// invoque lui-meme. Or la carte porte 101 entrees de
|
||||
// demons placees, affrontees tout au long de l assaut :
|
||||
// elles ne crediraient rien.
|
||||
//
|
||||
// Plutot que d enumerer 101 entrees -- liste qui
|
||||
// vieillirait mal --, on s appuie sur la donnee : le type
|
||||
// demon. Tous les demons de cette carte sont desormais
|
||||
// hostiles (faction 16). Les Seigneurs gangrebois,
|
||||
// Arganoth, Krosus et Gul dan sont traites avant et n
|
||||
// arrivent jamais ici : ils ont leurs propres criteres.
|
||||
// =====================================================
|
||||
if (creature->GetCreatureTemplate()->type == CREATURE_TYPE_DEMON)
|
||||
OnDemonDied();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,8 +805,37 @@ public:
|
||||
|
||||
static bool HandleNpcNearCommand(ChatHandler* handler, char const* args)
|
||||
{
|
||||
// =============================================================
|
||||
// SylvaniaCore : .npc near faisait tomber le serveur.
|
||||
//
|
||||
// SIGNALE EN JEU : « la commande .npc near fait planter le
|
||||
// serveur ». La requete preparee WORLD_SEL_CREATURE_NEAREST n'a
|
||||
// AUCUNE limite : elle calcule trois puissances sur les 384 000
|
||||
// lignes de la table creature, sans index utilisable, puis la
|
||||
// boucle ci-dessous envoie UN message de discussion par resultat.
|
||||
// Avec un rayon large, cela represente des dizaines de milliers
|
||||
// de paquets pour une seule commande.
|
||||
//
|
||||
// Deux garde-fous, la requete etant partagee avec d'autres
|
||||
// commandes :
|
||||
// - le rayon est plafonne ;
|
||||
// - le nombre de lignes affichees l'est aussi, et l'on ANNONCE
|
||||
// combien ont ete omises plutot que de tronquer en silence.
|
||||
// =============================================================
|
||||
float const RAYON_MAX = 500.0f;
|
||||
uint32 const LIGNES_MAX = 150;
|
||||
|
||||
float distance = (!*args) ? 10.0f : float((atof(args)));
|
||||
if (distance > RAYON_MAX)
|
||||
{
|
||||
handler->PSendSysMessage("Rayon ramene de %.0f a %.0f : au-dela la recherche parcourt toute la table et sature la session.", distance, RAYON_MAX);
|
||||
distance = RAYON_MAX;
|
||||
}
|
||||
if (distance <= 0.0f)
|
||||
distance = 10.0f;
|
||||
|
||||
uint32 count = 0;
|
||||
uint32 omises = 0;
|
||||
|
||||
Player* player = handler->GetSession()->GetPlayer();
|
||||
|
||||
@@ -838,14 +867,21 @@ public:
|
||||
if (!creatureTemplate)
|
||||
continue;
|
||||
|
||||
handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, std::to_string(guid).c_str(), entry, std::to_string(guid).c_str(), creatureTemplate->Name.c_str(), x, y, z, o, mapId);
|
||||
|
||||
++count;
|
||||
if (count > LIGNES_MAX)
|
||||
{
|
||||
++omises;
|
||||
continue;
|
||||
}
|
||||
|
||||
handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, std::to_string(guid).c_str(), entry, std::to_string(guid).c_str(), creatureTemplate->Name.c_str(), x, y, z, o, mapId);
|
||||
}
|
||||
while (result->NextRow());
|
||||
}
|
||||
|
||||
handler->PSendSysMessage(LANG_COMMAND_NEAR_NPC_MESSAGE, distance, count);
|
||||
if (omises)
|
||||
handler->PSendSysMessage("%u resultats supplementaires non affiches, plafond %u. Reduisez le rayon pour les voir.", omises, LIGNES_MAX);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,20 @@ public:
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
hyjalAI* ai = ENSURE_AI(hyjalAI, creature->AI());
|
||||
// SylvaniaCore : ENSURE_AI faisait tomber TOUT le serveur.
|
||||
//
|
||||
// GetAI() ne fabrique une hyjalAI que si GetHyjalAI() la trouve,
|
||||
// c est-a-dire dans l instance du Mont Hyjal. Ailleurs la creature
|
||||
// recoit une IA quelconque -- et ENSURE_AI, qui ASSERTE, tuait le
|
||||
// process. Constate en production : un exemplaire de Jaina (17772)
|
||||
// se trouvait sur la carte 0, a Hurlevent ; lui parler suffisait a
|
||||
// planter le serveur (SIGSEGV dans Trinity::Assert, appele depuis
|
||||
// npc_jaina_proudmoore::OnGossipHello).
|
||||
//
|
||||
// On echoue desormais proprement : le PNJ ne repond simplement pas.
|
||||
hyjalAI* ai = dynamic_cast<hyjalAI*>(creature->AI());
|
||||
if (!ai)
|
||||
return false;
|
||||
switch (action)
|
||||
{
|
||||
case GOSSIP_ACTION_INFO_DEF + 1:
|
||||
@@ -81,7 +94,20 @@ public:
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
hyjalAI* ai = ENSURE_AI(hyjalAI, creature->AI());
|
||||
// SylvaniaCore : ENSURE_AI faisait tomber TOUT le serveur.
|
||||
//
|
||||
// GetAI() ne fabrique une hyjalAI que si GetHyjalAI() la trouve,
|
||||
// c est-a-dire dans l instance du Mont Hyjal. Ailleurs la creature
|
||||
// recoit une IA quelconque -- et ENSURE_AI, qui ASSERTE, tuait le
|
||||
// process. Constate en production : un exemplaire de Jaina (17772)
|
||||
// se trouvait sur la carte 0, a Hurlevent ; lui parler suffisait a
|
||||
// planter le serveur (SIGSEGV dans Trinity::Assert, appele depuis
|
||||
// npc_jaina_proudmoore::OnGossipHello).
|
||||
//
|
||||
// On echoue desormais proprement : le PNJ ne repond simplement pas.
|
||||
hyjalAI* ai = dynamic_cast<hyjalAI*>(creature->AI());
|
||||
if (!ai)
|
||||
return false;
|
||||
if (ai->EventBegun)
|
||||
return false;
|
||||
|
||||
@@ -136,7 +162,20 @@ public:
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
hyjalAI* ai = ENSURE_AI(hyjalAI, creature->AI());
|
||||
// SylvaniaCore : ENSURE_AI faisait tomber TOUT le serveur.
|
||||
//
|
||||
// GetAI() ne fabrique une hyjalAI que si GetHyjalAI() la trouve,
|
||||
// c est-a-dire dans l instance du Mont Hyjal. Ailleurs la creature
|
||||
// recoit une IA quelconque -- et ENSURE_AI, qui ASSERTE, tuait le
|
||||
// process. Constate en production : un exemplaire de Jaina (17772)
|
||||
// se trouvait sur la carte 0, a Hurlevent ; lui parler suffisait a
|
||||
// planter le serveur (SIGSEGV dans Trinity::Assert, appele depuis
|
||||
// npc_jaina_proudmoore::OnGossipHello).
|
||||
//
|
||||
// On echoue desormais proprement : le PNJ ne repond simplement pas.
|
||||
hyjalAI* ai = dynamic_cast<hyjalAI*>(creature->AI());
|
||||
if (!ai)
|
||||
return false;
|
||||
ai->DeSpawnVeins();//despawn the alliance veins
|
||||
switch (action)
|
||||
{
|
||||
@@ -161,7 +200,20 @@ public:
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
hyjalAI* ai = ENSURE_AI(hyjalAI, creature->AI());
|
||||
// SylvaniaCore : ENSURE_AI faisait tomber TOUT le serveur.
|
||||
//
|
||||
// GetAI() ne fabrique une hyjalAI que si GetHyjalAI() la trouve,
|
||||
// c est-a-dire dans l instance du Mont Hyjal. Ailleurs la creature
|
||||
// recoit une IA quelconque -- et ENSURE_AI, qui ASSERTE, tuait le
|
||||
// process. Constate en production : un exemplaire de Jaina (17772)
|
||||
// se trouvait sur la carte 0, a Hurlevent ; lui parler suffisait a
|
||||
// planter le serveur (SIGSEGV dans Trinity::Assert, appele depuis
|
||||
// npc_jaina_proudmoore::OnGossipHello).
|
||||
//
|
||||
// On echoue desormais proprement : le PNJ ne repond simplement pas.
|
||||
hyjalAI* ai = dynamic_cast<hyjalAI*>(creature->AI());
|
||||
if (!ai)
|
||||
return false;
|
||||
if (ai->EventBegun)
|
||||
return false;
|
||||
|
||||
@@ -244,7 +296,20 @@ public:
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
hyjalAI* ai = ENSURE_AI(hyjalAI, creature->AI());
|
||||
// SylvaniaCore : ENSURE_AI faisait tomber TOUT le serveur.
|
||||
//
|
||||
// GetAI() ne fabrique une hyjalAI que si GetHyjalAI() la trouve,
|
||||
// c est-a-dire dans l instance du Mont Hyjal. Ailleurs la creature
|
||||
// recoit une IA quelconque -- et ENSURE_AI, qui ASSERTE, tuait le
|
||||
// process. Constate en production : un exemplaire de Jaina (17772)
|
||||
// se trouvait sur la carte 0, a Hurlevent ; lui parler suffisait a
|
||||
// planter le serveur (SIGSEGV dans Trinity::Assert, appele depuis
|
||||
// npc_jaina_proudmoore::OnGossipHello).
|
||||
//
|
||||
// On echoue desormais proprement : le PNJ ne repond simplement pas.
|
||||
hyjalAI* ai = dynamic_cast<hyjalAI*>(creature->AI());
|
||||
if (!ai)
|
||||
return false;
|
||||
uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT);
|
||||
|
||||
// Only let them get item if Azgalor is dead.
|
||||
|
||||
@@ -4664,9 +4664,52 @@ pbotasl = 88
|
||||
|
||||
pbottitle = 600
|
||||
|
||||
#
|
||||
# pbotqa
|
||||
# Description: Harnais d assurance qualite. Par defaut, un bot de terrain qui
|
||||
# se retrouve sur une carte d instance est renvoye chez lui.
|
||||
# A 1, il est autorise a y rester : cela permet d observer le
|
||||
# comportement des bots en donjon sans qu ils soient rapatries.
|
||||
# Ne pas activer en production.
|
||||
# Default: 0 - (Desactive)
|
||||
# 1 - (Actif)
|
||||
|
||||
pbotqa = 0
|
||||
|
||||
|
||||
#
|
||||
####################################################################################################
|
||||
|
||||
###################################################################################################
|
||||
# CUSTOM SYLVANIA : BOND HEROIQUE
|
||||
#
|
||||
# Multiplicateurs appliques au saut du Bond heroique (sorts 94954 et 6544). Le saut
|
||||
# EFFECTIF est porte par SPELL_EFFECT_DASH du sort 6544 en phase HIT, qui ecrase le
|
||||
# JUMP_DEST de 94954 en phase LAUNCH : les deux identifiants sont donc traites, pour
|
||||
# un ressenti coherent.
|
||||
#
|
||||
# Ces deux cles sont reglables A CHAUD via « .reload config », sans redemarrage.
|
||||
#
|
||||
# /!\ Ce sont des reglages de ressenti, pas des correctifs : la valeur Blizzlike est
|
||||
# 1.0 pour les deux. Les defauts ci-dessous sont deja un boost assume, et le royaume
|
||||
# va plus loin encore (2.8 / 4.0).
|
||||
#
|
||||
# HeroicLeap.SpeedMult
|
||||
# Description: Facteur de vitesse horizontale (1.0 = Blizzlike, ~21 yd/s).
|
||||
# Default: 1.7
|
||||
|
||||
HeroicLeap.SpeedMult = 1.7
|
||||
|
||||
#
|
||||
# HeroicLeap.HeightMult
|
||||
# Description: Facteur de hauteur d arc (1.0 = Blizzlike, 2.5 -> 10 yd).
|
||||
# Default: 2.5
|
||||
|
||||
HeroicLeap.HeightMult = 2.5
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
###################################################################################################
|
||||
# MODULE SIEGE DES CAPITALES (SylvaniaCore)
|
||||
#
|
||||
@@ -4910,3 +4953,100 @@ siege_horde_route_last = 2099
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
###################################################################################################
|
||||
# MODULE MERCENAIRES (SylvaniaCore)
|
||||
#
|
||||
# Le Portail d Invocation de Mercenaire (creature 1000010) loue des playerbots
|
||||
# au joueur, contre or et sans aucune garantie de duree : quitter le groupe,
|
||||
# renvoyer le mercenaire ou se deconnecter rompt le contrat sur-le-champ.
|
||||
#
|
||||
# pbotmerc
|
||||
# Description: Active le module.
|
||||
# Default: 0 - (Desactive)
|
||||
# 1 - (Actif)
|
||||
|
||||
pbotmerc = 0
|
||||
|
||||
#
|
||||
# pbotmerc_cost
|
||||
# Description: Prix d une invocation, en pieces d or.
|
||||
# Default: 100
|
||||
|
||||
pbotmerc_cost = 100
|
||||
|
||||
#
|
||||
# pbotmerc_max
|
||||
# Description: Nombre de mercenaires simultanes par joueur. Un groupe
|
||||
# compte cinq places, maitre inclus : au-dela de 4 il
|
||||
# faudrait convertir le groupe en raid, ce qui interdirait
|
||||
# les donjons. La valeur est donc plafonnee a 4.
|
||||
# Default: 4
|
||||
|
||||
pbotmerc_max = 4
|
||||
|
||||
#
|
||||
# pbotmerc_minlevel
|
||||
# Description: Niveau minimum du joueur pour employer un mercenaire.
|
||||
# Default: 10
|
||||
|
||||
pbotmerc_minlevel = 10
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
###################################################################################################
|
||||
# MODULE MERCENAIRES - VOLET CONVERSATION (SylvaniaCore)
|
||||
#
|
||||
# Le mercenaire parle par l intermediaire du modele de langage de son
|
||||
# employeur, avec la cle d API de celui-ci. La cle n est jamais enregistree :
|
||||
# elle vit en memoire le temps du contrat et disparait a sa rupture.
|
||||
# Le joueur la fournit en jeu par « !api <fournisseur> <modele> <cle> ».
|
||||
#
|
||||
# pbotmerc_chat
|
||||
# Description: Active le dialogue par modele de langage.
|
||||
# Default: 0 - (Desactive)
|
||||
# 1 - (Actif)
|
||||
|
||||
pbotmerc_chat = 0
|
||||
|
||||
#
|
||||
# pbotmerc_chat_cooldown
|
||||
# Description: Delai minimum, en secondes, entre deux repliques payees par
|
||||
# un meme joueur. Garde-fou contre les macros bavardes.
|
||||
# Default: 5
|
||||
|
||||
pbotmerc_chat_cooldown = 5
|
||||
|
||||
#
|
||||
# pbotmerc_chat_timeout
|
||||
# Description: Delai d expiration d un appel d API, en secondes.
|
||||
# Default: 30
|
||||
|
||||
pbotmerc_chat_timeout = 30
|
||||
|
||||
#
|
||||
# pbotmerc_chat_maxtokens
|
||||
# Description: Longueur maximale de la reponse, en jetons. Le chat du
|
||||
# client ne montre qu une ligne : inutile de voir grand.
|
||||
# Default: 160
|
||||
|
||||
pbotmerc_chat_maxtokens = 160
|
||||
|
||||
#
|
||||
# pbotmerc_chat_history
|
||||
# Description: Nombre d echanges gardes en memoire par mercenaire. Chaque
|
||||
# echange conserve est renvoye au modele, donc refacture.
|
||||
# Default: 6
|
||||
|
||||
pbotmerc_chat_history = 6
|
||||
|
||||
#
|
||||
# pbotmerc_chat_queue
|
||||
# Description: Profondeur maximale de la file d appels en attente.
|
||||
# Default: 32
|
||||
|
||||
pbotmerc_chat_queue = 32
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
Reference in New Issue
Block a user