модуль npc дипломатов
This commit is contained in:
Vendored
+4
@@ -125,4 +125,8 @@
|
|||||||
"C_Cpp.default.compilerPath": "/usr/bin/clang",
|
"C_Cpp.default.compilerPath": "/usr/bin/clang",
|
||||||
"cmake.sourceDirectory": ["${workspaceFolder}"],
|
"cmake.sourceDirectory": ["${workspaceFolder}"],
|
||||||
"cmake.buildDirectory": "${workspaceFolder}/var/build",
|
"cmake.buildDirectory": "${workspaceFolder}/var/build",
|
||||||
|
"Lua.diagnostics.globals": [
|
||||||
|
"RegisterCreatureGossipEvent",
|
||||||
|
"GetConfigValue"
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Start Zone Race Teleporters
|
||||||
|
|
||||||
|
Eluna module for race-specific start-zone teleport NPCs.
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- `start_zone_race_teleporters.lua`
|
||||||
|
- Generic gossip handler for all teleporter NPC entries.
|
||||||
|
- `sql/world/start_zone_race_teleporters.sql`
|
||||||
|
- Base world SQL for `creature_template` and `creature_template_model`.
|
||||||
|
- Stores ASCII fallback names in base tables and Russian `ruRU` strings in locale tables.
|
||||||
|
- Imported automatically by `./setup-modules.sh` when `ac-database` is running.
|
||||||
|
- `sql/world/examples/start_zone_race_teleporters_human_start_example.sql`
|
||||||
|
- Manual example spawn SQL for the human start zone only.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The module SQL does not create all world spawns automatically.
|
||||||
|
- Use the example spawn file as a template and add your own spawns for each start zone.
|
||||||
|
- Draenei and blood elf access are gated in Lua through the adapters in `start_zone_race_teleporters.lua`.
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
-- Example spawns for the human start zone (Northshire / Elwynn Forest).
|
||||||
|
-- This is intentionally a template: replace GUID range and exact coordinates for your layout.
|
||||||
|
-- The Lua script is generic, so you can repeat the same pattern for every other start zone.
|
||||||
|
|
||||||
|
SET @CGUID := 5300600; -- TODO: replace with a free creature GUID range on your world DB.
|
||||||
|
|
||||||
|
DELETE FROM `creature`
|
||||||
|
WHERE `guid` BETWEEN @CGUID AND @CGUID + 2;
|
||||||
|
|
||||||
|
INSERT INTO `creature` (
|
||||||
|
`guid`,
|
||||||
|
`id1`,
|
||||||
|
`id2`,
|
||||||
|
`id3`,
|
||||||
|
`map`,
|
||||||
|
`zoneId`,
|
||||||
|
`areaId`,
|
||||||
|
`spawnMask`,
|
||||||
|
`phaseMask`,
|
||||||
|
`equipment_id`,
|
||||||
|
`position_x`,
|
||||||
|
`position_y`,
|
||||||
|
`position_z`,
|
||||||
|
`orientation`,
|
||||||
|
`spawntimesecs`,
|
||||||
|
`wander_distance`,
|
||||||
|
`currentwaypoint`,
|
||||||
|
`curhealth`,
|
||||||
|
`curmana`,
|
||||||
|
`MovementType`,
|
||||||
|
`npcflag`,
|
||||||
|
`unit_flags`,
|
||||||
|
`dynamicflags`,
|
||||||
|
`ScriptName`,
|
||||||
|
`VerifiedBuild`,
|
||||||
|
`CreateObject`,
|
||||||
|
`Comment`
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
(@CGUID + 0, 910300, 0, 0, 0, 12, 0, 1, 1, 0, -8946.50, -136.20, 83.60, 0.95, 120, 0, 0, 0, 0, 0, 1, 0, 0, '', 12340, 0, 'Northshire example - dwarf teleporter'),
|
||||||
|
(@CGUID + 1, 910301, 0, 0, 0, 12, 0, 1, 1, 0, -8949.25, -132.70, 83.60, 1.15, 120, 0, 0, 0, 0, 0, 1, 0, 0, '', 12340, 0, 'Northshire example - night elf teleporter'),
|
||||||
|
(@CGUID + 2, 910302, 0, 0, 0, 12, 0, 1, 1, 0, -8952.10, -136.20, 83.60, 1.35, 120, 0, 0, 0, 0, 0, 1, 0, 0, '', 12340, 0, 'Northshire example - draenei teleporter');
|
||||||
@@ -0,0 +1,345 @@
|
|||||||
|
-- Start Zone Race Teleporters
|
||||||
|
-- World DB template for lua_scripts/StartZoneRaceTeleporters/start_zone_race_teleporters.lua
|
||||||
|
-- Imported automatically by ./setup-modules.sh when ac-database is running.
|
||||||
|
--
|
||||||
|
-- Safe default display IDs below reuse existing race placeholder/commoner models
|
||||||
|
-- from this local world DB. Replace them if you want female variants or custom looks.
|
||||||
|
-- Source examples:
|
||||||
|
-- Human male = 19178 (entry 18936, [PH] Gossip NPC, Human Male)
|
||||||
|
-- Dwarf male = 19174 (entry 19115, [PH] Gossip NPC, Dwarf Male)
|
||||||
|
-- Night Elf male= 19180 (entry 19116, [PH] Gossip NPC, Night Elf Male)
|
||||||
|
-- Orc male = 19182 (entry 19117, [PH] Gossip NPC, Orc Male)
|
||||||
|
-- Undead male = 19188 (entry 19119, [PH] Gossip NPC, Undead Male)
|
||||||
|
-- Tauren male = 19184 (entry 19118, [PH] Gossip NPC, Tauren Male)
|
||||||
|
-- Draenei male = 19172 (entry 19114, [PH] Gossip NPC, Draenei Male)
|
||||||
|
-- Blood Elf male= 19170 (entry 19113, [PH] Gossip NPC, Blood Elf Male)
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
|
||||||
|
SET @DISPLAY_HUMAN_MALE := 19178;
|
||||||
|
SET @DISPLAY_DWARF_MALE := 19174;
|
||||||
|
SET @DISPLAY_NIGHTELF_MALE := 19180;
|
||||||
|
SET @DISPLAY_ORC_MALE := 19182;
|
||||||
|
SET @DISPLAY_UNDEAD_MALE := 19188;
|
||||||
|
SET @DISPLAY_TAUREN_MALE := 19184;
|
||||||
|
SET @DISPLAY_DRAENEI_MALE := 19172;
|
||||||
|
SET @DISPLAY_BLOODELF_MALE := 19170;
|
||||||
|
|
||||||
|
SET @NPC_TEXT_HUMAN := 9102400;
|
||||||
|
SET @NPC_TEXT_DWARF := 9102401;
|
||||||
|
SET @NPC_TEXT_NIGHTELF := 9102402;
|
||||||
|
SET @NPC_TEXT_DRAENEI := 9102403;
|
||||||
|
SET @NPC_TEXT_ORC := 9102404;
|
||||||
|
SET @NPC_TEXT_UNDEAD := 9102405;
|
||||||
|
SET @NPC_TEXT_TAUREN := 9102406;
|
||||||
|
SET @NPC_TEXT_BLOODELF := 9102407;
|
||||||
|
|
||||||
|
-- Cache-bust migration:
|
||||||
|
-- move old teleporter spawns (910200-910223) to the new entry range (910300-910323)
|
||||||
|
-- so existing client-side creature cache does not keep showing stale names.
|
||||||
|
UPDATE `creature`
|
||||||
|
SET `id1` = CASE `id1`
|
||||||
|
WHEN 910200 THEN 910300
|
||||||
|
WHEN 910201 THEN 910301
|
||||||
|
WHEN 910202 THEN 910302
|
||||||
|
WHEN 910203 THEN 910303
|
||||||
|
WHEN 910204 THEN 910304
|
||||||
|
WHEN 910205 THEN 910305
|
||||||
|
WHEN 910206 THEN 910306
|
||||||
|
WHEN 910207 THEN 910307
|
||||||
|
WHEN 910208 THEN 910308
|
||||||
|
WHEN 910209 THEN 910309
|
||||||
|
WHEN 910210 THEN 910310
|
||||||
|
WHEN 910211 THEN 910311
|
||||||
|
WHEN 910212 THEN 910312
|
||||||
|
WHEN 910213 THEN 910313
|
||||||
|
WHEN 910214 THEN 910314
|
||||||
|
WHEN 910215 THEN 910315
|
||||||
|
WHEN 910216 THEN 910316
|
||||||
|
WHEN 910217 THEN 910317
|
||||||
|
WHEN 910218 THEN 910318
|
||||||
|
WHEN 910219 THEN 910319
|
||||||
|
WHEN 910220 THEN 910320
|
||||||
|
WHEN 910221 THEN 910321
|
||||||
|
WHEN 910222 THEN 910322
|
||||||
|
WHEN 910223 THEN 910323
|
||||||
|
ELSE `id1`
|
||||||
|
END
|
||||||
|
WHERE `id1` IN (
|
||||||
|
910200, 910201, 910202,
|
||||||
|
910203, 910204, 910205,
|
||||||
|
910206, 910207, 910208,
|
||||||
|
910209, 910210, 910211,
|
||||||
|
910212, 910213, 910214,
|
||||||
|
910215, 910216, 910217,
|
||||||
|
910218, 910219, 910220,
|
||||||
|
910221, 910222, 910223
|
||||||
|
);
|
||||||
|
|
||||||
|
DELETE FROM `npc_text`
|
||||||
|
WHERE `ID` IN (
|
||||||
|
@NPC_TEXT_HUMAN,
|
||||||
|
@NPC_TEXT_DWARF,
|
||||||
|
@NPC_TEXT_NIGHTELF,
|
||||||
|
@NPC_TEXT_DRAENEI,
|
||||||
|
@NPC_TEXT_ORC,
|
||||||
|
@NPC_TEXT_UNDEAD,
|
||||||
|
@NPC_TEXT_TAUREN,
|
||||||
|
@NPC_TEXT_BLOODELF
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO `npc_text` (`ID`, `text0_0`, `text0_1`)
|
||||||
|
VALUES
|
||||||
|
(@NPC_TEXT_HUMAN, 'I represent the humans. Are you ready to travel with me?', 'I represent the humans. Are you ready to travel with me?'),
|
||||||
|
(@NPC_TEXT_DWARF, 'I represent the dwarves. Are you ready to travel with me?', 'I represent the dwarves. Are you ready to travel with me?'),
|
||||||
|
(@NPC_TEXT_NIGHTELF, 'I represent the night elves. Are you ready to travel with me?', 'I represent the night elves. Are you ready to travel with me?'),
|
||||||
|
(@NPC_TEXT_DRAENEI, 'I represent the draenei. Are you ready to travel with me?', 'I represent the draenei. Are you ready to travel with me?'),
|
||||||
|
(@NPC_TEXT_ORC, 'I represent the orcs. Are you ready to travel with me?', 'I represent the orcs. Are you ready to travel with me?'),
|
||||||
|
(@NPC_TEXT_UNDEAD, 'I represent the undead. Are you ready to travel with me?', 'I represent the undead. Are you ready to travel with me?'),
|
||||||
|
(@NPC_TEXT_TAUREN, 'I represent the tauren. Are you ready to travel with me?', 'I represent the tauren. Are you ready to travel with me?'),
|
||||||
|
(@NPC_TEXT_BLOODELF, 'I represent the blood elves. Are you ready to travel with me?', 'I represent the blood elves. Are you ready to travel with me?');
|
||||||
|
|
||||||
|
DELETE FROM `npc_text_locale`
|
||||||
|
WHERE `ID` IN (
|
||||||
|
@NPC_TEXT_HUMAN,
|
||||||
|
@NPC_TEXT_DWARF,
|
||||||
|
@NPC_TEXT_NIGHTELF,
|
||||||
|
@NPC_TEXT_DRAENEI,
|
||||||
|
@NPC_TEXT_ORC,
|
||||||
|
@NPC_TEXT_UNDEAD,
|
||||||
|
@NPC_TEXT_TAUREN,
|
||||||
|
@NPC_TEXT_BLOODELF
|
||||||
|
)
|
||||||
|
AND `Locale` = 'ruRU';
|
||||||
|
|
||||||
|
INSERT INTO `npc_text_locale` (`ID`, `Locale`, `Text0_0`, `Text0_1`)
|
||||||
|
VALUES
|
||||||
|
(@NPC_TEXT_HUMAN, 'ruRU', 'Я представитель людей. Ты готов отправиться со мной?', 'Я представитель людей. Ты готов отправиться со мной?'),
|
||||||
|
(@NPC_TEXT_DWARF, 'ruRU', 'Я представитель дворфов. Ты готов отправиться со мной?', 'Я представитель дворфов. Ты готов отправиться со мной?'),
|
||||||
|
(@NPC_TEXT_NIGHTELF, 'ruRU', 'Я представитель ночных эльфов. Ты готов отправиться со мной?', 'Я представитель ночных эльфов. Ты готов отправиться со мной?'),
|
||||||
|
(@NPC_TEXT_DRAENEI, 'ruRU', 'Я представитель дренеев. Ты готов отправиться со мной?', 'Я представитель дренеев. Ты готов отправиться со мной?'),
|
||||||
|
(@NPC_TEXT_ORC, 'ruRU', 'Я представитель орков. Ты готов отправиться со мной?', 'Я представитель орков. Ты готов отправиться со мной?'),
|
||||||
|
(@NPC_TEXT_UNDEAD, 'ruRU', 'Я представитель нежити. Ты готов отправиться со мной?', 'Я представитель нежити. Ты готов отправиться со мной?'),
|
||||||
|
(@NPC_TEXT_TAUREN, 'ruRU', 'Я представитель тауренов. Ты готов отправиться со мной?', 'Я представитель тауренов. Ты готов отправиться со мной?'),
|
||||||
|
(@NPC_TEXT_BLOODELF, 'ruRU', 'Я представитель эльфов крови. Ты готов отправиться со мной?', 'Я представитель эльфов крови. Ты готов отправиться со мной?');
|
||||||
|
|
||||||
|
DELETE FROM `creature_template_model`
|
||||||
|
WHERE `CreatureID` IN (
|
||||||
|
910200, 910201, 910202,
|
||||||
|
910203, 910204, 910205,
|
||||||
|
910206, 910207, 910208,
|
||||||
|
910209, 910210, 910211,
|
||||||
|
910212, 910213, 910214,
|
||||||
|
910215, 910216, 910217,
|
||||||
|
910218, 910219, 910220,
|
||||||
|
910221, 910222, 910223,
|
||||||
|
910300, 910301, 910302,
|
||||||
|
910303, 910304, 910305,
|
||||||
|
910306, 910307, 910308,
|
||||||
|
910309, 910310, 910311,
|
||||||
|
910312, 910313, 910314,
|
||||||
|
910315, 910316, 910317,
|
||||||
|
910318, 910319, 910320,
|
||||||
|
910321, 910322, 910323
|
||||||
|
);
|
||||||
|
|
||||||
|
DELETE FROM `creature_template`
|
||||||
|
WHERE `entry` IN (
|
||||||
|
910200, 910201, 910202,
|
||||||
|
910203, 910204, 910205,
|
||||||
|
910206, 910207, 910208,
|
||||||
|
910209, 910210, 910211,
|
||||||
|
910212, 910213, 910214,
|
||||||
|
910215, 910216, 910217,
|
||||||
|
910218, 910219, 910220,
|
||||||
|
910221, 910222, 910223,
|
||||||
|
910300, 910301, 910302,
|
||||||
|
910303, 910304, 910305,
|
||||||
|
910306, 910307, 910308,
|
||||||
|
910309, 910310, 910311,
|
||||||
|
910312, 910313, 910314,
|
||||||
|
910315, 910316, 910317,
|
||||||
|
910318, 910319, 910320,
|
||||||
|
910321, 910322, 910323
|
||||||
|
);
|
||||||
|
|
||||||
|
DELETE FROM `creature_template_locale`
|
||||||
|
WHERE `entry` IN (
|
||||||
|
910200, 910201, 910202,
|
||||||
|
910203, 910204, 910205,
|
||||||
|
910206, 910207, 910208,
|
||||||
|
910209, 910210, 910211,
|
||||||
|
910212, 910213, 910214,
|
||||||
|
910215, 910216, 910217,
|
||||||
|
910218, 910219, 910220,
|
||||||
|
910221, 910222, 910223,
|
||||||
|
910300, 910301, 910302,
|
||||||
|
910303, 910304, 910305,
|
||||||
|
910306, 910307, 910308,
|
||||||
|
910309, 910310, 910311,
|
||||||
|
910312, 910313, 910314,
|
||||||
|
910315, 910316, 910317,
|
||||||
|
910318, 910319, 910320,
|
||||||
|
910321, 910322, 910323
|
||||||
|
)
|
||||||
|
AND `locale` = 'ruRU';
|
||||||
|
|
||||||
|
INSERT INTO `creature_template` (
|
||||||
|
`entry`,
|
||||||
|
`difficulty_entry_1`,
|
||||||
|
`difficulty_entry_2`,
|
||||||
|
`difficulty_entry_3`,
|
||||||
|
`KillCredit1`,
|
||||||
|
`KillCredit2`,
|
||||||
|
`name`,
|
||||||
|
`subname`,
|
||||||
|
`IconName`,
|
||||||
|
`gossip_menu_id`,
|
||||||
|
`minlevel`,
|
||||||
|
`maxlevel`,
|
||||||
|
`exp`,
|
||||||
|
`faction`,
|
||||||
|
`npcflag`,
|
||||||
|
`speed_walk`,
|
||||||
|
`speed_run`,
|
||||||
|
`speed_swim`,
|
||||||
|
`speed_flight`,
|
||||||
|
`detection_range`,
|
||||||
|
`scale`,
|
||||||
|
`rank`,
|
||||||
|
`dmgschool`,
|
||||||
|
`DamageModifier`,
|
||||||
|
`BaseAttackTime`,
|
||||||
|
`RangeAttackTime`,
|
||||||
|
`BaseVariance`,
|
||||||
|
`RangeVariance`,
|
||||||
|
`unit_class`,
|
||||||
|
`unit_flags`,
|
||||||
|
`unit_flags2`,
|
||||||
|
`dynamicflags`,
|
||||||
|
`family`,
|
||||||
|
`type`,
|
||||||
|
`type_flags`,
|
||||||
|
`lootid`,
|
||||||
|
`pickpocketloot`,
|
||||||
|
`skinloot`,
|
||||||
|
`PetSpellDataId`,
|
||||||
|
`VehicleId`,
|
||||||
|
`mingold`,
|
||||||
|
`maxgold`,
|
||||||
|
`AIName`,
|
||||||
|
`MovementType`,
|
||||||
|
`HoverHeight`,
|
||||||
|
`HealthModifier`,
|
||||||
|
`ManaModifier`,
|
||||||
|
`ArmorModifier`,
|
||||||
|
`ExperienceModifier`,
|
||||||
|
`RacialLeader`,
|
||||||
|
`movementId`,
|
||||||
|
`RegenHealth`,
|
||||||
|
`mechanic_immune_mask`,
|
||||||
|
`spell_school_immune_mask`,
|
||||||
|
`flags_extra`,
|
||||||
|
`ScriptName`,
|
||||||
|
`VerifiedBuild`
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
(910300, 0, 0, 0, 0, 0, 'Bromdur', 'Envoy of the Dwarves', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- human host -> dwarf destination
|
||||||
|
(910301, 0, 0, 0, 0, 0, 'Laelina', 'Envoy of the Night Elves', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- human host -> night elf destination
|
||||||
|
(910302, 0, 0, 0, 0, 0, 'Velaris', 'Envoy of the Draenei', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- human host -> draenei destination
|
||||||
|
|
||||||
|
(910303, 0, 0, 0, 0, 0, 'Edric', 'Envoy of the Humans', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- dwarf host -> human destination
|
||||||
|
(910304, 0, 0, 0, 0, 0, 'Shaeris', 'Envoy of the Night Elves', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- dwarf host -> night elf destination
|
||||||
|
(910305, 0, 0, 0, 0, 0, 'Irenius', 'Envoy of the Draenei', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- dwarf host -> draenei destination
|
||||||
|
|
||||||
|
(910306, 0, 0, 0, 0, 0, 'Roland', 'Envoy of the Humans', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- night elf host -> human destination
|
||||||
|
(910307, 0, 0, 0, 0, 0, 'Targrim', 'Envoy of the Dwarves', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- night elf host -> dwarf destination
|
||||||
|
(910308, 0, 0, 0, 0, 0, 'Adara', 'Envoy of the Draenei', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- night elf host -> draenei destination
|
||||||
|
|
||||||
|
(910309, 0, 0, 0, 0, 0, 'Mariella', 'Envoy of the Humans', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- draenei host -> human destination
|
||||||
|
(910310, 0, 0, 0, 0, 0, 'Kazgrim', 'Envoy of the Dwarves', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- draenei host -> dwarf destination
|
||||||
|
(910311, 0, 0, 0, 0, 0, 'Telarion', 'Envoy of the Night Elves', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- draenei host -> night elf destination
|
||||||
|
|
||||||
|
(910312, 0, 0, 0, 0, 0, 'Morvena', 'Envoy of the Forsaken', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- orc host -> undead destination
|
||||||
|
(910313, 0, 0, 0, 0, 0, 'Stonehorn', 'Envoy of the Tauren', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- orc host -> tauren destination
|
||||||
|
(910314, 0, 0, 0, 0, 0, 'Kalariel', 'Envoy of the Blood Elves', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- orc host -> blood elf destination
|
||||||
|
|
||||||
|
(910315, 0, 0, 0, 0, 0, 'Gorkan', 'Envoy of the Orcs', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- undead host -> orc destination
|
||||||
|
(910316, 0, 0, 0, 0, 0, 'Quietwind', 'Envoy of the Tauren', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- undead host -> tauren destination
|
||||||
|
(910317, 0, 0, 0, 0, 0, 'Selinar', 'Envoy of the Blood Elves', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- undead host -> blood elf destination
|
||||||
|
|
||||||
|
(910318, 0, 0, 0, 0, 0, 'Durmak', 'Envoy of the Orcs', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- tauren host -> orc destination
|
||||||
|
(910319, 0, 0, 0, 0, 0, 'Syren', 'Envoy of the Forsaken', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- tauren host -> undead destination
|
||||||
|
(910320, 0, 0, 0, 0, 0, 'Liadra', 'Envoy of the Blood Elves', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- tauren host -> blood elf destination
|
||||||
|
|
||||||
|
(910321, 0, 0, 0, 0, 0, 'Targok', 'Envoy of the Orcs', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- blood elf host -> orc destination
|
||||||
|
(910322, 0, 0, 0, 0, 0, 'Vargos', 'Envoy of the Forsaken', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340), -- blood elf host -> undead destination
|
||||||
|
(910323, 0, 0, 0, 0, 0, 'Graybull', 'Envoy of the Tauren', NULL, 0, 1, 1, 0, 35, 1, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340); -- blood elf host -> tauren destination
|
||||||
|
|
||||||
|
INSERT INTO `creature_template_locale` (`entry`, `locale`, `Name`, `Title`, `VerifiedBuild`)
|
||||||
|
VALUES
|
||||||
|
(910300, 'ruRU', 'Бромдур', 'Посланник дворфов', 12340),
|
||||||
|
(910301, 'ruRU', 'Лаэлина', 'Посланник ночных эльфов', 12340),
|
||||||
|
(910302, 'ruRU', 'Веларис', 'Посланник дренеев', 12340),
|
||||||
|
(910303, 'ruRU', 'Эдрик', 'Посланник людей', 12340),
|
||||||
|
(910304, 'ruRU', 'Шаэрис', 'Посланник ночных эльфов', 12340),
|
||||||
|
(910305, 'ruRU', 'Ирений', 'Посланник дренеев', 12340),
|
||||||
|
(910306, 'ruRU', 'Роланд', 'Посланник людей', 12340),
|
||||||
|
(910307, 'ruRU', 'Таргрим', 'Посланник дворфов', 12340),
|
||||||
|
(910308, 'ruRU', 'Адара', 'Посланник дренеев', 12340),
|
||||||
|
(910309, 'ruRU', 'Мариэлла', 'Посланник людей', 12340),
|
||||||
|
(910310, 'ruRU', 'Казгрим', 'Посланник дворфов', 12340),
|
||||||
|
(910311, 'ruRU', 'Тэларион', 'Посланник ночных эльфов', 12340),
|
||||||
|
(910312, 'ruRU', 'Морвена', 'Посланник нежити', 12340),
|
||||||
|
(910313, 'ruRU', 'Камнерог', 'Посланник тауренов', 12340),
|
||||||
|
(910314, 'ruRU', 'Калариэль', 'Посланник эльфов крови', 12340),
|
||||||
|
(910315, 'ruRU', 'Горкан', 'Посланник орков', 12340),
|
||||||
|
(910316, 'ruRU', 'Тихий Ветер', 'Посланник тауренов', 12340),
|
||||||
|
(910317, 'ruRU', 'Селинар', 'Посланник эльфов крови', 12340),
|
||||||
|
(910318, 'ruRU', 'Дурмак', 'Посланник орков', 12340),
|
||||||
|
(910319, 'ruRU', 'Сайрен', 'Посланник нежити', 12340),
|
||||||
|
(910320, 'ruRU', 'Лиадра', 'Посланник эльфов крови', 12340),
|
||||||
|
(910321, 'ruRU', 'Таргок', 'Посланник орков', 12340),
|
||||||
|
(910322, 'ruRU', 'Варгос', 'Посланник нежити', 12340),
|
||||||
|
(910323, 'ruRU', 'Седой Бык', 'Посланник тауренов', 12340);
|
||||||
|
|
||||||
|
INSERT INTO `creature_template_model` (
|
||||||
|
`CreatureID`,
|
||||||
|
`Idx`,
|
||||||
|
`CreatureDisplayID`,
|
||||||
|
`DisplayScale`,
|
||||||
|
`Probability`,
|
||||||
|
`VerifiedBuild`
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
(910300, 0, @DISPLAY_DWARF_MALE, 1, 1, 12340),
|
||||||
|
(910301, 0, @DISPLAY_NIGHTELF_MALE, 1, 1, 12340),
|
||||||
|
(910302, 0, @DISPLAY_DRAENEI_MALE, 1, 1, 12340),
|
||||||
|
|
||||||
|
(910303, 0, @DISPLAY_HUMAN_MALE, 1, 1, 12340),
|
||||||
|
(910304, 0, @DISPLAY_NIGHTELF_MALE, 1, 1, 12340),
|
||||||
|
(910305, 0, @DISPLAY_DRAENEI_MALE, 1, 1, 12340),
|
||||||
|
|
||||||
|
(910306, 0, @DISPLAY_HUMAN_MALE, 1, 1, 12340),
|
||||||
|
(910307, 0, @DISPLAY_DWARF_MALE, 1, 1, 12340),
|
||||||
|
(910308, 0, @DISPLAY_DRAENEI_MALE, 1, 1, 12340),
|
||||||
|
|
||||||
|
(910309, 0, @DISPLAY_HUMAN_MALE, 1, 1, 12340),
|
||||||
|
(910310, 0, @DISPLAY_DWARF_MALE, 1, 1, 12340),
|
||||||
|
(910311, 0, @DISPLAY_NIGHTELF_MALE, 1, 1, 12340),
|
||||||
|
|
||||||
|
(910312, 0, @DISPLAY_UNDEAD_MALE, 1, 1, 12340),
|
||||||
|
(910313, 0, @DISPLAY_TAUREN_MALE, 1, 1, 12340),
|
||||||
|
(910314, 0, @DISPLAY_BLOODELF_MALE, 1, 1, 12340),
|
||||||
|
|
||||||
|
(910315, 0, @DISPLAY_ORC_MALE, 1, 1, 12340),
|
||||||
|
(910316, 0, @DISPLAY_TAUREN_MALE, 1, 1, 12340),
|
||||||
|
(910317, 0, @DISPLAY_BLOODELF_MALE, 1, 1, 12340),
|
||||||
|
|
||||||
|
(910318, 0, @DISPLAY_ORC_MALE, 1, 1, 12340),
|
||||||
|
(910319, 0, @DISPLAY_UNDEAD_MALE, 1, 1, 12340),
|
||||||
|
(910320, 0, @DISPLAY_BLOODELF_MALE, 1, 1, 12340),
|
||||||
|
|
||||||
|
(910321, 0, @DISPLAY_ORC_MALE, 1, 1, 12340),
|
||||||
|
(910322, 0, @DISPLAY_UNDEAD_MALE, 1, 1, 12340),
|
||||||
|
(910323, 0, @DISPLAY_TAUREN_MALE, 1, 1, 12340);
|
||||||
@@ -0,0 +1,487 @@
|
|||||||
|
local SCRIPT_NAME = "start_zone_race_teleporters"
|
||||||
|
|
||||||
|
local GOSSIP_EVENT_ON_HELLO = 1
|
||||||
|
local GOSSIP_EVENT_ON_SELECT = 2
|
||||||
|
|
||||||
|
local GOSSIP_ICON_CHAT = 0
|
||||||
|
local GOSSIP_SENDER_MAIN = 0
|
||||||
|
local ACTION_TELEPORT = 100
|
||||||
|
local ACTION_TELEPORT_BLOCKED = 101
|
||||||
|
local ACTION_CLOSE = 102
|
||||||
|
local DEFAULT_GOSSIP_TEXT_ID = 1
|
||||||
|
|
||||||
|
local PROGRESSION_SETTINGS_SOURCE = "mod-individual-progression"
|
||||||
|
local PROGRESSION_SETTING_INDEX = 0
|
||||||
|
local DEFAULT_INDIVIDUAL_PROGRESSION_ENABLED = true -- Matches mod-individual-progression source default.
|
||||||
|
local DEFAULT_TBC_RACES_UNLOCK_PROGRESSION = 0 -- Matches mod-individual-progression source default.
|
||||||
|
|
||||||
|
local QUEST_STATUS_COMPLETE = 1
|
||||||
|
local QUEST_STATUS_REWARDED = 6
|
||||||
|
|
||||||
|
local FALLBACK_TBC_RACES_ALLOW_CONFIG_KEY = "StartZoneRaceTeleporters.AllowTbcRacesTeleport"
|
||||||
|
local FALLBACK_TBC_RACES_ALLOW_CONFIG_KEY_LEGACY = "StartZoneRaceTeleporters.AllowDraeneiTeleport" -- Legacy alias for older local configs.
|
||||||
|
local FALLBACK_TBC_RACES_REQUIRED_QUEST_ID = 0 -- TODO: replace with a confirmed unlock quest if you use quest/status fallback.
|
||||||
|
local FALLBACK_TBC_RACES_DEFAULT_ACCESS = false
|
||||||
|
|
||||||
|
local TRAVEL_BUTTON_LABEL = "Отправляемся в путь"
|
||||||
|
local CLOSE_BUTTON_LABEL = "Я пока останусь"
|
||||||
|
local UNAVAILABLE_SUFFIX = " [Недоступно]"
|
||||||
|
local ACCESS_DENIED_MESSAGE_DRAENEI = "Доступ к стартовой зоне дренеев ещё не открыт вашим индивидуальным прогрессом."
|
||||||
|
local ACCESS_DENIED_MESSAGE_BLOODELF = "Доступ к стартовой зоне эльфов крови ещё не открыт вашим индивидуальным прогрессом."
|
||||||
|
local INVALID_CONFIGURATION_MESSAGE = "Конфигурация телепорта не завершена. Сообщите администратору."
|
||||||
|
|
||||||
|
local LOCATIONS = {
|
||||||
|
-- These coordinates come from the local playercreateinfo table.
|
||||||
|
-- TODO: replace them if you want a custom landing point instead of the raw race spawn.
|
||||||
|
human = { map = 0, x = -8949.95, y = -132.493, z = 83.5312, o = 0.0 },
|
||||||
|
dwarf = { map = 0, x = -6240.32, y = 331.033, z = 382.758, o = 6.17716 },
|
||||||
|
nightelf = { map = 1, x = 10311.3, y = 832.463, z = 1326.41, o = 5.69632 },
|
||||||
|
orc = { map = 1, x = -618.518, y = -4251.67, z = 38.718, o = 0.0 },
|
||||||
|
undead = { map = 0, x = 1676.71, y = 1678.31, z = 121.67, o = 2.70526 },
|
||||||
|
tauren = { map = 1, x = -2917.58, y = -257.98, z = 52.9968, o = 0.0 },
|
||||||
|
draenei = { map = 530, x = -3961.64, y = -13931.2, z = 100.615, o = 2.08364 },
|
||||||
|
bloodelf = { map = 530, x = 10349.6, y = -6357.29, z = 33.4026, o = 5.31605 },
|
||||||
|
}
|
||||||
|
|
||||||
|
local PRESENTER_PROFILES = {
|
||||||
|
human = {
|
||||||
|
gossipTextId = 9102400,
|
||||||
|
},
|
||||||
|
dwarf = {
|
||||||
|
gossipTextId = 9102401,
|
||||||
|
},
|
||||||
|
nightelf = {
|
||||||
|
gossipTextId = 9102402,
|
||||||
|
},
|
||||||
|
draenei = {
|
||||||
|
gossipTextId = 9102403,
|
||||||
|
},
|
||||||
|
orc = {
|
||||||
|
gossipTextId = 9102404,
|
||||||
|
},
|
||||||
|
undead = {
|
||||||
|
gossipTextId = 9102405,
|
||||||
|
},
|
||||||
|
tauren = {
|
||||||
|
gossipTextId = 9102406,
|
||||||
|
},
|
||||||
|
bloodelf = {
|
||||||
|
gossipTextId = 9102407,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local DESTINATIONS = {
|
||||||
|
human = {
|
||||||
|
label = "Стартовая зона людей",
|
||||||
|
requiresIndividualProgress = false,
|
||||||
|
requiredProgressKey = nil,
|
||||||
|
},
|
||||||
|
dwarf = {
|
||||||
|
label = "Стартовая зона дворфов и гномов",
|
||||||
|
requiresIndividualProgress = false,
|
||||||
|
requiredProgressKey = nil,
|
||||||
|
},
|
||||||
|
nightelf = {
|
||||||
|
label = "Стартовая зона ночных эльфов",
|
||||||
|
requiresIndividualProgress = false,
|
||||||
|
requiredProgressKey = nil,
|
||||||
|
},
|
||||||
|
orc = {
|
||||||
|
label = "Стартовая зона орков и троллей",
|
||||||
|
requiresIndividualProgress = false,
|
||||||
|
requiredProgressKey = nil,
|
||||||
|
},
|
||||||
|
undead = {
|
||||||
|
label = "Стартовая зона нежити",
|
||||||
|
requiresIndividualProgress = false,
|
||||||
|
requiredProgressKey = nil,
|
||||||
|
},
|
||||||
|
tauren = {
|
||||||
|
label = "Стартовая зона тауренов",
|
||||||
|
requiresIndividualProgress = false,
|
||||||
|
requiredProgressKey = nil,
|
||||||
|
},
|
||||||
|
draenei = {
|
||||||
|
label = "Стартовая зона дренеев",
|
||||||
|
requiresIndividualProgress = true,
|
||||||
|
requiredProgressKey = "draenei_start_zone",
|
||||||
|
},
|
||||||
|
bloodelf = {
|
||||||
|
label = "Стартовая зона эльфов крови",
|
||||||
|
requiresIndividualProgress = true,
|
||||||
|
requiredProgressKey = "bloodelf_start_zone",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local TELEPORTER_LAYOUT = {
|
||||||
|
-- One generic script serves every start zone.
|
||||||
|
-- The host zone key only documents where each entry is meant to be spawned.
|
||||||
|
human = {
|
||||||
|
{ entry = 910300, destinationKey = "dwarf" },
|
||||||
|
{ entry = 910301, destinationKey = "nightelf" },
|
||||||
|
{ entry = 910302, destinationKey = "draenei" },
|
||||||
|
},
|
||||||
|
dwarf = {
|
||||||
|
{ entry = 910303, destinationKey = "human" },
|
||||||
|
{ entry = 910304, destinationKey = "nightelf" },
|
||||||
|
{ entry = 910305, destinationKey = "draenei" },
|
||||||
|
},
|
||||||
|
nightelf = {
|
||||||
|
{ entry = 910306, destinationKey = "human" },
|
||||||
|
{ entry = 910307, destinationKey = "dwarf" },
|
||||||
|
{ entry = 910308, destinationKey = "draenei" },
|
||||||
|
},
|
||||||
|
draenei = {
|
||||||
|
{ entry = 910309, destinationKey = "human" },
|
||||||
|
{ entry = 910310, destinationKey = "dwarf" },
|
||||||
|
{ entry = 910311, destinationKey = "nightelf" },
|
||||||
|
},
|
||||||
|
orc = {
|
||||||
|
{ entry = 910312, destinationKey = "undead" },
|
||||||
|
{ entry = 910313, destinationKey = "tauren" },
|
||||||
|
{ entry = 910314, destinationKey = "bloodelf" },
|
||||||
|
},
|
||||||
|
undead = {
|
||||||
|
{ entry = 910315, destinationKey = "orc" },
|
||||||
|
{ entry = 910316, destinationKey = "tauren" },
|
||||||
|
{ entry = 910317, destinationKey = "bloodelf" },
|
||||||
|
},
|
||||||
|
tauren = {
|
||||||
|
{ entry = 910318, destinationKey = "orc" },
|
||||||
|
{ entry = 910319, destinationKey = "undead" },
|
||||||
|
{ entry = 910320, destinationKey = "bloodelf" },
|
||||||
|
},
|
||||||
|
bloodelf = {
|
||||||
|
{ entry = 910321, destinationKey = "orc" },
|
||||||
|
{ entry = 910322, destinationKey = "undead" },
|
||||||
|
{ entry = 910323, destinationKey = "tauren" },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local function SafeSendNotification(player, message)
|
||||||
|
if type(player.SendNotification) == "function" then
|
||||||
|
player:SendNotification(message)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
player:SendBroadcastMessage(message)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function SafeGetConfigValue(key)
|
||||||
|
if type(GetConfigValue) ~= "function" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, value = pcall(GetConfigValue, key)
|
||||||
|
if not ok then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
|
||||||
|
local function NormalizeBoolean(value)
|
||||||
|
if type(value) == "boolean" then
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(value) == "number" then
|
||||||
|
return value ~= 0
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(value) ~= "string" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local normalized = value:lower()
|
||||||
|
if normalized == "1" or normalized == "true" or normalized == "yes" then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if normalized == "0" or normalized == "false" or normalized == "no" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GetConfigNumber(key, defaultValue)
|
||||||
|
local value = SafeGetConfigValue(key)
|
||||||
|
if value == nil or value == "" then
|
||||||
|
return defaultValue
|
||||||
|
end
|
||||||
|
|
||||||
|
local numericValue = tonumber(value)
|
||||||
|
if numericValue == nil then
|
||||||
|
return defaultValue
|
||||||
|
end
|
||||||
|
|
||||||
|
return numericValue
|
||||||
|
end
|
||||||
|
|
||||||
|
local function RequireLocation(locationKey)
|
||||||
|
assert(LOCATIONS[locationKey] ~= nil, string.format("%s: missing LOCATIONS[%q]", SCRIPT_NAME, locationKey))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function CreateTeleporterConfig(hostZoneKey, destinationKey)
|
||||||
|
local destinationConfig = DESTINATIONS[destinationKey]
|
||||||
|
local presenterProfile = PRESENTER_PROFILES[destinationKey]
|
||||||
|
assert(destinationConfig ~= nil, string.format("%s: missing DESTINATIONS[%q]", SCRIPT_NAME, destinationKey))
|
||||||
|
assert(presenterProfile ~= nil, string.format("%s: missing PRESENTER_PROFILES[%q]", SCRIPT_NAME, destinationKey))
|
||||||
|
|
||||||
|
RequireLocation(hostZoneKey)
|
||||||
|
RequireLocation(destinationKey)
|
||||||
|
|
||||||
|
return {
|
||||||
|
hostZoneKey = hostZoneKey,
|
||||||
|
destinationKey = destinationKey,
|
||||||
|
label = destinationConfig.label,
|
||||||
|
requiresIndividualProgress = destinationConfig.requiresIndividualProgress,
|
||||||
|
requiredProgressKey = destinationConfig.requiredProgressKey,
|
||||||
|
gossipTextId = presenterProfile.gossipTextId,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function BuildTeleporterNpcTable()
|
||||||
|
local teleporterNpcs = {}
|
||||||
|
|
||||||
|
for hostZoneKey, presenters in pairs(TELEPORTER_LAYOUT) do
|
||||||
|
for _, presenter in ipairs(presenters) do
|
||||||
|
assert(teleporterNpcs[presenter.entry] == nil, string.format("%s: duplicate teleporter entry %d", SCRIPT_NAME, presenter.entry))
|
||||||
|
teleporterNpcs[presenter.entry] = CreateTeleporterConfig(hostZoneKey, presenter.destinationKey)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return teleporterNpcs
|
||||||
|
end
|
||||||
|
|
||||||
|
local TELEPORTER_NPCS = BuildTeleporterNpcTable()
|
||||||
|
|
||||||
|
local function GetTeleporterConfigByEntry(entry)
|
||||||
|
return TELEPORTER_NPCS[entry]
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GetDestinationLocation(destinationKey)
|
||||||
|
return LOCATIONS[destinationKey]
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GetCurrentServerRequiredProgress(requiredProgressKey)
|
||||||
|
if requiredProgressKey == "draenei_start_zone" or requiredProgressKey == "bloodelf_start_zone" then
|
||||||
|
return GetConfigNumber("IndividualProgression.TbcRacesUnlockProgression", DEFAULT_TBC_RACES_UNLOCK_PROGRESSION)
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function IsCurrentServerProgressIntegrationEnabled()
|
||||||
|
local enabled = NormalizeBoolean(SafeGetConfigValue("IndividualProgression.Enable"))
|
||||||
|
if enabled ~= nil then
|
||||||
|
return enabled
|
||||||
|
end
|
||||||
|
|
||||||
|
return DEFAULT_INDIVIDUAL_PROGRESSION_ENABLED
|
||||||
|
end
|
||||||
|
|
||||||
|
local function TryCurrentServerProgressAccess(player, requiredProgressKey)
|
||||||
|
if not IsCurrentServerProgressIntegrationEnabled() then
|
||||||
|
return false, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local requiredProgressValue = GetCurrentServerRequiredProgress(requiredProgressKey)
|
||||||
|
if requiredProgressValue == nil then
|
||||||
|
return false, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(player.GetPlayerSettingValue) ~= "function" then
|
||||||
|
return false, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Current server integration:
|
||||||
|
-- mod-eluna exposes Player:GetPlayerSettingValue(...)
|
||||||
|
-- mod-individual-progression stores the progression state under source/index below.
|
||||||
|
local ok, currentProgressValue = pcall(
|
||||||
|
player.GetPlayerSettingValue,
|
||||||
|
player,
|
||||||
|
PROGRESSION_SETTINGS_SOURCE,
|
||||||
|
PROGRESSION_SETTING_INDEX
|
||||||
|
)
|
||||||
|
|
||||||
|
if not ok or type(currentProgressValue) ~= "number" then
|
||||||
|
return false, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return true, currentProgressValue >= requiredProgressValue
|
||||||
|
end
|
||||||
|
|
||||||
|
local function CanUseTbcRacesTeleportFallback(player)
|
||||||
|
local allowByConfigFlag = NormalizeBoolean(SafeGetConfigValue(FALLBACK_TBC_RACES_ALLOW_CONFIG_KEY))
|
||||||
|
if allowByConfigFlag == nil then
|
||||||
|
allowByConfigFlag = NormalizeBoolean(SafeGetConfigValue(FALLBACK_TBC_RACES_ALLOW_CONFIG_KEY_LEGACY))
|
||||||
|
end
|
||||||
|
|
||||||
|
if allowByConfigFlag == true then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if FALLBACK_TBC_RACES_REQUIRED_QUEST_ID > 0 then
|
||||||
|
local questStatus = player:GetQuestStatus(FALLBACK_TBC_RACES_REQUIRED_QUEST_ID)
|
||||||
|
if questStatus == QUEST_STATUS_COMPLETE or questStatus == QUEST_STATUS_REWARDED then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: Replace this fallback with your final project-specific unlock signal
|
||||||
|
-- if the current server integration is unavailable or intentionally disabled.
|
||||||
|
-- This fallback intentionally gates both TBC races together.
|
||||||
|
return FALLBACK_TBC_RACES_DEFAULT_ACCESS
|
||||||
|
end
|
||||||
|
|
||||||
|
local function CanUseDraeneiTeleport(player)
|
||||||
|
local handled, allowed = TryCurrentServerProgressAccess(player, "draenei_start_zone")
|
||||||
|
if handled then
|
||||||
|
return allowed
|
||||||
|
end
|
||||||
|
|
||||||
|
return CanUseTbcRacesTeleportFallback(player)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function CanUseBloodElfTeleport(player)
|
||||||
|
local handled, allowed = TryCurrentServerProgressAccess(player, "bloodelf_start_zone")
|
||||||
|
if handled then
|
||||||
|
return allowed
|
||||||
|
end
|
||||||
|
|
||||||
|
return CanUseTbcRacesTeleportFallback(player)
|
||||||
|
end
|
||||||
|
|
||||||
|
local ACCESS_RULES = {
|
||||||
|
draenei_start_zone = CanUseDraeneiTeleport,
|
||||||
|
bloodelf_start_zone = CanUseBloodElfTeleport,
|
||||||
|
}
|
||||||
|
|
||||||
|
local function CanUseTeleporter(player, teleporterConfig)
|
||||||
|
if not teleporterConfig.requiresIndividualProgress or teleporterConfig.requiredProgressKey == nil then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local accessRule = ACCESS_RULES[teleporterConfig.requiredProgressKey]
|
||||||
|
if type(accessRule) ~= "function" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return accessRule(player) == true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function BuildTravelButtonLabel(player, teleporterConfig)
|
||||||
|
if CanUseTeleporter(player, teleporterConfig) then
|
||||||
|
return TRAVEL_BUTTON_LABEL
|
||||||
|
end
|
||||||
|
|
||||||
|
return TRAVEL_BUTTON_LABEL .. UNAVAILABLE_SUFFIX
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GetTravelActionId(player, teleporterConfig)
|
||||||
|
if CanUseTeleporter(player, teleporterConfig) then
|
||||||
|
return ACTION_TELEPORT
|
||||||
|
end
|
||||||
|
|
||||||
|
return ACTION_TELEPORT_BLOCKED
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GetGossipTextId(teleporterConfig)
|
||||||
|
if teleporterConfig ~= nil and type(teleporterConfig.gossipTextId) == "number" then
|
||||||
|
return teleporterConfig.gossipTextId
|
||||||
|
end
|
||||||
|
|
||||||
|
return DEFAULT_GOSSIP_TEXT_ID
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GetAccessDeniedMessage(teleporterConfig)
|
||||||
|
if teleporterConfig.requiredProgressKey == "draenei_start_zone" then
|
||||||
|
return ACCESS_DENIED_MESSAGE_DRAENEI
|
||||||
|
end
|
||||||
|
|
||||||
|
if teleporterConfig.requiredProgressKey == "bloodelf_start_zone" then
|
||||||
|
return ACCESS_DENIED_MESSAGE_BLOODELF
|
||||||
|
end
|
||||||
|
|
||||||
|
return INVALID_CONFIGURATION_MESSAGE
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ShowTeleporterMenu(player, creature, teleporterConfig)
|
||||||
|
player:GossipClearMenu()
|
||||||
|
player:GossipMenuAddItem(
|
||||||
|
GOSSIP_ICON_CHAT,
|
||||||
|
BuildTravelButtonLabel(player, teleporterConfig),
|
||||||
|
GOSSIP_SENDER_MAIN,
|
||||||
|
GetTravelActionId(player, teleporterConfig)
|
||||||
|
)
|
||||||
|
player:GossipMenuAddItem(
|
||||||
|
GOSSIP_ICON_CHAT,
|
||||||
|
CLOSE_BUTTON_LABEL,
|
||||||
|
GOSSIP_SENDER_MAIN,
|
||||||
|
ACTION_CLOSE
|
||||||
|
)
|
||||||
|
player:GossipSendMenu(GetGossipTextId(teleporterConfig), creature)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function TeleportPlayer(player, destinationKey)
|
||||||
|
local location = GetDestinationLocation(destinationKey)
|
||||||
|
if location == nil then
|
||||||
|
SafeSendNotification(player, INVALID_CONFIGURATION_MESSAGE)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
player:Teleport(location.map, location.x, location.y, location.z, location.o)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function RaceTeleporter_OnGossipHello(_, player, creature)
|
||||||
|
if player == nil or creature == nil then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local teleporterConfig = GetTeleporterConfigByEntry(creature:GetEntry())
|
||||||
|
if teleporterConfig == nil then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
ShowTeleporterMenu(player, creature, teleporterConfig)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function RaceTeleporter_OnGossipSelect(_, player, creature, _, intid)
|
||||||
|
if player == nil or creature == nil then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local teleporterConfig = GetTeleporterConfigByEntry(creature:GetEntry())
|
||||||
|
if teleporterConfig == nil then
|
||||||
|
player:GossipComplete()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if intid == ACTION_CLOSE then
|
||||||
|
player:GossipComplete()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if intid == ACTION_TELEPORT_BLOCKED then
|
||||||
|
SafeSendNotification(player, GetAccessDeniedMessage(teleporterConfig))
|
||||||
|
ShowTeleporterMenu(player, creature, teleporterConfig)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if intid ~= ACTION_TELEPORT then
|
||||||
|
player:GossipComplete()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
player:GossipComplete()
|
||||||
|
TeleportPlayer(player, teleporterConfig.destinationKey)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
for entry in pairs(TELEPORTER_NPCS) do
|
||||||
|
RegisterCreatureGossipEvent(entry, GOSSIP_EVENT_ON_HELLO, RaceTeleporter_OnGossipHello)
|
||||||
|
RegisterCreatureGossipEvent(entry, GOSSIP_EVENT_ON_SELECT, RaceTeleporter_OnGossipSelect)
|
||||||
|
end
|
||||||
@@ -76,6 +76,9 @@ FORCE_PLAYERBOTS="${FORCE_PLAYERBOTS:-${ACORE_PLAYERBOTS_FORCE:-0}}"
|
|||||||
: "${ACORE_ELUNA_PLAYER_ANNOUNCE_RELOAD:=false}"
|
: "${ACORE_ELUNA_PLAYER_ANNOUNCE_RELOAD:=false}"
|
||||||
: "${ACORE_ELUNA_REQUIRE_PATHS:=}"
|
: "${ACORE_ELUNA_REQUIRE_PATHS:=}"
|
||||||
: "${ACORE_ELUNA_REQUIRE_CPATHS:=}"
|
: "${ACORE_ELUNA_REQUIRE_CPATHS:=}"
|
||||||
|
#
|
||||||
|
# Local Lua module SQL bootstrap.
|
||||||
|
: "${ACORE_IMPORT_START_ZONE_RACE_TELEPORTERS_SQL:=1}"
|
||||||
|
|
||||||
: "${ACORE_LEARNSPELLS_GAMEMASTERS:=0}"
|
: "${ACORE_LEARNSPELLS_GAMEMASTERS:=0}"
|
||||||
: "${ACORE_LEARNSPELLS_CLASS_SPELLS:=1}"
|
: "${ACORE_LEARNSPELLS_CLASS_SPELLS:=1}"
|
||||||
@@ -122,6 +125,7 @@ usage() {
|
|||||||
Usage: $(basename "$0") [--dry-run] [--force-playerbots]
|
Usage: $(basename "$0") [--dry-run] [--force-playerbots]
|
||||||
|
|
||||||
Configures AzerothCore module configs for this repository layout.
|
Configures AzerothCore module configs for this repository layout.
|
||||||
|
If ac-database is already running, it also imports local Lua-module bootstrap SQL.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--dry-run Show actions without changing files
|
--dry-run Show actions without changing files
|
||||||
@@ -181,6 +185,16 @@ sync_file() {
|
|||||||
log "synced ${target#$ROOT_DIR/}"
|
log "synced ${target#$ROOT_DIR/}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require_integer_flag() {
|
||||||
|
local name="$1"
|
||||||
|
local value="$2"
|
||||||
|
|
||||||
|
if ! [[ "$value" =~ ^[01]$ ]]; then
|
||||||
|
printf '%s must be 0 or 1, got: %s\n' "$name" "$value" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
escape_regex() {
|
escape_regex() {
|
||||||
printf '%s' "$1" | sed 's/[][(){}.^$*+?|\\/]/\\&/g'
|
printf '%s' "$1" | sed 's/[][(){}.^$*+?|\\/]/\\&/g'
|
||||||
}
|
}
|
||||||
@@ -232,6 +246,48 @@ set_config_value() {
|
|||||||
log "appended ${key} to ${file#$ROOT_DIR/}"
|
log "appended ${key} to ${file#$ROOT_DIR/}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
database_service_running() {
|
||||||
|
if ! command -v docker >/dev/null 2>&1; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker compose ps --status running --services 2>/dev/null | grep -qx 'ac-database'
|
||||||
|
}
|
||||||
|
|
||||||
|
import_world_sql_file() {
|
||||||
|
local file_path="$1"
|
||||||
|
|
||||||
|
if [[ ! -f "$file_path" ]]; then
|
||||||
|
log "skip missing ${file_path#$ROOT_DIR/}"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( DRY_RUN )); then
|
||||||
|
log "would import ${file_path#$ROOT_DIR/} into acore_world"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker compose exec -T ac-database bash -lc \
|
||||||
|
"mysql --default-character-set=utf8mb4 -uroot -p\"\$MYSQL_ROOT_PASSWORD\" acore_world" < "$file_path"
|
||||||
|
log "imported ${file_path#$ROOT_DIR/} into acore_world"
|
||||||
|
}
|
||||||
|
|
||||||
|
import_local_lua_module_sql() {
|
||||||
|
local start_zone_race_teleporters_sql="$ROOT_DIR/lua_scripts/StartZoneRaceTeleporters/sql/world/start_zone_race_teleporters.sql"
|
||||||
|
|
||||||
|
if [[ "$ACORE_IMPORT_START_ZONE_RACE_TELEPORTERS_SQL" == "0" ]]; then
|
||||||
|
log "StartZoneRaceTeleporters SQL import disabled, skipped"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! database_service_running; then
|
||||||
|
log "skip StartZoneRaceTeleporters SQL: ac-database is not running"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
import_world_sql_file "$start_zone_race_teleporters_sql"
|
||||||
|
}
|
||||||
|
|
||||||
ensure_world_conf() {
|
ensure_world_conf() {
|
||||||
if [[ -f "$WORLD_CONF" ]]; then
|
if [[ -f "$WORLD_CONF" ]]; then
|
||||||
return
|
return
|
||||||
@@ -515,6 +571,8 @@ main() {
|
|||||||
log "root: $ROOT_DIR"
|
log "root: $ROOT_DIR"
|
||||||
log "etc: $ETC_DIR"
|
log "etc: $ETC_DIR"
|
||||||
|
|
||||||
|
require_integer_flag "ACORE_IMPORT_START_ZONE_RACE_TELEPORTERS_SQL" "$ACORE_IMPORT_START_ZONE_RACE_TELEPORTERS_SQL"
|
||||||
|
|
||||||
ensure_runtime_dirs
|
ensure_runtime_dirs
|
||||||
sync_module_dists
|
sync_module_dists
|
||||||
cleanup_legacy_module_overrides
|
cleanup_legacy_module_overrides
|
||||||
@@ -525,6 +583,7 @@ main() {
|
|||||||
write_eluna_conf
|
write_eluna_conf
|
||||||
write_learnspells_conf
|
write_learnspells_conf
|
||||||
write_playerbots_conf
|
write_playerbots_conf
|
||||||
|
import_local_lua_module_sql
|
||||||
|
|
||||||
log "module bootstrap completed"
|
log "module bootstrap completed"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,6 +192,9 @@ run_one_shot_service "ac-db-import" "ac-db-import"
|
|||||||
log "importing custom SQL"
|
log "importing custom SQL"
|
||||||
bash "$ROOT_DIR/import-custom-sql.sh"
|
bash "$ROOT_DIR/import-custom-sql.sh"
|
||||||
|
|
||||||
|
log "applying post-database module setup"
|
||||||
|
bash "$ROOT_DIR/setup-modules.sh"
|
||||||
|
|
||||||
log "initializing client data"
|
log "initializing client data"
|
||||||
run_one_shot_service "ac-client-data-init" "ac-client-data-init"
|
run_one_shot_service "ac-client-data-init" "ac-client-data-init"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user