Merge pull request #5066 from dannuic/tob_loginpatches

TOB packet work through zone in
This commit is contained in:
Alex 2026-04-15 22:03:39 -07:00 committed by GitHub
commit 8e7964b835
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 837 additions and 751 deletions

View File

@ -856,82 +856,70 @@ namespace TOB
SETUP_VAR_ENCODE(LogServer_Struct);
ALLOC_LEN_ENCODE(1932);
//pvp
// pvp
if (emu->enable_pvp) {
*(char*)&__packet->pBuffer[0x04] = 1;
}
if (emu->enable_FV) {
//FV sets these both to 1
//one appears to enable the no drop flag the other just marks the server as special?
*(char*)&__packet->pBuffer[0x08] = 1;
*(char*)&__packet->pBuffer[0x0a] = 1;
*(char*)&__packet->pBuffer[0x08] = 1; // RP server
*(char*)&__packet->pBuffer[0x0a] = 1; // free loot server
}
//This has something to do with heirloom and prestige items but im not sure what it does
//Seems to sit at 0
// this lets you transfer no drop items in the shared bank
*(char*)&__packet->pBuffer[0x75d] = 0;
//not sure what this does, something to do with server select
// disable tutorial at character create/select
*(char*)&__packet->pBuffer[0x09] = 0;
//this appears to have some effect on the tradeskill system; disabling made by tags perhaps?
// this is the auto-identify flag
*(char*)&__packet->pBuffer[0x0b] = 0;
//not sure, setting it to the value ive seen
// not actually used in the client, has to do with name gen
*(char*)&__packet->pBuffer[0x0c] = 1;
//Something to do with languages
// unknown languages are gibberish
*(char*)&__packet->pBuffer[0x0d] = 1;
//These seem to affect if server has betabuff enabled
*(char*)&__packet->pBuffer[0x600] = 0;
*(char*)&__packet->pBuffer[0x601] = 0;
//This is set on test so it's probably indicating this is a test server
*(char*)&__packet->pBuffer[0x602] = 0;
//not sure, but it's grouped with the beta and test stuff
*(char*)&__packet->pBuffer[0x603] = 0;
// is_dev_server flags
*(char*)&__packet->pBuffer[0x600] = 0; // is beta server
*(char*)&__packet->pBuffer[0x601] = 0; // override allow beta buff (for any server)
*(char*)&__packet->pBuffer[0x602] = 0; // is test server (name reservations are unavailable)
*(char*)&__packet->pBuffer[0x603] = 0; // unused in the client
//world short name
strncpy((char*)&__packet->pBuffer[0x15], emu->worldshortname, 32);
//not sure, affects some player calculation but didn't care to look more
// static base HP/MP regen
*(char*)&__packet->pBuffer[0x5ec] = 0;
//Looks right
// use mail system
if (emu->enablemail) {
*(char*)&__packet->pBuffer[0x5f5] = 1;
}
//Looks right
// use voice macros
if (emu->enablevoicemacros) {
*(char*)&__packet->pBuffer[0x5f4] = 1;
}
//Not sure, sending what we've seen
// Disable character select buttons except create character
*(char*)&__packet->pBuffer[0x5f6] = 0;
//Not sure sending what we've seen
// enable tutorial at character create/select
*(char*)&__packet->pBuffer[0x5f8] = 1;
//Not sure sending what we've seen
// client defaults, unused
*(int32_t*)&__packet->pBuffer[0x63c] = -1;
//Test sets this to 1, everyone else seems to set it to 0
*(int32_t*)&__packet->pBuffer[0x640] = 0;
//Disassembly puts it next to code dealing with commands, ive not seen anyone send anything but 0
*(char*)&__packet->pBuffer[0x745] = 0;
//Something about item restrictions, seems to always be set to 1
*(char*)&__packet->pBuffer[0x750] = 1;
//This and 0x724 are often multiplied together in guild favor calcs, live and test send 1.0f
// these are always multiplied together in guild favor calcs for display, live and test send 1.0f
*(float*)&__packet->pBuffer[0x760] = 1.0f;
*(float*)&__packet->pBuffer[0x764] = 1.0f;
//This and 0x72c are often multiplied together in non-guild favor calcs, live and test send 1.0f
// these are always multiplied together in non-guild favor calcs for display, live and test send 1.0f
*(float*)&__packet->pBuffer[0x768] = 1.0f;
*(float*)&__packet->pBuffer[0x76c] = 1.0f;
@ -2599,16 +2587,16 @@ namespace TOB
eq_cse->Face = emu_cse->Face;
for (int equip_index = 0; equip_index < EQ::textures::materialCount; equip_index++) {
eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material;
eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1;
eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteModel;
eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HerosForgeModel;
eq_cse->Equip[equip_index].Material2 = emu_cse->Equip[equip_index].Unknown2;
eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color;
eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; // type
eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; // variation
eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteModel; // material
eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HerosForgeModel; // new armor id
eq_cse->Equip[equip_index].Material2 = emu_cse->Equip[equip_index].Unknown2; // new armor type
eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color; // tint
}
eq_cse->Unknown1 = 255;
eq_cse->Unknown2 = 0;
eq_cse->TextureType = 255;
eq_cse->HeadType = 0;
eq_cse->DrakkinTattoo = emu_cse->DrakkinTattoo;
eq_cse->DrakkinDetails = emu_cse->DrakkinDetails;
eq_cse->Deity = emu_cse->Deity;
@ -2620,18 +2608,16 @@ namespace TOB
eq_cse->EyeColor2 = emu_cse->EyeColor2;
eq_cse->HairStyle = emu_cse->HairStyle;
eq_cse->Beard = emu_cse->Beard;
eq_cse->GoHome = emu_cse->GoHome;
eq_cse->PreFTP = 1;
eq_cse->Tutorial = emu_cse->Tutorial;
eq_cse->DrakkinHeritage = emu_cse->DrakkinHeritage;
eq_cse->Enabled = emu_cse->Enabled;
eq_cse->GoHome = emu_cse->GoHome;
eq_cse->LastLogin = emu_cse->LastLogin;
eq_cse->Unknown3 = 0;
eq_cse->Unknown4 = 0;
eq_cse->Unknown5 = 0;
eq_cse->Unknown6 = 0;
eq_cse->Unknown7 = 0;
eq_cse->TooHighLevel = 0;
eq_cse->Usable = emu_cse->Enabled; // this doesn't seem to do anything
eq_cse->Shrouded = 0;
eq_cse->Unknown = 0;
eq_cse->CharacterId = 0;
eq_cse->Unknown8 = 1;
emu_ptr += sizeof(CharacterSelectEntry_Struct);
eq_ptr += sizeof(structs::CharacterSelectEntry_Struct);
@ -2646,21 +2632,23 @@ namespace TOB
ENCODE_LENGTH_EXACT(MaxCharacters_Struct);
SETUP_DIRECT_ENCODE(MaxCharacters_Struct, structs::MaxCharacters_Struct);
//OUT(max_chars);
eq->max_chars = 8; //needs to be fixed
eq->marketplace_chars = 0;
*eq = {0};
eq->total_character_slots = 8;
eq->marketplace_character_slots = 0;
eq->unknown008 = -1;
eq->unknown00c = 196608;
eq->unknown010 = 0;
eq->unknown014 = 0;
eq->unknown018 = 0;
eq->unknown01c = 0;
eq->unknown020 = -1;
eq->unknown024 = 0;
eq->unknown028 = 0;
eq->unknown02c = 0;
eq->unknown030 = 0;
eq->unknown034 = 0;
eq->head_start_button = 0;
eq->heroic_related = 0x0003;
eq->heroic_50_count = 0;
eq->heroic_100_count = 0;
eq->disable_character_creation = 0; // this works, but it soft-locks the UI for some reason, needs to be fixed
eq->monthly_claim = -1;
eq->marketplace_related = 0;
eq->add_marketplace_chars = 0;
eq->add_unknown = 0;
eq->legacy_characters_ruleset = 0;
eq->num_max_characters = 0;
eq->num_personas_available = 10;
eq->has_de_ranger = 1; // this is probably an expansion flag only
FINISH_ENCODE();
}
@ -3029,13 +3017,13 @@ namespace TOB
ENCODE_LENGTH_EXACT(ZoneChange_Struct);
SETUP_DIRECT_ENCODE(ZoneChange_Struct, structs::ZoneChange_Struct);
memcpy(eq->char_name, emu->char_name, sizeof(emu->char_name));
OUT_str(char_name);
OUT(zoneID);
OUT(instanceID);
OUT(y);
OUT(x);
OUT(z)
OUT(zone_reason);
OUT(z);
OUT(zone_reason);
OUT(success);
if (eq->success < 0)
@ -3544,6 +3532,20 @@ namespace TOB
FINISH_DIRECT_DECODE();
}
DECODE(OP_ApproveName)
{
DECODE_LENGTH_EXACT(structs::NameApproval_Struct);
SETUP_DIRECT_DECODE(NameApproval_Struct, structs::NameApproval_Struct);
IN_str(name);
IN(race_id);
IN(class_id);
// TODO: expand the approval logic to include the rest of the TOB struct values (and remove the direct translation here)
FINISH_DIRECT_DECODE();
}
DECODE(OP_AugmentInfo)
{
DECODE_LENGTH_EXACT(structs::AugmentInfo_Struct);
@ -3642,6 +3644,39 @@ namespace TOB
delete[] __eq_buffer;
}
DECODE(OP_CharacterCreate) {
DECODE_LENGTH_EXACT(structs::CharCreate_Struct);
SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct);
IN(gender);
IN(race);
IN(class_);
IN(deity);
IN(start_zone);
IN(haircolor);
IN(beard);
IN(beardcolor);
IN(hairstyle);
IN(face);
IN(eyecolor1);
IN(eyecolor2);
IN(drakkin_heritage);
IN(drakkin_tattoo);
IN(drakkin_details);
IN(STR);
IN(STA);
IN(AGI);
IN(DEX);
IN(WIS);
IN(INT);
IN(CHA);
IN(tutorial);
// TODO: can handle the heroic type here as well (new member)
FINISH_DIRECT_DECODE();
}
DECODE(OP_ClickDoor)
{
DECODE_LENGTH_EXACT(structs::ClickDoor_Struct);
@ -3868,7 +3903,7 @@ namespace TOB
DECODE_LENGTH_EXACT(structs::ClientZoneEntry_Struct);
SETUP_DIRECT_DECODE(ClientZoneEntry_Struct, structs::ClientZoneEntry_Struct);
memcpy(emu->char_name, eq->char_name, sizeof(emu->char_name));
IN_str(char_name);
FINISH_DIRECT_DECODE();
}

