Butin WoD/Legion : brancher les boss sur le Guide d aventure

Signalement Discord : les instances haut niveau ne lachent aucun equipement.

Sur ce core, le butin d equipement des boss modernes ne vient pas de
creature_loot_template mais de Unit::Kill, qui lit creature_template_journal
(entree -> JournalEncounterID) puis tire 2 objets dans JournalEncounterItem.db2
avec le bon masque de difficulte et le bon contexte d objet. Cette table ne
contenait que 45 lignes, toutes Burning Crusade : aucun boss de Draenor ni de
Legion, et ces boss ont lootid = 0. Ils ne lachaient donc rigoureusement rien.

44 correspondances ajoutees, etablies depuis les DB2 officiels du client
(JournalInstance -> JournalEncounter -> JournalEncounterCreature ->
CreatureDisplayInfoID -> creature_template.modelid), une seule creature par
rencontre et uniquement celles sans table de butin, pour ne rien doubler.
Couvre entre autres la Fonderie des Rochenoire (10 boss), les Docks de fer,
Haut-perchoir, le Pic Rochenoire, la Floraison eternelle, le Siege du
Triumvirat (4 boss), le Tombeau de Sargeras (6), Gul dan et Elisande.

Les scripts de generation et de verification sont dans chantiers/butin-journal.
This commit is contained in:
BlaMacfly
2026-09-10 19:50:19 +02:00
parent afb770d096
commit fa6d14c4a0
4 changed files with 219 additions and 0 deletions
@@ -0,0 +1,97 @@
# -*- coding: utf-8 -*-
"""Genere creature_template_journal pour les boss WoD/Legion sans butin.
Source officielle : JournalInstance -> JournalEncounter -> JournalEncounterCreature."""
import sys, subprocess, collections
sys.path.insert(0, '/home/ubuntu')
from db2read import DB2
D = '/home/ubuntu/server/data/dbc/enUS/'
CIBLES = [1175,1176,1182,1195,1209,1279,1358,1205,1228,
1456,1458,1466,1477,1492,1501,1544,1571,1753,1520,1530,1676]
# adds / decors qui partagent le modele du boss mais ne doivent rien lacher
EXCLUS = {
76057, # Carrion Worm (add de Bonemaw)
76874, 76945, 76884, # Dreadwing / Ironcrusher / Cruelfang (bestioles de Darmac)
77337, # Aknor Steelbringer (add de Flamebender)
76810, # Furnace Engineer
76087, # Defense Construct (Skyreach)
99801, 105383, 105322, 105304, # tentacules
117123, # Tidescale Legionnaire
122571, 125860, 122319, 125340, # adds du Siege du Triumvirat
118460, # Engine of Souls (l'encontre se termine sur Soul Queen Dejahna)
76018, 82556, # Drakonid Monstrosity (trash UBRS)
106482, # Malfurion (PNJ de la rencontre Cenarius)
120996, # doublon d'Atrigan
77810, # doublon de Soulbinder Nyami
84336, # doublon de Yalnu (pre-event)
83893, 83892, # Protecteurs anciens : on garde Dulhu comme porteur
76973, # Hans'gar : on garde Franzok
78237, # Phemos : on garde Pol
116689, # Atrigan : on garde Belac
118523, 118374, # Soeurs de la Lune : on garde Priestess Lunaspyre
102681, 102679, # Dragons du Cauchemar : on garde Lethon
80808, 80805, # Contremaitres du Rail-de-fer : on garde Ahri'ok Dugru
83613, # Koramar : on garde Skulloc
76806, # Haut fourneau : on garde Foreman Feldspar ? non -> voir plus bas
77231, 77477, # Vierges de fer : on garde Admiral Gar'an
}
# Haut fourneau : la rencontre se termine sur le Coeur de la Montagne
EXCLUS.discard(76806); EXCLUS.add(76809)
ji = DB2(D+'JournalInstance.db2', "ssiiiihhbbi", [1]*11, 10, -1)
je = DB2(D+'JournalEncounter.db2', "ssfhhhhbbii", [1,1,2,1,1,1,1,1,1,1,1], -1, -1)
jec = DB2(D+'JournalEncounterCreature.db2',"ssiiihbi", [1]*8, 7, 5)
jei = DB2(D+'JournalEncounterItem.db2', "ihbbbi", [1]*6, 5, 1)
instMap = {ji.getId(i): ji.getRaw(i,6,0,"h") for i in range(ji.recCount)}
encMap = {}
for i in range(je.recCount):
eid = je.getId(i); mid = instMap.get(je.getRaw(i,6,0,"h"), 0)
if mid in CIBLES: encMap[eid] = mid
nbItems = {eid: len(jei.parentMap.get(eid, [])) for eid in encMap}
disp = collections.defaultdict(set)
for eid, idxs in jec.parentMap.items():
if eid in encMap:
for r in idxs: disp[eid].add(jec.getRaw(r,2,0,"i"))
q = ("SELECT DISTINCT c.map, ct.entry, ct.name, ct.rank, ct.ScriptName, "
"ct.modelid1, ct.modelid2, ct.modelid3, ct.modelid4, "
"(SELECT COUNT(*) FROM creature c2 WHERE c2.id=ct.entry AND c2.map=c.map), "
"(SELECT COUNT(*) FROM creature_loot_template l WHERE l.entry=ct.lootid) "
"FROM creature c JOIN creature_template ct ON ct.entry=c.id "
"WHERE c.map IN (%s)" % ','.join(map(str, CIBLES)))
out = subprocess.run(['mysql','-N','-B','dc_world','-e',q], capture_output=True, text=True).stdout
byMapModel = collections.defaultdict(list)
for line in out.splitlines():
f = line.split('\t')
mp, entry, name, rank, script = int(f[0]), int(f[1]), f[2], int(f[3]), f[4]
spawns, butin = int(f[9]), int(f[10])
for m in (int(x) for x in f[5:9]):
if m: byMapModel[(mp, m)].append((entry, name, rank, script, spawns, butin))
rows, rejets = [], []
for eid, mid in sorted(encMap.items(), key=lambda kv: kv[1]):
cands, seen = [], set()
for d in disp.get(eid, ()):
for c in byMapModel.get((mid, d), []):
if c[0] in seen: continue
seen.add(c[0]); cands.append(c)
# on ne garde que les boss credibles, sans butin, hors liste d'exclusion
keep = [c for c in cands
if c[0] not in EXCLUS and c[5] == 0
and (c[3].startswith('boss_') or c[2] == 3 or (c[2] >= 1 and c[4] <= 3))]
if not keep:
rejets.append((mid, eid, nbItems.get(eid,0), [(c[0], c[1], c[5]) for c in cands]))
continue
keep.sort(key=lambda c: (0 if c[3].startswith('boss_') else 1, c[4]))
for c in keep:
rows.append((mid, eid, c[0], c[1], nbItems.get(eid,0)))
print("-- creature_template_journal : %d lignes" % len(rows))
for mid, eid, entry, name, n in rows:
print("(%d, %d), -- carte %d : %s (%d objets au journal)" % (entry, eid, mid, name, n))
print()
print("-- rencontres sans candidat retenu : %d" % len(rejets))
for mid, eid, n, cands in rejets:
print("-- carte %d rencontre %d (%d objets) -> %s" % (mid, eid, n, cands if cands else "aucun PNJ apparu"))
@@ -0,0 +1,25 @@
import sys, subprocess, collections
sys.path.insert(0, '/home/ubuntu')
from db2read import DB2
D = '/home/ubuntu/server/data/dbc/enUS/'
ji = DB2(D+'JournalInstance.db2', "ssiiiihhbbi", [1]*11, 10, -1)
je = DB2(D+'JournalEncounter.db2', "ssfhhhhbbii", [1,1,2,1,1,1,1,1,1,1,1], -1, -1)
jei = DB2(D+'JournalEncounterItem.db2', "ihbbbi", [1]*6, 5, 1)
instMap = {ji.getId(i): ji.getRaw(i,6,0,"h") for i in range(ji.recCount)}
enc = {}
for i in range(je.recCount):
enc[je.getId(i)] = (instMap.get(je.getRaw(i,6,0,"h"),0), je.getRaw(i,9,0,"i"))
rows = subprocess.run(['mysql','-N','-B','dc_world','-e',
"SELECT j.entry, j.JournalEncounterID, ct.name FROM creature_template_journal j "
"JOIN creature_template ct ON ct.entry=j.entry WHERE j.entry>70000"],
capture_output=True, text=True).stdout
print("entry\tenc\tcarte\tordre\tnbObjets\tnom")
bad=0
for line in rows.splitlines():
e, eid, name = line.split('\t'); eid=int(eid)
mid, oi = enc.get(eid, (0,0))
n = len(jei.parentMap.get(eid, []))
flag = "" if (mid and n) else " <<< PROBLEME"
if flag: bad+=1
print("%s\t%d\t%d\t%d\t%d\t%s%s" % (e, eid, mid, oi, n, name, flag))
print("problemes:", bad)
+91
View File
@@ -0,0 +1,91 @@
-- =====================================================================
-- Butin des donjons et raids WoD / Legion
--
-- Signalement Discord : « les instances HL ne loot pas de stuff ».
-- Cause : sur ce core, le butin d'equipement des boss modernes ne vient
-- PAS de `creature_loot_template` mais du Guide d'aventure de Blizzard :
-- `Unit::Kill` lit `creature_template_journal` (entree -> JournalEncounterID)
-- puis tire 2 objets au hasard dans JournalEncounterItem.db2, avec le
-- masque de difficulte et le contexte d'objet corrects.
-- Or `creature_template_journal` ne contenait que 45 lignes, toutes
-- Burning Crusade : aucun boss de Draenor ni de Legion n'y figurait,
-- et ces boss ont `lootid = 0` -> ils ne lachaient rigoureusement rien.
--
-- Correspondances etablies a partir des DB2 officiels du client :
-- JournalInstance (MapID) -> JournalEncounter -> JournalEncounterCreature
-- (CreatureDisplayInfoID) -> creature_template.modelid1..4
-- Une seule creature par rencontre (celle qui la conclut), et uniquement
-- celles qui n'ont aucune table de butin, pour ne rien doubler.
--
-- Applique le 2026-09-10.
-- =====================================================================
DELETE FROM `creature_template_journal` WHERE `entry` IN (
74366,81297,80816,83612,87420,76865,76814,76906,76806,76974,76877,77692,77182,77557,
75964,76141,76143,82682,84550,83846,76413,76021,77120,76585,91005,94960,95674,96759,
102682,104154,106643,116407,115767,116691,118462,117269,118518,122316,122313,122056,
124729,98965,79852,79912);
INSERT INTO `creature_template_journal` (`entry`,`JournalEncounterID`) VALUES
-- Mines de Sangyre (1175)
(74366, 893), -- Forgemaster Gog'duh
-- Docks de fer (1195)
(81297, 1235), -- Dreadfang (Fleshrender Nok'gar)
(80816, 1236), -- Ahri'ok Dugru (Contremaitres du Rail-de-fer)
(79852, 1237), -- Oshir
(83612, 1238), -- Skulloc
-- Auchindoun (1182) : PAS de ligne pour Azzakel. Le vrai boss (75927,
-- niveau 97, script boss_azzakel, 49 lignes de butin) n'est PAS apparu ;
-- le PNJ pose dans le donjon est un doublon de niveau 1 sans script.
-- C'est un defaut d'apparition, pas de butin : a corriger separement.
-- Aire de Haut-perchoir (1209)
(75964, 965), -- Ranjit
(76141, 966), -- Araknath
(76143, 967), -- Rukhran
-- Floraison eternelle (1279)
(82682, 1208), -- Archmage Sol
(84550, 1209), -- Xeri'tac
(83846, 1210), -- Yalnu
-- Pic Rochenoire, sommet (1358)
(76413, 1226), -- Orebender Gor'ashan
(76021, 1227), -- Kyrak
(79912, 1228), -- Commander Tharbek
(76585, 1229), -- Ragewing the Untamed
(77120, 1234), -- Warlord Zaela
-- Fonderie des Rochenoire (1205) - raid entier sans butin
(77182, 1202), -- Oregorger
(76974, 1155), -- Franzok (Hans'gar et Franzok)
(76865, 1122), -- Beastlord Darmac
(76877, 1161), -- Gruul
(76814, 1123), -- Flamebender Ka'graz
(76906, 1147), -- Operator Thogar
(76806, 1154), -- Heart of the Mountain (Haut fourneau)
(77692, 1162), -- Kromog
(77557, 1203), -- Admiral Gar'an (Vierges de fer)
(87420, 959), -- Blackhand
-- Repaire de Neltharion (1458)
(91005, 1673), -- Naraxas
-- Salles des Valeureux (1477)
(94960, 1485), -- Hymdall
(95674, 1487), -- Fenryr
-- Gouffre des ames (1492)
(96759, 1663), -- Helya
-- Donjon de Tenebreterre (1501)
(98965, 1672), -- Kur'talos Ravencrest
-- Cauchemar d'emeraude (1520)
(102682, 1704), -- Lethon (Dragons du Cauchemar)
-- Nighthold (1530)
(104154, 1737), -- Gul'dan
(106643, 1743), -- Grande magistrix Elisande
-- Tombeau de Sargeras (1676)
(116407, 1856), -- Harjatan
(115767, 1861), -- Mistress Sassz'ine
(116691, 1867), -- Belac (Inquisition demoniaque)
(118518, 1903), -- Priestess Lunaspyre (Soeurs de la Lune)
(118462, 1896), -- Soul Queen Dejahna (Hote desole)
(117269, 1898), -- Kil'jaeden
-- Siege du Triumvirat (1753) - donjon entier sans butin
(122313, 1979), -- Zuraal the Ascended
(122316, 1980), -- Saprish
(122056, 1981), -- Viceroy Nezhar
(124729, 1982); -- L'ura
@@ -0,0 +1,6 @@
-- Rollback de butin_journal_wod_legion.sql (2026-09-10)
DELETE FROM `creature_template_journal` WHERE `entry` IN (
74366,81297,80816,83612,87420,76865,76814,76906,76806,76974,76877,77692,77182,77557,
75964,76141,76143,82682,84550,83846,76413,76021,77120,76585,91005,94960,95674,96759,
102682,104154,106643,116407,115767,116691,118462,117269,118518,122316,122313,122056,
124729,98965,79852,79912);