¿Alguien sabe el offset del pChaosBoxState para la 1.04d? El que está creo que es para la 1.04e...
#define pChaosBoxState *(BYTE*)(*(DWORD*)(0x98670C4) + 0xC8) <-- ?????
El offset está bien, pero tenía que cambiar algunas funciones para hacerlo funcionar correctamente.
Si tenéis
1.04D con
z-team os posteo todo el código que estoy usando, con el fix de la Chaos Machine, el fix de las armas en DL/RF, el fix para no equipar/desequipar alas o Uniria en Icarus y el fix para que no desaparezcan items si desequipáis algo con el inventario lleno.
Voy a seguir el mismo esquema que dejó
@Llalex para que quede más ordenado:
stdafx.hAgregar al final:
//Click Derecho
#define MOVE_ITEM 1
Import.hAgregar al final:
//Click Derecho
#define pChaosBoxState *(BYTE*)(*(DWORD*)(0x98670C4) + 0xC8)
post_item.cppBuscar
"PostItem::PostItem ()" y agregar debajo de
"Hook();" //Click Derecho
#if(MOVE_ITEM)
last_tickcount_moveitem_ = 0;
#endif
Buscar
"void PostItem::Hook()" y agregar al final dentro de la función:
//Click Derecho
#if(MOVE_ITEM)
SetOp((LPVOID)(0x0083B7E4), (LPVOID)Equipments, ASM::JMP); //1.04D->0x0083B7E4 1.04E -> 0x0083B7E4 + 0x150
#endif
Buscar
"void PostItem::PostItemToWorldChatChannelImp" y reemplazarla en su totalidad:
void PostItem::PostItemToWorldChatChannelImp ( void * item_data ) {
// check window, not allow for shop, inventory, warehouse, etc
if ( gInterface.CheckWindow ( Trade ) ||
gInterface.CheckWindow ( Warehouse ) ||
gInterface.CheckWindow ( Shop ) ||
gInterface.CheckWindow ( Store ) ||
gInterface.CheckWindow ( OtherStore ) ||
gInterface.CheckWindow ( CashShop ) ||
gInterface.CheckWindow ( ExpandWarehouse ) )
{
return;
}
if ( GetTickCount() <= gPostItem.last_tickcount_post_ + 3000 )
{
return;
}
if ( GetKeyState ( VK_RBUTTON ) & 0x8000 && GetKeyState ( VK_CONTROL ) & 0x8000 )
{
PMSG_POSTITEM iMsg = { '\0' };
strcpy_s ( iMsg.chatmsg, ( char* ) pCurrentViewingItemName );
memcpy_s ( &iMsg.chatid[0], 10, ( char* ) oUserObjectStruct_, 10 );
memcpy_s ( &iMsg.item_data[0], 107, item_data, 107 );
iMsg.h.set( ( BYTE* )&iMsg, 0x78, sizeof ( iMsg ) );
gProtocol.DataSend ( ( BYTE* ) &iMsg, iMsg.h.size );
gPostItem.last_tickcount_post_ = GetTickCount();
}
//Click Derecho
#if(MOVE_ITEM)
else if (GetKeyState(VK_RBUTTON) & 0x8000 && GetTickCount() >= gPostItem.last_tickcount_moveitem_ + 250)
{
ObjectItem * lItem = (ObjectItem*)item_data;
if (lItem->ItemID < 0) { return; }
PMSG_ITEM_MOVE_RECV pMsg = { 0 };
pMsg.h.set( ( BYTE* )&pMsg, 0x79, 0x01, sizeof ( pMsg ) );
pMsg.Target = -1;
if (gInterface.CheckWindow(ChaosBox) && gInterface.CheckWindow(Inventory))
{
if ((pCursorX > 460))
{
pMsg.sFlag = 0;
pMsg.tFlag = 3;
pMsg.Target = 0;
pMsg.Source = lItem->PosX + lItem->PosY * 8 + 12;
}
else if (gInterface.CheckWindow(ExpandInventory) && pCursorX > 260)
{
pMsg.sFlag = 0;
pMsg.tFlag = 3;
pMsg.Target = 0;
pMsg.Source = lItem->PosX + lItem->PosY * 8 + 12 + 64;
if (pCursorY > 130)
pMsg.Source += 32;
}
else {
pMsg.sFlag = 3;
pMsg.tFlag = 0;
pMsg.Target = 0;
pMsg.Source = lItem->PosX + lItem->PosY * 8;
}
}
else
{
float v1 = 0;
if (gInterface.CheckWindow(Character))
v1 = *(float*)(0x00D24E88);
if ((pCursorX > 460 - v1))
{
pMsg.sFlag = 0;
pMsg.tFlag = 0;
pMsg.Source = lItem->PosX + lItem->PosY * 8 + 12;
}
else if (gInterface.CheckWindow(ExpandInventory) && pCursorX > 260 - v1)
{
pMsg.sFlag = 0;
pMsg.tFlag = 0;
pMsg.Source = lItem->PosX + lItem->PosY * 8 + 12 + 64;
if (pCursorY > 130)
pMsg.Source += 32;
}
pMsg.Target = 0;
}
gProtocol.DataSend ( ( BYTE* ) &pMsg, pMsg.h.size );
gPostItem.last_tickcount_moveitem_ = GetTickCount();
}
#endif
Agregar al final de
"post_item.cpp"//Click Derecho
#if(MOVE_ITEM)
void __declspec (naked) PostItem::Equipments() {
static DWORD mem = 0;
_asm {
mov eax, dword ptr ds : [ebp - 04]
mov mem, eax
}
RemoveEquipment((void *)mem);
_asm {
mov esp, ebp
pop ebp
ret 0004
}
}
void PostItem::RemoveEquipment(void * item_data) {
// check window, not allow for shop, inventory, warehouse, etc
if (gInterface.CheckWindow(Trade) ||
gInterface.CheckWindow(Warehouse) ||
gInterface.CheckWindow(Shop) ||
gInterface.CheckWindow(Store) ||
gInterface.CheckWindow(OtherStore) ||
gInterface.CheckWindow(CashShop) ||
gInterface.CheckWindow(ExpandWarehouse)) {
return;
}
if (GetKeyState(VK_RBUTTON) & 0x8000 && GetTickCount() >= gPostItem.last_tickcount_moveitem_ + 250)
{
ObjectItem * lItem = (ObjectItem*)item_data;
if (lItem->ItemID < 0) { return; }
PMSG_ITEM_MOVE_RECV pMsg = { 0 };
pMsg.h.set((LPBYTE)&pMsg, 0x79, 0x01, sizeof (pMsg));
pMsg.sFlag = 0;
pMsg.tFlag = 0;
pMsg.Source = lItem->PosX;
pMsg.Target = 0;
gProtocol.DataSend((BYTE*)&pMsg, pMsg.h.size);
gPostItem.last_tickcount_moveitem_ = GetTickCount();
}
}
#endif
"post_item.h"Agregar debajo de
"int PostItemColor;" //Click Derecho
#if(MOVE_ITEM)
static void Equipments();
static void RemoveEquipment(void * item_data);
#endif
Agregar debajo de
"char * draw_character_head_chat_text_base_address_;" //Click Derecho
#if(MOVE_ITEM)
DWORD last_tickcount_moveitem_;
#endif
"Protocol.cpp"Buscar
"case 0xF3:" y agregar a dentro de este case:
//Click Derecho
#if(MOVE_ITEM)
case 0xEE:
{
SetChaosBoxState((PMSG_SET_CHAOSBOX_STATE*)Data);
}
break;
#endif
Agregar al final de
"Protocol.cpp"//Click Derecho
#if(MOVE_ITEM)
void SetChaosBoxState(PMSG_SET_CHAOSBOX_STATE* Data){
pChaosBoxState = Data->state;
return;
}
#endif
"Protocol.h"Buscar
"struct PMSG_POSTITEM" y agregar debajo:
//Click Derecho
#if(MOVE_ITEM)
struct PMSG_ITEM_MOVE_RECV
{
//PBMSG_HEAD h;
PBMSG_HEAD2 h;
BYTE sFlag;
BYTE tFlag;
BYTE Source;
BYTE Target;
};
struct PMSG_SET_CHAOSBOX_STATE
{
//PBMSG_HEAD header; // C1:32
PBMSG_HEAD2 header; // C1:32
BYTE state;
};
#endif
Agregar al final de
"Protocol.h":
//Click Derecho
#if(MOVE_ITEM)
void SetChaosBoxState(PMSG_SET_CHAOSBOX_STATE* Data);
#endif
stdafx.hAgregar al final:
//Click Derecho
#define MOVE_ITEM 1
Protocol.cppAgregar al final:
//Click Derecho
#if(MOVE_ITEM)
//BYTE InventoryCheckInsertItem(int aIndex, WORD item) // OK
BYTE InventoryCheckInsertItem(int aIndex, CItem item) // OK
{
//CItem item;
int w,h,iwidth,iheight;
BYTE blank = 0;
if(item.GetSize((int &)iwidth,(int &)iheight)==0)
{
LogAdd(lMsg.Get(527),__FILE__,__LINE__);
return -1;
}
// Fix Click Derecho - No desequipar cosas con el inventario lleno
if (!CheckInventoryEmptySpace(&gObj[aIndex], iheight, iwidth))
{
return -1;
}
for(h = 0; h < MAX_INVENTORY_H; h++) //24
{
for(w = 0; w < 8; w++)
{
if(*(BYTE*)(gObj[aIndex].pInventoryMap+h*8+w) == 255)
{
blank = gObjInventoryRectCheck(aIndex,w,h,iwidth,iheight);
if(blank == 254)
{
goto GOTO_EndFunc;
}
if(blank != 255)
{
return blank;
}
}
}
}
GOTO_EndFunc:
return -1;
}
//bool IsLuckyItem(int item_num)
//{
// if( (item_num >= GET_ITEM(7,62) && item_num <= GET_ITEM(7,72))
// || (item_num >= GET_ITEM(8,62) && item_num <= GET_ITEM(8,72))
// || (item_num >= GET_ITEM(9,62) && item_num <= GET_ITEM(9,72))
// || (item_num >= GET_ITEM(10,62) && item_num <= GET_ITEM(10,72))
// || (item_num >= GET_ITEM(11,62) && item_num <= GET_ITEM(11,72))
// )
// {
// return true;
// }
// return false;
//}
void CGMoveItemProc(PMSG_MOVEITEM* aRecv, short aIndex)
{
int iwidth, iheight;
if (OBJMAX_RANGE(aIndex) == 0) { return; }
LPOBJ lpObj = &gObj[aIndex];
if (aRecv->Target == -1) { return; }
if (aRecv->tFlag == 3 && aRecv->sFlag == 0 && lpObj->pInventory[aRecv->Source].IsItem()) //check input item
{
//if (IsLuckyItem(lpObj->pInventory[aRecv->Source].m_Index))
if (g_LuckyItemManager.IsLuckyItemEquipment(lpObj->pInventory[aRecv->Source].m_Type))
{
return;
}
BYTE btItemType = 0;
btItemType |= (lpObj->pInventory[aRecv->Source].m_Type & 0x1E00) >> 5;
if ((btItemType + 2) == lpObj->pInventory[aRecv->Source].m_ItemOptionEx)
{
return;
}
}
//PMSG_ITEM_MOVE_RECV pMsg = { 0 };
PMSG_INVENTORYITEMMOVE pMsg = { 0 };
//pMsg.TargetSlot = -1;
pMsg.target_item_num = -1;
if (aRecv->tFlag == 3 && aRecv->sFlag == 0) //move Inv -> ChaosBox
{
// Fix Click Derecho - No mover Fenrir azul/negro/dorado en la ChaosBox
if (!lpObj->pInventory[aRecv->Source].IsItem() || ((lpObj->pInventory[aRecv->Source].m_Type == ITEMGET(13,37)) && (lpObj->pInventory[aRecv->Source].m_NewOption > 0)))
return; //no item
int p = 0, c = 0, d = 0, w = 0, h = 0, n = 0;
int Target = -1;
int TargetMap[CHAOS_BOX_SIZE] = { '\0' };
for (n = 0; n < CHAOS_BOX_SIZE; n++)
{
if (lpObj->pChaosBox[n].IsItem())
{
CItem ItemInfo = lpObj->pChaosBox[n];
if(ItemInfo.GetSize((int&)w,(int&)h)==0)
{
LogAdd(lMsg.Get(527),__FILE__,__LINE__);
return;
}
for (c = 0; c < w; c++)
{
for (d = 0; d < h; d++)
{
p = c + d * 8 + n;
if (p < CHAOS_BOX_SIZE)
{
TargetMap[p] = 1;
}
}
}
}
}
for (n = 0; n < CHAOS_BOX_SIZE; n++)
{
if (!TargetMap[n])
{
Target = n;
CItem item = lpObj->pInventory[aRecv->Source];
if(item.GetSize((int&)w,(int&)h)==0)
{
LogAdd(lMsg.Get(527),__FILE__,__LINE__);
return;
}
for (c = 0; c < w; c++)
{
for (d = 0; d < h; d++)
{
p = c + d * 8 + n;
if (p >= CHAOS_BOX_SIZE || TargetMap[p] || (n % 8) + c > 7) // 8) = 8
{
Target = -1;
}
}
}
if (Target != -1)
break;
}
}
if (Target != -1)
{
pMsg.target_item_num = Target;
ItemByteConvert(pMsg.sItemInfo, lpObj->pInventory[aRecv->Source]);
}
else
{
return; //no more empty slot to add.
}
}
else if (aRecv->tFlag == 0 && aRecv->sFlag == 3) //move ChaosBox -> Inv
{
if (!lpObj->pChaosBox[aRecv->Source].IsItem())
return; //no item
ItemByteConvert(pMsg.sItemInfo, lpObj->pChaosBox[aRecv->Source]);
int Target = InventoryCheckInsertItem(aIndex, lpObj->pChaosBox[aRecv->Source]);
//int Target = gObjInventoryInsertItem(aIndex, lpObj->pChaosBox[aRecv->Source]);
//if (Target == 0xFF)
if (Target == -1)
{
return;
}
pMsg.target_item_num = Target;
}
else if (aRecv->tFlag == 0 && aRecv->sFlag == 0) //equip/unequip item
{
if (!lpObj->pInventory[aRecv->Source].IsItem())
return;
ItemByteConvert(pMsg.sItemInfo, lpObj->pInventory[aRecv->Source]);
if (aRecv->Source > 11) { //wear equipment case
CItem ItemInfo = lpObj->pInventory[aRecv->Source];
LPITEM_ATTRIBUTE lpItemAttr = GetItemAttr(ItemInfo.m_Type);
//pMsg.target_item_num = ItemInfo.GetDetailItemType();
pMsg.target_item_num = lpItemAttr->ItemSlot;
if (pMsg.target_item_num == 0
&& lpObj->pInventory[0].IsItem() //slot 0 already has item
&& !lpObj->pInventory[1].IsItem() //slot 1 is empty
&& lpObj->pInventory[aRecv->Source].m_Type < ITEMGET(3, 0)) //sword,spear, maces item
pMsg.target_item_num = 1;
else if (pMsg.target_item_num == 10
&& lpObj->pInventory[10].IsItem() //slot 10 already has item
&& !lpObj->pInventory[11].IsItem()) //slot 11 empty
pMsg.target_item_num = 11;
else if (lpObj->pInventory[lpItemAttr->ItemSlot].IsItem()){
return; //already has item this slot
if (!gObjIsItemPut(lpObj, &ItemInfo, pMsg.target_item_num))
return;
}
}
else { //unequipment case
int Target = InventoryCheckInsertItem(aIndex, lpObj->pInventory[aRecv->Source]);
//int Target = gObjInventoryInsertItem(aIndex, lpObj->pInventory[aRecv->Source]);
//if (Target == 0xFF)
if (Target == -1)
{
return;
}
pMsg.target_item_num = Target;
}
}
else {
return; //invalid case
}
pMsg.sFlag = aRecv->sFlag;
pMsg.tFlag = aRecv->tFlag;
pMsg.source_item_num = aRecv->Source;
//this->CGItemMoveRecv(&pMsg, aIndex);
CGInventoryItemMove(&pMsg, aIndex);
if (aRecv->tFlag == 0 && aRecv->sFlag == 3)
{
GCUserChaosBoxSend(lpObj, 0);
//update chaosBox by new packet????
PMSG_SET_CHAOSBOX_STATE pMsg = { 0 };
pMsg.header.set((LPBYTE)&pMsg, 0xF3, 0xEE, sizeof(pMsg));
pMsg.state = 0; //0 = allow mix || 2 = disable mix
DataSend(aIndex, (LPBYTE)&pMsg, pMsg.header.size);
}
else if ((aRecv->tFlag == 3 && aRecv->sFlag == 0) || (aRecv->tFlag == 0 && aRecv->sFlag == 0))
{
if (!lpObj->pInventory[aRecv->Source].IsItem())
{
GCInventoryItemDeleteSend(aIndex, aRecv->Source, aRecv->sFlag);
}
}
return;
}
#endif
En
Protocol.cpp buscar
"GCPostItemProc((PMSG_POST_ITEM_RECV*)aRecv,aIndex);" y agregar debajo de su
"break":
//Click Derecho
#if(MOVE_ITEM)
case 0x79:
CGMoveItemProc((PMSG_MOVEITEM*)aRecv, aIndex);
break;
#endif
Protocol.hBuscar
"void GCPostItemProc(PMSG_POST_ITEM_RECV* lpMsg, int aIndex );" y agregar a continuación:
//Click Derecho
#if(MOVE_ITEM)
struct PMSG_MOVEITEM
{
//PBMSG_HEAD h;
PBMSG_HEAD2 h;
BYTE sFlag;
BYTE tFlag;
BYTE Source;
BYTE Target;
};
struct PMSG_SET_CHAOSBOX_STATE
{
//PBMSG_HEAD header; // C1:32
PBMSG_HEAD2 header; // C1:32
BYTE state;
};
#endif
Buscar
"void CGInventoryEquipment(_tagPMSG_REQ_INVENTORY_EQUIPMENT_ITEM * lpMsg, int iIndex);" y agregar a continuación:
//Click Derecho
#if(MOVE_ITEM)
void CGMoveItemProc(PMSG_MOVEITEM* aRecv, short aIndex);
//BYTE InventoryCheckInsertItem(int aIndex, WORD item);
BYTE InventoryCheckInsertItem(int aIndex, CItem item);
#endif
User.cppDentro de la función
"BOOL gObjIsItemPut(LPOBJ lpObj, CItem * lpItem, int pos )" buscar la línea de código
"if(lpObj->Class == CLASS_DARKLORD)" y reemplazarlo por lo siguiente:
if(lpObj->Class == CLASS_DARKLORD)
{
if((lpItem->m_Type>>9) == 2)
{
if(lpItem->m_Part != pos)
{
return false;
}
}
// Fix Click Derecho - Solo escudos/cuervo en el DL como segunda arma
else if ((lpItem->m_Type != MuItem::miHELPER_DARK_RAVEN && lpItem->GetDetailItemType() != MuItemType::mitSHIELD) && pos == 1)
{
return false;
}
}
Dentro de la misma función
"BOOL gObjIsItemPut(LPOBJ lpObj, CItem * lpItem, int pos )" buscar la condición
"if(lpObj->Class == CLASS_WIZARD)" y reemplazar por:
if(lpObj->Class == CLASS_WIZARD)
{
if((lpItem->m_Type>>9) == 5)
{
if(lpItem->m_Part != pos)
{
return false;
}
}
// Fix Click Derecho - Solo escudos en el SM como segunda arma
else if (lpItem->GetDetailItemType() != MuItemType::mitSHIELD && pos == 1)
{
return false;
}
}
Buscar la linea
"if(lpItem->m_Part != pos)" y agregar en la linea de arriba:
// Fix Click Derecho Armas RF
if(lpObj->Class == CLASS_MONK)
{
if(pos == 0 || pos == 1)
{
if(lpObj->pInventory[0].IsItem() == 1)
{
if ((lpItem->GetDetailItemType() == MuItemType::mitGloves) && (lpObj->pInventory[0].GetDetailItemType() != MuItemType::mitGloves) ||
(lpItem->GetDetailItemType() != MuItemType::mitGloves && lpObj->pInventory[0].GetDetailItemType() == MuItemType::mitGloves))
{
return false;
}
}
if(lpObj->pInventory[1].IsItem() == 1)
{
if ((lpItem->GetDetailItemType() == MuItemType::mitGloves) && (lpObj->pInventory[1].GetDetailItemType() != MuItemType::mitGloves) ||
(lpItem->GetDetailItemType() != MuItemType::mitGloves && lpObj->pInventory[1].GetDetailItemType() == MuItemType::mitGloves))
{
return false;
}
}
}
}
Seguimos en la función
"BOOL gObjIsItemPut(LPOBJ lpObj, CItem * lpItem, int pos )", buscamos la línea
"else if(lpItem->m_Type == ITEMGET(13,2))" y reemplazamos toda la condición por:
else if(lpItem->m_Type == ITEMGET(13,2))
{
// Fix Click Derecho - No equipar Uniria en Icarus
//if(lpObj->MapNumber == 7 || lpObj->Level < lpItem->m_RequireLevel)
if(lpObj->MapNumber == 7 || lpObj->MapNumber == 10 || lpObj->Level < lpItem->m_RequireLevel)
{
return false;
}
}
zzzitem.cppDentro de la función
"int CItem::GetDetailItemType()" hay que comprobar que todos los claw para RF están seteados aquí en el bloque de la condición if que tenga como "return" el valor "12":
Yo lo puse así, pero debéis incluir los valores de vuestros claw:
// Fix Click Derecho
//if( this->m_Type >= MuItem::miGROUP_SWORD_START+32 && this->m_Type <= MuItem::miGROUP_SWORD_START+35 )
if( (this->m_Type >= MuItem::miGROUP_SWORD_START+32 && this->m_Type <= MuItem::miGROUP_SWORD_START+35) ||
(this->m_Type >= MuItem::miGROUP_SWORD_START+40 && this->m_Type <= MuItem::miGROUP_SWORD_START+41) )
{
return MuItemType::mitGloves;
}
Espero que os ayude. :)