Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

Development v40 Beta Edition Source | Merry Christmas

Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
I've been going crazy trying to find the keylayout opcodes. Can anyone tell me what the recvop and sendop codes are for the keylayout? It's called keymap in Moopledev. Also is the keylayout not saving an issue for anyone else? Or is it just me?

This is v40 beta. Back in the original MapleStory client, key configuration layouts should save to your computer's registry. Not until like v49 or something did FuncKeyMapped get implemented, and v83 or higher had FuncQuickslotMapped packets. They shouldn't require any real handling/packets for them in this version though.
 
Newbie Spellweaver
Joined
May 14, 2015
Messages
26
Reaction score
1
Oh my lord, thank you so much for your response. I've been going crazy trying to figure this out. Any idea why the keys aren't being saved to my registry? Could it be due to me using windows 10?

-EDIT-
The solution was to run the client as an admin. That solved the issue.
 
Newbie Spellweaver
Joined
May 14, 2015
Messages
26
Reaction score
1
Anyone know why putting anything that isn't an equip into storage causes massive problems (items visually disappearing)? (I'm not talking about the NPE from item.copy). Changing the type to EQUIP during packet creation for takeoutstorage and storestorage helps by preventing the non equips from getting deleted, so I'm guessing (mplew.writeShort(type.getBitfieldEncoding())) clears out all of the x type and the rest of the packet just sends the client the updated storage info. But I'm not sure what's going on.
 
Last edited:
Skilled Illusionist
Joined
Apr 26, 2015
Messages
302
Reaction score
77
Anyone know why putting anything that isn't an equip into storage causes massive problems (items visually disappearing)? (I'm not talking about the NPE from item.copy). Changing the type to EQUIP during packet creation for takeoutstorage and storestorage helps by preventing the non equips from getting deleted, so I'm guessing (mplew.writeShort(type.getBitfieldEncoding())) clears out all of the x type and the rest of the packet just sends the client the updated storage info. But I'm not sure what's going on.
The packet structure is wrong.
Eric

Do you know how quests worked in this version?
 
Newbie Spellweaver
Joined
May 14, 2015
Messages
26
Reaction score
1
@br1337 I saw that you posted the correct scroll packet structure earlier. How did you figure it out? I found the function in IDA but I'm at a loss on how to make out whats going on. Maybe you can tell me the general idea on how to figure out the correct structure, so I'd be able to do the same for other potentially defective packet structures. Thanks

This is the current structure:

[A8 00] [09(storestorage)] [xx(numslots)] [xx xx(item type)] [xx num Equips] [item info] .... [00 00 00 00(adds this to end)]
Code:
int __usercall CTrunkDlg::OnPacket<eax>(int a1<ebp>, int a2<ebx>)
{
  int v2; // ecx@1
  int v3; // eax@1
  int result; // eax@2
  const RECT *v5; // edi@3
  int v6; // esi@4
  int v7; // eax@9
  int v8; // ecx@9
  int v9; // eax@10
  int v10; // eax@11
  int v11; // eax@12
  int v12; // eax@13
  int v13; // eax@15
  int v14; // ecx@22
  int v15; // ebx@24
  int v16; // eax@24
  int v17; // edi@24
  int v18; // ebx@26
  int v19; // eax@32
  int v20; // [sp-28h] [bp-28h]@15
  int v21; // [sp-24h] [bp-24h]@15
  int v22; // [sp-20h] [bp-20h]@15
  int v23; // [sp-1Ch] [bp-1Ch]@8
  int *v24; // [sp-18h] [bp-18h]@8
  int v25; // [sp-Ch] [bp-Ch]@1
  int v26; // [sp-8h] [bp-8h]@1
  int v27; // [sp-4h] [bp-4h]@1

  // Credits Sunnyboy @ http://forum.ragezone.com/
  sub_5F9280();
  v27 = v2; //stores original val of v2
  v26 = v2; //stores original val of v2
  v3 = *(_DWORD *)(a1 + 8) - 167; //not sure but takes int a1 and 
  v25 = a2; //erm ok
  //if v3?
  if ( v3 )
  {
    result = v3 - 1;
    if ( !result )
    {
      result = dword_670070;
      v5 = 0;
      if ( dword_670070 )
      {
        result = (*(int (__stdcall **)(int *****))(*(_DWORD *)(dword_670070 + 4) + 68))
(&off_670E68);
        v6 = result != 0 ? dword_670070 : 0;
      }
      else
      {
        v6 = 0;
      }
      if ( v6 )
      {
        //this is where stuff actuallly happens
        if ( !*(_DWORD *)(v6 + 232) )
        {
          *(_DWORD *)(a1 + 12) = 553648131;
          *(_DWORD *)(a1 + 8) = 553648131;
          v24 = &dword_636CF0;
          v23 = a1 + 8;
          *(_DWORD *)(a1 - 4) = 2;
          j__CxxThrowException(v23, v24);
        }
        v8 = *(_DWORD *)(a1 + 12);
        *(_DWORD *)(v6 + 232) = 0;
        //reads in a byte and casts it to an int from v8
        v7 = (unsigned __int8)CInPacket::Decode1(v8) - 7;
        if ( v7 )
        {
          v9 = v7 - 1;
          if ( !v9 )
          {
            v24 = 0;
            v23 = 0;
            v22 = 0;
            v21 = v8;
            v13 = (int)&v21;
            *(_DWORD *)(a1 + 12) = &v21;
            v20 = 531;                          // Please check and see if your inventory is full or not.
            goto LABEL_19;
          }
          v10 = v9 - 1;
          if ( v10 )
          {
            v11 = v10 - 2;
            if ( !v11 )
            {
              v24 = 0;
              v23 = 0;
              v22 = 0;
              v21 = v8;
              v13 = (int)&v21;
              *(_DWORD *)(a1 + 12) = &v21;
              v20 = 141;                        // You have not enough mesos.
              goto LABEL_19;
            }
            v12 = v11 - 1;
            if ( !v12 )
            {
              v24 = 0;
              v23 = 0;
              v22 = 0;
              v21 = v8;
              v13 = (int)&v21;
              *(_DWORD *)(a1 + 12) = &v21;
              v20 = 541;                        // The storage is full.
              goto LABEL_19;
            }
            if ( v12 != 2 )
            {
              v24 = 0;
              v23 = 0;
              v22 = 0;
              v21 = v8;
              v13 = (int)&v21;
              *(_DWORD *)(a1 + 12) = &v21;
              v20 = 532;                        // Due to an error, the trade did not happen.
LABEL_19:
              StringPool::GetString(a1, v13, v20);
              return CUtilDlg::Notice(a1);
            }
          }
          goto LABEL_29;
        }
        //if it gets here the storage operation can happen
        result = *(_DWORD *)(v6 + 228);
        if ( result > 0 && result <= 5 )
        {
          v14 = *(_DWORD *)(v6 + 156);
          if ( *(_DWORD *)(v14 + 60) != result )
            CCtrlTab::SetTab(v14, a2, a1, 0, result - 1);
          v15 = *(_DWORD *)(*(_DWORD *)(v6 + 172) + 56);
          v16 = sub_529947(v6);
          v17 = v16;
          if ( v16 < v15 )
            CCtrlScrollBar::SetCurPos(*(_DWORD *)(v6 + 172), v15, a1, v16, v16);
          v18 = v15 + 4;
          if ( v17 > v18 )
            CCtrlScrollBar::SetCurPos(*(_DWORD *)(v6 + 172), v18, a1, v17, v17 - 4);
          *(_DWORD *)(v6 + 216) = v17;
          v5 = 0;
LABEL_29:
          sub_526916(*(_DWORD *)(a1 + 12));
          return CWnd::InvalidateRect(v6, v5);
        }
      }
    }
  }
  else
  {
    if ( dword_670070 )
    {
      *(_DWORD *)(a1 + 12) = 553648131;
      *(_DWORD *)(a1 - 4) = 0;
      *(_DWORD *)(a1 - 16) = 553648131;
      j__CxxThrowException(a1 - 16, &dword_636CF0);
    }
    v19 = ZAllocEx<ZAllocAnonSelector>::Alloc(a1, 1464);
    *(_DWORD *)(a1 - 20) = v19;
    *(_DWORD *)(a1 - 4) = 1;
    if ( v19 )
      sub_5295D9(v19);
    v24 = *(int **)(a1 + 12);
    *(_DWORD *)(a1 - 4) = -1;
    result = sub_5268C7(v24);
  }
  return result;
}
 