View File

@ -66,11 +66,13 @@ E(OP_ZoneSpawns)
//list of packets we need to decode on the way in:
D(OP_Animation)
D(OP_ApplyPoison)
D(OP_ApproveName)
D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_BlockedBuffs)
D(OP_CastSpell)
D(OP_ChannelMessage)
D(OP_CharacterCreate)
D(OP_ClientUpdate)
D(OP_ClickDoor)
D(OP_Consider)

View File

@ -75,21 +75,28 @@ namespace TOB {
};
struct MaxCharacters_Struct {
/*000*/ uint32 max_chars;
/*004*/ uint32 marketplace_chars;
/*008*/ int32 unknown008; //some of these probably deal with heroic characters or something
/*00c*/ int32 unknown00c;
/*010*/ int32 unknown010;
/*014*/ int32 unknown014;
/*018*/ int32 unknown018;
/*01c*/ int32 unknown01c;
/*020*/ int32 unknown020;
/*024*/ int32 unknown024;
/*028*/ int32 unknown028;
/*02c*/ int32 unknown02c;
/*030*/ int32 unknown030;
/*034*/ int32 unknown034;
/*038*/
/*000*/ uint32 total_character_slots; // total character slots, different than max characters
/*004*/ uint32 marketplace_character_slots;
/*008*/ uint32 unknown008; // definitely 4 bytes, read in client, value for CEverQuest::Unknown0x0608
/*00c*/ uint8 head_start_button;
/*00d*/ uint8 unused00d;
/*00e*/ uint16 heroic_related;
/*010*/ int64 heroic_50_count; // read as 64 bits in the client
/*018*/ int32 heroic_100_count;
/*01c*/ uint8 disable_character_creation;
/*01d*/ uint8 unused01d[3];
/*020*/ int32 monthly_claim; // (-1 for don't set)
/*024*/ uint8 marketplace_related; // marketplace related boolean (int32 for convenience here, it's 4 bytes)
/*025*/ uint8 unused025[3];
/*028*/ int32 unused028;
/*02c*/ uint8 add_marketplace_chars; // boolean on whether to add or set marketplace characters
/*02d*/ uint8 add_unknown; // boolean on whether to add unknown008 or set marketplace characters to some unknown global
/*02e*/ uint8 legacy_characters_ruleset;
/*02f*/ uint8 unused02f;
/*030*/ int32 num_max_characters; // used for legacy exp calculation
/*034*/ int32 num_personas_available;
/*038*/ int32 has_de_ranger;
/*03c*/
};
struct ExpansionInfo_Struct {
@ -98,16 +105,16 @@ namespace TOB {
};
/*
* Visible equiptment.
* Visible equipment.
* Size: 20 Octets
*/
struct Texture_Struct
{
uint32 Material;
uint32 Unknown1;
uint32 EliteMaterial;
uint32 HeroForgeModel;
uint32 Material2; // Same as material?
uint32 Material; // type
uint32 Unknown1; // material
uint32 EliteMaterial; // variation
uint32 HeroForgeModel; // new armor ID
uint32 Material2; // new armor type
};
/*
@ -145,10 +152,10 @@ namespace TOB {
uint8 Gender;
uint8 Face;
CharSelectEquip Equip[9];
uint8 Unknown1; //Seen 256
uint8 Unknown2; //Seen 0
uint32 DrakkinTattoo;
uint32 DrakkinDetails;
uint8 TextureType; //Seen 256
uint8 HeadType; //Seen 0
uint32 DrakkinTattoo; // tattoo index
uint32 DrakkinDetails; // face attachment index
uint32 Deity;
uint32 PrimaryIDFile;
uint32 SecondaryIDFile;
@ -158,18 +165,16 @@ namespace TOB {
uint8 EyeColor2;
uint8 HairStyle;
uint8 Beard;
uint8 Enabled;
uint8 Tutorial;
uint32 DrakkinHeritage;
uint8 Unknown3;
uint8 GoHome;
uint8 Tutorial;
uint32 DrakkinHeritage; // parent ID
uint8 TooHighLevel;
uint8 PreFTP;
uint32 LastLogin;
uint8 Unknown4; // Seen 0
uint8 Unknown5; // Seen 0
uint8 Unknown6; // Seen 0
uint8 Unknown7; // Seen 0
uint32 CharacterId; //A Guess, Character I made a little bit after has a number a few hundred after the first
uint32 Unknown8; // Seen 1
uint8 Usable;
uint16 Shrouded;
uint8 Unknown;
uint64 CharacterId; // A Guess, Character I made a little bit after has a number a few hundred after the first
};
/*
@ -181,6 +186,50 @@ namespace TOB {
/*000*/ uint32 CharCount; //number of chars in this packet
};
/*
** Character Creation struct
** Length: 168 Bytes
** OpCode: 0x1859
*/
struct CharCreate_Struct
{
/*00*/ uint8 padding[72];
/*48*/ uint32 gender;
/*4c*/ uint32 race;
/*50*/ uint32 class_;
/*54*/ uint32 deity;
/*58*/ uint32 start_zone; // this is the zone ID of the start zone
/*5c*/ uint32 haircolor;
/*60*/ uint32 beard;
/*64*/ uint32 beardcolor;
/*68*/ uint32 hairstyle;
/*6c*/ uint32 face;
/*70*/ uint32 eyecolor1;
/*74*/ uint32 eyecolor2;
/*78*/ uint32 drakkin_heritage;
/*7c*/ uint32 drakkin_tattoo;
/*80*/ uint32 drakkin_details;
/*84*/ uint32 STR;
/*88*/ uint32 STA;
/*8c*/ uint32 AGI;
/*90*/ uint32 DEX;
/*94*/ uint32 WIS;
/*98*/ uint32 INT;
/*9c*/ uint32 CHA;
/*a0*/ uint32 tutorial;
/*a4*/ uint32 heroic_type;
/*a8*/
};
struct NameApproval_Struct {
char name[64];
uint32 race_id;
uint32 class_id;
uint32 deity_id;
uint32 heroic_type; // seen 0, client can also send 1-4
uint32 unknown; // always 0?
};
enum TOBAppearance : uint32
{
None,
@ -285,21 +334,21 @@ namespace TOB {
struct {
signed deltaHeading : 10;
signed animation : 10;
// unsigned pad1 : 12;
unsigned pad1 : 12;
signed deltaX : 13;
signed z : 19;
signed y : 19;
unsigned heading : 12;
// unsigned pad2 : 1;
unsigned pad2 : 1;
signed x : 19;
signed deltaZ : 13;
unsigned pitch : 12;
signed deltaY : 13;
// unsigned pad3 : 7;
unsigned pad3 : 7;
};
uint32_t raw[5];
};
@ -311,15 +360,15 @@ namespace TOB {
/*0x04*/ float delta_y;
/*0x08*/ float x;
/*0x0c*/ int animation : 10;
// signed padding1 : 22;
signed padding1 : 22;
/*0x10*/ float delta_x;
/*0x14*/ float z;
/*0x18*/ float delta_z;
/*0x1c*/ int heading : 12;
int pitch : 12;
// signed padding2 : 8;
signed padding2 : 8;
/*0x20*/ int delta_heading : 10;
// signed padding3 : 22;
signed padding3 : 22;
/*0x24*/
};
@ -399,8 +448,8 @@ namespace TOB {
struct EnterWorld_Struct {
/*000*/ char name[64];
/*064*/ int32 unknown1;
/*068*/ int32 unknown2; //tob handles these differently so for now im just going to ignore them till i figure it out
/*064*/ int32 unknown1; // this appears to always be 0
/*068*/ int32 zoneID; // this is -1 for "last zone"
};
struct ZoneChange_Struct {
@ -427,7 +476,7 @@ namespace TOB {
/*016*/ float z;
/*020*/ float heading;
/*024*/ uint32 type; //unknown... values
/*032*/ uint8 unknown032[144];
/*032*/ uint8 unknown032[144]; // this is mostly a string passed to the teleport function (follow starting at 0x1401F71BA), it appears to be an override for a message
/*172*/ uint32 unknown172;
/*176*/
};

File diff suppressed because it is too large Load Diff

View File

@ -14,18 +14,18 @@ OP_ExploreUnknown=0x0000 # used for unknown explorer
# world packets
# Required to reach Char Select:
OP_SendLoginInfo=0x722A
OP_SendLoginInfo=0x722a
OP_ApproveWorld=0x0000
OP_LogServer=0x2cae
OP_SendCharInfo=0x5d1a
OP_ExpansionInfo=0x393a
OP_EnterWorld=0x7fb8
OP_PostEnterWorld=0x1945
OP_World_Client_CRC1=0x777f
OP_World_Client_CRC2=0x492
OP_World_Client_CRC3=0x690
OP_SendSpellChecksum=0x0000
OP_SendSkillCapsChecksum=0x0000
OP_PostEnterWorld=0x1945 # unused
OP_World_Client_CRC1=0x777f # This is OP_SendExeChecksum
OP_World_Client_CRC2=0x0492 # This is OP_SendBaseDataChecksum
OP_World_Client_CRC3=0x0690 # This is OP_SendSkillCapsChecksum
OP_SendSpellChecksum=0x0000 # There is no spell checksum in TOB
OP_SendSkillCapsChecksum=0x0690
# Character Select Related:
OP_SendMaxCharacters=0x25eb
@ -34,15 +34,15 @@ OP_SendMembershipDetails=0x2373
OP_CharacterCreateRequest=0x6b67
OP_CharacterCreate=0x1859
OP_DeleteCharacter=0x71ca
OP_RandomNameGenerator=0x7f4a
OP_RandomNameGenerator=0x7f4a # TOB client no longer sends this, and the S->C packet isn't used by emu
OP_ApproveName=0x5306
OP_MOTD=0x1eef
OP_SetChatServer=0x0000
OP_SetChatServer2=0x34c1
OP_ZoneServerInfo=0x2323
OP_WorldComplete=0x1223
OP_WorldUnknown001=0x7723
OP_FloatListThing=0x504f
OP_WorldUnknown001=0x7723 # SetServerTime, S->C
OP_FloatListThing=0x504f # Movement History, C->S
# Reasons for Disconnect:
OP_ZoneUnavail=0x29a6
@ -54,8 +54,8 @@ OP_WorldLogout=0x0000
OP_WorldLevelTooHigh=0x0000
OP_CharInacessable=0x0000
OP_UserCompInfo=0x0000
OP_SendExeChecksum=0x0000
OP_SendBaseDataChecksum=0x0000
OP_SendExeChecksum=0x777f
OP_SendBaseDataChecksum=0x0492
# Zone in opcodes
OP_AckPacket=0x776d