I spent a few days on this since it didn't seem there had been any work in this area.
I haven't found the real gems of this feature yet, but I was able to decode a few opcodes related to it so far. Specifically, the Shroud Progression window, as well as the tree-list part of the Shroud Selection window. Haven't found the packet to actually transform yet, nor have I found the packet to fill out the ability/stats details of the Shroud Selection window.
I figured I'd post what I have and see if anyone can fill in some more, especially considering I may be distracted of late playing on Project1999
. The following applies to
Titanium only.
Opcodes
OP_ShroudSelectionWindow=0x65b1
OP_ShroudProgressionUpdate=0x4625
OP_ShroudBankEmpty=0x455f
OP_ShroudUnknown1=0x6d32 #size=8
OP_ShroudUnknown2=0x18cb #size=?
OP_ShroudUnknown3=0x1573 #size=?
OP_ShroudUnknown4=0x11cd #size=?
OP_ShroudUnknown5=0x7f63 #size=?
The first three I'm sure about. I'm suspicious that the last one is mischaracterized as OP_LockoutTimerInfo in the release version of patch_Titanium.conf.
Structures
OP_ShroudBankEmpty
I think OP_ShroudBankEmpty is pretty simple and requires no structure. It's sent as an opcode-only and merely prints out the message:
4558 "The Shroud Bank window was not opened, as there were no items that could be transferred from your previous form."
There are no conditionals that get in the way of that message being printed for that opcode, so I think that's all it does.
OP_ShroudProgressionUpdate
Code:
#pragma pack(1)
struct ShroudProgressionUpdate
{
uint32 numProgressions;
char progressionString[1];
};
#pragma pack()
numProgressions is the number of progressions contained within the packet. progressionString is a variable-length string describing the progressions. This string has several parts, each delimited by a 0x7 character. Here's an example string:
Code:
char progression_str[] =
"PROGRESSION" "\007" // must be the word 'PROGRESSION'
"1" "\007" // unknown integer
"Aberrations" "\007" // Progression name
"Imp Wizard 5" "\007" // Class name
"3" "\007" // How many unlocked?
"14" "\007" // How many total?
"Evil Eye Psion" "\007" // Next branch name
"Imp Wizard 10" "\007" // Next class name
"6" "\007" // Percentage complete
"PROGRESSION" "\007" // Here follows a second
"2" "\007" // progression described in
"Animals" "\007" // the same packet.
"Bear Beast 5" "\007"
"7" "\007"
"12" "\007"
"Wolf Beast" "\007"
"Bear Beast 10" "\007"
"25" "\007"
;
OP_ShroudSelectionWindow
Code:
#pragma pack(1)
struct ShroudSelectionWindow
{
uint32 triggerNPCID;
uint32 numShroudBankItems;
uint32 unknown2;
char shroudSelectionTreeString[1];
};
#pragma pack(0)
triggerNPCID is the ID of the NPC which was used to trigger the shroud selection window. eqgame.exe apparently hard-codes a maximum distance the player can be away from this NPC in order for the window to open, or else they'll get this string printed:
4555 "You cannot be transformed into a monster if you get that far."
triggerNPCID can be set to the player's own ID, in which case it'll always work.
numShroudBankItems is the number of items in the player's shroud bank. If this is anything but 0, eqgame.exe will not open the shroud selection window and will instead print the following string:
4557 "You must empty your Shroud Bank before you can polymorph again."
shroudSelectionTreeString works similarly to the string in OP_ShroudProgressionUpdate. It is a multi-part variable length string with 0x7 delimiters that looks like this:
Code:
char shroudselect_str[] =
"PROGRESSION" "\007" // 'PROGRESSION'
"1" "\007" // unknown integer
"Aberrations" "\007" // Progression name
"2" "\007" // unknown integer
"BRANCH" "\007" // 'BRANCH'
"3" "\007" // unknown integer
"Imp Wizard" "\007" // Branch name
"4" "\007" // unknown integer
"100" "\007" // Percentage complete
"TEMPLATE" "\007" // 'TEMPLATE'
"Imp Wizard 5" "\007" // Template name
"5" "\007" // Template level
"5" "\007" // UniqueID for this template
"1" "\007" // 1=there's more, 0=end
"TEMPLATE" "\007" // another template
"Imp Wizard 10" "\007"
"10" "\007"
"6" "\007"
"1" "\007"
"TEMPLATE" "\007" // another template
"Imp Wizard 15" "\007"
"15" "\007"
"7" "\007"
"1" "\007"
"BRANCH" "\007" // start a new branch
"8" "\007"
"Evil Eye Psion" "\007"
"9" "\007"
"50" "\007"
"TEMPLATE" "\007" // new branch's template1
"Evil Eye Psion 5" "\007"
"5" "\007"
"10" "\007"
"1" "\007"
"TEMPLATE" "\007" // new branch's template2
"Evil Eye Psion 10" "\007"
"10" "\007"
"11" "\007"
"1" "\007"
"TEMPLATE" "\007" // etc.
"Evil Eye Psion 15" "\007"
"15" "\007"
"12" "\007"
"0" "\007" // end it with a 0
;
Fairly straightforward. When the player is presented with the selection window, the game immediately highlights one of the templates and issues a 0x0000 opcode to the game client containing a 4-byte value. That 4-byte value is the UniqueID identified in the string for that template. Same happens if a user clicks on one of the other progressions/branches/templates in the window. Presumably, this is what is supposed to trigger the server to send another packet describing that template (stats, class, abilities, etc.) but that's the elusive opcode I haven't found yet.