Last edited:
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
The packet structure is wrong.
Eric

Do you know how quests worked in this version?

Quests back in v40beta were entirely server-sided. Not until way later did Nexon utilize ordinary quests with just EXP/Meso rewards as client-sided. I never checked them out in this source though so I'm not sure if they follow the same structure or not, but you have the IDB so it should be fairly easy to confirm :p

newbane2 v8/*(a1 + 12) are both pointers to *iPacket reference. Check out sub_526916(*(_DWORD *)(a1 + 12)); where it continues reading in the packet data and parses the items/etc. It's probably the bitfield encoding though like you said, the flags may have been different in v40b though that seems unlikely.
 
Newbie Spellweaver
Joined
May 14, 2015
Messages
26
Reaction score
1
@Eric is +12 from (a1 + 12) an offset? If so is it in bytes or bits? And when I see sometimes ax - x is that an offset in the opposite direction? The c++ pseudocode is kind of hard to follow.
I'm confused as to what the bitfield encoding is needed for.
Edit: This is what I've made out so far

Code:
void __userpurge sub_526916(int a1<ebx>, int a2<ebp>, int a3<edi>, int a4<esi>, int a5)
{
  int v5; // ecx@1
  int v6; // esi@1
  int v7; // ecx@1
  char v8; // al@1
  int v9; // ecx@1
  int v10; // eax@1
  int v11; // ecx@3
  signed __int16 v12; // ax@9
  int v13; // ecx@19
  int v14; // ST14_4@20
  char v15; // al@22
  int v16; // edi@22
  int v17; // esi@23
  int v18; // ecx@23
  int v19; // eax@23
  int v20; // ST14_4@23
  const CHAR *v21; // ST08_4@23
  void *v22; // esp@23
  const CHAR *v23; // ST08_4@23
  int v24; // eax@23
  int v25; // eax@25
  int v26; // eax@27
  int v27; // eax@27
  signed __int16 v28; // [sp-5Ch] [bp-5Ch]@10
  int v29; // [sp-58h] [bp-58h]@1
  int v30; // [sp-54h] [bp-54h]@1
  int v31; // [sp-50h] [bp-50h]@1

  sub_5F9280();
  v31 = a1;
  v30 = a4;
  v6 = v5;
  v7 = *(_DWORD *)(a2 + 8);
  v29 = a3;
  *(_DWORD *)(a2 - 36) = v6;
  v8 = CInPacket::Decode1(v7);                  // reads in a byte prob storage size
  v9 = *(_DWORD *)(a2 + 8);
  *(_DWORD *)(v6 + 220) = (unsigned __int8)v8;
  LOWORD(v10) = CInPacket::Decode2(v9);         // reads in the bitfield encoding (type) 
(short)
  *(_DWORD *)(a2 - 40) = v10;
  if ( v10 & 2 )
    *(_DWORD *)(v6 + 224) = CInPacket::Decode4(*(_DWORD *)(a2 + 8));// reads in the 
number of equips
  *(_DWORD *)(a2 - 20) = 0;
  *(_DWORD *)(a2 - 4) = 0;
  sub_529A38((void *)(a2 - 20));
  v11 = *(_DWORD *)(v6 + 184);
  *(_DWORD *)(a2 - 20) = *(_DWORD *)(v6 + 184);
  *(_DWORD *)(v6 + 184) = 0;
  *(_DWORD *)(a2 - 16) = 1;
  do
  {
    if ( *(_DWORD *)(a2 - 16) == 1 )            // if equip
    {
LABEL_13:
      v28 = 4;
      goto LABEL_14;
    }
    if ( *(_DWORD *)(a2 - 16) == 2 )            // if use
    {
      v28 = 8;
    }
    else
    {
      if ( *(_DWORD *)(a2 - 16) == 3 )          // if setup
      {
        v28 = 16;
      }
      else
      {
        if ( *(_DWORD *)(a2 - 16) == 4 )        // if etc
          goto LABEL_13;
        if ( *(_DWORD *)(a2 - 16) != 5 )        // if cash
        {
          v12 = 0;
          goto LABEL_15;
        }
        v28 = 64;
      }
    }
LABEL_14:
    v12 = v28;
LABEL_15:
    if ( *(_WORD *)(a2 - 40) & (unsigned __int16)v12 )
    {
      v15 = CInPacket::Decode1(*(_DWORD *)(a2 + 8));// reads 1 byte after the num items in 
storage which is item type I think
      v16 = 0;
      *(_DWORD *)(a2 - 28) = (unsigned __int8)v15;
      if ( (signed int)(unsigned __int8)v15 > 0 )
      {
        do                                      // this is the loop that adds the item data probably
        {
          sub_526BA4(a2 - 88);
          *(_BYTE *)(a2 - 4) = 1;
          v17 = sub_45FA26(0, a2, v16, v6);
          *(_BYTE *)(a2 - 4) = 2;
          sub_4AF372(v17);
          sub_40DAC2(a2 - 68);
          *(_DWORD *)(a2 - 64) = *(_DWORD *)(v17 + 4);
          *(_BYTE *)(a2 - 4) = 1;
          sub_40DAC2(a2 - 60);
          v18 = *(_DWORD *)(a2 - 64);
          *(_DWORD *)(a2 - 88) = *(_DWORD *)(v18 + 12);
          v19 = (*(int (__cdecl **)(int, int, int))(*(_DWORD *)v18 + 4))(v29, v30, v31);
          v20 = *(_DWORD *)(a2 - 88);
          *(_DWORD *)(a2 - 84) = v19;
          *(_DWORD *)(a2 - 80) = v16;
          v21 = *(const CHAR **)CItemInfo::GetItemName(a2, a2 - 48, v20);
          *(_BYTE *)(a2 - 4) = 3;
          v22 = alloca(2 * MultiByteToWideChar(0, 0, v21, -1, 0, 0));
          v6 = (int)&v29;
          v23 = *(const CHAR **)CItemInfo::GetItemName(a2, a2 - 44, *(_DWORD *)(a2 - 
88));
          *(_BYTE *)(a2 - 4) = 4;
          MultiByteToWideChar(0, 0, v23, -1, (LPWSTR)&v29, 1073741823);
          sub_40298A(a2, (int)&v29);
          _bstr_t::operator_(a2 - 32);
          sub_453530(a2 - 32);
          v24 = *(_DWORD *)(a2 - 44);
          *(_BYTE *)(a2 - 4) = 3;
          if ( v24 )
            sub_41E324((volatile LONG *)(v24 - 12));
          v25 = *(_DWORD *)(a2 - 48);
          *(_BYTE *)(a2 - 4) = 1;
          if ( v25 )
            sub_41E324((volatile LONG *)(v25 - 12));
          v26 = sub_48ACF0(a2 - 52, *(_DWORD *)(a2 - 88), 1, 0);
          
_com_ptr_t<_com_IIID<IWzGr2DLayer____s_GUID__GUID_6dc8c7ce_8e81_4420_b4f6_4b60
b7d5fcdf>>::operator_(*(_DWORD *)v26);
          v27 = *(_DWORD *)(a2 - 52);
          if ( v27 )
            (*(void (__stdcall **)(_DWORD))(*(_DWORD *)v27 + 8))(*(_DWORD *)(a2 - 52));
          sub_529A74(-1);
          sub_5299E1(a2 - 88);
          *(_BYTE *)(a2 - 4) = 0;
          sub_526BB2(a2 - 88);
          ++v16;
        }
        while ( v16 < *(_DWORD *)(a2 - 28) );
        v6 = *(_DWORD *)(a2 - 36);
      }
      v11 = *(_DWORD *)(a2 - 20);
    }
    else
    {
      *(_DWORD *)(a2 - 24) = 0;
      *(_DWORD *)(a2 - 28) = 0;
      while ( v11 && *(_DWORD *)(a2 - 24) < *(_DWORD *)(v11 - 4) )
      {
        v13 = *(_DWORD *)(a2 - 28) + v11;
        if ( *(_DWORD *)v13 / 1000000 == *(_DWORD *)(a2 - 16) )// probably gets the item type
        {
          v14 = v13;
          sub_529A74(-1);
          sub_5299E1(v14);
        }
        ++*(_DWORD *)(a2 - 24);
        *(_DWORD *)(a2 - 28) += 28;
        v11 = *(_DWORD *)(a2 - 20);
      }
    }
    ++*(_DWORD *)(a2 - 16);
  }
  while ( *(_DWORD *)(a2 - 16) <= 5 );
  *(_DWORD *)(v6 + 212) = -1;
  *(_DWORD *)(a2 - 4) = -1;
  sub_529A38((void *)(a2 - 20));
}
 
Last edited:
Skilled Illusionist
Joined
Jul 17, 2010
Messages
333
Reaction score
165
I'm confused as to what the bitfield encoding is needed for.
BitfieldEncoding (flag) is needed to split items into each item types (equip/use/setup/etc/cash or even meso).
Code:
  LOWORD([B]v10[/B]) = [B]CInPacket::Decode2(v9); [/B]        // reads in the bitfield encoding (type) 
(short)
  *(_DWORD *)[B](a2 - 40) = v10[/B];
  [B]if ( v10 & 2 )[/B]
    *(_DWORD *)(v6 + 224) = [B]CInPacket::Decode4[/B](*(_DWORD *)(a2 + 8));//hmm isn't this meso?
  *(_DWORD *)(a2 - 16) = 1;
  [B]do
  {[/B]
    if ( *(_DWORD *)(a2 - 16) == 1 )            // if equip
    {
[B]LABEL_13:[/B]
      [B]v28 = 4[/B];
      goto LABEL_14;
    }
    if ( *(_DWORD *)(a2 - 16) == 2 )            // if use
    {
      [B]v28 = 8[/B];
    }
    else
    {
      if ( *(_DWORD *)(a2 - 16) == 3 )          // if setup
      {
        [B]v28 = 16[/B];
      }
      else
      {
        if ( *(_DWORD *)(a2 - 16) == 4 )        // if etc
          [B]goto LABEL_13;[/B]//same to equip?
        if ( *(_DWORD *)(a2 - 16) != 5 )        // if cash
        {
          v12 = 0;
          goto LABEL_15;
        }
        [B]v28 = 64[/B];
      }
    }
LABEL_14:
    [B]v12 = v28;[/B]
LABEL_15:
    [B]if ([/B] *(_WORD *)[B](a2 - 40) &[/B] (unsigned __int16)[B]v12 )[/B]//if the bits 'flag' enabled
    {
      [B]v15 = CInPacket::Decode1[/B](*(_DWORD *)(a2 + 8));//item count
      v16 = 0;
      *(_DWORD *)[B](a2 - 28) =[/B] (unsigned __int8)[B]v15[/B];
      if ( (signed int)(unsigned __int8)v15 > 0 )
      {
        do                                      // this is the loop that adds the item data probably
        {
          //oh, wait iPacket disappeared lol
          ++v16;
        }
        while ( v16 < *(_DWORD *)[B](a2 - 28)[/B] );
      }
    }
    [B]++[/B]*(_DWORD *)[B](a2 - 16)[/B];
  [B]}
  while[/B] ( *(_DWORD *)[B](a2 - 16) <= 5[/B] );
 
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
What Yuuroido said. Also yes, the & 2 mask is for DBChar flags, and Meso is always 0x2 :p.

The "bitfield encoding" is just the mask Nexon uses for items. Nexon uses the below method (and do note that nTI simply means Type Index -> nItemID / 10000):
Code:
public static int get_item_type_from_typeindex(int nTI) {
	int dbcharFlag;
	switch (nTI) {
		case ItemType.Equip:
			dbcharFlag = DBChar.ItemSlotEquip.getFlag();//0x4
			break;
		case ItemType.Consume:
			dbcharFlag = DBChar.ItemSlotConsume.getFlag();//0x8
			break;
		case ItemType.Install:
			dbcharFlag = DBChar.ItemSlotInstall.getFlag();//0x10
			break;
		case ItemType.Etc:
			dbcharFlag = DBChar.ItemSlotEtc.getFlag();//0x20
			break;
		case ItemType.Cash:
			dbcharFlag = DBChar.ItemSlotCash.getFlag();//0x40
			break;
		default:
			dbcharFlag = 0;
			break;
	}
	return dbcharFlag;
}

Though I don't really notice a difference, did you compare the current packet vs the bytes in IDA? Your addItemInfo is already correct and I don't think storage has changed.
 
Joined
Apr 10, 2008
Messages
4,087
Reaction score
1,264
What @Yuuroido said. Also yes, the & 2 mask is for DBChar flags, and Meso is always 0x2 :p.

The "bitfield encoding" is just the mask Nexon uses for items. Nexon uses the below method (and do note that nTI simply means Type Index -> nItemID / 10000):
Code:
public static int get_item_type_from_typeindex(int nTI) {
    int dbcharFlag;
    switch (nTI) {
        case ItemType.Equip:
            dbcharFlag = DBChar.ItemSlotEquip.getFlag();//0x4
            break;
        case ItemType.Consume:
            dbcharFlag = DBChar.ItemSlotConsume.getFlag();//0x8
            break;
        case ItemType.Install:
            dbcharFlag = DBChar.ItemSlotInstall.getFlag();//0x10
            break;
        case ItemType.Etc:
            dbcharFlag = DBChar.ItemSlotEtc.getFlag();//0x20
            break;
        case ItemType.Cash:
            dbcharFlag = DBChar.ItemSlotCash.getFlag();//0x40
            break;
        default:
            dbcharFlag = 0;
            break;
    }
    return dbcharFlag;
}

Though I don't really notice a difference, did you compare the current packet vs the bytes in IDA? Your addItemInfo is already correct and I don't think storage has changed.

honestly setfield flags don't even matter as the client will always crash unless u send them all
 
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
honestly setfield flags don't even matter as the client will always crash unless u send them all

You can login just fine without sending them all. I ignore a lot of them in v90, and I was also able to trace a client crash issue with Resistance characters by removing the SkillRecord flag. Some aren't flags, and others are required to send no matter what (haven't tested every flag to see every one required tho, my best guess is just Character and Avatar).
 
Skilled Illusionist
Joined
Apr 26, 2015
Messages
302
Reaction score
77
Quests back in v40beta were entirely server-sided. Not until way later did Nexon utilize ordinary quests with just EXP/Meso rewards as client-sided. I never checked them out in this source though so I'm not sure if they follow the same structure or not, but you have the IDB so it should be fairly easy to confirm :p

@newbane2 v8/*(a1 + 12) are both pointers to *iPacket reference. Check out sub_526916(*(_DWORD *)(a1 + 12)); where it continues reading in the packet data and parses the items/etc. It's probably the bitfield encoding though like you said, the flags may have been different in v40b though that seems unlikely.

But do you know how the quest window worked in v40b?
I mean, how to make data appear in that window.
 
Newbie Spellweaver
Joined
May 14, 2015
Messages
26
Reaction score
1
Still can't figure out the packet structure for storage, but if anyone needs getNum and getText working here is the updated handler
Code:
public void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {            byte lastMsg = slea.readByte(); // 00 (last msg type I think)
            byte action = slea.readByte(); // 00 = end chat, 01 == follow
            if(action == 0x00) //end chat dispose
            {
                NPCScriptManager.getInstance().dispose(c);
            }
            else if (lastMsg == 0x02) //getText
            {
                String returnText = slea.readMapleAsciiString();
                NPCConversationManager cm = NPCScriptManager.getInstance().getCM(c);
                cm.setGetText(returnText);
                NPCScriptManager.getInstance().action(c, action, lastMsg, (byte) -1);
            }
            else if(lastMsg == 0x03) //getNum
            {
                int returnNum = slea.readInt();
                NPCConversationManager cm = NPCScriptManager.getInstance().getCM(c);
                cm.setGetNumber(returnNum);
                NPCScriptManager.getInstance().action(c, action, lastMsg, (byte) -1);
            }
            else 
            {
                byte selection = -1;
                if (slea.available() > 0) {
                    selection = slea.readByte();
                }
                NPCScriptManager.getInstance().action(c, action, lastMsg, selection);
            }
    }
 
Last edited:
Skilled Illusionist
Joined
Apr 26, 2015
Messages
302
Reaction score
77
Storage structure:

It work's for all categories but ETC. I don't know why..

 
Skilled Illusionist
Joined
Jul 17, 2010
Messages
333
Reaction score
165
Storage structure:

It work's for all categories but ETC. I don't know why..

Probably, this is why
Code:
if ( *(_DWORD *)(a2 - 16) == 1 )            // if equip
    {
[B]LABEL_13:
      v28 = 4;[/B]
      goto LABEL_14;
    }
//~snip~
        if ( *(_DWORD *)(a2 - 16) == 4 )        // if etc
          [B]goto LABEL_13[/B];
somehow they used the same flag as 'equip' for 'etc' on v40.
Therefore, you'll need to send both of equip&etc items when you store/takeout an equip/etc item. (correct me if I'm wrong)
 
Newbie Spellweaver
Joined
May 14, 2015
Messages
26
Reaction score
1
Guys when you see stuff like (a2 - 16), what is the -16? Is it an offset for the packet stream? And what does (a2-16) for example evaluate to? (bit, byte, int, etc)
 
Skilled Illusionist
Joined
Apr 26, 2015
Messages
302
Reaction score
77
Guys when you see stuff like (a2 - 16), what is the -16? Is it an offset for the packet stream? And what does (a2-16) for example evaluate to? (bit, byte, int, etc)
It's a memory address pointer.
 
Newbie Spellweaver
Joined
May 14, 2015
Messages
26
Reaction score
1
Before I waste anymore time, does CField_ContiMove__OnPacket exist in v40? I'm trying to get the boat headers. Or if anyone would be so kind as to give me the sendOp.

Also is there a easy way to find functions that are not under CField__OnPacket / CwContext__OnPacket(or w.e)? (like ContiMove)
 
Last edited:
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
Before I waste anymore time, does CField_ContiMove__OnPacket exist in v40? I'm trying to get the boat headers. Or if anyone would be so kind as to give me the sendOp.

Also is there a easy way to find functions that are not under CField__OnPacket / CwContext__OnPacket(or w.e)? (like ContiMove)

ContiMove inherits CField, so you can find it has an XREF to CField::OnPacket. Very easy to find it if you know your way around IDA :p. I don't know if it exists in v40beta, but considering the fact that Orbis exists in the client, I believe that the packets for continents would exist as well.
 
Back
Top