Files
sky_phone-sky-systems/sky_phone/source/shared/config_default.lua
T
2026-08-22 19:48:30 +02:00

1606 lines
49 KiB
Lua

-- GENERATED by frontend/build.cjs from config/config.lua and config/media.lua - do not edit.
-- Escrowed snapshot of the shipped defaults used by the Phone Configurator.
local realConfig = Config
Config = {}
--[[
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
-- auto, ak47, codem, core, jaksam, jpr, lj, mf, one, origen, ox, ps, qb, qs, smx, tgiann, hex, esx
-- Compatibility aliases: qb-inv -> qb, qbox -> ox
Inventory = "auto",
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; forced false for metadata-free inventories
Keybind = "F1", -- false disables the configurable phone key mapping
OpenRequestsPerMinute = 20,
AllowMovement = true, -- true: game input stays active while the mobile phone is open
HoldToLook = {
Enabled = true, -- hold the configured control to hide the cursor and look around; independent of AllowMovement
Control = 19, -- INPUT_CHARACTER_WHEEL (Left Alt by default)
},
DevelopmentCommand = true,
DeviceName = "iFruit Phone",
}
-- Server-wide availability for bundled apps. Set an entry to false to hide it
-- from every phone, the App Store and per-device app management.
Config.Apps = {
["app-store"] = true,
banking = true,
billing = true,
calculator = true,
calendar = true,
camera = true,
citymarkt = true,
citywarn = true,
clock = true,
companies = true,
crewlink = true,
crypto = true,
darkchat = true,
feather = true,
flare = true,
fliptok = true,
garage = true,
health = true,
house = true,
["local-pages"] = true,
mail = true,
map = true,
memory = true,
memos = true,
messages = true,
minesweeper = true,
music = true,
["neon-drop"] = true,
notes = true,
["number-merge"] = true,
phone = true,
photos = true,
picstagram = true,
radio = true,
settings = true,
["sky-flappy"] = true,
skyride = true,
snake = true,
["tower-stack"] = true,
weather = true,
["weazel-news"] = true,
}
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
}
Config.CustomApps = {
Enabled = true,
BundledApps = true,
ExternalApps = true,
Debug = false, -- 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,
TrustedAdapters = {},
}
Config.Security = {
MaximumAttempts = 5,
LockSeconds = 30,
AttemptsPerMinute = 12,
}
Config.AdminPanel = {
Enabled = true,
Command = "phonepanel",
MaximumPlayers = 128,
ReadRequestsPerMinute = 60,
ActionRequestsPerMinute = 30,
CredentialRevealsPerMinute = 6,
AuditLimit = 40,
ActivityLimit = 40,
}
Config.Sim = {
Enabled = true, -- false: devices receive a persistent random number automatically; forced false for metadata-free inventories
RegisteredItem = "sky_phone_sim_registered",
AnonymousItem = "sky_phone_sim_anonymous",
NumberLength = 10, -- total number of digits, including NumberPrefix
NumberPrefix = "", -- digits only; use "555", not "555-"
NumberGroups = { 3, 3, 4 }, -- display groups separated by spaces
}
-- =============================================================================
-- Calls, voice and radio
-- =============================================================================
Config.Speaker = {
Enabled = true, -- global phone and radio speaker controls
}
Config.Calls = {
VoiceProvider = "pma", -- auto, 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,
CleanupBatchSize = 250,
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",
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",
}
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
--[[
Sky Phone media configuration
This file is loaded on the server only. Keep API keys private. When the
phone configurator is enabled in config.lua, the active media configuration
is loaded from SQL and frontend builds copy the shipped values from this
file into source/shared/config_default.lua.
]]
Config.Media = {
-- Create or sign in to an account at https://developers.giphy.com/, open
-- the Developer Dashboard, choose "Create an API Key", and paste it here.
GiphyApiKey = "",
GifPageSize = 24,
GifRating = "pg-13",
UrlMaxLength = 2048,
AllowedGifHosts = { "giphy.com" },
-- Create or sign in at https://fivemanage.com/, create or select your team,
-- then open Dashboard > Tokens and create a token with Media access. Keep
-- this server-only token private and paste it here.
FiveManage = {
ApiKey = "",
BaseUrl = "https://api.fivemanage.com/api/v3/file",
RequestTimeoutMs = 10000,
UploadTimeoutMs = 25000,
},
Import = {
Enabled = true,
PageSize = 30,
MaxSelection = 10,
MaxPhotoBytes = 15 * 1024 * 1024,
MaxVideoBytes = 150 * 1024 * 1024,
RevalidateAfterSeconds = 3600,
ListActionsPerMinute = 60,
ImportActionsPerMinute = 20,
CandidateTtlSeconds = 300,
ManifestCacheSeconds = 30,
ManifestMaxBytes = 2 * 1024 * 1024,
ManifestMaxItems = 5000,
Websites = {
{
Id = "fivemanage",
Label = "FiveManage",
Enabled = true,
Adapter = "fivemanage",
Path = "sky_phone/imports",
MediaTypes = { "photo", "video" },
-- Direct Gallery links must use one of these hosts or a subdomain.
AllowedMediaHosts = { "fivemanage.com" },
},
--[[
{
Id = "city_media",
Label = "City Media",
Enabled = true,
Adapter = "manifest",
ManifestUrl = "https://media.example.com/sky-phone/media.json",
MediaTypes = { "photo", "video" },
AllowedMediaHosts = { "media.example.com", "cdn.example.com" },
Auth = {
Type = "bearer",
TokenConvar = "sky_phone_city_media_token",
},
RequiredAce = "sky_phone.import.city_media",
},
]]
},
},
Wallpaper = {
-- Shows the verified HTTPS media import directly in the wallpaper picker.
-- Camera and Photos wallpaper sources are not affected by this setting.
CustomUploadEnabled = true,
},
Photo = {
Encoding = "jpg",
Quality = 0.95,
},
Video = {
BitrateKbps = 1500,
},
UploadSessionTimeoutMs = 60000,
PageSize = 30,
}
ConfigDefaults = Config
Config = realConfig