Agency Docs
QBESXStandalone

Agency-Housing Конфигурация

Система жилья для FiveM на основе базы данных с автоматическим определением ESX, QBCore и QBox.

v1.79.0Платно5 Страницы

01Конфигурация

Быстрая установка · config.lua · Agency-Housing

Скачать config.lua

Config = {} -- ===================================================== -- GENERAL -- ===================================================== -- 'auto' detects ESX / QBCore / QBox automatically. Force with 'esx' or 'qbcore'. Config.Framework = 'auto' -- Language file to use. See locales/ — copy _template.lua to add your own. Config.Locale = 'en' -- Database table name (created by sql/install.sql) Config.TableName = 'agency_houses' Config.Debug = false -- Seconds a player has to wait between two actions that change something — -- locking a door, handing over a key, saving a layout. Zero switches it off, -- which is the default: it was a single throttle shared by every action, so two -- unrelated clicks in a row swallowed the second one. -- -- This is a throttle against event flooding, not a safety mechanism. Buying and -- selling are protected separately by a per-house lock held across the database -- write, and that does not depend on this value. Raise it only if you have a -- reason to slow players down. Config.ActionCooldown = 0.0 -- Heading shown on notifications. Without this Agency-Notify falls back to its -- own default ("SYSTEM ALERT"). Config.NotifyTitle = 'Housing' -- ===================================================== -- ACCENT COLOUR -- ===================================================== -- -- One colour runs through the whole script: the panels, the ground markers, the -- property border and the outline around a piece of furniture. Players pick -- theirs under Housing > Settings, and the choice is stored on their own machine -- — it is a preference, not something the server decides for everyone. -- -- `rgb` the colour itself. -- `deep` the far end of the gradients on the buttons and the badge. Roughly the -- same hue two steps darker; it is listed rather than calculated so a -- server can tune it by eye. -- `ink` text drawn ON the colour. A light accent needs dark ink and the other -- way round, which is the one thing that cannot be derived safely. -- -- Add your own by appending an entry. The swatch row in Settings is built from -- this list, so nothing else has to be touched. Config.DefaultAccent = 'gold' Config.Accents = { { key = 'gold', label = 'Gold', rgb = { 226, 182, 73 }, deep = { 168, 128, 31 }, ink = { 23, 18, 10 } }, { key = 'cyan', label = 'Cyan', rgb = { 0, 212, 255 }, deep = { 10, 127, 212 }, ink = { 0, 19, 29 } }, { key = 'mint', label = 'Mint', rgb = { 53, 214, 166 }, deep = { 15, 118, 110 }, ink = { 4, 26, 21 } }, { key = 'violet', label = 'Violet', rgb = { 168, 133, 247 }, deep = { 109, 74, 184 }, ink = { 20, 13, 33 } }, { key = 'crimson', label = 'Crimson', rgb = { 255, 92, 92 }, deep = { 178, 42, 42 }, ink = { 32, 10, 10 } }, { key = 'amber', label = 'Amber', rgb = { 255, 170, 0 }, deep = { 194, 112, 0 }, ink = { 32, 20, 0 } }, { key = 'steel', label = 'Steel', rgb = { 214, 219, 226 }, deep = { 138, 146, 158 }, ink = { 22, 24, 29 } }, } -- Whether the chosen colour also drives what is drawn in the world: the door -- marker, the property border, the build fence, the storage marker and the -- outline around a selected piece of furniture. Set to false to keep the -- colours configured further down no matter what a player picks. -- -- The garage keeps its own amber either way — that is what tells a parking spot -- from a doorstep at a glance — and so does the wardrobe. Config.AccentDrivesWorld = true -- ===================================================== -- PERMISSIONS -- ===================================================== -- Who may open the house creator UI (/createhouse). -- Checked in this order: FiveM ACE ("agency.housing" / "group.admin") -> framework group. Config.AdminGroups = { 'admin', 'superadmin', 'god' } -- ===================================================== -- HOTKEY / MENU -- ===================================================== -- Default key for the housing menu. Players can rebind it themselves under -- Settings > Key Bindings > FiveM, so this is only the starting value. Config.OpenKey = 'F7' -- Command behind the hotkey. Must stay registered — RegisterKeyMapping needs it. Config.MenuCommand = 'housing' -- The old chat commands. The hotkey menu covers all of them; set this to false -- if you do not want them cluttering the command list. Config.RegisterCommands = true Config.Commands = { create = 'createhouse', delete = 'deletehouse', list = 'houses', } -- Owner menu while standing inside your own house. Config.ManageKey = 'F3' Config.ManageCommand = 'housemenu' -- ===================================================== -- FURNISHING -- ===================================================== Config.MaxFurniture = 60 -- objects per house Config.FurnitureReach = 6.0 -- how far in front of the camera you can place -- The build camera is fenced in, otherwise you fly straight out of the -- apartment and across the map. Which fence applies depends on where you are -- furnishing from: -- -- inside a preset interior or a shell -- there is no plot around you, the -- room sits under the map, so the camera is held near the spawn point. -- on your own property (an MLO) -- the property border itself is the fence. -- You may furnish the whole plot: the garden, the driveway, every floor. Config.BuildBounds = { radius = 16.0, -- metres from the interior spawn point below = 4.0, -- how far you may drop below it above = 7.0, -- and rise above it -- Vertical range when the border is the fence. The plot itself has no -- ceiling, but a build camera needs one or it ends up in the stratosphere. zoneBelow = 8.0, zoneAbove = 30.0, -- The border drawn while furnishing a plot. Nothing draws it during normal -- play; in build mode it is the edge of what you may place on, and a fence -- you cannot see is one you keep bumping into. Taller than the creator's, -- because here you are looking down at it from a camera. fenceHeight = 3.0, fenceColor = { r = 226, g = 182, b = 73, a = 55 }, } -- ===================================================== -- GIZMO — the axes on a selected piece -- ===================================================== -- -- Click a piece in build mode and three axes appear on it. Drag one and only -- that direction changes; nothing slides sideways, nothing tilts by accident. -- G switches to moving, R to turning. Config.Gizmo = { enabled = true, -- How large the axes are on screen. They are drawn in metres but scaled -- with the camera distance, so this is roughly "fraction of the view". screenSize = 0.14, -- How close the cursor has to be to an axis to grab it, in screen units -- (0..1 across the window). 0.02 is about 20 px on a 1080p screen. pickRadius = 0.022, -- The axes start this far above the piece's origin, or they would come out -- of the floor for anything standing on the ground. lift = 0.05, -- The grid every drag snaps to. Either at 0 turns snapping off. moveSnap = 0.05, -- metres rotateSnap = 5.0, -- degrees -- How many degrees a full sweep of the handle across the screen turns the -- piece. Lower is finer. rotateSpan = 360.0, } -- ===================================================== -- MLO DOORS -- ===================================================== -- -- An MLO is part of the map: you cannot be teleported into it, you walk through -- its front door. So an MLO house is locked at that door rather than at a -- marker. The admin records the doors in the creator by looking at them; every -- client then registers them with the game's own door system, and the owner and -- their keyholders can lock and unlock them on the spot. Config.Doors = { max = 8, -- doors per house; a double door is two of them range = 1.6, -- how close you have to stand to work the lock -- How far the creator's aim reaches when recording a door. reach = 8.0, -- The dome sitting on a door, red while locked and green while open, the -- same reading Agency Doorlock uses. Off: up close it is a large coloured -- blob across the door itself, and the [E] card already says everything it -- said. Set enabled = true to bring it back — a smaller `size` is what -- makes it bearable at arm's length. -- -- Shown to everyone when on, not only to the owner: that a door can be -- locked at all is public information, whether you may work it or not. marker = { enabled = false, type = 28, -- dome distance = 12.0, -- metres size = 0.18, alpha = 110, bob = false, onlyWhenLocked = false, }, colors = { locked = { r = 255, g = 72, b = 72 }, unlocked = { r = 53, g = 214, b = 166 }, }, -- The [E] card at the bottom of the screen. Set to false for the plain 3D -- text this script drew before. prompt = true, -- The gesture played on whoever works the lock: a short forward reach, as -- if for a handle or a key fob. The same one Agency Doorlock uses, so a -- player sees one movement for locking a door anywhere on the server. -- -- Flag 48 in the code below is upper body plus secondary, which is what -- lets the animation play without stopping the player walking. animation = { enabled = true, dict = 'anim@heists@keycard@', name = 'exit', duration = 1100, -- ms }, } -- Catalogue for the furnishing mode. All GTA V base game props, so nothing has -- to be streamed. `cat` only groups them in the UI. -- -- Entries whose model does not exist in the running game are dropped on the -- client before the catalogue is shown (IsModelValid). That filter is what -- makes the generated families below safe: GTA prop names follow patterns, so -- the ranges are expanded blindly and whatever the game does not have simply -- never appears. Adding a range costs nothing and misses nothing. -- -- `variants` = number of texture variations (SET_OBJECT_TEXTURE_VARIATION). -- Most props have none, so the colour picker stays hidden unless set here. -- Use /housevariants on a placed object to find out. -- -- `image` = optional path to a real thumbnail, e.g. 'nui/img/couch.png'. -- Otherwise the card shows the picture taken by /housethumbs, or a drawn icon. Config.Furniture = {} --- Add one prop by name. local function add(cat, label, model, extra) local entry = { cat = cat, label = label, model = model } if extra then for k, v in pairs(extra) do entry[k] = v end end Config.Furniture[#Config.Furniture + 1] = entry end --- Expand a numbered family, optionally with letter variants. --- family('seating', 'Chair', 'prop_chair_%02d%s', 1, 12, { '', 'a', 'b', 'c' }) --- produces prop_chair_01, prop_chair_01a, prop_chair_01b … and the client --- throws away the ones this copy of GTA does not have. local function family(cat, label, pattern, from, to, letters) letters = letters or { '' } for n = from, to do for _, letter in ipairs(letters) do local model = pattern:format(n, letter) local name = ('%s %d%s'):format(label, n, letter ~= '' and letter:upper() or '') add(cat, name, model) end end end local AB = { '', 'a', 'b' } local ABC = { '', 'a', 'b', 'c' } -- ---------------- SEATING ---------------- family('seating', 'Chair', 'prop_chair_%02d%s', 1, 12, ABC) family('seating', 'Office Chair', 'prop_off_chair_%02d%s', 1, 8, AB) family('seating', 'Bench', 'prop_bench_%02d%s', 1, 12, AB) family('seating', 'Bar Stool', 'prop_bar_stool_%02d%s', 1, 3, AB) family('seating', 'Beach Chair', 'prop_beach_lounger_%02d%s',1, 3, AB) family('seating', 'Sofa', 'prop_rub_couch%02d%s', 1, 4, AB) add('seating', 'Living Room Sofa', 'v_club_officesofa') add('seating', 'Lounge Sofa', 'v_res_mbsofa') add('seating', 'Corner Sofa', 'v_res_d_sofa') add('seating', 'Trailer Sofa', 'v_res_tre_sofa') add('seating', 'Armchair', 'v_res_tre_chair') add('seating', 'Leather Armchair', 'v_res_m_armchair') add('seating', 'Beanbag', 'prop_beanbag_01') add('seating', 'Wheelchair', 'prop_wheelchair_01') -- ---------------- TABLES ---------------- family('tables', 'Table', 'prop_table_%02d%s', 1, 12, ABC) family('tables', 'Desk', 'prop_off_desk_%02d%s', 1, 6, AB) family('tables', 'Worktop', 'prop_tool_bench%02d%s', 1, 5, AB) add('tables', 'Glass Table', 'v_res_tre_table') add('tables', 'Coffee Table', 'v_res_mcoftable') add('tables', 'Poker Table', 'prop_poker_tabl_01') add('tables', 'Pool Table', 'prop_pooltable_02') add('tables', 'Patio Table', 'prop_patio_table_01') -- ---------------- BEDROOM ---------------- add('bedroom', 'Double Bed', 'v_res_fh_bed') add('bedroom', 'Bed', 'v_res_mbed') add('bedroom', 'Single Bed', 'v_res_tre_bed') add('bedroom', 'Bunk Bed', 'v_res_bunkbed') add('bedroom', 'Mattress', 'prop_rub_matress_01') family('bedroom', 'Mattress', 'prop_rub_matress_%02d%s', 1, 4, AB) add('bedroom', 'Wardrobe', 'v_res_fh_wardrobe') add('bedroom', 'Closet', 'v_res_mwardrobe') add('bedroom', 'Dresser', 'v_res_tre_drawers') add('bedroom', 'Chest of Drawers', 'v_res_fh_drawer') add('bedroom', 'Nightstand', 'v_res_m_bedsidetbl') family('bedroom', 'Mirror', 'prop_wall_mirror_%02d%s', 1, 3, AB) -- ---------------- KITCHEN ---------------- family('kitchen', 'Fridge', 'prop_fridge_%02d%s', 1, 5, AB) family('kitchen', 'Microwave', 'prop_micro_%02d%s', 1, 3, AB) family('kitchen', 'Cooker', 'prop_cooker_%02d%s', 1, 6, AB) family('kitchen', 'Sink', 'prop_sink_%02d%s', 1, 8, AB) family('kitchen', 'Bin', 'prop_bin_%02d%s', 1, 12, AB) add('kitchen', 'Bar Fridge', 'prop_bar_fridge_01') add('kitchen', 'Kitchen Counter', 'v_res_kitchen_unit') add('kitchen', 'Coffee Machine', 'prop_coffee_mac_01') add('kitchen', 'Toaster', 'prop_toaster_01') add('kitchen', 'Kettle', 'prop_kettle_01') add('kitchen', 'Water Cooler', 'prop_watercooler') add('kitchen', 'Bar Counter', 'prop_beer_bar_01') add('kitchen', 'Wine Rack', 'prop_wine_rack_01') -- ---------------- ELECTRONICS ---------------- family('tech', 'TV', 'prop_tv_flat_%02d%s', 1, 5, AB) family('tech', 'Monitor', 'prop_monitor_%02d%s', 1, 4, AB) family('tech', 'PC', 'prop_pc_%02d%s', 1, 4, AB) family('tech', 'Laptop', 'prop_laptop_%02d%s', 1, 4, AB) family('tech', 'Keyboard', 'prop_keyboard_%02d%s', 1, 3, AB) family('tech', 'Printer', 'prop_printer_%02d%s', 1, 3, AB) family('tech', 'Speaker', 'prop_speaker_%02d%s', 1, 9, AB) family('tech', 'Arcade Machine', 'prop_arcade_%02d%s', 1, 4, AB) add('tech', 'TV Stand', 'v_res_tre_tvstand') add('tech', 'Stereo', 'prop_boombox_01') add('tech', 'Telephone', 'prop_phone_ing') add('tech', 'Dartboard', 'prop_dartboard_01') -- ---------------- LIGHTING ---------------- family('light', 'Floor Lamp', 'prop_stand_lamp_%02d%s', 1, 4, AB) family('light', 'Table Lamp', 'prop_lamp_%02d%s', 1, 8, AB) family('light', 'Desk Lamp', 'prop_desk_lamp_%02d%s', 1, 3, AB) family('light', 'Ceiling Light', 'prop_light_ceiling_%02d%s',1, 5, AB) family('light', 'Wall Light', 'prop_wall_light_%02d%s', 1, 15, AB) family('light', 'Candle', 'prop_candle_%02d%s', 1, 4, AB) add('light', 'Neon Sign', 'prop_neon_sign_01') -- ---------------- DECOR ---------------- family('decor', 'Rug', 'prop_rug_%02d%s', 1, 6, AB) family('decor', 'Shelf', 'prop_shelves_%02d%s', 1, 6, AB) family('decor', 'Books', 'prop_books_%02d%s', 1, 6, AB) family('decor', 'Plant', 'prop_plant_%02d%s', 1, 4, ABC) family('decor', 'Indoor Plant', 'prop_plant_int_%02d%s', 1, 6, ABC) family('decor', 'Fern', 'prop_plant_fern_%02d%s', 1, 3, ABC) family('decor', 'Potted Plant', 'prop_pot_plant_%02d%s', 1, 8, ABC) family('decor', 'Cactus', 'prop_cactus_%02d%s', 1, 4, AB) family('decor', 'Vase', 'prop_vase_%02d%s', 1, 6, AB) family('decor', 'Clock', 'prop_clock_%02d%s', 1, 4, AB) family('decor', 'Boxes', 'prop_boxpile_%02d%s', 1, 8, ABC) family('decor', 'Crate', 'prop_box_wood%02d%s', 1, 8, AB) family('decor', 'Painting', 'prop_painting_%02d%s', 1, 6, AB) add('decor', 'Bookcase', 'v_res_tre_bookcase') add('decor', 'Curtains', 'v_res_curtains') add('decor', 'Safe', 'p_v_43_safe_s') add('decor', 'Gun Cabinet', 'prop_gun_case_01') add('decor', 'Dumbbell', 'prop_dumbbell_01') add('decor', 'Punching Bag', 'prop_boxing_bag_01') add('decor', 'Weight Bench', 'prop_gym_bench_01') add('decor', 'Fireplace', 'prop_fireplace_01') add('decor', 'Aquarium', 'prop_fish_tank_01') add('decor', 'Statue', 'prop_statue_01') add('decor', 'Globe', 'prop_globe_01') Config.FurnitureCategories = { 'seating', 'tables', 'bedroom', 'kitchen', 'tech', 'light', 'decor' } -- ===================================================== -- UPGRADES -- ===================================================== -- Bought once per house, paid from Config.Account. The camera module comes -- with a front door camera; further angles are placed by the owner. Config.Upgrades = { cameras = { label = 'Security Cameras', price = 35000, note = 'Front door camera included. Up to %s more at $%s each.', }, } Config.MaxCameras = 4 -- custom cameras on top of the door camera Config.CameraPrice = 5000 -- charged for every camera beyond the included one Config.CameraPanSpeed = 0.45 -- degrees per frame when panning a live feed with A/D Config.CameraReach = 5.0 -- how far from the cursor a camera hangs in open air -- Where the included door camera sits, relative to the entrance. -- -- Straight above the door puts it inside the porch roof on a lot of houses, so -- it is pulled back away from the building as well. The client additionally -- checks the spot for geometry and pulls it back further if it is buried. Config.DoorCamera = { height = 2.05, -- metres above the entrance back = 1.45, -- metres away from the door, towards the street pitch = -26.0, -- tilted down onto the doorstep label = 'Front Door', } -- A visible camera on the wall. Set enabled = false for invisible cameras. Config.CameraProp = { enabled = true, model = 'prop_cctv_cam_06a', headingOffset = 180.0, drop = 0.0, } -- ===================================================== -- PROPERTY ZONE -- ===================================================== -- -- The ground the house owns: the garden, the driveway, the yard, the rooms of -- an MLO. Every house has one — the border is walked on foot in the creator, -- corner by corner, and a house cannot be saved without it. -- -- Walked rather than picked, because a plot is never round. An L shaped yard, a -- driveway down one side, an MLO that has to be fenced along its own walls: a -- circle either misses half of it or swallows the street. -- -- The borders are handed to PolyZone (https://github.com/mkafrin/PolyZone), -- which is a required resource — see the README. Every border on the server is -- bundled into a single ComboZone, so the cost stays the same whether there are -- five properties or five hundred. Config.Zone = { -- How often the player's position is tested against the borders, in ms. -- 500 is PolyZone's own default and is plenty for walking pace. checkInterval = 500, -- Draws every border as a green PolyZone debug volume. Development only. debugPoly = false, poly = { minPoints = 3, -- fewer than three corners enclose nothing maxPoints = 24, -- the creator stops accepting corners here -- Corners dropped closer together than this are ignored, so holding E -- while walking does not fill the polygon with duplicates. snap = 1.2, -- No height setting. A property is the ground it stands on, all the -- way up and all the way down — a balcony, a roof terrace or the top -- floor of an MLO belongs to the plot as much as the lawn does. }, -- The camera the border is marked with. It lifts off above the admin and -- looks down, so the whole plot is in frame from the first second — walking -- a boundary on foot means never seeing the shape you are making. -- -- A line is cast from the camera onto the ground and a pole is drawn where -- it lands. That spot, not the camera, is where the corner goes. cam = { height = 14.0, -- metres above the player when it starts pitch = -55.0, -- how far it looks down to begin with speed = 0.35, -- metres per frame boost = 3.2, -- multiplier while holding Shift slow = 0.30, -- multiplier while holding Alt lookSens = 5.0, -- mouse sensitivity reach = 600.0, -- how far the marker line is cast, in metres pole = 2.6, -- height of the pole drawn at the marked spot }, -- The fence drawn while a border is being marked in the creator. It is not -- shown during play at all: a wall in the middle of a garden is in the way -- of the house it belongs to, and from inside it stands in your window. borderColor = { r = 226, g = 182, b = 73, a = 90 }, borderHeight = 1.6, -- how tall that fence is drawn, in metres } -- ===================================================== -- GARAGE -- ===================================================== -- -- A house can have a garage point recorded in the creator. Standing on it, the -- owner and their keyholders get a prompt that hands over to whatever garage -- script the server runs — this resource does not manage vehicles itself. Config.Garage = { enabled = true, label = 'Garage', -- Which resource handles the vehicles. Agency-Garage is wired up below; -- for anything else, replace `open` and leave `register` empty. resource = 'Agency-Garage', -- What the garage script should know about a house garage. -- `access` is deliberately absent: this resource already draws the marker -- and checks who owns the house, so the garage script must not add a second -- prompt on the same spot. template = { type = 'public', category = 'car', }, -- The car appears on the garage point itself, deliberately without any -- offset. An offset keeps the point's height while moving sideways, so on -- a garage under a building it puts the car through the ceiling and onto -- the roof. The garage script only treats a point as blocked when another -- vehicle stands within 2.6 m -- a player standing there is fine -- so the -- point is the one spot guaranteed to be on the right floor. --- Announce a house garage to the garage script. Runs whenever houses sync. register = function(house, id, point) if GetResourceState(Config.Garage.resource) ~= 'started' then return end exports[Config.Garage.resource]:RegisterGarage(id, { label = house.name, type = Config.Garage.template.type, category = Config.Garage.template.category, store = vector3(point.x, point.y, point.z), -- Marks this as a house garage: the garage script must not settle -- cars on the world ground here. A house sits inside a shell or an -- interior, where that ground is the roof above it. houseGarage = true, spawns = { vector4(point.x, point.y, point.z, point.h or 0.0) }, }) end, --- Announce it to the garage script's server side too. --- --- The client draws the menu, but the server decides whether the garage id --- is real before it hands out vehicles. Registering on one side only means --- the menu opens and is immediately refused as unknown. registerServer = function(house, id, point) if GetResourceState(Config.Garage.resource) ~= 'started' then return end exports[Config.Garage.resource]:RegisterGarage(id, { label = house.name, type = Config.Garage.template.type, category = Config.Garage.template.category, store = vector3(point.x, point.y, point.z), -- Marks this as a house garage: the garage script must not settle -- cars on the world ground here. A house sits inside a shell or an -- interior, where that ground is the roof above it. houseGarage = true, spawns = { vector4(point.x, point.y, point.z, point.h or 0.0) }, }) end, -- The short camera move played while a car is handed out. The player is -- hidden and stepped aside for it, because the car appears exactly where -- they are standing and would otherwise trap them inside it. handover = { enabled = true, distance = 6.0, -- how far the camera sits from the car height = 1.9, -- how far above it swing = 38.0, -- degrees the camera travels around the car entry = 320, -- glide from the player's view into the shot time = 1400, -- milliseconds the swing may take AT MOST wait = 5000, -- ceiling when the shot starts before the car is -- ordered, so it covers the trip to the server linger = 140, -- how long the camera holds once the car is there fade = 220, -- blend back to the player view, in milliseconds standoff = 3.0, -- where the player is put down next to the car }, --- Open it for the owner standing on the point. open = function(house, id) if GetResourceState(Config.Garage.resource) ~= 'started' then -- Fall back to an event so a different garage script can pick it up. return TriggerEvent('agency-housing:garage:open', house.id, house.name) end exports[Config.Garage.resource]:OpenGarage(id) end, } -- ===================================================== -- STORAGE AND WARDROBE -- ===================================================== -- -- Both are optional points inside the house, placed by the owner from their own -- panel (F3) rather than by an admin in the creator: they are fittings, not -- architecture, and the person living there knows where the box belongs. Only -- the owner may move them; owner and key holders may use them, the same rule -- the garage follows. -- -- Setting `enabled = false` here removes the row from the owner panel as well, -- so a server without stashes never offers one. -- -- The hooks below are wired to what this server actually runs (jpr-inventory -- and illenium-appearance). Swap the bodies for a different resource; nothing -- else in the script cares how the menu is opened. Config.Stash = { enabled = true, label = 'Storage', slots = 50, maxWeight = 400000, -- grams, matching QB weight units --- Stash id. Per house, so a key holder reaches the same box as the owner. id = function(house) return ('agency_house_%s'):format(house.id) end, --- Empty the box when the house is sold. The stash id is per house, so --- without this the next buyer inherits whatever the last owner left in it. --- --- Left switched off because there is no shared way to clear a stash: every --- inventory does it differently, and calling the wrong export silently --- does nothing. Fill in the one line your inventory needs, e.g. --- --- ox_inventory : exports.ox_inventory:ClearInventory(stashId) --- qs-inventory : exports['qs-inventory']:ClearStash(stashId) --- qb-inventory : MySQL.query('DELETE FROM stashitems WHERE stash = ?', { stashId }) --- --- The house table is passed too, for inventories that key off the owner. clear = nil, --- Open the box. QB-style inventories expect both of these: the server --- event opens it, the client event tells the interface which stash is --- currently on screen so items get put back in the right place. open = function(house, stashId) TriggerServerEvent('inventory:server:OpenInventory', 'stash', stashId, { maxweight = Config.Stash.maxWeight, slots = Config.Stash.slots, }) TriggerEvent('inventory:client:SetCurrentStash', stashId) end, } Config.Wardrobe = { enabled = true, label = 'Wardrobe', --- Open the outfit menu. --- Note the spelling: illenium-appearance registers this event with a --- single 'p' in "apearance". That is their typo, not one here -- the --- event does not fire if it is corrected. open = function(house) TriggerEvent('illenium-apearance:client:outfitsCommand') end, } -- ===================================================== -- SOUNDS -- ===================================================== -- -- The door sounds are synthesised in the interface, not loaded from audio -- files: files added to a resource do not reliably reach a client that already -- has it cached, and a sample pack would have to be shipped and licensed. -- Shape and pitch live in nui/script.js under DOOR. Config.Sounds = { enabled = true, volume = 0.45, -- 0 to 1 -- How long the door takes to shut behind you, in milliseconds. -- -- The slam used to fire the instant you pressed the exit marker, while you -- were still standing in the room and the screen had not even begun to -- fade. 400 ms puts it where the fade finishes and you are outside, which -- is when a door actually falls shut. Raise it for a heavier door. closeDelay = 400, } -- ===================================================== -- DOORBELL -- ===================================================== Config.Doorbell = { enabled = true, cooldown = 12, -- seconds between rings, per house, to stop bell spam range = 12.0, -- how far from the entrance the ring is still heard waitTime = 90, -- seconds a caller stays listed in the owner's panel -- Played for whoever is inside. Any frontend sound pair works. sound = { name = 'TIMER_STOP', set = 'HUD_MINI_GAME_SOUNDSET' }, } -- ===================================================== -- ECONOMY -- ===================================================== Config.Account = 'bank' -- 'bank' or 'cash' — account used to buy houses Config.SellPercentage = 0.60 -- refund when a player sells their house Config.MaxHousesPerPlayer = 2 -- 0 = unlimited Config.MaxKeyholders = 8 -- how many people an owner may hand keys to -- ===================================================== -- INTERACTION -- ===================================================== Config.InteractKey = 38 -- E Config.InteractDistance = 1.6 Config.Marker = { enabled = true, type = 21, size = { x = 0.28, y = 0.28, z = 0.22 }, color = { r = 226, g = 182, b = 73, a = 140 }, drawDistance = 12.0, bobUpAndDown = true, -- Entrances are recorded from the player's position, and a ped's origin -- sits roughly 0.9 m above the ground it stands on. Without this correction -- the marker floats at head height. Raise it towards 0 if your entrances -- were recorded on stairs or a raised doorstep. zOffset = -0.75, -- Height of the "[E] House" text above the entrance. textOffset = 0.35, } -- Each state gets its own colour, scale and name suffix so a house changing -- hands is actually visible on the map, not just technically different. -- -- `shortRange = true` means the blip only appears on the minimap when you are -- near it — that is the normal GTA behaviour and keeps the map clean. Set it to -- false for a state you want pinned across the whole map at all times. -- Colours a house can be given on the map, offered as swatches in the creator. -- `id` is the GTA blip colour; `hex` is only what the swatch looks like in the -- interface, so it can be tuned to match without touching the game value. Config.BlipColors = { { id = 1, label = 'Red', hex = '#d6342b' }, { id = 5, label = 'Yellow', hex = '#f2d43b' }, { id = 17, label = 'Orange', hex = '#f08a20' }, { id = 2, label = 'Green', hex = '#4caf50' }, { id = 3, label = 'Blue', hex = '#29a3e0' }, { id = 26, label = 'Purple', hex = '#9b59d0' }, { id = 27, label = 'Pink', hex = '#e06fa5' }, { id = 4, label = 'White', hex = '#f4f5f7' }, } -- What a house may override on its own, and within which limits. A house that -- overrides nothing follows the state colours below, which is still the normal -- case — the overrides are for the handful of places that should stand out. Config.BlipOverride = { minScale = 0.40, maxScale = 1.40, step = 0.05, } Config.Blips = { enabled = true, -- Sprite 374 is the house-with-a-dollar-sign icon: right for something on -- the market, wrong once it belongs to someone. Sprite 40 is the plain -- house without the price tag. forSale = { sprite = 374, color = 2, scale = 0.75, -- green, house + $ shortRange = true, suffix = ' — For sale', }, owned = { sprite = 40, color = 3, scale = 0.85, -- blue, plain house shortRange = true, suffix = ' — Yours', }, keyholder = { sprite = 40, color = 26, scale = 0.70, -- purple, plain house shortRange = true, suffix = ' — Key', }, other = { sprite = 40, color = 4, scale = 0.60, -- white, plain house shortRange = true, suffix = ' — Sold', }, showOwnedByOthers = false, -- set true to draw the 'other' state above } -- ===================================================== -- 3D PREVIEW (creator "View in 3D") -- ===================================================== Config.Preview = { distance = 3.2, -- starting camera distance in metres minDist = 0.8, -- fully zoomed in maxDist = 7.0, -- fully zoomed out (kept inside the room, see fovMax) zoomStep = 0.45, -- metres per mouse wheel notch zoomSmooth = 0.25, -- 0..1, how fast the camera eases to the new distance orbitSpeed = 0.25, -- degrees per frame height = 0.9, -- camera height above the interior spawn point -- GTA interiors are only drawn while the camera is inside them, so pulling -- the camera far enough back to "see it all" would just show the void. -- Zooming out widens the lens instead: same viewpoint, much more in frame. fovMin = 50.0, -- fully zoomed in fovMax = 100.0, -- fully zoomed out -- Free-fly mode (F). A camera has no body: it cannot fall through the map, -- get stuck in geometry or take fall damage, which is why the preview flies -- instead of teleporting the player. freeSpeed = 0.10, -- metres per frame freeBoost = 3.5, -- multiplier while holding Shift freeSlow = 0.30, -- multiplier while holding Alt lookSens = 6.0, -- mouse sensitivity fadeMs = 150, -- blend between entries } -- ===================================================== -- SHELLS / INTERIORS -- ===================================================== -- `category` groups the entry in the creator UI: 'house', 'mlo' or 'shell'. -- It is purely cosmetic — `type` below decides how the entry actually works. -- -- Two supported modes per shell entry: -- -- type = 'interior' -> teleports into an existing GTA V interior. Works on ANY -- server, no extra resource, no props to stream. -- type = 'shell' -> spawns a shell prop under the map (needs a shells -- resource such as qb-interiors / ox_shells that provides -- the model). Left in as ready-to-use examples. -- -- `interior` is the vector4 the player is teleported to (x, y, z, heading). -- `exitOffset` is only used by type = 'shell'. -- -- TIP: every coordinate below can be re-recorded live. Open /createhouse, stand -- where you want the interior spawn to be and press "Use my position" — the -- house is then stored with its own interior coords and this list is ignored -- for that house. No config editing needed. Config.ShellSpawn = vector3(1200.0, 4800.0, -100.0) -- base point for type='shell' Config.Shells = { -- ---------- VANILLA GTA V INTERIORS (no dependencies) ---------- ['motel'] = { label = 'Motel Room', category = 'house', type = 'interior', price = 25000, interior = vector4(152.11, -1004.36, -99.0, 340.0), }, ['apartment_low'] = { label = 'Low End Apartment', category = 'house', type = 'interior', price = 55000, interior = vector4(265.97, -1007.44, -101.01, 0.0), }, ['apartment_mid'] = { label = 'Mid End Apartment', category = 'house', type = 'interior', price = 95000, interior = vector4(346.77, -1012.85, -99.19, 180.0), }, ['apartment_high'] = { label = 'High End Apartment', category = 'house', type = 'interior', price = 180000, interior = vector4(-786.87, 315.76, 217.64, 180.0), }, ['eclipse_towers'] = { label = 'Eclipse Towers Penthouse', category = 'house', type = 'interior', price = 420000, interior = vector4(-774.01, 342.02, 196.69, 180.0), }, ['trailer'] = { label = 'Trailer', category = 'house', type = 'interior', price = 18000, interior = vector4(1972.03, 3815.72, 33.43, 120.0), }, ['stilt_house'] = { label = 'Stilt House (Vinewood Hills)', category = 'house', type = 'interior', price = 650000, interior = vector4(-174.29, 497.06, 137.67, 180.0), }, ['garage_small'] = { label = 'Small Garage', category = 'mlo', type = 'interior', price = 40000, interior = vector4(227.19, -991.42, -99.5, 90.0), }, ['garage_large'] = { label = 'Large Garage', category = 'mlo', type = 'interior', price = 120000, interior = vector4(174.06, -1002.66, -99.5, 90.0), }, ['office'] = { label = 'Executive Office', category = 'mlo', type = 'interior', price = 300000, interior = vector4(-141.24, -620.83, 168.82, 270.0), }, ['clubhouse'] = { label = 'Biker Clubhouse', category = 'mlo', type = 'interior', price = 260000, interior = vector4(1108.03, -3157.11, -37.51, 180.0), }, ['bunker'] = { label = 'Bunker', category = 'mlo', type = 'interior', price = 500000, interior = vector4(894.53, -3245.86, -98.27, 0.0), }, ['hangar'] = { label = 'Hangar', category = 'mlo', type = 'interior', price = 380000, interior = vector4(-1267.02, -3013.35, -49.5, 330.0), }, ['nightclub'] = { label = 'Nightclub', category = 'mlo', type = 'interior', price = 750000, interior = vector4(-1605.53, -3012.7, -78.02, 180.0), }, ['arcade'] = { label = 'Arcade', category = 'mlo', type = 'interior', price = 340000, interior = vector4(2721.5, -376.02, -48.5, 180.0), }, -- ---------- SHELL PROPS (require a shells resource) ---------- ['shell_small'] = { label = 'Small Shell House', category = 'shell', type = 'shell', model = 'shell_v16low', price = 90000, exitOffset = vector3(0.0, -3.5, 1.0), }, ['shell_medium'] = { label = 'Medium Shell House', category = 'shell', type = 'shell', model = 'shell_v16mid', price = 170000, exitOffset = vector3(1.4, -4.2, 1.1), }, ['shell_large'] = { label = 'Large Shell Mansion', category = 'shell', type = 'shell', model = 'shell_v16high', price = 400000, exitOffset = vector3(3.2, -6.1, 1.2), }, } -- Order the shells appear in the creator UI. Keys not listed are appended. Config.ShellOrder = { 'trailer', 'motel', 'apartment_low', 'garage_small', 'apartment_mid', 'garage_large', 'apartment_high', 'clubhouse', 'office', 'arcade', 'hangar', 'eclipse_towers', 'bunker', 'stilt_house', 'nightclub', 'shell_small', 'shell_medium', 'shell_large', }

02SQL файл

Импортируйте этот SQL файл в базу данных перед запуском ресурса:

-- ===================================================================== -- Agency Housing - Database -- -- Two tables. `agency_houses` holds the houses themselves, one row each. -- `agency_house_inside` remembers who was inside which house, so a player -- who disconnects indoors is put back where they were on the next join -- instead of on the pavement outside. -- -- The resource adds later columns by itself on every start -- (ALTER TABLE ... ADD COLUMN IF NOT EXISTS), so an existing install only -- ever needs the two CREATE statements below. Running this file twice is -- harmless: every statement is IF NOT EXISTS. -- -- The table name follows Config.TableName. Rename it here too if you -- change it there. -- ===================================================================== CREATE TABLE IF NOT EXISTS `agency_houses` ( `id` INT AUTO_INCREMENT PRIMARY KEY, -- What the house is and what it costs. `name` VARCHAR(64) NOT NULL, `shell` VARCHAR(64) DEFAULT NULL, -- interior | shell | mlo. Decides whether the house is entered through a -- marker or walked into through its own front door. `kind` VARCHAR(16) NOT NULL DEFAULT interior, `price` INT NOT NULL DEFAULT 0, -- Positions, each stored as JSON. `interior` is only set when the house -- carries its own recorded coordinates; otherwise the shell entry in -- config.lua applies. `entrance` LONGTEXT DEFAULT NULL, `interior` LONGTEXT DEFAULT NULL, `exit_point` LONGTEXT DEFAULT NULL, `stash_point` LONGTEXT DEFAULT NULL, `wardrobe_point` LONGTEXT DEFAULT NULL, `garage` LONGTEXT DEFAULT NULL, -- The property border: the corners walked in the creator, handed to -- PolyZone on start. Required for houses created since borders exist. `zone` LONGTEXT DEFAULT NULL, -- The MLO doors this house owns, for kind = mlo. `doors` LONGTEXT DEFAULT NULL, -- Per-house map blip override: {"name":"Villa","color":5,"scale":0.9} -- Any field may be absent; what is missing follows the state styles in -- Config.Blips (for sale / owned / keyholder). `blip` LONGTEXT DEFAULT NULL, -- Ownership. `owner` is the framework identifier, NULL while the house -- is unsold. `owner` VARCHAR(64) DEFAULT NULL, `owner_name` VARCHAR(64) DEFAULT NULL, `keys` LONGTEXT DEFAULT NULL, -- State flags. `locked` TINYINT(1) NOT NULL DEFAULT 1, `for_sale` TINYINT(1) NOT NULL DEFAULT 1, `show_blip` TINYINT(1) NOT NULL DEFAULT 1, -- What the owner did with the place. `furniture` LONGTEXT DEFAULT NULL, `upgrades` LONGTEXT DEFAULT NULL, `cameras` LONGTEXT DEFAULT NULL, `created_by` VARCHAR(64) DEFAULT NULL, INDEX `owner` (`owner`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- Who is inside which house. One row per player at most, hence the -- identifier as primary key: the resource writes with ON DUPLICATE KEY. CREATE TABLE IF NOT EXISTS `agency_house_inside` ( `identifier` VARCHAR(64) NOT NULL PRIMARY KEY, `house_id` INT NOT NULL, `since` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, INDEX `house_id` (`house_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

После этой страницы всё ещё не получается? Дальше подключается наша поддержка.