{
	"title": "ODK project live config template",
	"type": "object",
	"properties": {
		"ODK": {
			"type": "object",
			"description": "Live config for ODK features",
			"properties": {
				"Event": {
					"type": "object",
					"description": "Information related to the current event.",
					"properties": {
						"Name": {
							"type": "string",
							"default": "ODK Event",
							"description": "The name of the current event."
						}
					}
				},
				"AvatarSelector": {
					"type": "object",
					"description": "Settings related to BPC_AvatarSelector (now deprecated)",
					"properties": {
						"Enabled": {
							"type": "boolean",
							"default": false,
							"description": "If true, the avatar selector widget will be available."
						},
						"ShowOnStartupIfDefaultAvatar": {
							"type": "boolean",
							"default": false,
							"description": "If true, the avatar selector widget will be opened on begin play."
						},
						"AllowListCollectionContractsArray": {
							"type": "array",
							"items": {
								"type": "string"
							},
							"default": [],
							"description": "If not empty, only contracts in this list will be shown in the avatar selector."
						}
					}
				},
				"ScreenshotCam": {
					"type": "object",
					"description": "Settings related to BPC_ODKCamComponent",
					"properties": {
						"Enabled": {
							"type": "boolean",
							"default": true,
							"description": "If true, the selfie cam key binding will be active."
						},
						"UploadAfterSave": {
							"type": "boolean",
							"default": true,
							"description": "If true, the screenshot will be automatically uploaded after it is saved."
						},
						"MintScreenshotOnUpload": {
							"type": "boolean",
							"default": true,
							"description": "If true, the screenshot will minted into an NFT automatically when uploaded."
						},
						"MovementModes": {
							"type": "object",
							"description": "Enable/Disable Selfie Camera based on movement modes",
							"properties": {
								"AllowDuringGliding": {
									"type": "boolean",
									"default": false,
									"description": "If true, the screenshot camera can be used when in gliding mode."
								},
								"AllowDuringGrinding": {
									"type": "boolean",
									"default": false,
									"description": "If true, the screenshot camera can be used when in grinding mode."
								}
							}
						},
						"FadeCameraBetweenModes": {
							"type": "boolean",
							"default": true,
							"description": "If true, the camera will fade to black briefly between camera modes."
						},
						"NearClipPlane": {
							"type": "number",
							"default": 3.0,
							"minimum": 2.0,
							"maximum": 12.0,
							"description": "Near clip plane of the Selfie Camera. Project default is usually 10, a setting above this will clip more of the character mesh, further from the camera. For example, a value of 20 will likely cull the head of the character."
						},
						"SnapshotCooldown": {
							"type": "number",
							"default": 3.0,
							"description": "The time between snapshots to prevent user spamming."
						},
						"ScreenshotResolution": {
							"type": "object",
							"description": "Resolution of the saved and uploaded image.",
							"properties": {
								"x": {
									"type": "number",
									"default": 1280,
									"minimum": 64.0,
									"maximum": 4096.0,
									"description": "Horizontal resolution."
								},
								"y": {
									"type": "number",
									"default": 720,
									"minimum": 64.0,
									"maximum": 4096.0,
									"description": "Vertical resolution."
								}
							}
						},
						"ZoomRange": {
							"type": "object",
							"description": "Zoom range of the camera actors. Default focal length is 10, the higher the number the closer the camera appears",
							"properties": {
								"min": {
									"type": "number",
									"default": 3,
									"minimum": 3,
									"maximum": 20,
									"description": "Minimum focal length."
								},
								"max": {
									"type": "number",
									"default": 20,
									"minimum": 10,
									"maximum": 30,
									"description": "Maximum focal length."
								}
							}
						},
						"CameraAperture": {
							"type": "number",
							"default": 8,
							"minimum": 1.8,
							"maximum": 40.0,
							"description": "Aperture of the screenshot camera. The lower the number, the more background blur."
						},
						"FirstPersonCam": {
							"type": "object",
							"description": "Settings related to the SelfieCam actor",
							"properties": {
								"InvertYAxis": {
									"type": "boolean",
									"default": false,
									"description": "If true, the first person cam key Mouse/Gamepad Y axis will be inverted."
								},
								"CameraRotationOffset": {
									"type": "object",
									"description": "Relative location offset to fine tune the camera location, offset from the hand socket.",
									"properties": {
										"x": {
											"type": "number",
											"default": 0.0,
											"description": "Rotation offset in x."
										},
										"y": {
											"type": "number",
											"default": 0.0,
											"description": "Rotation offset in x."
										},
										"z": {
											"type": "number",
											"default": 0.0,
											"description": "Rotation offset in x."
										}
									}
								},
								"CameraLocationOffset": {
									"type": "object",
									"description": "Relative location offset to fine tune the camera location, offset from the hand socket.",
									"properties": {
										"x": {
											"type": "number",
											"default": 0.0,
											"description": "Rotation offset in x."
										},
										"y": {
											"type": "number",
											"default": 30.0,
											"description": "Rotation offset in x."
										},
										"z": {
											"type": "number",
											"default": 0.0,
											"description": "Rotation offset in x."
										}
									}
								}
							}
						},
						"SelfieCam": {
							"type": "object",
							"description": "Settings related to the SelfieCam actor",
							"properties": {
								"InvertYAxis": {
									"type": "boolean",
									"default": false,
									"description": "If true, the selfie cam key Mouse/Gamepad Y axis will be inverted."
								},
								"CameraRotationOffset": {
									"type": "object",
									"description": "Relative location offset to fine tune the camera location, offset from the hand socket.",
									"properties": {
										"x": {
											"type": "number",
											"default": 0.0,
											"description": "Rotation offset in x."
										},
										"y": {
											"type": "number",
											"default": -15.0,
											"description": "Rotation offset in x."
										},
										"z": {
											"type": "number",
											"default": 0.0,
											"description": "Rotation offset in x."
										}
									}
								},
								"CameraLocationOffset": {
									"type": "object",
									"description": "Relative location offset to fine tune the camera location, offset from the hand socket.",
									"properties": {
										"x": {
											"type": "number",
											"default": -5.0,
											"description": "Rotation offset in x."
										},
										"y": {
											"type": "number",
											"default": -5.0,
											"description": "Rotation offset in x."
										},
										"z": {
											"type": "number",
											"default": -15.0,
											"description": "Rotation offset in x."
										}
									}
								},
								"SelfieStickArmLengthThreshold": {
									"type": "number",
									"default": 40.0,
									"description": "The threshold for arm length before the selfie stick is utilised. For reference, a Koda has an arm length of around 36 units, a voyager has an arm lenth around 54 units"
								},
								"SelfieStickCameraRotationOffset": {
									"type": "object",
									"description": "Relative location offset to fine tune the camera location, offset from the hand socket.",
									"properties": {
										"x": {
											"type": "number",
											"default": 0.0,
											"description": "Rotation offset in x."
										},
										"y": {
											"type": "number",
											"default": 0.0,
											"description": "Rotation offset in x."
										},
										"z": {
											"type": "number",
											"default": 0.0,
											"description": "Rotation offset in x."
										}
									}
								},
								"SelfieStickCameraLocationOffset": {
									"type": "object",
									"description": "Relative location offset to fine tune the camera location, offset from the hand socket.",
									"properties": {
										"x": {
											"type": "number",
											"default": 0.0,
											"description": "Rotation offset in x."
										},
										"y": {
											"type": "number",
											"default": 0.0,
											"description": "Rotation offset in x."
										},
										"z": {
											"type": "number",
											"default": 0.0,
											"description": "Rotation offset in x."
										}
									}
								},
								"Sensitivity": {
									"type": "number",
									"default": 1.0,
									"description": "Selfie cam camera sensitivity."
								},
								"AlignPawnToCameraRotation": {
									"type": "boolean",
									"default": true,
									"description": "If true, the character will rotate so that the selfie cam is looking in the same direction as the original camera."
								}
							}
						},
						"OrbitCam": {
							"type": "object",
							"description": "Settings related to the SelfieCam actor",
							"properties": {
								"Sensitivity": {
									"type": "number",
									"default": 1.0,
									"description": "Selfie cam camera sensitivity."
								}
							}
						}
					}
				},
				"Collections": {
					"type": "object",
					"description": "Settings related to Project specific Collections",
					"properties": {
						"AllowImageUpload": {
							"type": "boolean",
							"default": true,
							"description": "If true, image upload will be enabled for create datasource objects."
						}
					}
				},
				"EditorVariables": {
					"type": "object",
					"description": "Debug/In-Editor only values",
					"properties": {
						"MuteMillicastInEditor": {
							"type": "boolean",
							"default": false,
							"description": "If true, Millicast screens will be muted when playing in editor."
						}
					}
				},
				"GucciTrail": {
					"type": "object",
					"description": "Settings related to Gucci trails.",
					"properties": {
						"EnableOnClients": {
							"type": "boolean",
							"default": true,
							"description": "If true, trails will be given to players owning the gucci NFTs."
						},
						"ForceLoadOnBots": {
							"type": "boolean",
							"default": false,
							"description": "If true, all bots will be given gucci trails."
						},
						"CollectionName": {
							"type": "string",
							"default": "KodaPendant",
							"description": "The collection name to check for to enable gucci trails"
						}
					}
				},
				"Train": {
					"type": "object",
					"description": "Train debugging",
					"properties": {
						"AllowPitchAdjustment": {
							"type": "boolean",
							"default": true,
							"description": "If true, the train will change pitch."
						},
						"AllowHeightAdjustment": {
							"type": "boolean",
							"default": true,
							"description": "If true, the train will change pitch."
						},
						"DebugSpeed": {
							"type": "number",
							"default": 1.0,
							"description": "Speed multiplier for debugging."
						}
					}
				},
				"Bubbles": {
					"type": "object",
					"description": "Bubbles related settings.",
					"properties": {
						"Enabled": {
							"type": "boolean",
							"description": "This boolean enables/disables the Bubbles Feature.",
							"default": true
						},
						"UseUsernameForRoomNames": {
							"type": "boolean",
							"description": "If false, users can enter custom room names. If true, rooms will be named <UserName>'s Bubble.",
							"default": true
						},
						"Logging": {
							"type": "boolean",
							"description": "If false, LogBubbles macros will disabled in development builds.",
							"default": false
						},
						"UseShortDeeplinkURL": {
							"type": "boolean",
							"description": "If true, when generating a deeplink replaces 'project', 'world', and 'intent' with 'p', 'w', and 'i', to help mitigate GFN's 128 char limit for opening URLs. This should be on unless the webapp does not support these short keys.",
							"default": false
						},
						"MaxBubbleCapacity": {
							"type": "number",
							"description": "The maximum capacity allowed for bubbles. Minimum value of 1.",
							"minimum": 1.0,
							"default": 500.0
						},
						"MaxRoomNameCharacters": {
							"type": "number",
							"description": "The maximum number of characters allowed in a room name.",
							"minimum": 10.0,
							"default": 24
						},
						"OwnerSpeed": {
							"type": "number",
							"description": "The movement speed of the owner of a Bubble.",
							"minimum": 0.0,
							"default": 175
						},
						"ParticipantSpeed": {
							"type": "number",
							"description": "The movement speed of participants in a Bubble.",
							"minimum": 0.0,
							"default": 130
						},
						"PlayerDensityPerMeter": {
							"type": "number",
							"description": "The amount of space awarded each participant in a bubble. Affects radius of Bubbles.",
							"minimum": 0.01,
							"default": 0.1
						},
						"AudienceSphereCoverage": {
							"type": "number",
							"description": "The percentage of the sphere around which users will wrap. Affects radius of Bubbles.",
							"minimum": 0.01,
							"maximum": 1.0,
							"default": 0.4
						},
						"PlayerPushbackRadius": {
							"type": "number",
							"description": "Players will use this radius to push themselves away from other players.",
							"minimum": 0.0,
							"default": 50.0
						},
						"UseLegacySeatAssignment": {
							"type": "boolean",
							"description": "If enabled, uses the old seat-index assignment method. This prevents players swapping about to fill gaps, but does not protect against bubbles shrinking in size and indexes becoming invalid. Note: This must be applied BEFORE players join the deployment. It cannot be set at runtime.",
							"default": false
						},
						"MovementMode": {
							"type": "object",
							"description": "Container for movement mode settings.",
							"properties": {
								"Free": {
									"type": "object",
									"description": "Container for 'free' movement settings.",
									"properties": {
										"Speed": {
											"type": "number",
											"description": "Speed at which participants can move about in this movement mode.",
											"default": 130.0
										},
										"SpeakerMinRadius": {
											"type": "number",
											"description": "The minimum radius % a Speaker can move to.",
											"minimum": 0.0,
											"maximum": 1.0,
											"default": 0.0
										},
										"SpeakerMaxRadius": {
											"type": "number",
											"description": "The maximum radius % a Speaker can move to.",
											"minimum": 0.0,
											"maximum": 1.0,
											"default": 0.6
										},
										"ListenerMinRadius": {
											"type": "number",
											"description": "The minimum radius % a Listenercan move to.",
											"minimum": 0.0,
											"maximum": 1.0,
											"default": 0.7
										},
										"ListenerMaxRadius": {
											"type": "number",
											"description": "The maximum radius % a Listener can move to.",
											"minimum": 0.0,
											"maximum": 1.0,
											"default": 0.85
										},
										"OwnerRepulsionRadius": {
											"type": "number",
											"description": "The radius around the owner of the Bbubble into which participants cannot move.",
											"minimum": 0.0,
											"default": 300.0
										}
									}
								},
								"Fixed": {
									"type": "object",
									"description": "Container for 'fixed' movement settings.",
									"properties": {
										"ListenerScale": {
											"type": "string",
											"description": "Vector string. Scale applied to fixed positions for Listeners.",
											"default": "(X=0.85,Y=1.0,Z=1.0)"
										},
											"SpeakerScale": {
											"type": "string",
											"description": "Vector string. Scale applied to fixed positions for Speakers.",
											"default": "(X=0.85,Y=1.0,Z=0.5)"
										}
									}
								},
								"Owner": {
									"type": "object",
									"description": "Container for 'owner' settings.",
									"properties": {
										"Speed": {
											"type": "number",
											"description": "Speed at which the owner can move the Bubble about.",
											"default": 175.0
										}
									}
								}
							}
						},
						"Bots": {
							"type": "object",
							"description": "Bot settings for Bubbles.",
							"properties": {
								"WaitMin": {
									"type": "number",
									"description": "The minimum length of time between attempted bot actions.",
									"minimum": 1.0,
									"maximum": 60.0,
									"default": 5.0
								},
								"WaitMax": {
									"type": "number",
									"minimum": 1.0,
									"maximum": 60.0,
									"description": "The maximum length of time between attempted bot actions.",
									"default": 15.0
								},
								"ChanceToCreate": {
									"type": "number",
									"description": "(If Not In Bubble) Chance a bot will create a Bubble if not in one.",
									"default": 0.1
								},
								"ChanceToCreatePrivate": {
									"type": "number",
									"description": "(If ChanceToCreate succeeds) Chance a bot will create a private Bubble when creating one.",
									"default": 0.1
								},
								"ChanceToJoin": {
									"type": "number",
									"description": "(If Not In Bubble) Chance a bot will join a Bubble if not in one.",
									"default": 0.1
								},
								"ChanceToJoinPrivate": {
									"type": "number",
									"description": "(If ChanceToJoin succeeds) Chance a bot will try and join a private Bubble if not in one.",
									"default": 0.1
								},
								"ChanceToAcceptInvite": {
									"type": "number",
									"description": "(If Not In Bubble) Chance a bot will accept an invite. Will attempt even if no invites extended (in which case it will just fail).",
									"default": 0.5
								},
								"ChanceToLeave": {
									"type": "number",
									"description": "(If Speaker or Listener) Chance a bot will leave a Bubble if in one.",
									"default": 0.1
								},
								"ChanceToEmote": {
									"type": "number",
									"description": "(If Listener) Chance a bot will do an emote in a Bubble.",
									"default": 0.2
								},
								"ChanceToRequestSpeaker": {
									"type": "number",
									"description": "(If Listener) Chance a bot will request Speaker in a Bubble.",
									"default": 0.1
								},
								"ChanceToKick": {
									"type": "number",
									"description": "(If Owner) Chance a Bubble owner bot will kick a user.",
									"default": 0.1
								},								
								"ChanceToEnd": {
									"type": "number",
									"description": "(If Owner) Chance a bot will end a Bubble if an owner.",
									"default": 0.1
								},
								"ChanceToInvite": {
									"type": "number",
									"description": "(If Owner) Chance a Bubble owner bot will invite a user.",
									"default": 0.1
								},
								"ChanceToInviteAsSpeaker": {
									"type": "number",
									"description": "(Requires ChanceToInvite succeeds) Chance a Bubble owner bot will invite a user as a Speaker.",
									"default": 0.1
								},
								"ChanceToAcceptAccessChangeRequest": {
									"type": "number",
									"description": "(If Owner) Chance a Bubble owner bot will accept a Speaker access request.",
									"default": 0.1
								},
								"ChanceToAcceptJoinRequest": {
									"type": "number",
									"description": "(If Owner) Chance a Bubble owner bot will accept a request to join.",
									"default": 0.1
								},
								"ChanceToAcceptJoinRequestAsSpeaker": {
									"type": "number",
									"description": "(If ChanceToAcceptJoinRequest succeeds) Chance a Bubble owner bot will accept a request to join as a Speaker.",
									"default": 0.1
								}
							}
						}
					}
				},
				"CoopEmotes": {
					"type": "object",
					"description": "CoopEmotes related settings.",
					"properties": {
						"Enabled": {
							"type": "boolean",
							"description": "This boolean enables/disables the Coop Emotes Feature.",
							"default": true
						},
						"OnChainEnabled": {
							"type": "boolean",
							"description": "Requires coop emotes to be onchain before they can be used. This is a temporary feature to test onchain emotes.",
							"default": true
						}
					}
				},
				"Emotes": {
					"type": "object",
					"description": "Emote related settings.",
					"properties": {
						"Favourites": {
							"type": "object",
							"description": "Emote Favourite settings.",
							"properties": {
								"Enabled": {
									"type": "boolean",
									"default": false,
									"description": "Enable saving favourites in the emote wheel."
								}
							}
						}
					}
				},
				"Attachments": {
					"type": "object",
					"description": "Settings related to Avatar attachments",
					"properties": {
						"AttachmentListAssets": {
							"type": "array",
							"items": {
								"type": "string"
							},
							"default": [
								"/ODK/Blueprints/Attachments/DA_AttachmentList_KodaCam.DA_AttachmentList_KodaCam"
							],
							"description": "A list of PDA_AttachmentList assets to propogate the AttachmentManager"
						}
					}
				},
				"Revocation": {
					"type": "object",
					"description": "Settings related to recoking access to features",
					"properties": {
						"RevertAvatarOnLossOfOwnership": {
							"type": "boolean",
							"default": true,
							"description": "If enabled, the player's avatar will be reset when they lose ownership of the avatar"
						},
						"KickPlayerOnLossOfWorldAccess": {
							"type": "boolean",
							"default": true,
							"description": "If enabled, the player will be kicked from the game if access is revoked"
						}
					}
				},
				"WebBrowser": {
					"type": "object",
					"description": "Settings related to web browser features",
					"properties": {
						"Enabled": {
							"type": "boolean",
							"default": true,
							"description": "Enables the web browser interface"
						},
						"WidgetDelayOnUrlLoad": {
							"type": "number",
							"default": 1.4,
							"description": "The delay in seconds before the web browser widget is shown after a URL is loaded"
						},
						"WidgetDelayOnUrlQuickLoad": {
							"type": "number",
							"default": 0.7,
							"description": "The delay in seconds before the web browser widget is shown after a URL is quick loaded"
						},
						"ActivateAnimationSpeed": {
							"type": "number",
							"default": 4.0,
							"description": "The speed of the activate animation for the web browser widget"
						},
						"DeactivateAnimationSpeed": {
							"type": "number",
							"default": 4.0,
							"description": "The speed of the activate animation for the web browser widget"
						},
						"BaseURL": {
							"type": "string",
							"default": "https://o7e.dev",
							"description": "The base URL for the web browser widget"
						},
						"ReadyResponseTimeout": {
							"type": "number",
							"default": 15.0,
							"description": "Amount of time to allow browser to send 'ready' response back to client before registering open url as a failure"
						},
						"ShowBrowserOnFailure": {
							"type": "boolean",
							"default": true,
							"description": "If initial overlay load fails, show web browser anyway to help debug errors"
						},
						"ProfileShowAllTabs": {
							"type": "boolean",
							"default": true,
							"description": "If the self overlay should show all tabs (include quests + travel) or just the base set"
						}
					}
				},
				"Sprays": {
					"type": "object",
					"description": "Settings related to a users wallet",
					"properties": {
						"Enabled": {
							"type": "boolean",
							"default": true,
							"description": "If enabled, players can spray images onto the world. Will also remove all sprays from the world but not from persistence."
						},
						"ClearPersistence": {
							"type": "boolean",
							"default": true,
							"description": "If enabled, will trigger the removal of all sprays in the world and the deletion of the persistence data."
						},
						"MaxSpraysInWorld": {
							"type": "number",
							"default": 2000.0,
							"description": "The maximum number of sprays that can exist in the world. Older sprays will be replaced by newer ones."
						},
						"MaxSpraysPerPlayer": {
							"type": "number",
							"default": 8.0,
							"description": "The maximum number of sprays a single player can put down. Older sprays will be replaced by newer ones."
						},
						"Duration": {
							"type": "number",
							"default": 604800.0,
							"description": "Duration in seconds that a spray will stay in the world"
						}
					}
				},
				"Wallet": {
					"type": "object",
					"description": "Settings related to a users wallet",
					"properties": {
						"ShowWalletNotifications": {
							"type": "boolean",
							"default": true,
							"description": "If enabled, use the quick load feature for the web browser"
						},
						"SocketKeepAliveTimer": {
							"type": "number",
							"default": 60.0,
							"description": "The time in seconds between keep alive messages to the wallet web sockets"
						},
						"PrintBalanceUpdateEvents": {
							"type": "boolean",
							"default": false,
							"description": "If enabled, print wallet events to the console"
						},
						"UseDeltaMode": {
							"type": "boolean",
							"default": true,
							"description": "If websocket deltas should be used"
						},
						"Contracts": {
							"type": "object",
							"description": "Settings related to a users wallet",
							"properties": {
								"Quests": {
									"type": "string",
									"default": "0x4D7AB2eBEe815E5689dbF4f39822Cd0b60D8529f",
									"description": "Contract Address for the Quest tokens. Note: This is project specific."
								},
								"Achievements": {
									"type": "string",
									"default": "0x4D7AB2eBEe815E5689dbF4f39822Cd0b60D8529f",
									"description": "Contract Address for the Achievement tokens. Note: This is project specific."
								},
								"Other": {
									"type": "string",
									"default": "0x9f00f0b42df3bb78524aac644fd53c44e3a36f62",
									"description": "Contract Address for non-registered token types"
								}
							}
						}
					}
				},
				"Quests": {
					"type": "object",
					"description": "Information related to Quests.",
					"properties": {
						"DeuceQuestID": {
							"type": "number",
							"default": 1,
							"description": "The quest ID for the deuce quest."
						},
						"MonitoredQuestGroups": {
							"type": "array",
							"items": {
								"type": "string"
							},
							"default": [
								"whitespace",
								"odk"
							],
							"description": "A list of Quest groups to show on the HUD"
						},
						"AvailableQuests": {
							"type": "array",
							"items": {
								"type": "string"
							},
							"default": [],
							"description": "A list of available quests for the current level"
						}
					}
				},
				"TaskFlows": {
					"type": "object",
					"description": "Information related to Task Flows.",
					"properties": {
						"LoggingEnabled": {
							"type": "boolean",
							"default": true,
							"description": "Whether logging is enabled for task flow system.."
						}
					}
				}
				,
				"Analytics": {
					"type": "object",
					"description": "Information related to Analytics.",
					"properties": {
						"MixpanelProjectToken": {
							"type": "string",
							"default": "",
							"description": "Mixpanel project token. Only valid if using mix panel analytics integration"
						}
					}
				},
				"WorldTravel": {
					"type": "object",
					"description": "Information related to World Travel.",
					"properties": {
						"DefaultWorld": {
							"type": "string",
							"default": "",
							"description": "The default World Name for World Travel. This can be a partial match, for example World123 would match if a world was found called World123abc"
						}
					}
				}
			}
		}
	}
}