Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Struct trade
- typedef struct
- {
- bool isTrading;
- bool WaitingData;
- bool Confirm;
- DWORD Gold;
- clock_t Timer;
- WORD ClientID;
- st_Item Itens[15];
- char TradeItemSlot[15];
- } st_Trade;
- // Declaração em .h
- #define MAX_PLAYER 100
- extern st_Trade Trade[MAX_PLAYER+1];
- // Declare num .cpp
- st_Trade Trade[MAX_PLAYER+1];
- // Em um .cpp com Hooks
- void __declspec(naked) NKD_NewTrade()
- {
- static const int dwContinue = 0x00438D57;
- __asm
- {
- PUSH [EBP + 08h]
- PUSH [EBP + 0Ch]
- CALL NKD_SystemTrade
- JMP dwContinue
- }
- }
- // Chame a função usando:
- JMP_NEAR(0x4323F4, &NKD_NewTrade, 2);
- // Um novo .cpp contendo o código:
- /*
- -------------
- by Shepher
- -------------
- */
- void OpenTrade(short ClientID, short MobID)
- {
- // Usado após o Request, onde é enviado o trade totalmente vazio
- SendTrade p;
- memset(&p, 0, sizeof p);
- p.Header.ClientId = MobID;
- p.OtherClientid = ClientID;
- p.Header.Size = 156;
- p.Header.PacketId = 0x383;
- for(UINT8 i=0;i<15;i++)
- p.TradeItemSlot[i] = 255;
- SendPacket((BYTE*)&p, MobID, 156);
- }
- void SendAllTrade(short ClientID, short MobID)
- {
- // Envia o trade completo para o MobID
- SendTrade p;
- memset(&p, 0, sizeof p);
- p.Header.ClientId = MobID;
- p.OtherClientid = ClientID;
- p.Header.Size = 156;
- p.Header.PacketId = 0x383;
- p.Confirma = Trade[ClientID].Confirm;
- for(UINT8 i=0;i<15;i++)
- {
- p.TradeItem[i] = Trade[ClientID].Itens[i];
- p.TradeItemSlot[i] = Trade[ClientID].TradeItemSlot[i];
- }
- p.Gold = Trade[ClientID].Gold;
- SendPacket((BYTE*)&p, MobID, 156);
- }
- void CloseTrade(short ClientID)
- {
- // Fecha o trade dos dois usuários
- memset(Trade[ClientID].TradeItemSlot, 255, sizeof(char) * 15);
- memset(Trade[ClientID].Itens, 0, sizeof st_Item * 15);
- Trade[ClientID].isTrading = false;
- Trade[ClientID].Timer = 0;
- Trade[ClientID].Confirm = false;
- Trade[ClientID].WaitingData = false;
- PacketHeader Header;
- Header.ClientId = ClientID;
- Header.Size = 12;
- Header.PacketId = 0x384;
- SendPacket((BYTE*)&Header, ClientID, 12);
- if(Trade[Trade[ClientID].ClientID].isTrading && Trade[Trade[ClientID].ClientID].ClientID != 0 && StatusPlayer(Trade[Trade[ClientID].ClientID].ClientID) == 22)
- {
- // Checa se o outro jogador está em modo troca e se ele é um jogador válido
- // Evita bugs com o outro char ficar em modo troca ainda
- Trade[Trade[ClientID].ClientID].isTrading = false;
- Trade[Trade[ClientID].ClientID].Timer = 0;
- Trade[Trade[ClientID].ClientID].Confirm = false;
- Trade[Trade[ClientID].ClientID].WaitingData = false;
- memset(Trade[Trade[ClientID].ClientID].Itens, 0, sizeof st_Item * 15);
- memset(Trade[Trade[ClientID].ClientID].TradeItemSlot, 0, sizeof(char) * 15);
- Header.ClientId = Trade[ClientID].ClientID;
- SendPacket((BYTE*)&Header, Trade[ClientID].ClientID, 12);
- Trade[Trade[ClientID].ClientID].ClientID = 0;
- }
- Trade[ClientID].ClientID = 0;
- }
- void CheckItensOnTrade(short ClientID, short MobID)
- {
- // Sua função é checar se os itens colocados no trade realmente existem no inventário do usuário
- // Se não existirem, provavelmente é uma tentativa de hack pois o client não se enganará com isso
- st_Mob *player = (st_Mob*)GetMobFromIndex(ClientID);
- st_Mob *mob = (st_Mob*)GetMobFromIndex(MobID);
- for(UINT8 i=0;i<15;i++)
- {
- if(Trade[ClientID].Itens[i].Index == 255)
- continue;
- if(!memcmp(&Trade[ClientID].Itens[i], &player->Inventory[Trade[ClientID].TradeItemSlot[i]], 8))
- {
- CloseTrade(ClientID);
- break;
- }
- if(!memcmp(&Trade[MobID].Itens[i], &mob->Inventory[Trade[MobID].TradeItemSlot[i]], 8))
- {
- CloseTrade(MobID);
- break;
- }
- }
- }
- bool CanTrade(UINT16 Index)
- {
- // Função que serve para adicionar Itens imóveis
- switch(Index)
- {
- case 5338:
- case 4138:
- case 413:
- return false;
- default:
- return true;
- }
- return true;
- }
- bool AddItensOnTrade(SendTrade *p)
- {
- // Serve para a verificação de um item imóvel e para adicionar os itens do trade a struct trade do usuário
- for(UINT8 i=0;i<15;i++)
- {
- if(!CanTrade(p->TradeItem[i].Index))
- {
- SendClientMsg(p->Header.ClientId, "Item imóvel!");
- return false;
- }
- Trade[p->Header.ClientId].TradeItemSlot[i] = p->TradeItemSlot[i];
- memcpy(&Trade[p->Header.ClientId].Itens[i], &p->TradeItem[i], 8);
- }
- st_Mob *player = (st_Mob*)GetMobFromIndex(p->Header.ClientId);
- st_Mob *mob = (st_Mob*)GetMobFromIndex(p->OtherClientid);
- if(p->Gold > player->Gold)
- return false;
- if(player->Gold + Trade[p->OtherClientid].Gold > 2000000000)
- {
- SendClientMsg(p->Header.ClientId, "Limite de 2bilhões de gold");
- SendClientMsg(p->OtherClientid, "Limite de 2bilhões de gold");
- return false;
- }
- if(mob->Gold + Trade[p->Header.ClientId].Gold > 2000000000)
- {
- SendClientMsg(p->Header.ClientId, "Limite de 2bilhões de gold");
- SendClientMsg(p->OtherClientid, "Limite de 2bilhões de gold");
- return false;
- }
- return true;
- }
- BYTE GetAmountItemOnTrade(short ClientID)
- {
- // Retorna quantos itens foram colocados no trade do usuário
- BYTE val = 0;
- for(UINT8 i=0;i<15;i++)
- if(Trade[ClientID].Itens[i].Index != 0)
- val++;
- return val;
- }
- void NKD_SystemTrade(BYTE *m_PacketBuffer, int ClientID)
- {
- SendTrade *p = (SendTrade*)m_PacketBuffer;
- if(StatusPlayer(p->OtherClientid) != 22)
- {
- // Checa se o usuário está realmente online
- SendClientMsg(ClientID, "O usuário não está conectado!");
- return;
- }
- SendClientMsg(ClientID, "O sistema de troca está em fase de testes.");
- SendClientMsg(ClientID, "Caso encontre algum bug, por favor, reporte.");
- SendClientMsg(p->OtherClientid, "O sistema de troca está em fase de testes.");
- SendClientMsg(p->OtherClientid, "Caso encontre algum bug, por favor, reporte.");
- if(!Trade[p->OtherClientid].isTrading && !Trade[ClientID].isTrading)
- {
- // Verifica se nenhum dos dois jogadores está com trade
- // Se os dois não estiverem, quer dizer que foi enviado um pedido para Trade
- Sleep(2000);
- OpenTrade(ClientID, p->OtherClientid);
- Trade[ClientID].WaitingData = true;
- Trade[ClientID].Timer = clock();
- Trade[ClientID].isTrading = true;
- Trade[ClientID].ClientID = p->OtherClientid;
- Trade[ClientID].Confirm = false;
- Trade[p->OtherClientid].Timer = clock();
- Trade[p->OtherClientid].isTrading = true;
- Trade[p->OtherClientid].ClientID = ClientID;
- Trade[p->OtherClientid].Confirm = false;
- }
- else if(Trade[p->OtherClientid].isTrading && Trade[p->OtherClientid].ClientID != ClientID)
- {
- // Se você está sem o modo trade e o usuário que foi pedido estiver em negociação
- // a mensagem abaixo é mostrada
- SendClientMsg(ClientID, "O outro jogador já está em negociação!");
- }
- else { // Caso não seja um request, será feito as verificações para envio de item/confirm etc.
- if(Trade[ClientID].isTrading && Trade[ClientID].ClientID != p->OtherClientid)
- {
- // Para evitar qualquer tipo de bug se o jogador já está em troca
- // o trade do mesmo é fechado
- SendClientMsg(ClientID, "Você já está em modo troca!");
- CloseTrade(ClientID);
- }
- else if(Trade[p->OtherClientid].isTrading && !Trade[ClientID].isTrading && Trade[p->OtherClientid].WaitingData)
- {
- // Checa se o usuário que foi pedido o trade está sem trade novamente e se
- // o usuário que enviou o trade está realmente esperando o trade
- Trade[ClientID].isTrading = true;
- Trade[ClientID].WaitingData = true;
- Trade[ClientID].Confirm = false;
- Trade[ClientID].Timer = clock();
- Trade[ClientID].ClientID = p->OtherClientid;
- OpenTrade(ClientID, p->OtherClientid);
- }
- else if(p->Confirma)
- {
- if(clock() - Trade[ClientID].Timer < 2 *CLOCKS_PER_SEC)
- {
- // O próprio cliente existe proteção, mas como o packet pode ser manipulado e/ou enviado
- // pelo próprio usuário como forma de hack, é feito a proteção no servidor também
- // Caso queira, coloque um CloseTrade ao final dessa condição porque o client provavelmente não se enganará
- SendClientMsg(ClientID, "Aguarde 2 segundos e confirme");
- Trade[ClientID].Timer = clock();
- }
- else {
- Trade[ClientID].Confirm = p->Confirma;
- if(Trade[p->OtherClientid].Confirm)
- {
- int amount_TradeOID = GetAmountItemOnTrade(p->OtherClientid);
- int amount_TradeCID = GetAmountItemOnTrade(ClientID);
- if(GetAmountItem(ClientID, 0) < amount_TradeOID)
- {
- // Checa se a quantidade de itens nulos no inventário do usuário é igual ou maior
- // que a quantidade de itens colocadas no trade
- SendClientMsg(ClientID, "Você não possui espaço no inventário");
- SendClientMsg(p->OtherClientid, "O outro jogador não possui espaço no inventário");
- CloseTrade(ClientID);
- }
- else if(GetAmountItem(p->OtherClientid, 0) < amount_TradeCID)
- {
- // Checa se a quantidade de itens nulos no inventário do usuário é igual ou maior
- // que a quantidade de itens colocadas no trade
- SendClientMsg(p->OtherClientid, "Você não possui espaço no inventário");
- SendClientMsg(ClientID, "O outro jogador não possui espaço no inventário");
- CloseTrade(ClientID);
- } else {
- st_Mob *player = (st_Mob*)GetMobFromIndex(ClientID);
- st_Mob *mob = (st_Mob*)GetMobFromIndex(p->OtherClientid);
- int SlotID = 0;
- int SlotOID = 0;
- for(UINT8 i=0;i<15;i++)
- {
- // Faz o loop para todos os itens do trade
- // Slot livre do inventário
- if(Trade[ClientID].Itens[i].Index != 0)
- SlotID = GetFirstSlotSADD(p->OtherClientid, 0, 64);
- // Slot livre do inventário
- if(Trade[p->OtherClientid].Itens[i].Index != 0)
- SlotOID = GetFirstSlotSADD(ClientID, 0, 64);
- // Checa se os valores retornados são válidos
- // Se retornar -1 quer dizer que a funçaõ anterior (GetAmountItem) aconteceu algum erro
- if(SlotID == -1 || SlotOID == -1) {
- // O erro aconteceu então a mensagem é enviada aos dois players e o trade dos mesmos é fechado
- SendClientMsg(ClientID, "Ocorreu um erro!");
- SendClientMsg(p->OtherClientid, "Ocorreu um erro!");
- CloseTrade(ClientID);
- }
- // Checa se existe algum item no slot correspondente do trade
- if(Trade[ClientID].Itens[i].Index != 0) {
- // Copia o item que está no trade do outro usuário
- memcpy(&mob->Inventory[SlotID], &Trade[ClientID].Itens[i], sizeof st_Item);
- // Apaga o item do inventário do outro usuário
- memset(&player->Inventory[Trade[ClientID].TradeItemSlot[i]], 0, sizeof st_Item);
- // Atualiza o slot do personagem em que o item foi apagado
- SendSlot(ClientID, Trade[ClientID].TradeItemSlot[i]);
- SendSlot(p->OtherClientid, SlotID);
- }
- // Checa se existe algum item no slot correspondente do trade
- if(Trade[p->OtherClientid].Itens[i].Index != 0) {
- // Copia o item que está no trade do outro usuário
- memcpy(&player->Inventory[SlotOID], &Trade[p->OtherClientid].Itens[i], sizeof st_Item);
- // Apaga o item do inventário do outro usuário
- memset(&mob->Inventory[Trade[p->OtherClientid].TradeItemSlot[i]], 0, sizeof st_Item);
- // Atualiza o slot do personagem em que o item foi apagado
- SendSlot(p->OtherClientid, Trade[p->OtherClientid].TradeItemSlot[i]);
- SendSlot(ClientID, SlotOID);
- }
- }
- // Adiciona o gold colocado no trade
- player->Gold += Trade[p->OtherClientid].Gold;
- // Adiciona o gold colocado no trade do outro player
- mob->Gold += Trade[ClientID].Gold;
- // Retira o gold colocado no trade
- player->Gold -= Trade[ClientID].Gold;
- // Retira o gold colocado no trade
- mob->Gold -= Trade[p->OtherClientid].Gold;
- // Atualiza o gold do inventário dos dois players
- SendStats(ClientID);
- SendStats(p->OtherClientid);
- CloseTrade(ClientID);
- }
- } else
- // Se o outro usuário não confirmou ainda o trade, apenas é enviado para o outro usuário
- // o botão de confirmação juntamente com os itens/gold do trade
- SendAllTrade(ClientID, p->OtherClientid);
- }
- }
- else {
- // Aqui o usuário apenas colocou os itens no slot
- if(!AddItensOnTrade(p)) // Aconteceu algum erro ao adicionar os itens ao trade
- CloseTrade(ClientID);
- else {
- // Não aconteceu erro, então é setado tudo normalmente
- Trade[ClientID].Gold = p->Gold;
- Trade[ClientID].Confirm = false;
- Trade[Trade[ClientID].ClientID].Confirm = false;
- Trade[ClientID].Timer = clock();
- Trade[ClientID].Confirm = false;
- SendAllTrade(ClientID, p->OtherClientid);
- }
- }
- }
- ZeroMemory(m_PacketBuffer, 156);
- }
- // Ideia para usuários não leigos:
- // ItemList com EF_NOTRADE para itens que não podem ser trocados. Aí você adapta conforme quiser
- // Shepher & fabiosam
Advertisement
Add Comment
Please, Sign In to add comment