Por que os sistemas de restaurantes melhoram a dramatização
Os sistemas de alimentação e restaurante estão entre os recursos mais envolventes socialmente que você pode adicionar a um servidor de RPG FiveM. Ao contrário das atividades individuais, como mineração ou pesca, os restaurantes criam pontos de encontro orgânicos onde os jogadores cozinham, servem e comem juntos. Um sistema de restaurante bem projetado dá aos jogadores civis um trabalho significativo que não envolve crime, fornece uma razão para os personagens visitarem os locais regularmente e introduz um dreno na economia através da compra de ingredientes. Os restaurantes também criam cadeias de abastecimento quando combinados com roteiros de agricultura ou caça, o que significa que um jogador cultiva tomates, outro os entrega e um terceiro os cozinha em um hambúrguer. Esse ciclo de jogo interconectado é o que separa um servidor ativo de outro onde os jogadores apenas percorrem a mesma rota repetidamente. Os próprios alimentos podem fornecer buffs temporários à saúde, resistência ou regeneração de armadura, tornando os restaurantes relevantes para todos os jogadores no servidor, independentemente de seu trabalho ou facção.
Configuração de restaurante e design de menu
Comece definindo a localização do seu restaurante, seus cardápios e os ingredientes necessários para cada prato. Uma configuração baseada em dados permite que os proprietários de servidores adicionem novos restaurantes sem modificar a lógica central. Cada restaurante deve ter uma identidade única através de suas ofertas de menu, adereços internos e uniformes dos funcionários dos NPCs. Estruture sua configuração para que cada item do menu liste os ingredientes necessários, o tempo de elaboração, o preço de venda e quaisquer efeitos de buff que conceda ao consumidor. Esta abordagem significa que equilibrar sua economia alimentar se resume a ajustar os valores de configuração em vez de reescrever o código:
Config.Restaurants = {
['burgershot'] = {
label = 'Burger Shot',
blip = { sprite = 106, color = 1, scale = 0.8 },
zones = {
counter = vector3(-1196.42, -894.04, 13.98),
kitchen = vector3(-1199.71, -897.12, 13.98),
storage = vector3(-1202.84, -899.35, 13.98),
},
menu = {
{
item = 'bleeder_burger',
label = 'Bleeder Burger',
price = 25,
ingredients = {
{ item = 'raw_patty', amount = 2 },
{ item = 'burger_bun', amount = 1 },
{ item = 'lettuce', amount = 1 },
{ item = 'cheese_slice', amount = 2 },
},
craftTime = 8000,
buffs = {
hunger = 45,
thirst = 5,
armor_regen = { amount = 2, duration = 120 }
}
},
{
item = 'heartstopper',
label = 'Heart Stopper',
price = 40,
ingredients = {
{ item = 'raw_patty', amount = 3 },
{ item = 'burger_bun', amount = 1 },
{ item = 'bacon', amount = 4 },
{ item = 'cheese_slice', amount = 3 },
{ item = 'onion_ring', amount = 2 },
},
craftTime = 12000,
buffs = {
hunger = 80,
thirst = -10,
stamina_boost = { amount = 15, duration = 180 }
}
},
},
requiredJob = 'burgershot',
},
}A mesa zones separa o restaurante em áreas funcionais. A zona do balcão é onde os clientes fazem os pedidos e recebem a comida. A zona da cozinha é restrita aos funcionários que a utilizam para cozinhar. A zona de armazenamento é onde os ingredientes são armazenados e gerenciados. Esta separação espacial força um fluxo de trabalho realista onde um cozinheiro não pode servir os clientes diretamente do fogão, criando um trabalho de equipa natural entre o pessoal da recepção e da cozinha.
Mecânica de Culinária e Fluxo de Artesanato
O processo de cozimento deve ser interativo sem ser tedioso. Quando um jogador começa a cozinhar um item, verifique se todos os ingredientes necessários existem no inventário de armazenamento do restaurante, subtraia-os e inicie uma barra de progresso ou sequência de minijogo. Barras de progresso simples funcionam para itens básicos, mas adicionar minijogos de verificação de habilidade para pratos premium cria uma sensação de domínio e evita façanhas culinárias AFK. A animação de culinária deve usar nativos apropriados do GTA, como os cenários da churrasqueira ou do balcão da cozinha, para comunicar visualmente o que o jogador está fazendo aos observadores próximos:
function StartCooking(restaurantId, menuIndex)
local restaurant = Config.Restaurants[restaurantId]
local recipe = restaurant.menu[menuIndex]
-- Check ingredients in storage
local hasAll = lib.callback.await('restaurant:checkIngredients', false,
restaurantId, recipe.ingredients)
if not hasAll then
lib.notify({ description = 'Missing ingredients!', type = 'error' })
return
end
-- Lock player into cooking animation
local playerPed = PlayerPedId()
local animDict = 'mini@repair'
lib.requestAnimDict(animDict)
TaskPlayAnim(playerPed, animDict, 'fixing_a_player', 8.0, -8.0,
-1, 1, 0, false, false, false)
-- Cooking progress with skill check
local success = lib.skillCheck(
{'easy', 'easy', 'medium'},
{'w', 'a', 's', 'd'}
)
ClearPedTasks(playerPed)
if success then
TriggerServerEvent('restaurant:finishCooking', restaurantId, menuIndex)
lib.notify({ description = 'Cooked: ' .. recipe.label, type = 'success' })
else
-- Failed cooking wastes some ingredients
TriggerServerEvent('restaurant:failedCooking', restaurantId, menuIndex)
lib.notify({ description = 'Burnt the food! Some ingredients wasted.',
type = 'error' })
end
endA mecânica de verificação de habilidade adiciona um elemento de risco-recompensa à culinária. As tentativas fracassadas devem desperdiçar uma parte dos ingredientes, em vez de todos eles, para que os novos jogadores não sejam severamente punidos e, ao mesmo tempo, incentivem o aprimoramento de habilidades. Você pode dimensionar a dificuldade com base no valor do prato, fazendo com que itens baratos sejam fáceis de cozinhar e pratos caros e exclusivos exijam atenção genuína. Isso cria uma progressão natural onde os novos funcionários começam com itens simples e avançam até o menu premium.
Cadeia de fornecimento de ingredientes
Os restaurantes precisam de um fluxo constante de ingredientes, e a forma como os jogadores obtêm esses ingredientes define grande parte do ciclo de jogo. Existem três abordagens comuns: compra de fornecedores atacadistas de NPCs, aquisição de fazendas ou caça administradas por jogadores e um modelo híbrido. A abordagem grossista é mais simples de implementar e garante disponibilidade, mas carece de interação entre os jogadores. O abastecimento de outros participantes cria relações económicas ricas, mas corre o risco de paralisação dos restaurantes quando os fornecedores estão offline. O modelo híbrido funciona melhor: ingredientes básicos como pães, óleo e temperos vêm de NPCs, enquanto ingredientes premium como carne fresca, vegetais orgânicos e molhos especiais devem ser obtidos nas atividades dos jogadores. Isto garante que os restaurantes possam sempre operar a um nível básico, ao mesmo tempo que recompensam toda a cadeia de abastecimento quando todas as peças se conectam. Implementar um sistema de armazenamento por restaurante que rastreie as quantidades de ingredientes e permita que os gerentes façam pedidos no atacado que descontam da conta bancária do restaurante:
RegisterNetEvent('restaurant:orderSupplies', function(restaurantId, order)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
-- Verify player is manager rank
if Player.PlayerData.job.name ~= restaurantId then return end
if Player.PlayerData.job.grade.level < 3 then
TriggerClientEvent('QBCore:Notify', src,
'Only managers can order supplies', 'error')
return
end
-- Calculate total cost
local totalCost = 0
for _, item in ipairs(order) do
local wholesalePrice = Config.WholesalePrices[item.name]
if wholesalePrice then
totalCost = totalCost + (wholesalePrice * item.amount)
end
end
-- Deduct from restaurant bank account
local balance = exports['qb-management']:GetAccount(restaurantId)
if balance < totalCost then
TriggerClientEvent('QBCore:Notify', src,
'Insufficient restaurant funds', 'error')
return
end
exports['qb-management']:RemoveMoney(restaurantId, totalCost)
-- Add items to restaurant storage
for _, item in ipairs(order) do
AddToRestaurantStorage(restaurantId, item.name, item.amount)
end
TriggerClientEvent('QBCore:Notify', src,
string.format('Order placed! $%d deducted', totalCost), 'success')
end)Pedidos do cliente e fluxo de serviço
A experiência do cliente deve ser perfeita, quer ele esteja fazendo um pedido de um caixa NPC ou de um funcionário do jogador. Quando um cliente se aproxima da zona de balcão, exiba uma interface de menu mostrando os itens disponíveis com seus preços e quaisquer descrições de buffs ativos. Para restaurantes com funcionários de jogadores, o pedido deve ser encaminhado para o display da cozinha para que os cozinheiros vejam os pedidos recebidos em tempo real. Implemente um sistema de fila de pedidos que rastreie cada pedido desde a colocação, passando pela preparação até a entrega. Isso cria uma simulação de fast-food em que a cozinha fica sobrecarregada durante os períodos de pico, adicionando uma pressão autêntica à função de cozinhar. Mostre o status do pedido aos clientes com indicadores simples: pedido, cozinhando, pronto para retirada. Quando a comida estiver pronta, avise o cliente e deixe-o retirá-la no balcão. Para uma experiência premium, permita que os garçons dos jogadores entreguem comida diretamente aos clientes sentados nas mesas, ganhando gorjetas com base na velocidade do serviço.
Fãs de comida e efeitos de consumo
Os alimentos devem fornecer benefícios significativos ao jogo, além de simplesmente restaurar a fome. Implemente um sistema de buff onde diferentes alimentos concedem modificações temporárias nas estatísticas que incentivam os jogadores a comer estrategicamente antes das atividades. Uma refeição para aumentar a resistência antes de uma perseguição a pé, um prato de regeneração de armadura antes de um assalto ou uma refeição para recuperar a saúde ao longo do tempo após uma luta, todos tornam os alimentos genuinamente valiosos na economia do servidor. Rastreie os buffs ativos por jogador e exiba-os no HUD para que os jogadores saibam quais efeitos eles têm atualmente e quando expiram:
local activeBuffs = {}
function ApplyFoodBuff(buffType, amount, duration)
-- Remove existing buff of same type
if activeBuffs[buffType] then
activeBuffs[buffType].active = false
end
activeBuffs[buffType] = {
amount = amount,
endTime = GetGameTimer() + (duration * 1000),
active = true
}
-- Send buff data to HUD
SendNUIMessage({
action = 'addBuff',
buffType = buffType,
amount = amount,
duration = duration
})
-- Create buff application thread
CreateThread(function()
local buff = activeBuffs[buffType]
while buff.active and GetGameTimer() < buff.endTime do
if buffType == 'armor_regen' then
local current = GetPedArmour(PlayerPedId())
if current < 100 then
SetPedArmour(PlayerPedId(), math.min(100, current + amount))
end
elseif buffType == 'stamina_boost' then
RestorePlayerStamina(PlayerId(), amount * 0.1)
elseif buffType == 'health_regen' then
local current = GetEntityHealth(PlayerPedId())
local max = GetEntityMaxHealth(PlayerPedId())
if current < max then
SetEntityHealth(PlayerPedId(), math.min(max, current + amount))
end
end
Wait(1000)
end
activeBuffs[buffType] = nil
SendNUIMessage({ action = 'removeBuff', buffType = buffType })
end)
endEquilibre os buffs de comida com cuidado para que melhorem a jogabilidade sem se tornarem obrigatórios. Os buffs devem fornecer uma vantagem notável sem serem tão poderosos que os jogadores se sintam forçados a comer antes de cada atividade. Mantenha a duração moderada, entre dois e cinco minutos, para que a economia de buffs permaneça ativa. Considere adicionar retornos decrescentes se o mesmo alimento for consumido repetidamente em um curto período para evitar explorações de acúmulo de buffs.
Gestão de funcionários e folha de pagamento
Um sistema de restaurante precisa de uma hierarquia adequada com diferentes funções e permissões. Defina pelo menos três níveis: trabalhador, supervisor e gerente. Os trabalhadores podem cozinhar itens e servir os clientes. Os supervisores podem fazer tudo o que os trabalhadores fazem, além de gerenciar o armazenamento de ingredientes e aprovar pedidos. Os gerentes têm controle total, incluindo contratação e demissão de funcionários, definição de preços e acesso à conta bancária do restaurante. Vincule a folha de pagamento à receita do restaurante para que os funcionários ganhem um salário base mais comissão sobre os itens que cozinham ou servem pessoalmente. Isso incentiva a participação ativa, em vez do ponto AFK. Acompanhe estatísticas individuais dos funcionários, como itens preparados, clientes atendidos e receita gerada, para criar tabelas de classificação e avaliações de desempenho que acrescentam profundidade à experiência de trabalho.
Otimização de desempenho
Os sistemas de restaurantes envolvem múltiplas zonas de interação, NPCs, objetos de apoio e rastreamento de pedidos em tempo real que podem prejudicar o desempenho do cliente se não forem otimizados cuidadosamente. Use interações do sistema alvo em vez de verificações de distância baseadas em marcadores para eliminar cálculos de coordenadas por quadro. Somente renderize adereços internos do restaurante quando os jogadores estiverem dentro do prédio usando verificações IsPlayerInScope. Agrupe suas mensagens NUI para a exibição da fila de pedidos, em vez de enviar atualizações individuais para cada alteração de pedido. No lado do servidor, armazene em cache os inventários de armazenamento do restaurante na memória e grave no banco de dados em um intervalo de tempo, em vez de após cada alteração de ingrediente. Quando vários restaurantes estiverem ativos simultaneamente, escalone os ciclos de sincronização do banco de dados para evitar picos de gravação. Limpe todos os blips, props e entidades NPC quando o recurso parar para evitar entidades órfãs que se acumulam nas reinicializações do recurso. Teste seu sistema sob carga com vários restaurantes operando, vários cozinheiros trabalhando simultaneamente e um fluxo constante de pedidos de clientes para identificar gargalos antes que seus jogadores os encontrem para você.
