#1
1 дн. назад
Спойлер
#if !defined MAX_TRADE_SLOTS
#define MAX_TRADE_SLOTS 12
#endif
enum e_TRADE_STATUS
{
trade_TargetID,
trade_IsConfirmed,
bool:trade_IsOpen,
trade_MoneyOffer,
trade_ItemSlot[MAX_TRADE_SLOTS],
trade_ItemId[MAX_TRADE_SLOTS],
trade_ItemCount[MAX_TRADE_SLOTS]
};
new PlayerTrade[MAX_PLAYERS][e_TRADE_STATUS];
// --- Синхронизация UI ---
forward UpdateTradeUI(playerid);
public UpdateTradeUI(playerid)
{
if(!PlayerTrade[playerid][trade_IsOpen]) return 0;
new targetid = PlayerTrade[playerid][trade_TargetID];
// TODO: CEF/TextDraw — отрисовать окно трейда для playerid
// TODO: CEF — отрисовать окно "Игрок предлагает вам" для targetid
// Пример:
// if(PlayerTrade[targetid][trade_IsOpen] && PlayerTrade[targetid][trade_TargetID] == playerid)
// CallRemoteFunction("CEF_RefreshPartnerOffer", "ii", targetid, playerid);
return 1;
}
// --- Сброс данных трейда ---
stock ResetTradeData(playerid, targetid)
{
PlayerTrade[playerid][trade_TargetID] = targetid;
PlayerTrade[playerid][trade_IsConfirmed] = 0;
PlayerTrade[playerid][trade_IsOpen] = true;
PlayerTrade[playerid][trade_MoneyOffer] = 0;
for(new i = 0; i < MAX_TRADE_SLOTS; i++)
{
PlayerTrade[playerid][trade_ItemSlot][i] = -1;
PlayerTrade[playerid][trade_ItemId][i] = 0;
PlayerTrade[playerid][trade_ItemCount][i] = 0;
}
return 1;
}
// --- Открытие интерфейса ---
stock OpenTradeInterface(playerid)
{
// TODO: CEF — показать окно трейда
UpdateTradeUI(playerid);
return 1;
}
// --- Команда /trade ---
CMD:trade(playerid, params[])
{
new targetid;
if(sscanf(params, "u", targetid))
return SendClientMessage(playerid, -1, "{FFCC00}Используйте: /trade [ID/Никнейм]");
if(!IsPlayerConnected(targetid))
return SendClientMessage(playerid, -1, "{FF0000}Игрок не в сети.");
if(targetid == playerid)
return SendClientMessage(playerid, -1, "{FF0000}Вы не можете торговать сами с собой.");
if(PlayerTrade[playerid][trade_IsOpen])
return SendClientMessage(playerid, -1, "{FF0000}У вас уже открыт трейд.");
if(PlayerTrade[targetid][trade_IsOpen])
return SendClientMessage(playerid, -1, "{FF0000}Этот игрок сейчас занят другим обменом.");
new Float:x, Float:y, Float:z;
GetPlayerPos(playerid, x, y, z);
if(!IsPlayerInRangeOfPoint(targetid, 5.0, x, y, z))
return SendClientMessage(playerid, -1, "{FF0000}Игрок слишком далеко от вас.");
SetPVarInt(targetid, "Trade_Request_From", playerid);
new str[160];
format(str, sizeof(str), "{66CC00}%s предлагает вам обменяться предметами. Введите {FFFF00}/accept trade{66CC00} для согласия.", GetPlayerNameEx(playerid));
SendClientMessage(targetid, -1, str);
format(str, sizeof(str), "{66CC00}Вы отправили предложение обмена %s. Ожидайте ответа...", GetPlayerNameEx(targetid));
SendClientMessage(playerid, -1, str);
return 1;
}
// --- Принятие трейда (вызывать из /accept) ---
stock AcceptTradeOffer(playerid)
{
new inviter = GetPVarInt(playerid, "Trade_Request_From");
if(!IsPlayerConnected(inviter) || inviter == INVALID_PLAYER_ID)
{
SendClientMessage(playerid, -1, "{FF0000}Предложение обмена не найдено или игрок вышел.");
return 0;
}
DeletePVar(playerid, "Trade_Request_From");
ResetTradeData(playerid, inviter);
ResetTradeData(inviter, playerid);
OpenTradeInterface(playerid);
OpenTradeInterface(inviter);
return 1;
}
// --- Клик по предмету в инвентаре ---
stock ClickItemInInventory(playerid, inv_slot)
{
if(!PlayerTrade[playerid][trade_IsOpen]) return 0;
if(PlayerTrade[playerid][trade_IsConfirmed])
return SendClientMessage(playerid, -1, "{FF0000}Вы уже подтвердили сделку! Сбросьте её, чтобы изменить предметы.");
// TODO: Проверка пустого слота — адаптировать под g_player_inventory
// if(g_player_inventory[playerid][inv_slot][item_id] == 0) return 0;
for(new i = 0; i < MAX_TRADE_SLOTS; i++)
if(PlayerTrade[playerid][trade_ItemSlot][i] == inv_slot)
return SendClientMessage(playerid, -1, "{FF0000}Этот предмет уже в трейде!");
new trade_idx = -1;
for(new i = 0; i < MAX_TRADE_SLOTS; i++)
{
if(PlayerTrade[playerid][trade_ItemSlot][i] == -1)
{
trade_idx = i;
break;
}
}
if(trade_idx == -1)
return SendClientMessage(playerid, -1, "{FF0000}Вы не можете выставить больше 12 предметов на обмен.");
PlayerTrade[playerid][trade_ItemSlot][trade_idx] = inv_slot;
// TODO: Заполнить trade_ItemId / trade_ItemCount из g_player_inventory
// PlayerTrade[playerid][trade_ItemId][trade_idx] = g_player_inventory[playerid][inv_slot][item_id];
// PlayerTrade[playerid][trade_ItemCount][trade_idx] = g_player_inventory[playerid][inv_slot][item_count];
PlayerTrade[playerid][trade_IsConfirmed] = 0;
new targetid = PlayerTrade[playerid][trade_TargetID];
if(IsPlayerConnected(targetid))
PlayerTrade[targetid][trade_IsConfirmed] = 0;
UpdateTradeUI(playerid);
return 1;
}
// --- Клик по предмету в трейде (убрать из сделки) ---
stock ClickItemInTradeOffer(playerid, trade_slot)
{
if(!PlayerTrade[playerid][trade_IsOpen]) return 0;
if(PlayerTrade[playerid][trade_IsConfirmed])
return SendClientMessage(playerid, -1, "{FF0000}Вы уже подтвердили сделку! Сбросьте её сначала.");
if(PlayerTrade[playerid][trade_ItemSlot][trade_slot] == -1) return 0;
PlayerTrade[playerid][trade_ItemSlot][trade_slot] = -1;
PlayerTrade[playerid][trade_ItemId][trade_slot] = 0;
PlayerTrade[playerid][trade_ItemCount][trade_slot] = 0;
PlayerTrade[playerid][trade_IsConfirmed] = 0;
new targetid = PlayerTrade[playerid][trade_TargetID];
if(IsPlayerConnected(targetid))
PlayerTrade[targetid][trade_IsConfirmed] = 0;
UpdateTradeUI(playerid);
return 1;
}
// --- Чат внутри трейда ---
stock SendTradeChatMessage(playerid, const text[])
{
if(!PlayerTrade[playerid][trade_IsOpen]) return 0;
new targetid = PlayerTrade[playerid][trade_TargetID];
if(!IsPlayerConnected(targetid)) return 0;
new str[150];
format(str, sizeof(str), "[Трейд] %s: %s", GetPlayerNameEx(playerid), text);
SendClientMessage(playerid, 0xFFAA00AA, str);
SendClientMessage(targetid, 0xFFAA00AA, str);
return 1;
}
// --- Подтверждение сделки ---
stock ClickConfirmTrade(playerid)
{
if(!PlayerTrade[playerid][trade_IsOpen]) return 0;
new targetid = PlayerTrade[playerid][trade_TargetID];
if(!IsPlayerConnected(targetid)) return 0;
if(PlayerTrade[playerid][trade_IsConfirmed])
{
PlayerTrade[playerid][trade_IsConfirmed] = 0;
SendClientMessage(playerid, -1, "Вы отменили подтверждение сделки.");
UpdateTradeUI(playerid);
return 1;
}
PlayerTrade[playerid][trade_IsConfirmed] = 1;
SendClientMessage(playerid, -1, "{66CC00}Вы подтвердили готовность к обмену. Ожидание второго игрока...");
UpdateTradeUI(playerid);
if(PlayerTrade[targetid][trade_IsConfirmed])
FinalizeTrade(playerid, targetid);
return 1;
}
// --- Финальная транзакция ---
stock FinalizeTrade(p1, p2)
{
// TODO: Проверка лимитов веса у обоих игроков
for(new i = 0; i < MAX_TRADE_SLOTS; i++)
{
// Предметы от p1 -> p2
if(PlayerTrade[p1][trade_ItemSlot][i] != -1)
{
// TODO: Inventory_Add(p2, PlayerTrade[p1][trade_ItemId][i], PlayerTrade[p1][trade_ItemCount][i]);
// TODO: Inventory_DeleteSlot(p1, PlayerTrade[p1][trade_ItemSlot][i]);
}
// Предметы от p2 -> p1
if(PlayerTrade[p2][trade_ItemSlot][i] != -1)
{
// TODO: Inventory_Add(p1, PlayerTrade[p2][trade_ItemId][i], PlayerTrade[p2][trade_ItemCount][i]);
// TODO: Inventory_DeleteSlot(p2, PlayerTrade[p2][trade_ItemSlot][i]);
}
}
// TODO: Обмен деньгами через trade_MoneyOffer
// TODO: Inventory_Save(p1); Inventory_Save(p2);
CloseTrade(p1);
CloseTrade(p2);
SendClientMessage(p1, -1, "{00FF00}Обмен успешно совершен!");
SendClientMessage(p2, -1, "{00FF00}Обмен успешно совершен!");
return 1;
}
// --- Закрытие трейда ---
stock CloseTrade(playerid)
{
PlayerTrade[playerid][trade_IsOpen] = false;
PlayerTrade[playerid][trade_IsConfirmed] = 0;
// TODO: CEF — скрыть окно
return 1;
}
Сливаю для вас рабочую систему /trade для своей копии Black Russia