Arquitetura do Sistema de Propriedade
Um sistema imobiliário transforma seu servidor FiveM de uma coleção de edifícios inacessíveis em um mercado imobiliário onde os jogadores compram, vendem e alugam casas, apartamentos e espaços comerciais. A arquitetura gira em torno de um banco de dados de registro de propriedades que rastreia todas as propriedades disponíveis no servidor com sua localização, tipo, proprietário atual, valor de mercado e configuração interna. Ao contrário dos scripts habitacionais simples que permitem apenas que os jogadores comprem uma lista predeterminada de propriedades, um sistema imobiliário bem projetado inclui um trabalho de agente imobiliário que cria transações orientadas pelo jogador com exibições, negociações e estruturas de comissão. O sistema precisa ser integrado ao recurso de fechadura de porta do seu servidor para que a propriedade da propriedade conceda ou revogue automaticamente o acesso ao edifício físico e com sistemas de carregamento interno, como MLOs personalizados ou interiores instanciados. Planeje três categorias de propriedades desde o início: propriedades residenciais para moradia dos jogadores, propriedades comerciais para empresas de propriedade dos jogadores e propriedades para aluguel que geram renda passiva para os proprietários.
Banco de dados e listagens de propriedades
O banco de dados de propriedades é a base sobre a qual todos os outros componentes são construídos. Cada registro de propriedade precisa de metadados extensos, incluindo o interior do shell ou MLO que usa, as coordenadas de entrada e saída, disponibilidade de garagem, capacidade de armazenamento e histórico de preços. Mantenha uma tabela de listagens separada que monitore quais propriedades estão atualmente no mercado, o preço pedido, o agente de listagem e há quanto tempo estão listadas. Essa separação permite acompanhar o histórico do mercado e calcular tendências de valor da propriedade ao longo do tempo. Aqui está um esquema de banco de dados que suporta todo o ciclo de vida imobiliário:
CREATE TABLE IF NOT EXISTS properties (
id INT AUTO_INCREMENT PRIMARY KEY,
property_id VARCHAR(50) NOT NULL UNIQUE,
label VARCHAR(100) NOT NULL,
property_type ENUM('house', 'apartment', 'commercial', 'penthouse') NOT NULL,
owner VARCHAR(50) DEFAULT NULL,
price INT NOT NULL,
original_price INT NOT NULL,
interior VARCHAR(50) DEFAULT 'standard_1bed',
enter_coords JSON NOT NULL,
exit_coords JSON DEFAULT NULL,
garage_slots INT DEFAULT 0,
stash_slots INT DEFAULT 50,
has_wardrobe TINYINT DEFAULT 1,
is_furnished TINYINT DEFAULT 1,
neighborhood VARCHAR(50) DEFAULT 'downtown',
purchased_at BIGINT DEFAULT NULL,
INDEX idx_owner (owner),
INDEX idx_type (property_type),
INDEX idx_neighborhood (neighborhood)
);
CREATE TABLE IF NOT EXISTS property_listings (
id INT AUTO_INCREMENT PRIMARY KEY,
property_id VARCHAR(50) NOT NULL,
asking_price INT NOT NULL,
listing_agent VARCHAR(50) DEFAULT NULL,
listed_at BIGINT NOT NULL,
status ENUM('active', 'pending', 'sold', 'cancelled') DEFAULT 'active',
buyer VARCHAR(50) DEFAULT NULL,
sold_at BIGINT DEFAULT NULL,
sold_price INT DEFAULT NULL,
INDEX idx_status (status),
INDEX idx_agent (listing_agent)
);Preencha a tabela de propriedades com todas as propriedades disponíveis em seu servidor durante a configuração inicial. Cada propriedade deve ter coordenadas cuidadosamente definidas para pontos de entrada que se alinhem com as posições das portas ou zonas de interação. O campo original_price preserva o valor base para cálculos de mercado, enquanto o campo price reflete o valor de mercado atual que muda com base na demanda da vizinhança, nas melhorias feitas pelo proprietário e nas condições econômicas gerais do servidor.
Sistema de trabalho de agente imobiliário
O trabalho do corretor imobiliário é onde o elemento humano faz esse sistema brilhar. Os agentes atuam como intermediários entre compradores e vendedores, realizando exibições de propriedades, negociando preços e ganhando comissões sobre as vendas concluídas. Defina níveis de trabalho que desbloqueiem listagens cada vez melhores: os agentes juniores cuidam de apartamentos e pequenas casas, os agentes seniores acessam propriedades de luxo e espaços comerciais, e o proprietário da agência gerencia a equipe e fica com uma parte de todas as comissões. Quando um jogador interessado em comprar uma propriedade entra em contato com um agente, o agente pode iniciar uma exibição que teletransporta ambos os jogadores para o interior da propriedade para um passeio. Aqui está a lógica da transação de exibição e venda:
RegisterNetEvent('realestate:server:startShowing', function(propertyId, buyerId)
local src = source
local Agent = QBCore.Functions.GetPlayer(src)
local Buyer = QBCore.Functions.GetPlayer(buyerId)
if not Agent or not Buyer then return end
if Agent.PlayerData.job.name ~= 'realtor' then return end
local property = MySQL.query.await(
'SELECT * FROM properties WHERE property_id = ? AND owner IS NULL',
{propertyId}
)
if not property or not property[1] then
return TriggerClientEvent('QBCore:Notify', src, 'Property not available', 'error')
end
local prop = property[1]
local enterCoords = json.decode(prop.enter_coords)
-- Teleport both to property
TriggerClientEvent('realestate:client:enterShowing', src, prop, enterCoords)
TriggerClientEvent('realestate:client:enterShowing', buyerId, prop, enterCoords)
TriggerClientEvent('QBCore:Notify', buyerId,
'Showing: ' .. prop.label .. ' - $' .. prop.price, 'info')
end)
RegisterNetEvent('realestate:server:purchaseProperty', function(propertyId, buyerId, agreedPrice)
local src = source
local Agent = QBCore.Functions.GetPlayer(src)
local Buyer = QBCore.Functions.GetPlayer(buyerId)
if not Agent or not Buyer then return end
if Agent.PlayerData.job.name ~= 'realtor' then return end
local property = MySQL.query.await(
'SELECT * FROM properties WHERE property_id = ? AND owner IS NULL',
{propertyId}
)
if not property or not property[1] then return end
if not Buyer.Functions.RemoveMoney('bank', agreedPrice, 'property-purchase') then
return TriggerClientEvent('QBCore:Notify', src, 'Buyer cannot afford this', 'error')
end
local commission = math.floor(agreedPrice * 0.05)
Agent.Functions.AddMoney('bank', commission, 'realtor-commission')
MySQL.update(
'UPDATE properties SET owner = ?, price = ?, purchased_at = ? WHERE property_id = ?',
{Buyer.PlayerData.citizenid, agreedPrice, os.time(), propertyId}
)
MySQL.update(
'UPDATE property_listings SET status = "sold", buyer = ?, sold_at = ?, sold_price = ? WHERE property_id = ? AND status = "active"',
{Buyer.PlayerData.citizenid, os.time(), agreedPrice, propertyId}
)
TriggerClientEvent('QBCore:Notify', src,
'Sale complete! Commission: $' .. commission, 'success')
TriggerClientEvent('QBCore:Notify', buyerId,
'Congratulations! You now own ' .. property[1].label, 'success')
TriggerEvent('doorlock:server:updateProperty', propertyId, Buyer.PlayerData.citizenid)
end)A taxa de comissão deve ser configurável e potencialmente variável com base no nível de escolaridade do agente. Os agentes seniores podem ganhar 7% de comissão, enquanto os juniores ganham apenas 3%, motivando a progressão na carreira no setor imobiliário. Acompanhe o volume total de vendas e os ganhos de comissões de cada agente no banco de dados para criar tabelas de classificação de desempenho e desbloquear bônus para os melhores desempenhos.
Sistema de hipoteca e financiamento
A maioria dos intervenientes não consegue adquirir imediatamente propriedades de elevado valor, pelo que um sistema hipotecário aumenta drasticamente o conjunto de potenciais compradores e torna o mercado imobiliário acessível aos intervenientes mais recentes. Quando um comprador não puder pagar o preço total, ofereça uma opção de hipoteca que exija uma porcentagem configurável de entrada, normalmente de 10 a 20% do valor da propriedade. O saldo restante é pago em parcelas regulares, deduzidas automaticamente da conta bancária do jogador a cada reinicialização do servidor ou em intervalos programados. Acompanhe os detalhes da hipoteca, incluindo valor principal, taxa de juros, saldo restante, valor do pagamento mensal e histórico de pagamentos. Se um jogador perder muitos pagamentos consecutivos, acione um processo de execução hipotecária que retoma a posse da propriedade e a recoloca no mercado com desconto. A taxa de juros cria um custo real para o empréstimo que incentiva os jogadores a pagarem suas hipotecas antecipadamente, quando possível, e o sistema gera um dreno constante na oferta de dinheiro que ajuda a combater a inflação na economia do servidor.
Renda de aluguel e sistema de senhorio
Os jogadores que possuem múltiplas propriedades devem ser capazes de alugá-las para obter renda passiva, criando uma dinâmica proprietário-inquilino que gera uma dramatização contínua. Quando o proprietário de um imóvel deseja alugar seu imóvel, ele define um valor de aluguel mensal e o lista como disponível para aluguel na imobiliária ou em listagem direta. Os inquilinos têm acesso chave à propriedade e podem utilizar a arrecadação, guarda-roupa e garagem durante o período do arrendamento. O aluguel é cobrado automaticamente de acordo com um cronograma configurável e depositado na conta bancária do locador. Aqui está a implementação do sistema de aluguel:
Config.RentalSettings = {
minRentPrice = 100,
maxRentPrice = 50000,
collectionInterval = 86400, -- every 24 hours real time
maxMissedPayments = 3,
depositMultiplier = 2, -- security deposit = 2x monthly rent
}
RegisterNetEvent('realestate:server:listForRent', function(propertyId, rentPrice)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
local property = MySQL.query.await(
'SELECT * FROM properties WHERE property_id = ? AND owner = ?',
{propertyId, Player.PlayerData.citizenid}
)
if not property or not property[1] then return end
if rentPrice < Config.RentalSettings.minRentPrice or
rentPrice > Config.RentalSettings.maxRentPrice then
return TriggerClientEvent('QBCore:Notify', src, 'Invalid rent price', 'error')
end
MySQL.insert(
'INSERT INTO property_rentals (property_id, landlord, rent_price, deposit, listed_at) VALUES (?, ?, ?, ?, ?)',
{propertyId, Player.PlayerData.citizenid, rentPrice,
rentPrice * Config.RentalSettings.depositMultiplier, os.time()}
)
TriggerClientEvent('QBCore:Notify', src,
'Property listed for rent at $' .. rentPrice .. '/day', 'success')
end)
-- Automated rent collection thread
CreateThread(function()
while true do
Wait(1000 * 60 * 60) -- Check every hour
local rentals = MySQL.query.await(
'SELECT * FROM property_rentals WHERE tenant IS NOT NULL AND status = "active"'
)
for _, rental in ipairs(rentals or {}) do
if os.time() - rental.last_collected >= Config.RentalSettings.collectionInterval then
local success = ProcessRentPayment(rental)
if not success then
HandleMissedPayment(rental)
end
end
end
end
end)A caução protege os proprietários de inquilinos que danificam a propriedade ou saem sem aviso prévio. Quando um inquilino termina o seu contrato de arrendamento, o depósito é devolvido menos quaisquer deduções por danos. Implementar um sistema de condições de propriedade que rastreie o desgaste, dando aos proprietários um motivo legítimo para reter parte do depósito se o inquilino não tiver cuidado com a propriedade. Isso cria cenários naturais de resolução de conflitos que impulsionam a representação entre proprietários e inquilinos.
Preços de mercado dinâmico
Um mercado imobiliário estático rapidamente se torna obsoleto quando todas as propriedades desejáveis são compradas. A precificação dinâmica mantém o mercado interessante ajustando os valores das propriedades com base na atividade real no servidor. Acompanhe vários fatores que influenciam o valor do bairro: o número de vendas recentes numa área, a proximidade de locais populares, como centros de emprego e lojas, estatísticas de criminalidade do sistema policial e a proporção global de propriedades ocupadas e vagas. Quando um bairro tem uma procura elevada com muitas compras recentes, os valores dos imóveis aumentam gradualmente, criando um elemento especulativo onde os primeiros compradores em áreas emergentes lucram à medida que o bairro se desenvolve. Por outro lado, áreas de alta criminalidade ou bairros com muitas propriedades vagas apresentam valores decrescentes. Execute o ajuste do mercado como uma tarefa agendada do servidor que recalcula todos os valores das propriedades semanalmente, aplicando as alterações gradualmente para evitar choques repentinos no mercado. Exiba as tendências do mercado no painel NUI da agência imobiliária para que agentes e compradores possam tomar decisões informadas sobre onde investir.
Exibições de propriedades e interface NUI
A interface NUI é onde agentes e compradores navegam pelas propriedades disponíveis, revisam detalhes e iniciam transações. Crie uma página de listagem de propriedades limpa e com aparência profissional que exiba cada propriedade disponível com sua foto ou visualização do interior, localização no mapa, preço, número de quartos, capacidade de garagem e classificação do bairro. Inclua opções de filtragem e classificação para que os usuários possam restringir os resultados por tipo de propriedade, faixa de preço e localização. Quando um corretor seleciona um imóvel para exibição, o sistema deve exibir uma rota até a entrada do imóvel e notificar o comprador para segui-la. Dentro da propriedade, forneça um modo de tour interativo onde o agente pode destacar recursos usando marcadores 3D ou anotações de texto. Após a exibição, apresente ao comprador um painel de confirmação de compra ou aluguel que mostra o detalhamento financeiro completo, incluindo preço, impostos, comissão do agente e termos de hipoteca, se aplicável. A interface também deve incluir uma guia de histórico de transações onde os jogadores podem revisar suas compras, vendas e pagamentos de aluguel anteriores para obter total transparência financeira.
Customização de Imóveis e Valorização
Permitir que os proprietários personalizem suas propriedades acrescenta um toque pessoal e cria uma economia de atualização que aumenta o valor das propriedades ao longo do tempo. Implemente um sistema de colocação de móveis que permita aos jogadores comprar e posicionar móveis no interior de suas propriedades, semelhante à forma como o GTA Online lida com a personalização de apartamentos. Cada item de mobiliário adquirido aumenta o valor melhorado da propriedade; portanto, quando o proprietário eventualmente vende, ele recupera parte do investimento em móveis. Além dos móveis, ofereça atualizações estruturais, como reformas de cozinhas, reformas de banheiros e instalações de sistemas de segurança que aumentam o valor base do imóvel em uma porcentagem. Acompanhe todas as melhorias em uma tabela de modificações de propriedade para que a listagem de imóveis possa mostrar aos potenciais compradores exatamente quais atualizações foram feitas. As propriedades comerciais devem suportar atualizações específicas do negócio, como vitrines para uma loja, equipamentos de cozinha para um restaurante ou racks de servidores para uma empresa de tecnologia, vinculando o sistema de propriedade ao ciclo mais amplo de jogo comercial. A combinação da dinâmica do mercado baseada na localização e das melhorias impulsionadas pelos jogadores cria um rico ecossistema imobiliário onde o imobiliário se torna uma estratégia legítima de construção de riqueza, em vez de apenas um local para guardar artigos e mudar de roupa.

