--[[ Sky Phone configuration General settings live in this file. Media providers and upload limits live in config/media.lua, while translations remain in config/locales/*.lua. Sections marked "SERVER ONLY" are guarded with IsDuplicityVersion(), so passwords, API keys, migration settings, and server-owned locations are not applied by game clients. Keep option names unchanged. Restart sky_phone after editing this file. ]] -- ============================================================================= -- Core, framework and device -- ============================================================================= Config.Bridge = { Framework = "auto", -- auto, esx, qbox, qb Inventory = "auto", -- auto, ox, qb, lj, qs, codem, core, mf, smx, hex, esx Locale = "en", CallbackTimeout = 15000, Debug = false, -- true: show debug/info output; warnings and errors are always shown } Config.Command = "phone" Config.Phone = { Item = "phone", Unique = true, -- true: data follows each phone item; false: one persistent phone per character; hex/esx require false Keybind = "F1", -- false disables the configurable phone key mapping AllowMovement = true, -- true: game input stays active while the mobile phone is open DevelopmentCommand = true, DeviceName = "iFruit Phone", } Config.TestData = { Enabled = false, -- development/test servers only; keep disabled in production Command = "phonetestdata", AdminOnly = false, -- enable only on development servers; every run is scoped to the executing player's phone AdminGroups = { "admin", "superadmin" }, } Config.CustomApps = { Enabled = true, BundledApps = true, ExternalApps = true, Debug = true, -- detailed client traces for exports, registration, catalog sync and lifecycle events ReadyTimeoutMs = 8000, MaximumMessageBytes = 65536, MaximumStorageBytesPerApp = 262144, MaximumStorageValueBytes = 65536, -- Bridge v1 ceiling; lower values tighten the server policy. MaximumStorageKeyLength = 64, -- Bridge v1 ceiling; lower values tighten the server policy. MaximumStorageKeysPerApp = 128, StorageRequestsPerMinute = 120, AllowRemoteOrigins = { -- ["https://apps.example.com"] = true, }, TrustedAdapters = {}, } Config.Security = { MaximumAttempts = 5, LockSeconds = 30, AttemptsPerMinute = 12, } Config.Sim = { Enabled = true, -- false: devices receive a persistent random number automatically; hex/esx require false RegisteredItem = "sky_phone_sim_registered", AnonymousItem = "sky_phone_sim_anonymous", NumberLength = 10, NumberPrefix = "", NumberGroups = { 3, 3, 4 }, } -- ============================================================================= -- Calls, voice and radio -- ============================================================================= Config.Speaker = { Enabled = true, -- global phone and radio speaker controls } Config.Calls = { VoiceProvider = "pma", -- yaca (alias: yaca-voice), pma (alias: pma-voice), saltychat (alias: salty) RingSeconds = 30, ContactNameMaxLength = 80, ContactNotesMaxLength = 500, RecentPageSize = 100, } Config.Payphones = { Enabled = true, -- Existing world props with these models are detected automatically. Props = { "prop_phonebox_01b", "p_phonebox_01b_s", "prop_phonebox_01a", "prop_phonebox_04", }, -- Additional booths are spawned only at these custom positions. CustomProp = "prop_phonebox_01b", CustomLocations = { -- vector4(x, y, z, heading), }, ReplacementProp = "sf_prop_sf_phonebox_01b_s", PricePerSecond = 1, PaymentAccount = "cash", -- cash or bank Currency = "$", NoAnswerTimeoutSeconds = 30, CallerNumber = "PAYPHONE", InteractionDistance = 1.8, ServerValidationDistance = 3.0, MaximumCallDistance = 4.0, ScanDistance = 25.0, ScanIntervalMs = 1000, ModelLoadTimeoutMs = 5000, Animation = { Dictionary = "anim@scripted@payphone_hits@male@", PedClip = "FXFR_PAV_1_INTRO_MALE", PropClip = "FXFR_PAV_1_INTRO_PHONE", HangupDurationMs = 2000, }, } Config.Radio = { VoiceProvider = "auto", -- auto, yaca, pma, saltychat DefaultVolume = 50, HistoryLimit = 8, FrequencyMin = 0.1, FrequencyMax = 999.9, FrequencyDecimals = 1, AllowSecondary = true, Notifications = false, AutoRejoin = false, DisplayName = { Enabled = true, MaxLength = 32, AllowedJobs = { -- Job name = minimum grade. Unlisted jobs cannot set a radio display name. police = 0, sheriff = 0, fib = 0, army = 0, ambulance = 0, }, }, Hud = { Enabled = true, SpeakerPersistMilliseconds = 3000, Position = { Horizontal = "right", -- left or right Vertical = "top", -- top or bottom HorizontalOffset = 2.0, -- vh VerticalOffset = 30.0, -- vh }, }, Badge = { Enabled = true, MaxLength = 8, ForbiddenPatterns = { "88", "1488", "18", "14", "28", "198" }, }, LockedChannels = { { range = { 0.1, 100.0 }, jobs = { police = true, sheriff = true, fib = true, army = true, ambulance = true, }, }, }, } -- ============================================================================= -- Phone presentation and animations -- ============================================================================= Config.Animations = { Enabled = true, PropModel = "prop_npc_phone_02", PropBone = 28422, LoadTimeoutMs = 5000, ContextPollMs = 250, Dictionaries = { OnFoot = "cellphone@", Driver = "anim@cellphone@in_car@ds", Passenger = "anim@cellphone@in_car@ps", Camera = "cellphone@self", }, Clips = { TextIn = "cellphone_text_in", TextRead = "cellphone_text_read_base", TextOut = "cellphone_text_out", TextToCall = "cellphone_text_to_call", CallListen = "cellphone_call_listen_base", CallToText = "cellphone_call_to_text", CallOut = "cellphone_call_out", Camera = "selfie", }, Transforms = { Portrait = { position = vector3(0.0, 0.0, 0.0), rotation = vector3(0.0, 0.0, 0.0), }, Landscape = { position = vector3(0.0, 0.0, 0.0), rotation = vector3(0.0, 0.0, 90.0), }, }, } -- ============================================================================= -- Built-in applications -- ============================================================================= Config.Messages = { BodyMaxLength = 2000, ConversationScanLimit = 1000, ThreadPageSize = 200, SendsPerMinute = 30, MediaLoadsPerMinute = 120, VoiceMaxDurationMs = 30000, VoiceMaxBase64Length = 180000, VoiceWaveformSamples = 48, VideoMaxDurationMs = 30000, DeleteBatchSize = 20, } Config.Memos = { MaximumCount = 100, MaximumDurationMs = 300000, MaximumBytes = 2 * 1024 * 1024, MaximumWaveformSamples = 96, TitleMaxLength = 120, NoteMaxLength = 2000, UploadsPerMinute = 10, WritesPerMinute = 60, ListsPerMinute = 60, MaximumPendingUploads = 1, UploadSessionTimeoutMs = 60000, } Config.EasyShare = { Enabled = true, DefaultVisibility = "everyone", -- everyone, contacts or hidden MaximumDistance = 15.0, HistoryLimit = 50, PendingSeconds = 30, TransferDurationMs = 3000, RequestsPerMinute = 12, BootstrapRequestsPerMinute = 30, VisibilityUpdatesPerMinute = 10, ActionsPerMinute = 30, PayloadMaxBytes = 24000, } Config.DarkChat = { AliasMaxLength = 32, BodyMaxLength = 2000, ThreadPageSize = 200, SendsPerMinute = 30, ActionsPerMinute = 60, ReportsPerDay = 10, VoiceMaxDurationMs = 60000, VoiceMaxBase64Length = 360000, VoiceWaveformSamples = 48, CleanupIntervalSeconds = 30, AllowedDisappearTimers = { [0] = true, [-1] = true, -- after reading [60] = true, [300] = true, [3600] = true, [86400] = true, [604800] = true, }, } Config.Mail = { Domain = "ifruit.com", LocalPartMinLength = 3, LocalPartMaxLength = 32, PasswordMinLength = 6, PasswordMaxLength = 64, SubjectMaxLength = 120, BodyMaxLength = 20000, MaxRecipients = 10, PageSize = 50, AuthAttemptsPerMinute = 5, MailboxNameMaxLength = 50, MaxMailboxes = 20, MailboxRequestsPerMinute = 12, DeleteBatchSize = 50, DeleteRequestsPerMinute = 12, } Config.Banking = { Currency = "$", MinimumAmount = 1, MaximumAmount = 1000000, ActionsPerMinute = 12, HistoryLimit = 50, } Config.Health = { DailyStepGoal = 8000, SampleIntervalMs = 500, ReportIntervalSeconds = 30, ReportsPerMinute = 4, MaximumSpeedMetersPerSecond = 12.0, EmergencyNumber = "911", ProfileTextMaxLength = 500, } Config.Billing = { Enabled = true, Currency = "$", PaymentAccount = "bank", -- bank or cash MinimumAmount = 1, MaximumAmount = 1000000, PageSize = 30, UrgentLimit = 5, ActionsPerMinute = 8, AllowDisputes = true, DefaultDueDays = 7, MaximumTitleLength = 160, MaximumDescriptionLength = 1000, } Config.Garage = { System = "auto", -- auto, custom, esx, qb, qbox, ak47, bp, cd, codem, ds-servercreator, hex, jg, my, okok, op, quasar, rx, vms, ws, zyke_garages MaximumVehicles = 250, RequestsPerMinute = 30, VehicleImages = { Enabled = true, UrlTemplate = "https://cdn.sky-systems.net/vehicles/{model}.png", -- Optional spawn-name overrides for garages that only store model hashes. -- Example: [970598228] = "sultan", ModelNames = {}, }, Custom = { Table = "", OwnerColumn = "", }, Valet = { Enabled = true, Price = 750, Account = "bank", -- bank or cash RequestsPerMinute = 3, CooldownSeconds = 60, TimeoutSeconds = 180, SpawnDistance = 110.0, ArrivalDistance = 14.0, DriveSpeed = 20.0, DrivingStyle = 786603, DriverModel = "s_m_m_autoshop_01", -- The current valet driver route supports road vehicles. Keep non-road types disabled. VehicleTypes = { car = true, bike = true, boat = false, plane = false, helicopter = false, }, }, } Config.Housing = { System = "auto", -- auto, rtx, quasar, vms, rx, nolag, sn, esx_property, qbx_properties AutoPriority = { "esx_property", "qbx_properties", "rtx", "quasar", "vms", "rx", "nolag", "sn" }, MaximumProperties = 50, OverviewRequestsPerMinute = 30, ActionsPerMinute = 12, Camera = { HeightAboveEntrance = 2.5, FieldOfView = 55.0, MinimumFieldOfView = 20.0, MaximumFieldOfView = 75.0, RotateSpeed = 0.65, ExitControl = 177, -- Backspace NightVisionControl = 38, -- E ZoomInControl = 241, -- Mouse wheel up ZoomOutControl = 242, -- Mouse wheel down LeftControl = 174, RightControl = 175, UpControl = 172, DownControl = 173, }, } Config.Marketplace = { PageSize = 20, MessagePageSize = 50, OfferHistorySize = 50, MaxActiveListings = 15, MaxImages = 6, TitleMinLength = 5, TitleMaxLength = 70, DescriptionMinLength = 20, DescriptionMaxLength = 2000, MessageMaxLength = 1000, MaximumPrice = 100000000, ListingLifetimeDays = 7, Categories = { "vehicles", "property", "electronics", "clothing", "tools", "leisure", "services", "jobs", "wanted", "other", }, Districts = { "los_santos", "vinewood", "vespucci", "south_los_santos", "sandy_shores", "paleto_bay", "blaine_county", }, PhotoGradients = { "linear-gradient(145deg, #ff9a62, #5f2c82 58%, #141e30)", "linear-gradient(160deg, #67d5b5, #26648e 55%, #0b132b)", "linear-gradient(135deg, #fbc2eb, #a6c1ee 48%, #302b63)", "linear-gradient(150deg, #f6d365, #fda085 45%, #512b58)", "linear-gradient(145deg, #ff6b6b, #845ec2 52%, #0f2027)", "linear-gradient(150deg, #00c9a7, #4d8076 46%, #1f3a5f)", "linear-gradient(135deg, #ffc75f, #f96d80 48%, #4b4453)", }, } Config.LocalPages = { PageSize = 20, MaxImages = 6, ProfileHandleMinLength = 3, ProfileHandleMaxLength = 24, ProfileBioMaxLength = 160, TitleMinLength = 5, TitleMaxLength = 80, BodyMinLength = 10, BodyMaxLength = 1500, Categories = { "recommendation", "wanted", "service", "event", "place", "community" }, CityMarktSharesPerDay = 1, } -- ============================================================================= -- Social applications -- ============================================================================= Config.FlipTok = { PageSize = 12, CaptionMaxLength = 500, CommentMaxLength = 300, BioMaxLength = 160, PasswordMinLength = 8, PasswordMaxLength = 72, MaxVideoDurationMs = 300000, MaxPostMedia = 10, MusicTracks = {}, VerifyCommand = "fliptokverify", AdminGroups = { "admin" }, ReportWebhookConvar = "sky_phone_fliptok_report_webhook", } Config.Picstagram = { PageSize = 12, CommentPageSize = 100, MaxPostMedia = 5, CaptionMaxLength = 800, CommentMaxLength = 300, BioMaxLength = 160, LocationMaxLength = 80, StoryTextMaxLength = 160, StoryLifetimeSeconds = 24 * 60 * 60, PasswordMinLength = 8, PasswordMaxLength = 72, PostsPerMinute = 6, StoriesPerMinute = 6, CommentsPerMinute = 20, ReportDetailsMaxLength = 500, ReportReasons = { "spam", "harassment", "dangerous", "illegal", "other" }, VerifyCommand = "picstagramverify", AdminGroups = { "admin" }, } Config.Feather = { PageSize = 20, TextMaxLength = 360, BioMaxLength = 160, DisplayNameMaxLength = 50, HandleMaxLength = 30, SearchMaxLength = 80, HashtagMaxLength = 64, TrendingTopicLimit = 10, ReportDetailsMaxLength = 500, MaxImages = 4, PostsPerMinute = 8, ActionsPerMinute = 90, ReportsPerDay = 10, } -- ============================================================================= -- Utilities, groups and transport -- ============================================================================= Config.MapMarkers = { MaximumMarkers = 50, LabelMaxLength = 40, ActionsPerMinute = 60, } Config.CrewLink = { UsernameMinLength = 3, UsernameMaxLength = 20, PasswordMinLength = 8, PasswordMaxLength = 72, GroupNameMinLength = 3, GroupNameMaxLength = 32, MaximumGroupsPerProfile = 5, MaximumMembersPerGroup = 16, InviteCodeLength = 8, InviteLifetimeSeconds = 30, NearbyInviteDistance = 5.0, NearbyScanLimit = 12, PingLabelMaxLength = 48, PingLifetimeSeconds = 300, MaximumActivePings = 12, ActionsPerMinute = 30, LiveRequestsPerMinute = 120, OverheadRefreshMilliseconds = 3000, OverheadDistance = 50.0, ExternalPingResources = { -- ["example_resource"] = true, }, } Config.Calendar = { TitleMaxLength = 120, NoteMaxLength = 2000, MaximumDurationSeconds = 7 * 24 * 60 * 60, MaximumQuerySeconds = 370 * 24 * 60 * 60, PastEditSeconds = 365 * 24 * 60 * 60, FutureSeconds = 5 * 365 * 24 * 60 * 60, ReminderPollSeconds = 15, } Config.SkyRide = { PaymentAccount = "bank", Currency = "$", ProfileNameMinLength = 2, ProfileNameMaxLength = 50, DistanceUnit = "kilometer", -- kilometer or mile QuoteLifetimeSeconds = 120, HistoryLimit = 50, ReadsPerMinute = 120, ActionsPerMinute = 30, QuotesPerMinute = 20, RecoveryIntervalSeconds = 15, PaymentPendingRecoverySeconds = 30, PickupSelectionRadius = 150.0, ArrivalRadius = 40.0, CompletionRadius = 80.0, MinimumDistanceMeters = 250, MaximumDistanceMeters = 40000, RouteDistanceMultiplier = 1.25, AverageSpeedMetersPerSecond = 12.0, DriverPayoutPercent = 85, RatingCommentMaxLength = 300, MaximumTip = 10000, CustomFare = { Enabled = true, MinimumPrice = 5, MaximumPrice = 100000, MinimumCalculatedMultiplier = 0.5, MaximumCalculatedMultiplier = 3.0, }, DriverJobs = { taxi = 0, }, Services = { { Id = "taxi", Seats = 4, EtaMinutes = 3, BaseFare = 12, PricePerKilometer = 18, PricePerMile = 29, PricePerMinute = 1, MinimumFare = 15, }, { Id = "comfort", Seats = 4, EtaMinutes = 5, BaseFare = 16, PricePerKilometer = 24, PricePerMile = 39, PricePerMinute = 2, MinimumFare = 22, }, { Id = "xl", Seats = 6, EtaMinutes = 7, BaseFare = 20, PricePerKilometer = 30, PricePerMile = 48, PricePerMinute = 2, MinimumFare = 28, }, { Id = "premium", Seats = 4, EtaMinutes = 8, BaseFare = 28, PricePerKilometer = 40, PricePerMile = 64, PricePerMinute = 3, MinimumFare = 38, }, }, QuickLocations = { { Id = "legion-square", Label = "Legion Square", Coords = vector3(-265.1, -960.2, 31.2), }, { Id = "diamond-casino", Label = "Diamond Casino", Coords = vector3(925.2, 46.4, 81.1), }, { Id = "airport", Label = "Los Santos Airport", Coords = vector3(-1037.7, -2737.8, 20.2), }, { Id = "vinewood", Label = "Vinewood", Coords = vector3(-594.4, -929.9, 23.9), }, }, } Config.Crypto = { Enabled = true, Currency = "$", BankAccount = "bank", AssetScale = 1000000, PriceScale = 100, QuoteLifetimeSeconds = 8, PriceTickMinimumSeconds = 7, PriceTickMaximumSeconds = 12, MarketsPerTickMinimum = 8, MarketsPerTickMaximum = 12, TickMovementDivisor = 10, RandomImpulseDivisor = 3, MomentumDecayBasisPoints = 8000, MomentumImpulseBasisPoints = 2000, MeanReversionBasisPoints = 55, CycleDurationMinimumTicks = 14, CycleDurationMaximumTicks = 30, CycleStrengthMinimumBasisPoints = 2800, CycleStrengthMaximumBasisPoints = 5200, CycleTransitionBasisPoints = 1800, GlobalCycleMinimumTicks = 24, GlobalCycleMaximumTicks = 54, GlobalTrendMinimumBasisPoints = 8, GlobalTrendMaximumBasisPoints = 24, MarketShockChanceBasisPoints = 100, MarketShockMinimumMultiplier = 2, MarketShockMaximumMultiplier = 3, MaximumMovementMultiplier = 3, HistoryRetentionTicks = 4096, SparklinePoints = 48, SessionSeconds = 30 * 60, RecentAuthenticationSeconds = 5 * 60, PasswordMinLength = 8, PasswordMaxLength = 72, HandleMinLength = 3, HandleMaxLength = 20, FeeBasisPoints = 75, MinimumFee = 1, MinimumSettlement = 10, MaximumSettlement = 250000, MaximumTradeNotional = 100000, MaximumPositionQuantity = 100000, MaximumTransferQuantity = 100000, DailyDepositLimit = 500000, DailyWithdrawalLimit = 250000, DailyTradeLimit = 500000, ActionsPerMinute = 30, LoginAttempts = 5, LockoutSeconds = 5 * 60, TreasuryCash = 5000000, Markets = { { Id = "aurora", Symbol = "AUR", Name = "Aurora", Color = "#25d9ad", Logo = "◈", InitialPrice = 12850, MinimumPrice = 3000, MaximumPrice = 80000, VolatilityBasisPoints = 180, IssuedSupply = 1000000, TreasuryInventory = 850000, }, { Id = "vertex", Symbol = "VTX", Name = "Vertex", Color = "#4d8cff", Logo = "◆", InitialPrice = 4275, MinimumPrice = 800, MaximumPrice = 30000, VolatilityBasisPoints = 260, IssuedSupply = 2500000, TreasuryInventory = 2100000, }, { Id = "ember", Symbol = "EMB", Name = "Ember", Color = "#ff9d54", Logo = "✦", InitialPrice = 980, MinimumPrice = 100, MaximumPrice = 12000, VolatilityBasisPoints = 340, IssuedSupply = 8000000, TreasuryInventory = 6800000, }, { Id = "titan", Symbol = "TTN", Name = "Titan", Color = "#8f7cff", Logo = "⬢", InitialPrice = 425000000, MinimumPrice = 100000000, MaximumPrice = 900000000, VolatilityBasisPoints = 65, IssuedSupply = 21000, TreasuryInventory = 17500, }, { Id = "crown", Symbol = "CRN", Name = "Crown", Color = "#f6c453", Logo = "♛", InitialPrice = 128000000, MinimumPrice = 25000000, MaximumPrice = 350000000, VolatilityBasisPoints = 85, IssuedSupply = 64000, TreasuryInventory = 51000, }, { Id = "atlas", Symbol = "ATL", Name = "Atlas", Color = "#e66f9e", Logo = "▲", InitialPrice = 12000000, MinimumPrice = 3000000, MaximumPrice = 30000000, VolatilityBasisPoints = 110, IssuedSupply = 250000, TreasuryInventory = 205000, }, { Id = "zenith", Symbol = "ZNT", Name = "Zenith", Color = "#6b8cff", Logo = "✥", InitialPrice = 68000000, MinimumPrice = 18000000, MaximumPrice = 160000000, VolatilityBasisPoints = 95, IssuedSupply = 125000, TreasuryInventory = 99000, }, { Id = "celestium", Symbol = "CLS", Name = "Celestium", Color = "#8ad8ff", Logo = "✧", InitialPrice = 8450000, MinimumPrice = 1500000, MaximumPrice = 22000000, VolatilityBasisPoints = 125, IssuedSupply = 420000, TreasuryInventory = 340000, }, { Id = "orbit", Symbol = "ORB", Name = "Orbit", Color = "#57c7ff", Logo = "◎", InitialPrice = 1244000, MinimumPrice = 250000, MaximumPrice = 3500000, VolatilityBasisPoints = 145, IssuedSupply = 900000, TreasuryInventory = 735000, }, { Id = "helix", Symbol = "HLX", Name = "Helix", Color = "#c47cff", Logo = "⌁", InitialPrice = 582000, MinimumPrice = 90000, MaximumPrice = 1600000, VolatilityBasisPoints = 175, IssuedSupply = 1400000, TreasuryInventory = 1140000, }, { Id = "nova", Symbol = "NVA", Name = "Nova", Color = "#ff6f91", Logo = "✺", InitialPrice = 325000, MinimumPrice = 50000, MaximumPrice = 900000, VolatilityBasisPoints = 210, IssuedSupply = 2200000, TreasuryInventory = 1800000, }, { Id = "prism", Symbol = "PRM", Name = "Prism", Color = "#5ee1c4", Logo = "◇", InitialPrice = 74500, MinimumPrice = 12000, MaximumPrice = 240000, VolatilityBasisPoints = 195, IssuedSupply = 3800000, TreasuryInventory = 3100000, }, { Id = "quantum", Symbol = "QTM", Name = "Quantum", Color = "#7a9cff", Logo = "◉", InitialPrice = 21400, MinimumPrice = 3500, MaximumPrice = 85000, VolatilityBasisPoints = 230, IssuedSupply = 5200000, TreasuryInventory = 4250000, }, { Id = "drift", Symbol = "DRF", Name = "Drift", Color = "#4ecdc4", Logo = "≋", InitialPrice = 7600, MinimumPrice = 900, MaximumPrice = 30000, VolatilityBasisPoints = 280, IssuedSupply = 12000000, TreasuryInventory = 9800000, }, { Id = "pulse", Symbol = "PLS", Name = "Pulse", Color = "#ff5f7f", Logo = "◍", InitialPrice = 1840, MinimumPrice = 200, MaximumPrice = 9000, VolatilityBasisPoints = 320, IssuedSupply = 18000000, TreasuryInventory = 14800000, }, { Id = "moss", Symbol = "MOS", Name = "Moss", Color = "#64c987", Logo = "♧", InitialPrice = 460, MinimumPrice = 60, MaximumPrice = 2400, VolatilityBasisPoints = 360, IssuedSupply = 36000000, TreasuryInventory = 29500000, }, { Id = "flux", Symbol = "FLX", Name = "Flux", Color = "#a777e3", Logo = "ϟ", InitialPrice = 238, MinimumPrice = 35, MaximumPrice = 1400, VolatilityBasisPoints = 390, IssuedSupply = 44000000, TreasuryInventory = 36000000, }, { Id = "tide", Symbol = "TDE", Name = "Tide", Color = "#46a6ff", Logo = "≈", InitialPrice = 125, MinimumPrice = 20, MaximumPrice = 700, VolatilityBasisPoints = 410, IssuedSupply = 60000000, TreasuryInventory = 49000000, }, { Id = "spark", Symbol = "SPK", Name = "Spark", Color = "#ffb84d", Logo = "✹", InitialPrice = 74, MinimumPrice = 12, MaximumPrice = 420, VolatilityBasisPoints = 430, IssuedSupply = 85000000, TreasuryInventory = 70000000, }, { Id = "pebble", Symbol = "PBL", Name = "Pebble", Color = "#9aa8b8", Logo = "●", InitialPrice = 22, MinimumPrice = 4, MaximumPrice = 160, VolatilityBasisPoints = 470, IssuedSupply = 150000000, TreasuryInventory = 124000000, }, { Id = "nano", Symbol = "NNO", Name = "Nano", Color = "#5bd6ff", Logo = "η", InitialPrice = 9, MinimumPrice = 1, MaximumPrice = 85, VolatilityBasisPoints = 520, IssuedSupply = 260000000, TreasuryInventory = 214000000, }, { Id = "shard", Symbol = "SHD", Name = "Shard", Color = "#70e0d0", Logo = "△", InitialPrice = 5, MinimumPrice = 1, MaximumPrice = 55, VolatilityBasisPoints = 560, IssuedSupply = 420000000, TreasuryInventory = 345000000, }, { Id = "pixel", Symbol = "PXL", Name = "Pixel", Color = "#ff78c8", Logo = "▦", InitialPrice = 3, MinimumPrice = 1, MaximumPrice = 32, VolatilityBasisPoints = 610, IssuedSupply = 700000000, TreasuryInventory = 580000000, }, { Id = "dust", Symbol = "DST", Name = "Dust", Color = "#c4b5a5", Logo = "·", InitialPrice = 1, MinimumPrice = 1, MaximumPrice = 18, VolatilityBasisPoints = 680, IssuedSupply = 1200000000, TreasuryInventory = 990000000, }, }, } -- ============================================================================= -- Server-only configuration -- ============================================================================= if IsDuplicityVersion() then -- ------------------------------------------------------------------------- -- Server secrets -- ------------------------------------------------------------------------- Config.Server = { -- Keep these values private and stable. Changing a pepper invalidates existing app passwords. PasscodePepper = "f626581802800478346266e66414d8e6f2c28050214a593c25901904c162bffe", CrewLinkPasswordPepper = "2751e5729aee4955a529c1a87104b58fbe1d7280b18b66264236028caa06eb47", FlipTokPasswordPepper = "a85ea307680f1205a4fda03be8af18ecf7edf16ffc83450b90cac7e41a9719a7", PicstagramPasswordPepper = "653e41dd19aba5ef750a668ad1886273ba7d0e0420bd5c745748df80a6e22676", } -- ------------------------------------------------------------------------- -- Company directory -- ------------------------------------------------------------------------- Config.Companies = { Enabled = true, PageSize = 20, MaximumPageSize = 50, MaximumOpenRequestsPerSim = 5, MaximumServices = 25, MaximumRequestMedia = 3, SubjectMaxLength = 120, RequestBodyMaxLength = 2000, MessageMaxLength = 2000, ProfileDescriptionMaxLength = 1000, DistrictMaxLength = 80, AddressMaxLength = 160, ServiceTitleMaxLength = 80, ServiceDescriptionMaxLength = 500, ServicePriceMaxLength = 80, AnnouncementTitleMaxLength = 120, AnnouncementBodyMaxLength = 1000, AvailabilityMaximumSeconds = 24 * 60 * 60, AnnouncementMaximumSeconds = 30 * 24 * 60 * 60, RetentionDays = 180, RateLimits = { Read = 120, Search = 60, CreateRequest = 5, Message = 30, RequestAction = 30, Profile = 12, CallAvailability = 30, }, CallRouting = { MaxAttempts = 3, RingSeconds = 10, }, Categories = { "public_services", "vehicles", "transport", }, Statuses = { new = true, assigned = true, in_progress = true, waiting_customer = true, completed = true, cancelled = true, }, AvailabilityStatuses = { available = true, busy = true, closed = true, }, Definitions = { police = { Job = "police", Name = "Los Santos Police Department", Category = "public_services", Public = true, Emergency = true, Verified = true, Icon = "shield", LogoUrl = "https://picsum.photos/seed/companies-police-logo/180/180", Description = "Public safety, emergency response, and police services.", DefaultAvailability = "closed", AcceptsRequests = false, District = "Mission Row", LocationLabel = "Mission Row Police Station", Address = "Mission Row Police Station", Location = vector3(425.1, -979.5, 30.7), ServiceLine = { Number = "911", AutoContact = true, CanCall = true, CanMessage = false, Routing = "round_robin", MinimumGrade = 0, }, Permissions = { WorkQueue = 0, Availability = 1, Assign = 2, Profile = 3, Hours = 3, Services = 3, Announcement = 3, }, Services = {}, }, ambulance = { Job = "ambulance", Name = "Emergency Medical Services", Category = "public_services", Public = true, Emergency = true, Verified = true, Icon = "medical", LogoUrl = "https://picsum.photos/seed/companies-ems-logo/180/180", Description = "Emergency medical response and patient care.", DefaultAvailability = "closed", AcceptsRequests = false, District = "Pillbox Hill", LocationLabel = "Pillbox Hill Medical Center", Address = "Pillbox Hill Medical Center", Location = vector3(307.2, -595.3, 43.3), ServiceLine = { Number = "912", AutoContact = true, CanCall = true, CanMessage = false, Routing = "round_robin", MinimumGrade = 0, }, Permissions = { WorkQueue = 0, Availability = 1, Assign = 2, Profile = 3, Hours = 3, Services = 3, Announcement = 3, }, Services = {}, }, fire = { Job = "fire", Name = "Los Santos Fire Department", Category = "public_services", Public = true, Emergency = true, Verified = true, Icon = "flame", LogoUrl = "https://picsum.photos/seed/companies-fire-logo/180/180", Description = "Fire response, rescue, and public safety services.", DefaultAvailability = "closed", AcceptsRequests = false, District = "El Burro Heights", LocationLabel = "Capital Boulevard Fire Station", Address = "Capital Boulevard Fire Station", Location = vector3(1200.6, -1473.6, 34.9), ServiceLine = { Number = "913", AutoContact = true, CanCall = true, CanMessage = false, Routing = "round_robin", MinimumGrade = 0, }, Permissions = { WorkQueue = 0, Availability = 1, Assign = 2, Profile = 3, Hours = 3, Services = 3, Announcement = 3, }, Services = {}, }, mechanic = { Job = "mechanic", Name = "Los Santos Customs", Category = "vehicles", Public = true, Emergency = false, Verified = true, Icon = "wrench", LogoUrl = "https://picsum.photos/seed/companies-mechanic-logo/180/180", Description = "Vehicle diagnostics, repairs, and roadside assistance.", DefaultAvailability = "closed", AcceptsRequests = true, District = "Burton", LocationLabel = "Los Santos Customs", Address = "Carcer Way", Location = vector3(-337.3, -136.9, 39.0), ServiceLine = { Number = "5550101000", AutoContact = true, CanCall = true, CanMessage = false, Routing = "round_robin", MinimumGrade = 0, }, Permissions = { WorkQueue = 0, Availability = 1, Assign = 2, Profile = 3, Hours = 3, Services = 3, Announcement = 3, }, Services = { { Id = "mechanic-repair", Title = "Vehicle repair", Description = "Diagnostics and repairs for road vehicles.", Price = "Price after inspection", RequestsEnabled = true, }, { Id = "mechanic-towing", Title = "Roadside assistance", Description = "Assistance for disabled vehicles.", Price = "Price by distance", RequestsEnabled = true, }, }, }, taxi = { Job = "taxi", Name = "Downtown Cab Co.", Category = "transport", Public = true, Emergency = false, Verified = true, Icon = "car", LogoUrl = "https://picsum.photos/seed/companies-taxi-logo/180/180", Description = "Staffed taxi rides throughout Los Santos and Blaine County.", DefaultAvailability = "closed", AcceptsRequests = true, District = "East Vinewood", LocationLabel = "Downtown Cab Co.", Address = "Tangerine Street", Location = vector3(895.0, -179.2, 74.7), ServiceLine = { Number = "5550102000", AutoContact = true, CanCall = true, CanMessage = false, Routing = "round_robin", MinimumGrade = 0, }, Permissions = { WorkQueue = 0, Availability = 1, Assign = 2, Profile = 3, Hours = 3, Services = 3, Announcement = 3, }, Services = { { Id = "taxi-ride", Title = "Taxi ride", Description = "Request a staffed taxi service.", Price = "Metered fare", RequestsEnabled = true, }, }, }, }, } -- ------------------------------------------------------------------------- -- Music library -- ------------------------------------------------------------------------- Config.Music = { -- Files are found recursively in config/music by their Id. For example, -- Id = "night-drive" finds night-drive.ogg/mp3 and optional artwork with -- the same name (.webp/.png/.jpg/.jpeg), even inside subdirectories. Tracks = { -- { -- Id = "night-drive", -- Title = "Night Drive", -- Artist = "Sky Records", -- }, }, MaximumPersonalSongs = 100, MaximumPlaylists = 50, MaximumPlaylistSongs = 250, PlaylistNameMaxLength = 80, ActionsPerMinute = 30, MetadataTimeoutMs = 4500, } -- ------------------------------------------------------------------------- -- Weazel News -- ------------------------------------------------------------------------- Config.WeazelNews = { Enabled = true, PageSize = 20, MaximumOffset = 10000, MaximumImages = 6, SearchMaxLength = 80, DraftTitleMinLength = 1, DraftBodyMinLength = 1, TitleMinLength = 1, TitleMaxLength = 160, BodyMinLength = 1, BodyMaxLength = 12000, ExcerptMaxLength = 240, RateLimits = { Read = 120, Write = 20, }, Categories = { "official", "events", "jobs", "news", "business", }, -- Framework job name = minimum grade. Every listed job can manage every article. AllowedJobs = { weazel = 0, reporter = 0, }, } -- ------------------------------------------------------------------------- -- CityWarn population warnings -- ------------------------------------------------------------------------- Config.CityWarn = { Enabled = true, PageSize = 30, MaximumActiveAlerts = 20, TitleMaxLength = 120, BodyMaxLength = 2000, InstructionsMaxLength = 2000, UpdateMaxLength = 2000, AreaLabelMaxLength = 120, MinimumRadius = 100, MaximumRadius = 10000, DefaultDurationMinutes = 60, MaximumDurationMinutes = 1440, RequireDuty = true, RateLimits = { Read = 180, Write = 20, }, Publishers = { police = { MinimumGrade = 2, MaximumSeverity = "extreme", CityWide = true, Categories = { "public_safety", "police", "infrastructure", "evacuation" }, }, fire = { MinimumGrade = 2, MaximumSeverity = "extreme", CityWide = true, Categories = { "public_safety", "fire", "infrastructure", "evacuation" }, }, ambulance = { MinimumGrade = 2, MaximumSeverity = "danger", CityWide = false, Categories = { "public_safety", "medical", "evacuation" }, }, government = { MinimumGrade = 2, MaximumSeverity = "extreme", CityWide = true, Categories = { "public_safety", "police", "fire", "medical", "infrastructure", "evacuation" }, }, }, } -- ------------------------------------------------------------------------- -- Database migrations -- ------------------------------------------------------------------------- Config.Migrations = Config.Migrations or {} -- Manual, non-destructive import from LB Phone's `phone_*` database tables. -- The migration never starts during a resource/server restart. Completed -- domains are recorded in `sky_phone_migrations` for idempotent retries. -- Import: skyphone:migrate lb-phone -- Console preview: skyphone:migrate lb-phone dry -- Idempotent retry: skyphone:migrate lb-phone force -- Remove imported Sky data: skyphone:migrate lb-phone remove Config.Migrations.LbPhone = { SourcePrefix = "phone_", -- auto: direct framework identifier first, then an unambiguous license match. -- identifier: only match phone_phones.owner_id to the framework identifier. -- license: only resolve phone_phones.owner_id through the framework license. IdentifierMode = "auto", Domains = { devices = true, settings = true, alarms = true, contacts = true, blocked = true, calls = true, messages = true, photos = true, notes = true, wallet = true, voiceMemos = true, picstagram = true, mail = true, mapMarkers = true, darkChat = true, flipTok = true, feather = true, flare = true, }, } end