feat(covenant): P2 - soulbind conduit collection + socketing + spell application

Unblocks covenant P2 by building the conduit sub-system the soulbind
gameplay hangs off of (all garrison-talent opcodes were Handle_NULL).

Data (Phase A): add the SoulbindConduit.db2 store (Meta 0x2632E47D
already present) so conduits can be validated by type/covenant/spec.

Collection (Phase B): the conduit collection is server-authoritative -
Player now tracks owned conduits (conduitId -> RankIndex) and socketed
conduits (GarrTalent node -> conduitId + treeId), both persisted to new
character_soulbind_conduits / character_soulbind_conduit_sockets tables
loaded at login. CollectConduit() grants at the data-driven lowest
RankIndex defined for the conduit (never assumes 0; refuses if there is
no rank row). The "conduit add" GM command is the interim grant trigger;
auto-collection from conduit items needs the item-to-conduit link (TODO).

Socketing (Phase C): CMSG_GARRISON_SOCKET_TALENT now decodes to
{ u32 GarrTalentID, u32 count, count x (SoulbindConduitID, Rank) } - the
pair mirrors this protocol's GarrisonTalentSocketData. The handler routes
to Player::SocketConduit, which validates the conduit exists, is owned,
and its covenant matches, then persists and casts the conduit's
SoulbindConduitRank->SpellID aura. ApplyConduitSpells/RemoveConduitSpells
gate on the active soulbind's tree, re-apply on login (mirrors
_LoadGlyphAuras) and swap on soulbind switch.

Server-authoritative: the client-sent rank is ignored (server uses its
own collection). The socket wire's leading id / pair order carry a
NEEDS-CONFIRM (sniff) flag, but the handler fails closed - an unowned or
invalid id simply no-ops, so a misread can never corrupt state or apply a
wrong spell.
This commit is contained in:
luis
2026-07-06 15:16:59 -03:00
parent 283c56f934
commit 8680d8b2ca
19 changed files with 411 additions and 35 deletions
@@ -0,0 +1,19 @@
--
-- Soulbind conduit collection + socketed conduits (covenant P2 conduit sub-system)
--
DROP TABLE IF EXISTS `character_soulbind_conduits`;
CREATE TABLE `character_soulbind_conduits` (
`guid` bigint unsigned NOT NULL DEFAULT '0',
`conduitId` int unsigned NOT NULL DEFAULT '0',
`rankIndex` int unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`guid`,`conduitId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Player soulbind conduit collection (owned conduit -> rank)';
DROP TABLE IF EXISTS `character_soulbind_conduit_sockets`;
CREATE TABLE `character_soulbind_conduit_sockets` (
`guid` bigint unsigned NOT NULL DEFAULT '0',
`garrTalentId` int unsigned NOT NULL DEFAULT '0',
`conduitId` int unsigned NOT NULL DEFAULT '0',
`garrTalentTreeId` int unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`guid`,`garrTalentId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Conduits socketed into soulbind tree nodes';
@@ -0,0 +1,13 @@
--
-- SoulbindConduit.db2 hotfix table (covenant P2 conduit sub-system)
--
DROP TABLE IF EXISTS `soulbind_conduit`;
CREATE TABLE `soulbind_conduit` (
`ID` int unsigned NOT NULL DEFAULT '0',
`ConduitType` tinyint unsigned NOT NULL DEFAULT '0',
`CovenantID` int NOT NULL DEFAULT '0',
`SpecSetID` int NOT NULL DEFAULT '0',
`Flags` int NOT NULL DEFAULT '0',
`VerifiedBuild` int NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`,`VerifiedBuild`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;