Spirit Shrouds
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) Code:
char progression_str[] = Code:
#pragma pack(1) 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[] = |
Confirmed that OP_ShroudUnknown5=0x7f63 is the same as OP_ShroudProgressionUpdate=0x4625 in terms of what it does and what its packet structure looks like. Basically, both opcodes perform the same function, except that 0x7f63 does one tiny extra step that doesn't seem to have anything to do with the packet contents (perhaps a window reset?).
This also confirms that patch_Titanium.conf mischaracterizes 0x7f63 as OP_LockoutTimerInfo. |
I have nothing to add at the moment and can't really poke around at it yet because I'm working on something else: but it's quite interesting.
|
Opcodes
OP_ShroudUnknown4=0x11cd #size=? This was a mistake on my part. Didn't mean to include this in list of shroud-related opcodes. OP_ShroudUnknown2=0x18cb #size=? Has been decoded: OP_ShroudSelEquipDetail=0x18cb Structures OP_ShroudSelEquipDetail Code:
#pragma pack(1) unknown2 must be -1 (ie. 0xFFFFFFFF). pktSize = the entire size of serializedItem plus the size of pktSize itself. serializedItem is a variable-length serialized data stream generated by the Titanium::SerializeItem(...) function. What this opcode/packet does is display item details, presumably for a currently selected item, in the Shroud Selection window. You'll notice I made UniqueID an signed int here. This is because eqgame.exe will "UniqueID = -(UniqueID);" if it receives a UniqueID in the OP_ShroudSelectionWindow packet that is less than 0 (ie. >0x7FFFFFFF). |
OP_ShroudUnknown3=0x1573
This one has been most problematic to reverse engineer. It's almost as if the server needs to be directly aware of some object pointer offsets found in eqgame.exe. One thing I found by investigating this was that the value of UniqueID in the above Opcodes cannot be random. Code:
.text:004FF9C9 sub_4FF9C9 proc near ; CODE XREF: sub_4244BA+Ap div dword ptr [ecx+4] This essentially takes our UniqueID, divides it by 0x17 and only uses the remainder. (UniqueID % 23) It then multiplies by 4 (it's probably doing pointer math), and offsets a pointer by that amount and grabs the value at that new location: .text:004FF9D7 mov eax, [eax+edx*4] That value must be non-zero: .text:004FF9E4 test eax, eax .text:004FF9E6 jnz short loc_4FF9DC Then, we assume that value is yet another pointer and compare the second uint32 at the pointer's destination with our original UniqueID: .text:004FF9DC cmp [eax+4], esi If we don't find it, we increment our pointer by two unit32s and try the loop back to the non-zero check and do it again. .text:004FF9DF jz short loc_4FF9E8 .text:004FF9E1 mov eax, [eax+8] All of this means that the UniqueID is much more than just a UniqueID. It's also an offset for a pointer that expects to find the same offset value somewhere in a structure at its destination. Its giving me a headache. :) Now, I did find only one such possible UniqueID that would satisfy this algorithm. The problem is, that UniqueID was 0x8800001F. As mentioned in a prior post, this value makes an invalid UniqueID because this is < 0 and becomes 0x77FFFFE1 before being saved by the client. :( Best I can tell, my real problem may be that something hasn't yet been set in the object I'm referencing here. (Faced similar problems getting the other opcodes to work--if the shroud selection window weren't open when the opcode was sent, a subroutine would return a 0 result because an object lookup would fail.) At this time, I'm not sure what else I need to send to get that object reference to be valid. Alas, I'll keep hacking away at it. One last note about this one: the contents of the packet aren't even referenced by this point, but this subroutine's failure cascades into the entire packet being discarded. The UniqueID in this problem is referring to the UniqueID of the currently highlighted template in the shroud selection window. The window must be open for this opcode to even get this far, however. Of that I am certain. So, too, am I certain that OP_ShroudUnknown1=0x6d32 is also handled by this window. |
One more one more note. :)
I'm pretty sure OP_ShroudUnknown3 is an ability description opcode in the same fashion that OP_ShroudSelEquipDetail is an item description opcode. Why? Because the text "This is a passive ability; it does not need to be activated." is used within the processing for this opcode. |
I doubt the server would need to know anything about the internal data pointers of the client outside of simple offsets(wouldn't be the first packet to work like this). It's probably holding a set of data in memory from a previous operation and using it to parse that packet.
|
Indeed, as was the case for the other ones (ie. you couldn't get an object ptr for OP_ShroudSelEquipDetail without having first opened the window via OP_ShroudSelectionWindow). There's a sub that's specific to these opcodes and I've exhausted them hunting for the one that enables this one. I think I'll need to dig into some of the higher level unhandled opcodes. Just in a few minutes, I found quite a few that weren't referenced in patch_Titanium.conf, so I can go through those, I guess:
#0x11cd .text:00404D2A #0xd743 .text.004515DA #0x79b4 .text.00461682 #0x7c59 .text.00461671 #0x7abc .text.0046168E #0x7c12 .text.0046169A #0x7c32 .text.004616A6 #0x6966 .text.004611AC #0x6A00 .text.004611B5 #0x6C97 .text.004611BD |
bumping this, because it's an A+ thread
|
All times are GMT -4. The time now is 06:41 AM. |
Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.