Files
sky_phone/sky_phone/config/config.lua
T

1484 lines
45 KiB
Lua

--[[
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.SkyPic = {
PageSize = 30,
ThreadPageSize = 200,
InboxPageSize = 100,
SuggestionLimit = 20,
SearchLimit = 30,
HandleMinLength = 3,
HandleMaxLength = 24,
DisplayNameMaxLength = 40,
BioMaxLength = 160,
MessageMaxLength = 2000,
CaptionMaxLength = 160,
OverlayTextMaxLength = 160,
MinimumViewSeconds = 1,
MaximumViewSeconds = 10,
MaximumSnapRecipients = 20,
MaximumMediaPerSend = 10,
MaximumSnapMessagesPerSend = 40,
MaximumFriends = 500,
MaximumPendingRequests = 100,
MaximumActiveStories = 50,
UnopenedSnapLifetimeSeconds = 30 * 24 * 60 * 60,
ReplayWindowSeconds = 5 * 60,
TextAfterReadLifetimeSeconds = 24 * 60 * 60,
StoryLifetimeSeconds = 24 * 60 * 60,
CleanupIntervalSeconds = 45,
ProfileActionsPerMinute = 10,
ReadActionsPerMinute = 120,
SearchActionsPerMinute = 30,
FriendActionsPerMinute = 30,
MessagesPerMinute = 30,
SnapsPerMinute = 20,
SnapRecipientsPerMinute = 120,
OpensPerMinute = 120,
StoriesPerMinute = 6,
StoryViewsPerMinute = 120,
}
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