From c9e584bf2bb8cce6dc2c7eb0e21662396b748b86 Mon Sep 17 00:00:00 2001 From: test Date: Mon, 18 May 2026 13:08:04 +0300 Subject: [PATCH] Add Essence 520 race/class reference data, starters, and lvlupgain. --- docker/initdb/02b_game_classes_ref.sql | 68 ++++++++ docker/initdb/04_seed_classes_essence520.sql | 161 +++++++++++++++++++ install.sh | 1 + 3 files changed, 230 insertions(+) create mode 100644 docker/initdb/02b_game_classes_ref.sql create mode 100644 docker/initdb/04_seed_classes_essence520.sql diff --git a/docker/initdb/02b_game_classes_ref.sql b/docker/initdb/02b_game_classes_ref.sql new file mode 100644 index 0000000..95e6419 --- /dev/null +++ b/docker/initdb/02b_game_classes_ref.sql @@ -0,0 +1,68 @@ +-- Справочники рас/классов и стартовые наборы (L2J / Essence, protocol 520). +-- Основные шаблоны всё равно в XML datapack; это минимум для БД и отладки. + +CREATE TABLE IF NOT EXISTS ref_races ( + race_id SMALLINT NOT NULL PRIMARY KEY, + code VARCHAR(20) NOT NULL UNIQUE, + name_en VARCHAR(40) NOT NULL, + name_ru VARCHAR(40) NOT NULL, + enabled BOOLEAN NOT NULL DEFAULT TRUE, + spawn_x INTEGER NOT NULL, + spawn_y INTEGER NOT NULL, + spawn_z INTEGER NOT NULL, + spawn_heading INTEGER NOT NULL DEFAULT 0 +); + +CREATE TABLE IF NOT EXISTS ref_classes ( + class_id INTEGER NOT NULL PRIMARY KEY, + code VARCHAR(40) NOT NULL, + name_en VARCHAR(60) NOT NULL, + name_ru VARCHAR(60) NOT NULL, + race_id SMALLINT NOT NULL REFERENCES ref_races (race_id), + parent_id INTEGER REFERENCES ref_classes (class_id), + class_level SMALLINT NOT NULL DEFAULT 0, + is_mage BOOLEAN NOT NULL DEFAULT FALSE, + is_summoner BOOLEAN NOT NULL DEFAULT FALSE, + can_create BOOLEAN NOT NULL DEFAULT FALSE, + sex_restrict SMALLINT NOT NULL DEFAULT 0, + CONSTRAINT chk_sex_restrict CHECK (sex_restrict IN (0, 1, 2)) +); + +CREATE INDEX IF NOT EXISTS idx_ref_classes_race ON ref_classes (race_id); +CREATE INDEX IF NOT EXISTS idx_ref_classes_parent ON ref_classes (parent_id); +CREATE INDEX IF NOT EXISTS idx_ref_classes_create ON ref_classes (can_create) WHERE can_create; + +-- Совместимость со старыми инсталляторами L2J +CREATE TABLE IF NOT EXISTS class_list ( + id INTEGER NOT NULL PRIMARY KEY, + class_name VARCHAR(40) NOT NULL +); + +CREATE TABLE IF NOT EXISTS starter_equipment ( + id SERIAL PRIMARY KEY, + class_id INTEGER NOT NULL REFERENCES ref_classes (class_id), + sex SMALLINT NOT NULL DEFAULT 0, + item_id INTEGER NOT NULL, + amount BIGINT NOT NULL DEFAULT 1, + enchant_level INTEGER NOT NULL DEFAULT 0, + equipped BOOLEAN NOT NULL DEFAULT FALSE, + paperdoll_slot SMALLINT NOT NULL DEFAULT 0, + UNIQUE (class_id, sex, item_id) +); + +CREATE TABLE IF NOT EXISTS starter_skills ( + class_id INTEGER NOT NULL REFERENCES ref_classes (class_id), + skill_id INTEGER NOT NULL, + skill_level INTEGER NOT NULL DEFAULT 1, + PRIMARY KEY (class_id, skill_id) +); + +-- Упрощённые приросты HP/MP на 1–20 ур. (если сервер читает из БД) +CREATE TABLE IF NOT EXISTS lvlupgain ( + class_id INTEGER NOT NULL, + level SMALLINT NOT NULL, + hp_gain DOUBLE PRECISION NOT NULL DEFAULT 0, + mp_gain DOUBLE PRECISION NOT NULL DEFAULT 0, + cp_gain DOUBLE PRECISION NOT NULL DEFAULT 0, + PRIMARY KEY (class_id, level) +); diff --git a/docker/initdb/04_seed_classes_essence520.sql b/docker/initdb/04_seed_classes_essence520.sql new file mode 100644 index 0000000..169dfbc --- /dev/null +++ b/docker/initdb/04_seed_classes_essence520.sql @@ -0,0 +1,161 @@ +-- Расы, классы (Mobius ClassId), стартовая экипировка и скиллы для создания персонажа. + +INSERT INTO ref_races (race_id, code, name_en, name_ru, spawn_x, spawn_y, spawn_z, spawn_heading) +VALUES + (0, 'HUMAN', 'Human', 'Человек', -82698, 243547, -3731, 0), + (1, 'ELF', 'Elf', 'Эльф', 45953, 42000, -3504, 0), + (2, 'DARK_ELF', 'Dark Elf', 'Тёмный эльф', 28377, 10916, -4224, 0), + (3, 'ORC', 'Orc', 'Орк', -44884, -115346, -240, 0), + (4, 'DWARF', 'Dwarf', 'Гном', 116551, -182493, -1520, 0), + (5, 'KAMAEL', 'Kamael', 'Камаэль', -118070, 45942, 420, 0), + (6, 'ERTHEIA', 'Ertheia', 'Эртея', 207559, 86429, -1000, 0) +ON CONFLICT (race_id) DO UPDATE SET + name_en = EXCLUDED.name_en, + name_ru = EXCLUDED.name_ru, + spawn_x = EXCLUDED.spawn_x, + spawn_y = EXCLUDED.spawn_y, + spawn_z = EXCLUDED.spawn_z; + +-- parent_id NULL = базовый класс на экране создания +INSERT INTO ref_classes (class_id, code, name_en, name_ru, race_id, parent_id, class_level, is_mage, is_summoner, can_create, sex_restrict) +VALUES + (0, 'FIGHTER', 'Human Fighter', 'Воин (чел.)', 0, NULL, 0, FALSE, FALSE, TRUE, 0), + (10, 'MAGE', 'Human Mystic', 'Мистик (чел.)', 0, NULL, 0, TRUE, FALSE, TRUE, 0), + (18, 'ELVEN_FIGHTER', 'Elven Fighter', 'Воин (эльф)', 1, NULL, 0, FALSE, FALSE, TRUE, 0), + (25, 'ELVEN_MAGE', 'Elven Mystic', 'Мистик (эльф)', 1, NULL, 0, TRUE, FALSE, TRUE, 0), + (31, 'DARK_FIGHTER', 'Dark Fighter', 'Воин (т.эльф)', 2, NULL, 0, FALSE, FALSE, TRUE, 0), + (38, 'DARK_MAGE', 'Dark Mystic', 'Мистик (т.эльф)', 2, NULL, 0, TRUE, FALSE, TRUE, 0), + (44, 'ORC_FIGHTER', 'Orc Fighter', 'Воин (орк)', 3, NULL, 0, FALSE, FALSE, TRUE, 0), + (49, 'ORC_MAGE', 'Orc Shaman', 'Шаман (орк)', 3, NULL, 0, FALSE, FALSE, TRUE, 0), + (53, 'DWARVEN_FIGHTER', 'Dwarven Fighter', 'Воин (гном)', 4, NULL, 0, FALSE, FALSE, TRUE, 0), + (123, 'MALE_SOLDIER', 'Male Soldier', 'Солдат (М)', 5, NULL, 0, FALSE, FALSE, TRUE, 1), + (124, 'FEMALE_SOLDIER', 'Female Soldier', 'Солдат (Ж)', 5, NULL, 0, FALSE, FALSE, TRUE, 2), + (182, 'ERTHEIA_FIGHTER', 'Ertheia Fighter', 'Воин (эртея)', 6, NULL, 0, FALSE, FALSE, TRUE, 0), + (183, 'ERTHEIA_WIZARD', 'Ertheia Wizard', 'Маг (эртея)', 6, NULL, 0, TRUE, FALSE, TRUE, 0) +ON CONFLICT (class_id) DO UPDATE SET + name_ru = EXCLUDED.name_ru, + can_create = EXCLUDED.can_create; + +-- Первые профессии (не на экране создания, но нужны в справочнике / class_list) +INSERT INTO ref_classes (class_id, code, name_en, name_ru, race_id, parent_id, class_level, is_mage, is_summoner, can_create, sex_restrict) +VALUES + (1, 'WARRIOR', 'Warrior', 'Воитель', 0, 0, 1, FALSE, FALSE, FALSE, 0), + (4, 'KNIGHT', 'Human Knight', 'Рыцарь', 0, 0, 1, FALSE, FALSE, FALSE, 0), + (7, 'ROGUE', 'Rogue', 'Разбойник', 0, 0, 1, FALSE, FALSE, FALSE, 0), + (11, 'WIZARD', 'Wizard', 'Маг', 0, 10, 1, TRUE, FALSE, FALSE, 0), + (15, 'CLERIC', 'Cleric', 'Клерик', 0, 10, 1, TRUE, FALSE, FALSE, 0), + (19, 'ELVEN_KNIGHT', 'Elven Knight', 'Светлый рыцарь', 1, 18, 1, FALSE, FALSE, FALSE, 0), + (22, 'ELVEN_SCOUT', 'Elven Scout', 'Разведчик', 1, 18, 1, FALSE, FALSE, FALSE, 0), + (26, 'ELVEN_WIZARD', 'Elven Wizard', 'Маг эльфов', 1, 25, 1, TRUE, FALSE, FALSE, 0), + (29, 'ORACLE', 'Oracle', 'Оракул', 1, 25, 1, TRUE, FALSE, FALSE, 0), + (32, 'PALUS_KNIGHT', 'Palus Knight', 'Тёмный рыцарь', 2, 31, 1, FALSE, FALSE, FALSE, 0), + (35, 'ASSASSIN', 'Assassin', 'Убийца', 2, 31, 1, FALSE, FALSE, FALSE, 0), + (39, 'DARK_WIZARD', 'Dark Wizard', 'Тёмный маг', 2, 38, 1, TRUE, FALSE, FALSE, 0), + (42, 'SHILLIEN_ORACLE', 'Shillien Oracle', 'Оракул Шилен', 2, 38, 1, TRUE, FALSE, FALSE, 0), + (45, 'ORC_RAIDER', 'Orc Raider', 'Налётчик', 3, 44, 1, FALSE, FALSE, FALSE, 0), + (47, 'ORC_MONK', 'Orc Monk', 'Монах', 3, 44, 1, FALSE, FALSE, FALSE, 0), + (50, 'ORC_SHAMAN', 'Orc Shaman', 'Шаман', 3, 49, 1, TRUE, FALSE, FALSE, 0), + (54, 'SCAVENGER', 'Scavenger', 'Собиратель', 4, 53, 1, FALSE, FALSE, FALSE, 0), + (56, 'ARTISAN', 'Artisan', 'Ремесленник', 4, 53, 1, FALSE, FALSE, FALSE, 0), + (125, 'TROOPER', 'Trooper', 'Трупер', 5, 123, 1, FALSE, FALSE, FALSE, 1), + (126, 'WARDER', 'Warder', 'Вардер', 5, 124, 1, FALSE, FALSE, FALSE, 2), + (184, 'MARAUDER', 'Marauder', 'Мародёр', 6, 182, 1, FALSE, FALSE, FALSE, 0), + (185, 'CLOUD_BREAKER', 'Cloud Breaker', 'Прорицатель', 6, 183, 1, TRUE, FALSE, FALSE, 0) +ON CONFLICT (class_id) DO NOTHING; + +-- class_list (L2J): все зарегистрированные class_id +INSERT INTO class_list (id, class_name) +SELECT class_id, code FROM ref_classes +ON CONFLICT (id) DO UPDATE SET class_name = EXCLUDED.class_name; + +-- Стартовая экипировка (упрощённо; уточните item_id под ваш datapack Samurai Crow) +-- paperdoll: 0=под оружием, 6=оружие, 10=голова, 11=перчатки, 12=грудь, 13=ноги, 14=обувь +INSERT INTO starter_equipment (class_id, sex, item_id, amount, equipped, paperdoll_slot) VALUES + (0, 0, 2369, 1, TRUE, 6), + (0, 0, 1146, 1, TRUE, 12), + (0, 0, 1147, 1, TRUE, 13), + (0, 0, 1123, 1, TRUE, 14), + (10, 0, 6, 1, TRUE, 6), + (10, 0, 425, 1, TRUE, 12), + (10, 0, 461, 1, TRUE, 13), + (10, 0, 1123, 1, TRUE, 14), + (18, 0, 2369, 1, TRUE, 6), + (18, 0, 1146, 1, TRUE, 12), + (18, 0, 1147, 1, TRUE, 13), + (18, 0, 1123, 1, TRUE, 14), + (25, 0, 6, 1, TRUE, 6), + (25, 0, 425, 1, TRUE, 12), + (25, 0, 461, 1, TRUE, 13), + (25, 0, 1123, 1, TRUE, 14), + (31, 0, 2369, 1, TRUE, 6), + (31, 0, 1146, 1, TRUE, 12), + (31, 0, 1147, 1, TRUE, 13), + (31, 0, 1123, 1, TRUE, 14), + (38, 0, 6, 1, TRUE, 6), + (38, 0, 425, 1, TRUE, 12), + (38, 0, 461, 1, TRUE, 13), + (38, 0, 1123, 1, TRUE, 14), + (44, 0, 2369, 1, TRUE, 6), + (44, 0, 1146, 1, TRUE, 12), + (44, 0, 1147, 1, TRUE, 13), + (44, 0, 1123, 1, TRUE, 14), + (49, 0, 6, 1, TRUE, 6), + (49, 0, 425, 1, TRUE, 12), + (49, 0, 461, 1, TRUE, 13), + (49, 0, 1123, 1, TRUE, 14), + (53, 0, 2369, 1, TRUE, 6), + (53, 0, 1146, 1, TRUE, 12), + (53, 0, 1147, 1, TRUE, 13), + (53, 0, 1123, 1, TRUE, 14), + (123, 1, 2369, 1, TRUE, 6), + (123, 1, 1146, 1, TRUE, 12), + (123, 1, 1147, 1, TRUE, 13), + (123, 1, 1123, 1, TRUE, 14), + (124, 2, 2369, 1, TRUE, 6), + (124, 2, 1146, 1, TRUE, 12), + (124, 2, 1147, 1, TRUE, 13), + (124, 2, 1123, 1, TRUE, 14), + (182, 0, 2369, 1, TRUE, 6), + (182, 0, 1146, 1, TRUE, 12), + (182, 0, 1147, 1, TRUE, 13), + (182, 0, 1123, 1, TRUE, 14), + (183, 0, 6, 1, TRUE, 6), + (183, 0, 425, 1, TRUE, 12), + (183, 0, 461, 1, TRUE, 13), + (183, 0, 1123, 1, TRUE, 14) +ON CONFLICT (class_id, sex, item_id) DO NOTHING; + +-- Стартовые умения (уровень 1) +INSERT INTO starter_skills (class_id, skill_id, skill_level) VALUES + (0, 3, 1), + (10, 1177, 1), + (18, 3, 1), + (25, 1177, 1), + (31, 3, 1), + (38, 1177, 1), + (44, 3, 1), + (49, 1001, 1), + (53, 3, 1), + (123, 3, 1), + (124, 3, 1), + (182, 3, 1), + (183, 1177, 1) +ON CONFLICT DO NOTHING; + +-- lvlupgain: базовые приросты для creatable классов (уровни 1–20) +INSERT INTO lvlupgain (class_id, level, hp_gain, mp_gain, cp_gain) +SELECT c.class_id, lv.lvl, + CASE WHEN c.is_mage THEN 8.0 ELSE 12.0 END, + CASE WHEN c.is_mage THEN 6.0 ELSE 2.0 END, + CASE WHEN c.is_mage THEN 6.0 ELSE 10.0 END +FROM ref_classes c +CROSS JOIN generate_series(1, 20) AS lv(lvl) +WHERE c.can_create +ON CONFLICT DO NOTHING; + +-- Метаданные для админки / отладки +INSERT INTO global_data (var, value) +VALUES + ('essence_creatable_classes', '0,10,18,25,31,38,44,49,53,123,124,182,183'), + ('essence_races_enabled', '0,1,2,3,4,5,6') +ON CONFLICT (var) DO UPDATE SET value = EXCLUDED.value; diff --git a/install.sh b/install.sh index fcf8a77..a4f0699 100644 --- a/install.sh +++ b/install.sh @@ -197,6 +197,7 @@ EV_PORT="$(read_env_val POSTGRES_PORT)" info "Строка подключения с хоста Ubuntu: postgresql://${EV_USER}:***@127.0.0.1:${EV_PORT}/${EV_DB}" info "Из контейнеров в этой compose-сети: хост postgres, порт 5432." info "Тест-аккаунты: admin/admin и test/test." +info "Классы: ref_classes / class_list (создание: 0,10,18,25,31,38,44,49,53,123,124,182,183)." info "Клиент: protocol 520, логин 127.0.0.1:2106, мир 127.0.0.1:7777." echo "" info "Полезные команды:"