-- Consts
local STICK_SELECT = {'Movement', 'Camera', 'Gyro'};
local MODID_SELECT = {'SHIFT', 'CTRL', 'ALT'};
local MODID_EXTEND = {'SHIFT', 'CTRL', 'ALT', 'CTRL-SHIFT', 'ALT-SHIFT', 'ALT-CTRL'};
local STARGET_OPTS = {[0] = OFF, [1] = 'Gamepad', [2] = 'KBM', [3] = ALWAYS};
local BINDINGS_OPT = KEY_BINDINGS_MAC or 'Bindings';

-- Helpers
local BLUE = GenerateClosure(ColorMixin.WrapTextInColorCode, BLUE_FONT_COLOR)
local unpack, _, db = unpack, ...; _ = CPAPI.Define; db.Data();

------------------------------------------------------------------------------------------------------------
-- Variables
------------------------------------------------------------------------------------------------------------
db:Register('Variables', CPAPI.Callable({
	_(GENERAL, SETTING_GROUP_SYSTEM);
	useCharacterSettings = _{Bool(false);
		name = 'Character Specific';
		desc = 'Use character specific addon settings for this character.';
		list = 'ConsolePort';
	};
	actionPageCondition = _{String(nil);
		name = 'Action Page Condition';
		desc = 'Macro condition to evaluate action bar page.';
		hide = true;
	};
	actionPageResponse = _{String(nil);
		name = 'Action Page Response';
		desc = 'Response to condition for custom processing.';
		hide = true;
	};
	classFileOverride = _{String(nil);
		name = 'Override Class File';
		desc = 'Override class theme for interface styling.';
		hide = true;
	};
	--------------------------------------------------------------------------------------------------------
	_('Crosshair', INTERFACE_LABEL);
	--------------------------------------------------------------------------------------------------------
	crosshairEnable = _{Bool(true);
		name = 'Enable';
		desc = 'Enables a crosshair to reveal your hidden center cursor position at all times.';
		note = 'Use together with [@cursor] macros to place reticle spells in a single click.';
	};
	crosshairSizeX = _{Number(24, 1, true);
		name = 'Width';
		desc = 'Width of the crosshair, in scaled pixel units.';
		deps = { crosshairEnable = true };
		advd = true;
	};
	crosshairSizeY = _{Number(24, 1, true);
		name = 'Height';
		desc = 'Height of the crosshair, in scaled pixel units.';
		deps = { crosshairEnable = true };
		advd = true;
	};
	crosshairCenter = _{Number(0.2, 0.05, true);
		name = 'Center Gap';
		desc = 'Center gap, as fraction of overall crosshair size.';
		deps = { crosshairEnable = true };
		advd = true;
	};
	crosshairThickness = _{Number(2, 0.025, true);
		name = 'Thickness';
		desc = 'Thickness in scaled pixel units.';
		note = 'Value below two may appear interlaced or not at all.';
		deps = { crosshairEnable = true };
		advd = true;
	};
	crosshairColor = _{Color('ff00fcff');
		name = 'Color';
		desc = 'Color of the crosshair.';
		deps = { crosshairEnable = true };
	};
	--------------------------------------------------------------------------------------------------------
	_('Movement', SETTING_GROUP_SYSTEM);
	--------------------------------------------------------------------------------------------------------
	mvmtAnalog = _{Bool(true);
		name = 'Analog Movement';
		desc = 'Movement is analog, translated from your movement stick angle.';
		note = 'Disable to use discrete legacy movement controls.';
	};
	mvmtStrafeAngleTravel = _{Range(0, 5, 0, 180);
		name = 'Strafe Angle (Travel)';
		desc = 'Controls when your character transitions from strafing to facing your movement stick direction. Expressed in degrees, from looking straight forward.';
		note = 'When set to zero, always face your movement stick direction.\nWhen set to max, never face your movement stick direction.';
	};
	mvmtStrafeAngleCombat = _{Range(180, 5, 0, 180);
		name = 'Strafe Angle (Combat)';
		desc = 'Controls when your character transitions from strafing to facing your movement stick direction while in combat. Expressed in degrees, from looking straight forward.';
		note = 'When set to zero, always face your movement stick direction.\nWhen set to max, never face your movement stick direction.';
	};
	mvmtRunThreshold = _{Range(db:GetCVar('GamePadRunThreshold', 0.5), 0.05, 0, 1);
		name = 'Run / Walk Threshold';
		desc = 'Controls when your character starts running. Expressed as a fraction of your total movement stick radius.';
	};
	mvmtTurnWithCamera = _{Map(db:GetCVar('GamePadTurnWithCamera', 2), {[0] = NEVER, [1] = 'In Combat', [2] = ALWAYS});
		name = 'Turn Character With Camera';
		desc = 'Turn your character facing when you turn your camera angle.';
	};
	mvmtStrafeAngleTravelMacro = _{String(nil);
		name = 'Strafe Angle Macro Condition (Travel)';
		desc = 'Macro condition to override the strafe angle threshold for travel.';
		note = 'Takes the format of...\n'
			.. BLUE'[condition] angle; nil'
			.. '\n...where each condition/angle is separated by a semicolon, and "nil" clears the override.';
		advd = true;
	};
	mvmtStrafeAngleCombatMacro = _{String(nil);
		name = 'Strafe Angle Macro Condition (Combat)';
		desc = 'Macro condition to override the strafe angle threshold for combat.';
		note = 'Takes the format of...\n'
			.. BLUE'[condition] angle; nil'
			.. '\n...where each condition/angle is separated by a semicolon, and "nil" clears the override.';
		advd = true;
	};
	--------------------------------------------------------------------------------------------------------
	_(BINDING_HEADER_TARGETING, BINDING_HEADER_TARGETING);
	--------------------------------------------------------------------------------------------------------
	trgtEnemy = _{Map(db:GetCVar('SoftTargetEnemy', 0), STARGET_OPTS);
		name = 'Enemy Soft Targeting';
		desc = 'Target enemies automatically by looking at them.';
		note = 'Use a targeting binding to turn a soft target into a hard target.';
	};
	trgtFriend = _{Map(db:GetCVar('SoftTargetFriend', 0), STARGET_OPTS);
		name = 'Friend Soft Targeting';
		desc = 'Target friends automatically by looking at them.';
		note = 'A friendly soft target can be acquired while having an enemy hard target.';
	};
	trgtEnemyTooltip = _{Bool(db:GetCVar('SoftTargetTooltipEnemy', false));
		name = 'Show Enemy Tooltip';
		desc = 'Show tooltip for enemy target.';
	};
	trgtFriendTooltip = _{Bool(db:GetCVar('SoftTargetTooltipFriend', false));
		name = 'Show Friendly Tooltip';
		desc = 'Show tooltip for friendly target.';
	};
	trgtEnemyIcon = _{Bool(db:GetCVar('SoftTargetIconEnemy', false));
		name = 'Show Enemy Target Icon';
		desc = 'Show icon above the current enemy soft target.';
		deps = { trgtEnemy = function(value) return value > 0 end };
	};
	trgtFriendIcon = _{Bool(db:GetCVar('SoftTargetIconFriend', false));
		name = 'Show Friendly Target Icon';
		desc = 'Show icon above the current friendly soft target.';
		deps = { trgtFriend = function(value) return value > 0 end };
	};
	trgtEnemyNameplate = _{Bool(db:GetCVar('SoftTargetNameplateEnemy', true));
		name = 'Show Enemy Nameplate';
		desc = 'Always show nameplate for soft enemy target.';
		deps = { trgtEnemy = function (value) return value > 0 end };
	};
	trgtFriendNameplate = _{Bool(db:GetCVar('SoftTargetNameplateFriend', false));
		name = 'Show Friendly Nameplate';
		desc = 'Always show nameplate for soft friendly target.';
		deps = { trgtFriend = function (value) return value > 0 end };
	};
	trgtForce = _{Map(db:GetCVar('SoftTargetForce', 0), {[0] = OFF, [1] = ENEMY, [2] = FRIEND});
		name = 'Force Hard Target';
		desc = 'Auto-set target to match soft target.';
		advd = true;
	};
	trgtMatchLocked = _{Map(db:GetCVar('SoftTargetMatchLocked', 0), {[0] = OFF, [1] = 'Explicit', [2] = 'Implicit'});
		name = 'Target Match Lock';
		desc = 'Match appropriate soft target to locked target.';
		note = 'Explicit only matches hard locked targets through using a targeting binding, while implicit matches targets you attack.';
		advd = true;
	};
	trgtShowInteractHint = _{Bool(true);
		name = 'Show Interact Hint';
		desc = 'Show interact binding hint on interactables.';
	};
	trgtShowInteractNameplate = _{Bool(true);
		name = 'Use Interact Nameplate Tooltip';
		desc = 'Show interact tooltip on nameplates, when applicable.';
		hide = not CPAPI.IsRetailVersion;
	};
	trgtShowMinimalInteractNamePlate = _{Bool(false);
		name = 'Minimal Interact Nameplate Tooltip';
		desc = 'Removes the tooltip background for a minimalistic look.';
		hide = not CPAPI.IsRetailVersion;
		deps = { trgtShowInteractNameplate = true };
		advd = true;
	};
	--------------------------------------------------------------------------------------------------------
	_(MOUSE_LABEL, SETTING_GROUP_SYSTEM); -- Mouse
	--------------------------------------------------------------------------------------------------------
	mouseHandlingEnabled = _{Bool(true);
		name = 'Enable Mouse Handling';
		desc = 'Enable custom mouse handling, automating cursor toggling and timeout while using left and right mouse button emulation.';
		note = 'While disabled, cursor timeout, and toggling between free-roaming and center-fixed cursor are also disabled.';
		advd = true;
	};
	mouseHandlingReversed = _{Bool(false);
		name = 'Reverse Mouse Handling';
		desc = 'Left mouse button emulation toggles center-fixed mode instead of free-roaming mode. Right mouse button emulation toggles free-roaming mode instead of center-fixed mode.',
		note = 'Combine with '..BLUE(INTERACT_ON_LEFT_CLICK_TEXT)..' to make left click work similarly to right click without risk of unwanted combat engagements.',
		advd = true;
	};
	mouseFreeCursorReticle = _{Map(0, {[0] = OFF, [1] = VIDEO_OPTIONS_ENABLED, [2] = TARGET});
		name = 'Cursor Reticle Targeting';
		desc = 'Reticle targeting uses free cursor instead of staying center-fixed.';
		note = 'Reticle targeting means anything you place on the ground.';
	};
	mouseHideCursorOnMovement = _{Bool(false);
		name = 'Hide Cursor On Movement';
		list = 'Visibility';
		desc = 'Cursor hides when you start moving, if free of obstacles.';
		note = 'Requires Settings > Hide Cursor on Stick Input set to None.';
	};
	mouseAlwaysCentered = _{Bool(false);
		name = 'Always Show Mouse Cursor';
		list = 'Visibility';
		desc = 'Always keep cursor centered and visible when controlling camera.';
	};
	mouseShowCenterTooltip = _{Bool(true);
		name = 'Show Centered Cursor Tooltip';
		desc = 'Show tooltip for mouseover targets when cursor is centered.';
	};
	mouseAutoControlPickup = _{Bool(true);
		name = 'Automatically Control Cursor Pickups';
		desc = 'Automatically control cursor when picking up items.';
		advc = true;
	};
	mouseAutoClearCenter = _{Number(2.0, 0.25, true);
		name = 'Automatic Cursor Timeout';
		desc = 'Time in seconds to automatically hide centered cursor.';
		advd = true;
	};
	mouseFreeCursorEnableTime = _{Number(0.15, 0.05, true);
		name = 'Free Cursor Timein';
		desc = 'Time in seconds to enable free cursor.';
		note = 'Needs to be long enough to press and release the button.';
		advd = true;
	};
	doubleTapTimeout = _{Number(0.25, 0.05, true);
		name = 'Double Tap Timeframe';
		desc = 'Timeframe to toggle the mouse cursor when double-tapping a selected modifier.';
		advd = true;
	};
	doubleTapModifier = _{Select('<none>', '<none>', unpack(MODID_SELECT));
		name = 'Double Tap Modifier';
		list = 'Visibility';
		desc = 'Which modifier to use to toggle the mouse cursor when double-tapped.';
	};
	--------------------------------------------------------------------------------------------------------
	_('Radial Menus', INTERFACE_LABEL);
	--------------------------------------------------------------------------------------------------------
	radialClearFocusMode = _{Map(1, {[1] = 'Either', [2] = 'Timeout', [3] = 'Deadzone'});
		name = 'Clear Focus Mode';
		desc = 'How to clear focus after intercepting stick input.';
		note = 'Timeout clears focus after a set time, deadzone clears focus when stick input is neutral.';
	};
	radialClearFocusTime = _{Number(1.5, 0.025);
		name = 'Clear Focus Time';
		desc = 'Time to clear focus after intercepting stick input, in seconds.';
		deps = { radialClearFocusMode = function(value) return value ~= 3 end };
	};
	radialClearFocusDeadzone = _{Range(0, 0.0025, 0, 0.25);
		name = 'Clear Focus Deadzone';
		desc = 'Deadzone to clear focus after intercepting stick input.';
		deps = { radialClearFocusMode = function(value) return value ~= 2 end };
	};
	radialActionDeadzone = _{Range(0.5, 0.05, 0, 1);
		name = 'Valid Action Deadzone';
		desc = 'Deadzone for simple point-to-select rings.';
	};
	radialCosineDelta = _{Delta(1);
		name = 'Axis Interpretation';
		desc = 'Correlation between stick position and pie selection.';
		note = '+ Normal\n- Inverted';
		advd = true;
	};
	radialPrimaryStick = _{Select('Movement', unpack(STICK_SELECT));
		name = 'Primary Stick';
		desc = 'Stick to use for main radial actions.';
		note = 'Make sure your choice does not conflict with your bindings.';
	};
	radialScale = _{Number(1, 0.025, true);
		name = 'Ring Scale';
		desc = 'Scale of all radial menus, relative to UI scale.';
		advd = true;
	};
	radialPreferredSize = _{Number(400, 25, true);
		name = 'Ring Size';
		desc = 'Preferred size of radial menus, in pixels.';
		advd = true;
	};
	radialNormalColor = _{Color(CPAPI.GetMutedClassColor(0.6, true));
		name = 'Normal Color';
		list = COLORS;
		desc = 'Normal background color of pie slices.';
		advd = true;
	};
	radialActiveColor = _{Color(GREEN_FONT_COLOR);
		name = 'Active Color';
		list = COLORS;
		desc = 'Color of the active slice.';
		advd = true;
	};
	radialHiliteColor = _{Color(NORMAL_FONT_COLOR);
		name = 'Highlight Color';
		list = COLORS;
		desc = 'Color of a partially selected slice.';
		advd = true;
	};
	radialStickyColor = _{Color(ORANGE_FONT_COLOR);
		name = 'Sticky Color';
		list = COLORS;
		desc = 'Color of the sticky selection slice.';
		advd = true;
	};
	radialAccentColor = _{Color(CPAPI.GetClassColorObject());
		name = 'Accent Color';
		list = COLORS;
		desc = 'Color accent of radial menu items.';
		advd = true;
	};
	--------------------------------------------------------------------------------------------------------
	_('Keyboard', INTERFACE_LABEL);
	--------------------------------------------------------------------------------------------------------
	keyboardEnable = _{Bool(false);
		name = 'Enable';
		desc = 'Enables a radial on-screen keyboard that can be used to type messages.';
	};
	--------------------------------------------------------------------------------------------------------
	_('Raid Cursor', BINDING_HEADER_TARGETING);
	--------------------------------------------------------------------------------------------------------
	raidCursorScale = _{Number(1, 0.1);
		name = 'Scale';
		desc = 'Scale of the cursor.';
	};
	raidCursorMode = _{Map(1, {'Redirect', FOCUS, TARGET}),
		name = 'Targeting Mode';
		desc = 'Change how the raid cursor acquires a target. Redirect and focus modes will reroute appropriate spells without changing your target.';
		note = 'Basic redirect cannot route macros or ambiguous spells. Use target mode or focus mode with [@focus] macros to control behavior.';
	};
	raidCursorModifier = _{Select('<none>', '<none>', unpack(MODID_EXTEND));
		name = 'Modifier';
		desc = 'Which modifier to use with the movement buttons to move the cursor.';
		note = 'The bindings underlying the button combinations will be unavailable while the cursor is in use.\n\nModifier can also be configured on a per button basis.';
	};
	raidCursorUp = _{Button('PADDUP', true);
		name = 'Move Up';
		desc = 'Button to move the cursor up.';
		deps = { raidCursorModifier = '<none>' };
		advd = true;
	};
	raidCursorDown = _{Button('PADDDOWN', true);
		name = 'Move Down';
		desc = 'Button to move the cursor down.';
		deps = { raidCursorModifier = '<none>' };
		advd = true;
	};
	raidCursorLeft = _{Button('PADDLEFT', true);
		name = 'Move Left';
		desc = 'Button to move the cursor left.';
		deps = { raidCursorModifier = '<none>' };
		advd = true;
	};
	raidCursorRight = _{Button('PADDRIGHT', true);
		name = 'Move Right';
		desc = 'Button to move the cursor right.';
		deps = { raidCursorModifier = '<none>' };
		advd = true;
	};
	raidCursorFilter = _{String(nil);
		name = 'Filter Condition';
		desc = 'Filter condition to find raid cursor frames, as a boolean expression in Lua.';
		note = BLUE'node' .. ' is the current frame under scrutinization.\n'
			.. BLUE'unit' .. ' is the current unit ID for the frame.';
		advd = true;
	};
	raidCursorPriorityOverride = _{Bool(false);
		name = 'Priority Override';
		desc = 'Prioritize raid cursor bindings over other override bindings.';
		advd = true;
	};
	raidCursorWrapDisable = _{Bool(false);
		name = 'Disable Wrapping';
		desc = 'Prevent the cursor from wrapping when navigating.';
		advd = true;
	};
	raidCursorPortraitShow = _{Bool(true);
		name = 'Show Portrait';
		desc = 'Show portrait for the current unit, with health percentage and applicable spell casts.';
		advd = true;
	};
	raidCursorPointerAnimation = _{Bool(true);
		name = 'Enable Animation';
		desc = 'Pointer arrow rotates in the direction of travel, and portraits scale up and down on movement.';
		advd = true;
	};
	raidCursorPointerSize = _{Number(22, 2, true);
		name = 'Pointer Size';
		desc = 'Size of pointer arrow, in pixels.';
		advd = true;
	};
	raidCursorPointerOffset = _{Number(-2, 1);
		name = 'Pointer Offset';
		desc = 'Offset of pointer arrow, from the selected node center, in pixels.';
		advd = true;
	};
	raidCursorTravelTime = _{Range(4, 1, 1, 10);
		name = 'Travel Time';
		desc = 'How long the cursor should take to transition from one node to another.';
		note = 'Higher is slower.';
		advd = true;
	};
	--------------------------------------------------------------------------------------------------------
	_('Interface Cursor', INTERFACE_LABEL);
	--------------------------------------------------------------------------------------------------------
	UIenableCursor = _{Bool(true);
		name = ENABLE;
		desc = 'Enable interface cursor. Disable to use mouse-based interface interaction.';
	};
	UIWrapDisable = _{Bool(false);
		name = 'Disable Wrapping';
		desc = 'Prevent the cursor from wrapping when navigating.';
		advd = true;
	};
	--------------------------------------------------------------------------------------------------------
	_('Unit Hotkeys', BINDING_HEADER_TARGETING);
	--------------------------------------------------------------------------------------------------------
	unitHotkeyFocusMode = _{Bool(false);
		name = 'Use Focus Mode';
		desc = 'Hotkeys control your focus target instead of your current target.';
	};
	unitHotkeyInstantMode = _{Bool(true);
		name = 'Use Instant Mode';
		desc = 'Hotkeys activate their target immediately.';
	};
	unitHotkeyStaticMode = _{Bool(false);
		name = 'Use Static Mode';
		desc = 'Hotkeys always target the same unit.';
	};
	unitHotkeyDefaultMode = _{Bool(true);
		name = 'Default to '..BLUE(GetBindingName('TARGETSCANENEMY'));
		desc = 'Hotkeys use '..BLUE(GetBindingName('TARGETSCANENEMY'))..' when no target is selected.';
	};
	unitHotkeyNamePlates = _{Bool(true);
		name = 'Show on Name Plates';
		desc = 'Hotkey prompts appear on applicable name plates.';
	};
	unitHotkeyGhostMode = _{Bool(false);
		name = 'Always Show';
		desc = 'Hotkey prompts linger on unit frames after targeting.';
	};
	unitHotkeyGhostAlpha = _{Number(0.5, 0.05, true);
		name = 'Inactive Opacity';
		desc = 'Opacity of inactive hotkey prompts on unit frames after targeting.';
	};
	unitHotkeySize = _{Number(CPAPI.IsClassicEraVersion and 32 or 24, 1);
		name = 'Size';
		desc = 'Size of unit hotkeys, in pixels.';
	};
	unitHotkeyOffsetX = _{Number(0, 1, true);
		name = 'Horizontal Offset';
		desc = 'Horizontal offset of the hotkey prompt position, in pixels.';
		advd = true;
	};
	unitHotkeyOffsetY = _{Number(0, 1, true);
		name = 'Vertical Offset';
		desc = 'Vertical offset of the hotkey prompt position, in pixels.';
		advd = true;
	};
	unitHotkeyOffsetFL = _{Number(10, 1, true);
		name = 'Frame Level Offset';
		desc = 'Frame level offset of the hotkey prompt, relative to the unit frame.';
		note = 'Higher values appear on top of lower values. Valid range 0-10000.';
		advd = true;
	};
	unitHotkeyTokens = _{String('raid1-9; raid10-40; party1-4; player; boss1-4; arena1-5; party1-4pet; raid1-40target');
		name = 'Unit Pool';
		desc = 'Match criteria for unit pool, each type separated by semicolon.';
		note = 'E.g. '..BLUE('party1-4')..'; '..BLUE('player')..' will match party1, party2, party3, party4, and player.';
		advd = true;
	};
	unitHotkeySet = _{Select('Dynamic', 'Dynamic', 'Left', 'Right', 'Custom');
		name = 'Button Set';
		desc = 'Which button set to use for unit hotkeys.';
		note = 'Dynamic will use the button set that does not conflict with your '..BLUE'L[Target Unit Frames (Hold)]'..' binding.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyButton1 = _{Button('PAD1');
		name = 'Combo Button 1';
		desc = 'Button to use for combo hotkey 1.';
		note = 'Requires '..BLUE'L[Button Set]'..' > '..BLUE'L[Custom]'..' to control each button individually.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyButton2 = _{Button('PAD2');
		name = 'Combo Button 2';
		desc = 'Button to use for combo hotkey 2.';
		note = 'Requires '..BLUE'L[Button Set]'..' > '..BLUE'L[Custom]'..' to control each button individually.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyButton3 = _{Button('PAD3');
		name = 'Combo Button 3';
		desc = 'Button to use for combo hotkey 3.';
		note = 'Requires '..BLUE'L[Button Set]'..' > '..BLUE'L[Custom]'..' to control each button individually.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyButton4 = _{Button('PAD4');
		name = 'Combo Button 4';
		desc = 'Button to use for combo hotkey 4.';
		note = 'Requires '..BLUE'L[Button Set]'..' > '..BLUE'L[Custom]'..' to control each button individually.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyButton5 = _{Button('PADDDOWN', true):Set('none', true);
		name = 'Combo Button 5';
		desc = 'Button to use for combo hotkey 5.';
		note = 'Requires '..BLUE'L[Button Set]'..' > '..BLUE'L[Custom]'..' to control each button individually.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyButton6 = _{Button('PADDRIGHT', true):Set('none', true);
		name = 'Combo Button 6';
		desc = 'Button to use for combo hotkey 6.';
		note = 'Requires '..BLUE'L[Button Set]'..' > '..BLUE'L[Custom]'..' to control each button individually.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyButton7 = _{Button('PADDLEFT', true):Set('none', true);
		name = 'Combo Button 7';
		desc = 'Button to use for combo hotkey 7.';
		note = 'Requires '..BLUE'L[Button Set]'..' > '..BLUE'L[Custom]'..' to control each button individually.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyButton8 = _{Button('PADDUP', true):Set('none', true);
		name = 'Combo Button 8';
		desc = 'Button to use for combo hotkey 8.';
		note = 'Requires '..BLUE'L[Button Set]'..' > '..BLUE'L[Custom]'..' to control each button individually.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyColor1 = _{Color('ffffffff');
		name = 'Combo Color 1';
		desc = 'Color tint for combo hotkey 1.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyColor2 = _{Color('ffffffff');
		name = 'Combo Color 2';
		desc = 'Color tint for combo hotkey 2.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyColor3 = _{Color('ffffffff');
		name = 'Combo Color 3';
		desc = 'Color tint for combo hotkey 3.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyColor4 = _{Color('ffffffff');
		name = 'Combo Color 4';
		desc = 'Color tint for combo hotkey 4.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyColor5 = _{Color('ffffffff');
		name = 'Combo Color 5';
		desc = 'Color tint for combo hotkey 5.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyColor6 = _{Color('ffffffff');
		name = 'Combo Color 6';
		desc = 'Color tint for combo hotkey 6.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyColor7 = _{Color('ffffffff');
		name = 'Combo Color 7';
		desc = 'Color tint for combo hotkey 7.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	unitHotkeyColor8 = _{Color('ffffffff');
		name = 'Combo Color 8';
		desc = 'Color tint for combo hotkey 8.';
		list = CONTROLS_LABEL;
		advd = true;
	};
	--------------------------------------------------------------------------------------------------------
	_(ACCESSIBILITY_LABEL, INTERFACE_LABEL); -- Accessibility
	--------------------------------------------------------------------------------------------------------
	autoSellJunk = _{Bool(true);
		name = 'Auto-Sell Junk';
		desc = 'Automatically sell junk when interacting with a merchant.';
	};
	autoSellJunkLevelLimit = _{Number(10, 1, true);
		name = 'Auto-Sell Gear Level Limit';
		desc = 'Equippable items of poor quality will not be sold while your character is below this level.';
		advd = true;
	};
	UIscale = _{Number(1, 0.025, true);
		name = 'Global Scale';
		desc = 'Scale of most ConsolePort frames, relative to UI scale.';
		note = 'Action bar is scaled separately.';
		advd = true;
	};
	--------------------------------------------------------------------------------------------------------
	_('Power Level', INTERFACE_LABEL);
	--------------------------------------------------------------------------------------------------------
	powerLevelShow = _{Bool(false);
		name = 'Show Gauge';
		desc = 'Display power level for the current active gamepad.';
		note = 'This will not work with Xbox controllers connected via bluetooth. The Xbox Adapter is required.';
	};
	powerLevelShowIcon = _{Bool(true);
		name = 'Show Type Icon';
		desc = 'Display icon next to the power level for the current active gamepad.';
		note = 'Types are PlayStation, Xbox, or Generic.';
	};
	powerLevelShowText = _{Bool(true);
		name = 'Show Status Text';
		desc = 'Display power level status text for the current active gamepad.';
		note = 'Critical, Low, Medium, High, Wired/Charging, or Unknown/Disconnected.';
	};
	--------------------------------------------------------------------------------------------------------
	_( ACTIONBARS_LABEL, SETTING_GROUP_GAMEPLAY ); -- Action Bars
	--------------------------------------------------------------------------------------------------------
	bindingShowExtraBars = _{Bool(false);
		name = 'Show All Action Bars';
		desc = 'Show bonus bar configuration for characters without stances.';
		advd = true;
	};
	bindingShowSpellMenuGrid = _{Bool(false);
		name = 'Show Action Bar Grid on Spell Pickup';
		desc = 'Display the action bar grid when picking up a spell on the cursor.';
		advd = true;
	};
	disableHotkeyRendering = _{Bool(false);
		name = 'Disable Hotkey Rendering';
		desc = 'Disables customization to hotkeys on regular action bars.';
		advd = true;
	};
	useAtlasIcons = _{Bool(not CPAPI.IsClassicEraVersion);
		name = 'Use Default Hotkey Icons';
		desc = 'Uses the default hotkey icons instead of the custom icons provided by ConsolePort.';
		note = 'Requires reload.';
		hide = CPAPI.IsClassicEraVersion;
		advd = true;
	};
	--------------------------------------------------------------------------------------------------------
	_( BINDINGS_OPT, SETTING_GROUP_GAMEPLAY ); -- Bindings
	--------------------------------------------------------------------------------------------------------
	bindingOverlapEnable = _{Bool(false);
		name = 'Allow Binding Overlap';
		desc = 'Allow binding multiple combos to the same binding.';
		advd = true;
	};
	bindingAllowSticks = _{Bool(false);
		name = 'Allow Radial Bindings';
		desc = 'Allow binding discrete radial stick inputs.';
		advd = true;
	};
	bindingAutomaticBackup = _{Bool(true);
		name = 'Automatic Binding Backups';
		desc = 'Automatically backup your bindings when you change them, for import and export.';
		list = 'Presets';
		advd = true;
	};
	emulatePADPADDLE1 = _{Pseudokey('none');
		name = 'Emulate P1 '..(KEY_PADPADDLE1 or '');
		desc = 'Keyboard button to emulate the paddle 1 button.';
		advd = true;
	};
	emulatePADPADDLE2 = _{Pseudokey('none');
		name = 'Emulate P2 '..(KEY_PADPADDLE2 or '');
		desc = 'Keyboard button to emulate the paddle 2 button.';
		advd = true;
	};
	emulatePADPADDLE3 = _{Pseudokey('none');
		name = 'Emulate P3 '..(KEY_PADPADDLE3 or '');
		desc = 'Keyboard button to emulate the paddle 3 button.';
		advd = true;
	};
	emulatePADPADDLE4 = _{Pseudokey('none');
		name = 'Emulate P4 '..(KEY_PADPADDLE4 or '');
		desc = 'Keyboard button to emulate the paddle 4 button.';
		advd = true;
	};
	interactButton = _{Button('PAD1', true):Set('none', true);
		name = 'Click Override Button';
		desc = 'Button or combination used to click when a given condition applies, but act as a normal binding otherwise.';
		note = 'Use a shoulder button combined with crosshair for smooth and precise interactions. The click is performed at crosshair or cursor location.';
		advd = true;
	};
	interactCondition = _{String('[vehicleui] nil; [@target,noharm][@target,noexists][@target,harm,dead] TURNORACTION; nil');
		name = 'Click Override Condition';
		desc = 'Macro condition to enable the click override button. The default condition clicks right mouse button when there is no enemy target.';
		note = 'Takes the format of...\n'
			.. BLUE'[condition] bindingID; nil'
			.. '\n...where each condition/binding is separated by a semicolon, and "nil" clears the override.';
		advd = true;
	};
	--------------------------------------------------------------------------------------------------------
	_('Touchpad', SETTING_GROUP_SYSTEM);
	--------------------------------------------------------------------------------------------------------
	LEDMode = _{Map(1, {[1] = FACTION, [2] = TARGET, [3] = PLAYER, [4] = 'RGB', [5] = CUSTOM, [6] = OFF});
		name = 'LED Color Type';
		desc = 'Type of LED color to use for the touchpad.';
		note = 'Requires a touchpad with LED support.';
		hide = not C_GamePad.SetLedColor;
		list = COLOR;
	};
	LEDColor = _{Color('ff00fcff');
		name = 'LED Custom Color';
		desc = 'Custom color to use for the touchpad LED.';
		hide = not C_GamePad.SetLedColor;
		deps = { LEDMode = 5 };
		list = COLOR;
	};
},  --------------------------------------------------------------------------------------------------------
function(self, key) return (rawget(self, key) or {})[1] end))