Scriptname zbfConfig extends zbfConfigBase

zbfSexLab Property SexLab Auto
zbfBondageShell Property Main Auto

;
; Settings variables
; 

; Global variables
GlobalVariable Property zbfSettingUpdateInterval Auto
GlobalVariable Property zbfSettingDisableEffects Auto
GlobalVariable Property zbfSettingSpeedMult Auto
GlobalVariable Property zbfSettingBlindStrength Auto
GlobalVariable Property zbfSettingBlindPulseStrength Auto

; Global variable setting indices
Int oidUpdateInterval
Int oidDisableEffects
Int oidSpeedMult
Int oidBlindStrength
Int oidBlindPulseStrength

; Settings

; 5.50

; Gag sounds selection (female)
Int oidGagSoundFemale
Int Property idxGagSoundFemale Auto Hidden
String[] sGagSoundFemale
; Gag sounds selection (male)
Int oidGagSoundMale
Int Property idxGagSoundMale Auto Hidden
String[] sGagSoundMale
; Gag sound volume
Int oidGagSoundVolume
Float Property fGagSoundVolume Auto Hidden
; Gag sound frequency
Int oidGagSoundFrequency
Float Property fGagSoundFrequency Auto Hidden
; Gag sound repeat
Int oidGagSoundRepeat
Bool Property bGagSoundRepeat Auto Hidden
; Gag sound repeat
Int oidForceAi
Bool Property bForceAi Auto Hidden
; Gag sound spread
Float Property fGagSoundFreqVariance = 1.5 AutoReadOnly Hidden
; Bound offset selection
Int oidDefaultOffset
Int Property idxDefaultOffset Auto Hidden
String[] sDefaultOffset

; 5.60
String[] sUpdateInterval
Int oidUpdateIntervalPlayer
Int Property idxUpdateIntervalPlayer Auto Hidden
Int oidUpdateIntervalNpc
Int Property idxUpdateIntervalNpc Auto Hidden
Int oidGagSoundAuto
Bool Property bGagSoundAuto Auto Hidden
Int oidRebuildBaseAnimations ; Just a button

; Animation control
String[] sAnimationTypes
Int oidAnimationTypes
Int idxAnimationTypes
String[] sAnimationIndex
String[] sAnimationId
Int oidAnimationIndex
Int idxAnimationIndex
String sSelectedAnimationEvent
Int oidPlayIdleAnimation
zbfSexLabBaseEntry SelectedBaseEntry
String sSelectedSexLabActor1Base
String sSelectedSexLabActor2Base
Int oidPlaySexLabAnimation
Bool bFilterActor1
Int oidFilterActor1
Bool bFilterActor2
Int oidFilterActor2

; 5.62
Int oidAnimationHelp

; Loose buttons and other misc controls
Int oidRegisterSexLab
Int oidRestart
Int oidReleaseAi
Int oidResetControls

; 6.00
Bool Property bOverrideSexLabSound Auto Hidden
Int oidOverrideSexLabSound
Bool Property bForceSilenceSexLabSound Auto Hidden
Int oidForceSilenceSexLabSound
Int oidDebugLogging
Bool Property bDebugLogging Auto Hidden

Int oidTestButton


; Convenience properties
Bool Property bDisableEffects
	Bool Function Get()
		Return zbfSettingDisableEffects.GetValueInt() != 0
	EndFunction
EndProperty
Float Property fUpdateInterval
	Float Function Get()
		Return zbfSettingUpdateInterval.GetValue()
	EndFunction
EndProperty
Float Property fSpeedMult
	Float Function Get()
		Return zbfSettingSpeedMult.GetValue()
	EndFunction
EndProperty
Float Property fBlindStrength
	Float Function Get()
		Return zbfSettingBlindStrength.GetValue()
	EndFunction
EndProperty
Float Property fBlindPulseStrength
	Float Function Get()
		Return zbfSettingBlindPulseStrength.GetValue()
	EndFunction
EndProperty
Float Property fUpdateIntervalPlayer
	Float Function Get()
		Return IndexToUpdateInterval(idxUpdateIntervalPlayer)
	EndFunction
EndProperty
Float Property fUpdateIntervalNpc
	Float Function Get()
		Return IndexToUpdateInterval(idxUpdateIntervalNpc)
	EndFunction
EndProperty
Int Property iDefaultOffset
	Int Function Get()
		If idxDefaultOffset == 0
			Return 11
		ElseIf idxDefaultOffset == 1
			Return 1
		ElseIf idxDefaultOffset == 2
			Return 6
		ElseIf idxDefaultOffset == 3
			Return 2
		EndIf
		Return 11
	EndFunction
EndProperty

Int Function GetVersion()
	Return zbfUtil.GetVersion()
EndFunction

Function OnUpdateEvent(Int aiOldVersion, Int aiVersion)
	Log("OnUpdateEvent", ModName + ": Version from "	+ aiOldVersion + " to " + aiVersion, iForce)
	Log("OnUpdateEvent", ModName + ": Update proceeding", iForce)
	Log("OnUpdateEvent", ModName + ": Script version " + zbfUtil.GetVersion(), iForce)

	RestartAllQuests()

	If aiOldVersion < 500
		zbfSettingUpdateInterval.SetValue(0.5)
		zbfSettingDisableEffects.SetValueInt(0)
		zbfSettingSpeedMult.SetValueInt(70)
		zbfSettingBlindStrength.SetValueInt(50)
		zbfSettingBlindPulseStrength.SetValueInt(50)
	EndIf

	If aiOldVersion <= 550
		; Nothing yet
		idxGagSoundFemale = 1
		idxGagSoundMale = 0
		fGagSoundVolume = 100.0
		fGagSoundFrequency = 10.0
		bGagSoundRepeat = False
		bForceAi = False
		idxDefaultOffset = 0
	EndIf

	If aiOldVersion <= 560
		idxGagSoundMale = 2
		idxGagSoundFemale = 3

		idxUpdateIntervalPlayer = 0
		idxUpdateIntervalNpc = 2

		fGagSoundVolume = 100.0
		bGagSoundAuto = True

		idxAnimationTypes = 0
		idxAnimationIndex = 0

		bFilterActor1 = True
		bFilterActor2 = True
	EndIf
	
	If aiOldVersion <= 600
		bOverrideSexLabSound = True
		bForceSilenceSexLabSound = False
		bDebugLogging = False
	EndIf

	Log("OnUpdateEvent", ModName + " quest running (zbf) - " + Main.IsRunning(), iForce)
	Log("OnUpdateEvent", ModName + " quest running (zbfSexLab) - " + SexLab.IsRunning(), iForce)
	Log("OnUpdateEvent", ModName + " quest running (zbfConfig) - " + IsRunning(), iForce)

	; Start up SexLab integration, do not automatically register animations
	SexLab.LinkDependency()
	SexLab.RebuildBaseAnimations()
	SexLab.RebuildVoices()
	SexLab.RegisterForSexLabEvents()

	Log("OnUpdateEvent", ModName + " finished updating.", iForce)
	Debug.Notification(ModName + " version " + zbfUtil.GetVersionStr())
EndFunction

;
; Settings parameters
;
Float Function GetFloat(Int aiOption)
	If aiOption == oidUpdateInterval
		Return fUpdateInterval
	ElseIf aiOption == oidDisableEffects
		Return bDisableEffects As Float
	ElseIf aiOption == oidSpeedMult
		Return fSpeedMult
	ElseIf aiOption == oidBlindStrength
		Return fBlindStrength
	ElseIf aiOption == oidBlindPulseStrength
		Return fBlindPulseStrength

	; 5.50
	ElseIf aiOption == oidGagSoundFemale
		Return idxGagSoundFemale
	ElseIf aiOption == oidGagSoundMale
		Return idxGagSoundMale
	ElseIf aiOption == oidGagSoundVolume
		Return fGagSoundVolume
	ElseIf aiOption == oidGagSoundFrequency
		Return fGagSoundFrequency
	ElseIf aiOption == oidForceAi
		Return bForceAi As Float
	ElseIf aiOption == oidGagSoundRepeat
		Return bGagSoundRepeat As Float
	ElseIf aiOption == oidDefaultOffset
		Return idxDefaultOffset

	; 5.60
	ElseIf aiOption == oidUpdateIntervalPlayer
		Return idxUpdateIntervalPlayer
	ElseIf aiOption == oidUpdateIntervalNpc
		Return idxUpdateIntervalNpc
	ElseIf aiOption == oidGagSoundAuto
		Return bGagSoundAuto As Float
	ElseIf aiOption == oidAnimationTypes
		Return idxAnimationTypes
	ElseIf aiOption == oidAnimationIndex
		Return idxAnimationIndex
	ElseIf aiOption == oidFilterActor1
		Return bFilterActor1 As Float
	ElseIf aiOption == oidFilterActor2
		Return bFilterActor2 As Float
		
	; 5.63
	ElseIf aiOption == oidOverrideSexLabSound
		Return bOverrideSexLabSound As Float
	ElseIf aiOption == oidForceSilenceSexLabSound
		Return bForceSilenceSexLabSound As Float
	ElseIf aiOption == oidDebugLogging
		Return bDebugLogging As Float

	EndIf

	Log("GetFloat", "Unknown configuration option requested", iWarning)
EndFunction

Function SetFloat(Int aiOption, Float afValue)
	Bool abValue = (afValue != 0)
	Int aiValue = (afValue As Int)

	If aiOption == oidUpdateInterval
		zbfSettingUpdateInterval.SetValue(afValue)
	ElseIf aiOption == oidDisableEffects
		zbfSettingDisableEffects.SetValue(afValue)
	ElseIf aiOption == oidSpeedMult
		zbfSettingSpeedMult.SetValue(afValue)
	ElseIf aiOption == oidBlindStrength
		zbfSettingBlindStrength.SetValue(afValue)
	ElseIf aiOption == oidBlindPulseStrength
		zbfSettingBlindPulseStrength.SetValue(afValue)

	; 5.50
	ElseIf aiOption == oidGagSoundFemale
		idxGagSoundFemale = aiValue
	ElseIf aiOption == oidGagSoundMale
		idxGagSoundMale = aiValue
	ElseIf aiOption == oidGagSoundVolume
		fGagSoundVolume = afValue
	ElseIf aiOption == oidGagSoundFrequency
		fGagSoundFrequency = afValue
	ElseIf aiOption == oidForceAi
		bForceAi = abValue
	ElseIf aiOption == oidGagSoundRepeat
		bGagSoundRepeat = abValue
	ElseIf aiOption == oidDefaultOffset
		idxDefaultOffset = aiValue

	; 5.60
	ElseIf aiOption == oidUpdateIntervalPlayer
		idxUpdateIntervalPlayer = aiValue
	ElseIf aiOption == oidUpdateIntervalNpc
		idxUpdateIntervalNpc = aiValue
	ElseIf aiOption == oidGagSoundAuto
		bGagSoundAuto = abValue
	ElseIf aiOption == oidAnimationTypes
		idxAnimationTypes = aiValue
	ElseIf aiOption == oidAnimationIndex
		idxAnimationIndex = aiValue
	ElseIf aiOption == oidFilterActor1
		bFilterActor1 = abValue
	ElseIf aiOption == oidFilterActor2
		bFilterActor2 = abValue

	; 5.63
	ElseIf aiOption == oidOverrideSexLabSound
		bOverrideSexLabSound = abValue
	ElseIf aiOption == oidForceSilenceSexLabSound
		bForceSilenceSexLabSound = abValue
	ElseIf aiOption == oidDebugLogging
		bDebugLogging = abValue

	; End of list ...
	EndIf
EndFunction

String[] Function GetStrings(Int aiOption)
	If aiOption == oidGagSoundFemale
		Return sGagSoundFemale
	ElseIf aiOption == oidGagSoundMale
		Return sGagSoundMale
	ElseIf aiOption == oidDefaultOffset
		Return sDefaultOffset

	; 5.60
	ElseIf aiOption == oidUpdateIntervalPlayer
		Return sUpdateInterval
	ElseIf aiOption == oidUpdateIntervalNpc
		Return sUpdateInterval
	ElseIf aiOption == oidAnimationTypes
		Return sAnimationTypes
	ElseIf aiOption == oidAnimationIndex
		Return sAnimationIndex

	EndIf

	Log("GetStrings", "Unregistered string requested", iWarning)
	Return Parent.GetStrings(aiOption)
EndFunction

Float Function IndexToUpdateInterval(Int iIndex)
	If iIndex == 0
		Return 0.5
	ElseIf iIndex == 3
		Return 10.0
	ElseIf iIndex == 1
		Return 1.0
	ElseIf iIndex == 2
		Return 5.0
	EndIf
	Return 1.0
EndFunction

String Function BoolToStr(Bool abValue)
	If abValue == True
		Return "$ZazAP_Yes"
	EndIf
	Return "$ZazAP_No"
EndFunction

Function ShowActorStatus(Actor akActor)
	If akActor == None
		Return
	EndIf

	Int i
	AddHeaderOption(akActor.GetDisplayName())
	String header = "$ZazAP_Required"
	String[] tags = Main.GetRequiredSexLabTags(akActor)
	i = tags.Length
	While i > 0
		i -= 1
		If tags[i] != ""
			CreateTextOption(header, tags[i], "$ZazAP_RequiredDesc")
			header = ""
		EndIf
	EndWhile
	AddEmptyOption()
	header = "$ZazAP_Blocked"
	tags = Main.GetBlockedSexLabTags(akActor)
	i = tags.Length
	While i > 0
		i -= 1
		If tags[i] != ""
			CreateTextOption(header, tags[i], "$ZazAP_BlockedDesc")
			header = ""
		EndIf
	EndWhile
	AddEmptyOption()
EndFunction

;
; MCM event overrides
;
Function OnPageDraw(String asPage)
	Int i

	Pages = New String[4]
	Pages[0] = "$ZazAP_General"
	Pages[1] = "$ZazAP_SexLab"
	Pages[2] = "$ZazAP_PlayerCC"
	Pages[3] = "$ZazAP_AnimationTest"

	sDefaultOffset = New String[4]
	sDefaultOffset[0] = "$ZazAP_OffsetDefault"
	sDefaultOffset[1] = "$ZazAP_OffsetNoStruggle"
	sDefaultOffset[2] = "$ZazAP_OffsetLegacy"
	sDefaultOffset[3] = "$ZazAP_OffsetLightStruggle"

	sGagSoundFemale = New String[5]
	sGagSoundFemale[0] = "$ZazAP_VoiceDisable"
	sGagSoundFemale[1] = "$ZazAP_VoiceCustom"
	sGagSoundFemale[2] = "$ZazAP_VoiceSoft"
	sGagSoundFemale[3] = "$ZazAP_VoiceNormal"
	sGagSoundFemale[4] = "$ZazAP_VoiceFrustrated"

	sGagSoundMale = New String[3]
	sGagSoundMale[0] = "$ZazAP_VoiceDisable"
	sGagSoundMale[1] = "$ZazAP_VoiceCustom"
	sGagSoundMale[2] = "$ZazAP_VoiceNormal"

	sUpdateInterval = New String[4]
	sUpdateInterval[0] = "$ZazAP_HalfSecond"
	sUpdateInterval[1] = "$ZazAP_OneSecond"
	sUpdateInterval[2] = "$ZazAP_FiveSecond"
	sUpdateInterval[3] = "$ZazAP_TenSecond"

	SetCursorFillMode(TOP_TO_BOTTOM)
	SetCursorPosition(0)

	; Link SexLab
	oidRegisterSexLab = -1

	If asPage == "" || asPage =="$ZazAP_General"
		; Left side
		AddHeaderOption("$ZazAP_General")
		oidDisableEffects = CreateToggleOption("$ZazAP_Disable", bDisableEffects, False, "$ZazAP_DisableDesc")
		CreateTextOption("$ZazAP_Version", zbfUtil.GetVersionStr(), "")
		AddEmptyOption()

		AddHeaderOption("$ZazAP_UpdateInterval")
		;oidUpdateInterval = CreateSliderOption("$ZazAP_UpdateInterval", fUpdateInterval, 0.1, 5.0, 0.5, 0.1, "$ZazAP_Seconds_1", "$ZazAP_UpdateIntervalDesc")
		oidUpdateIntervalPlayer = CreateMenuOption("$ZazAP_UpdateIntervalPlayer", idxUpdateIntervalPlayer, sUpdateInterval, 0, "$ZazAP_UpdateIntervalPlayerDesc")
		oidUpdateIntervalNpc = CreateMenuOption("$ZazAP_UpdateIntervalNpc", idxUpdateIntervalNpc, sUpdateInterval, 2, "$ZazAP_UpdateIntervalNpcDesc")
		AddEmptyOption()

		AddHeaderOption("$ZazAP_Cleaning")
		oidRestart = CreateTextOption("$ZazAP_CleanRestart", "$ZazAP_Restart", "$ZazAP_CleanRestartDesc")
		oidDebugLogging = CreateToggleOption("$ZazAP_DebugLog", bDebugLogging, False, "$ZazAP_DebugLogDesc")
		AddEmptyOption()

		; Right side
		SetCursorPosition(1)

		AddHeaderOption("$ZazAP_OffsetHeader")
		oidDefaultOffset = CreateMenuOption("$ZazAP_OffsetAnim", idxDefaultOffset, sDefaultOffset, 0, "$ZazAP_OffsetAnimDesc")
		AddEmptyOption()

		AddHeaderOption("$ZazAP_GagHeader")
		oidGagSoundFemale = CreateMenuOption("$ZazAP_GagSoundFemale", idxGagSoundFemale, sGagSoundFemale, 3, "$ZazAP_GagSoundDesc")
		oidGagSoundMale = CreateMenuOption("$ZazAP_GagSoundMale", idxGagSoundMale, sGagSoundMale, 2, "$ZazAP_GagSoundDesc")
		oidGagSoundVolume = CreateSliderOption("$ZazAP_GagSoundVolume", fGagSoundVolume, 10.0, 100.0, 100.0, 10.0, "$ZazAP_Percent_0", "$ZazAP_GagSoundVolumeLong")
		oidGagSoundRepeat = CreateToggleOption("$ZazAP_GagSoundRepeat", bGagSoundRepeat, False, "$ZazAP_GagSoundRepeatDesc")
		oidGagSoundFrequency = CreateSliderOption("$ZazAP_GagSoundFrequency", fGagSoundFrequency, 1.0, 120.0, 10.0, 1.0, "$ZazAP_Seconds_0", "$ZazAP_GagSoundFrequencyDesc")
		oidGagSoundAuto = CreateToggleOption("$ZazAP_GagSoundAuto", bGagSoundAuto, False, "$ZazAP_GagSoundAutoDesc")
		AddEmptyOption()

		AddHeaderOption("$ZazAP_MovementSpeedHeader")
		oidSpeedMult = CreateSliderOption("$ZazAP_MovementSpeed", fSpeedMult, 10.0, 100.0, 70.0, 1.0, "$ZazAP_Percent_0", "$ZazAP_MovementSpeedLong")
		AddEmptyOption()

		AddHeaderOption("$ZazAP_Blindfold")
		oidBlindStrength = CreateSliderOption("$ZazAP_BlindfoldAmount", fBlindStrength, 0.0, 100.0, 50.0, 10.0, "$ZazAP_Percent_0", "$ZazAP_BlindfoldAmount")
		oidBlindPulseStrength = CreateSliderOption("$ZazAP_BlindfoldPulse", fBlindPulseStrength, 0.0, 100.0, 50.0, 10.0, "$ZazAP_Percent_0", "$ZazAP_BlindfoldPulseLong")
		AddEmptyOption()
	EndIf

	If asPage == "$ZazAP_PlayerCC"
		AddHeaderOption("$ZazAP_PlayerAiHeader")
		oidForceAi = CreateToggleOption("$ZazAP_PlayerForceAi", bForceAi, False, "$ZazAP_PlayerForceAiDesc")
		CreateTextOption("$ZazAP_PlayerAiReferences", Main.GetAiRef(), "$ZazAP_PlayerAiReferencesLong")
		oidReleaseAi = CreateTextOption("$ZazAP_PlayerAiRelease", "", "$ZazAP_PlayerAiReleaseLong")
		AddEmptyOption()

		AddHeaderOption("$ZazAP_RegistrationsHeader")
		zbfPlayerControl[] Regs = Main.PlayerControlRegs
		i = 0
		While i < Regs.Length
			If Regs[i] != None
				CreateTextOption(Regs[i].ModName, "", "$ZazAP_RegistrationsDesc")
			EndIf
			i += 1
		EndWhile

		SetCursorPosition(1)
		AddHeaderOption("$ZazAP_PlayerControlHeader")
		CreateTextOption("$ZazAP_PlayerControlMovement", BoolToStr(Game.IsMovementControlsEnabled()), "")
		CreateTextOption("$ZazAP_PlayerControlActivate", BoolToStr(Game.IsActivateControlsEnabled()), "")
		CreateTextOption("$ZazAP_PlayerControlFastTravel", BoolToStr(Game.IsFastTravelEnabled()), "")
		CreateTextOption("$ZazAP_PlayerControlFighting", BoolToStr(Game.IsFightingControlsEnabled()), "")
		CreateTextOption("$ZazAP_PlayerControlJournal", BoolToStr(Game.IsJournalControlsEnabled()), "")
		CreateTextOption("$ZazAP_PlayerControlLooking", BoolToStr(Game.IsLookingControlsEnabled()), "")
		CreateTextOption("$ZazAP_PlayerControlSneaking", BoolToStr(Game.IsSneakingControlsEnabled()), "")
		CreateTextOption("$ZazAP_PlayerControlMenu", BoolToStr(Game.IsMenuControlsEnabled()), "")
		oidResetControls = CreateTextOption("$ZazAP_PlayerControlRestore", "", "$ZazAP_PlayerControlRestoreLong")
		AddEmptyOption()
	EndIf

	If asPage == "$ZazAP_SexLab"
		AddHeaderOption("$ZazAP_SexLabIntegration")
		oidRegisterSexLab = -1

		If SexLab.HasSexLab()
			Int iVersion = SexLab.GetVersion()
			String sVersion = SexLab.GetStringVer()

			CreateTextOption("$ZazAP_SexLabVersion", sVersion, "$ZazAP_SexLabVersion")
			If iVersion >= 15000
				If SexLab.IsFullyRegistered()
					CreateTextOption("$ZazAP_SexLabAnimations", "$ZazAP_SexLabRegistered", "", aiFlags = OPTION_FLAG_DISABLED)
				Else
					oidRegisterSexLab = CreateTextOption("$ZazAP_SexLabAnimations", "$ZazAP_SexLabRegister", "$ZazAP_SexLabRegisterDesc")
				EndIf
			EndIf
			oidRebuildBaseAnimations = CreateTextOption("$ZazAP_BaseAnimation", "$ZazAP_BaseAnimationRebuild", "$ZazAP_BaseAnimationDesc")
			AddEmptyOption()

			;AddHeaderOption("Test stuff")
			;oidTestButton = CreateTextOption("Press me", "Yes!!", "Oh, yea!")
			;AddEmptyOption()

			AddHeaderOption("$ZazAP_GagHeader")
			oidOverrideSexLabSound = CreateToggleOption("$ZazAP_SexLabGagEnable", bOverrideSexLabSound, True, "$ZazAP_SexLabGagEnableDesc")
			oidForceSilenceSexLabSound = CreateToggleOption("$ZazAP_SexLabGagSilence", bForceSilenceSexLabSound, False, "$ZazAP_SexLabGagSilenceDesc")
			AddEmptyOption()

			SetCursorPosition(1)
			AddHeaderOption("$ZazAP_BaseAnimationHeader")
			i = SexLab.BaseSlots.Length
			While i > 0
				i -= 1
				If SexLab.BaseSlots[i].Name != ""
					CreateTextOption(SexLab.BaseSlots[i].Name, "", "")
				EndIf
			EndWhile
			AddEmptyOption()

			If iVersion >= 15000
				AddHeaderOption("$ZazAP_SexLabAnimsHeader")
				i = SexLab.GetAnimCount()
				While i > 0
					i -= 1
					CreateTextOption(SexLab.GetAnimName(i), BoolToStr(SexLab.GetAnimRegistered(i)), "")
				EndWhile
			Else
				CreateTextOption("$ZazAP_SexLabAnimations", "$ZazAP_SexLabTooOld", "$ZazAP_SexLabTooOldDesc")
			EndIf
		Else
			CreateTextOption("$ZazAP_SexLab", "$ZazAP_SexLabNotFound", "$ZazAP_SexLabNotFoundDesc")
		EndIf
		AddEmptyOption()
	EndIf

	; Test page for running animations
	If asPage == "$ZazAP_AnimationTest"
		Actor kActor1 = Game.GetPlayer()
		Actor kActor2 = Game.GetCurrentCrosshairRef() As Actor
		Int iActorCount = 1
		
		Int iActor1BindType = Main.GetBindTypeFromWornKeywords(kActor1)
		Int iActor2BindType = Main.iBindUnbound
		If kActor2 != None
			iActor2BindType = Main.GetBindTypeFromWornKeywords(kActor2)
			iActorCount = 2
		EndIf
		
		Bool bCanSexLab = (idxAnimationTypes == 4)
		Bool bCanIdle = (idxAnimationTypes != 4) && (iActor1BindType != Main.iBindUnbound)

		sAnimationTypes = New String[5]
		sAnimationTypes[0] = "$ZazAP_AnimTypePose"
		sAnimationTypes[1] = "$ZazAP_AnimTypeHorny"
		sAnimationTypes[2] = "$ZazAP_AnimTypeStruggle"
		sAnimationTypes[3] = "$ZazAP_AnimTypeOffset"
		sAnimationTypes[4] = "$ZazAP_AnimTypeSexLab"

		SetCursorPosition(0)
		;AddHeaderOption("$ZazAP_ActorSelectionHeader")
		;CreateTextOption("$ZazAP_ActorSelection1", kActor1.GetDisplayName(), "$ZazAP_ActorSelectionDesc")
		If kActor2 != None
		;	CreateTextOption("$ZazAP_ActorSelection2", kActor2.GetDisplayName(), "$ZazAP_ActorSelectionDesc")
		EndIf
		;AddEmptyOption()

		sSelectedAnimationEvent = ""
		SelectedBaseEntry = None

		AddHeaderOption("$ZazAP_ActorSelectionHeader")
		oidAnimationTypes = CreateMenuOption("$ZazAP_AnimationType", idxAnimationTypes, sAnimationTypes, 0, "$ZazAP_AnimationTypeDesc")
		If idxAnimationTypes == 3
			sAnimationIndex = New String[1]
			sAnimationIndex[0] = "0"
		ElseIf idxAnimationTypes == 2
			sAnimationIndex = New String[8]
			sAnimationIndex[0] = "$ZazAP_AnimDesc01"
			sAnimationIndex[1] = "$ZazAP_AnimDesc02"
			sAnimationIndex[2] = "$ZazAP_AnimDesc03"
			sAnimationIndex[3] = "$ZazAP_AnimDesc04"
			sAnimationIndex[4] = "$ZazAP_AnimDesc05"
			sAnimationIndex[5] = "$ZazAP_AnimDesc06"
			sAnimationIndex[6] = "$ZazAP_AnimDesc11"
			sAnimationIndex[7] = "$ZazAP_AnimDesc12"
		ElseIf idxAnimationTypes == 0
			sAnimationIndex = New String[15]
			sAnimationIndex[0] = "$ZazAP_AnimDesc01"
			sAnimationIndex[1] = "$ZazAP_AnimDesc02"
			sAnimationIndex[2] = "$ZazAP_AnimDesc03"
			sAnimationIndex[3] = "$ZazAP_AnimDesc04"
			sAnimationIndex[4] = "$ZazAP_AnimDesc05"
			sAnimationIndex[5] = "$ZazAP_AnimDesc06"
			sAnimationIndex[6] = "$ZazAP_AnimDesc07"
			sAnimationIndex[7] = "$ZazAP_AnimDesc08"
			sAnimationIndex[8] = "$ZazAP_AnimDesc09"
			sAnimationIndex[9] = "$ZazAP_AnimDesc10"
			sAnimationIndex[10] = "$ZazAP_AnimDesc11"
			sAnimationIndex[11] = "$ZazAP_AnimDesc12"
			sAnimationIndex[12] = "$ZazAP_AnimDesc13"
			sAnimationIndex[13] = "$ZazAP_AnimDesc14"
			sAnimationIndex[14] = "$ZazAP_AnimDesc15"
		ElseIf idxAnimationTypes == 4
			zbfSexLabBaseEntry[] list = SexLab.GetEntries(True, True)

			SexLab.FilterEntriesOnActorCount(list, 1, iActorCount)
			If bFilterActor1
				SexLab.FilterEntries(list, 1, Main.GetRequiredSexLabTags(kActor1), Main.GetBlockedSexLabTags(kActor1))
			EndIf
			If bFilterActor2 && (kActor2 != None)
				SexLab.FilterEntries(list, 2, Main.GetRequiredSexLabTags(kActor2), Main.GetBlockedSexLabTags(kActor2))
			EndIf

			sAnimationIndex = New String[15]
			sAnimationId = New String[15]
			i = list.Length
			Int j = 0
			While i > 0
				i -= 1
				If list[i] != None
					sAnimationIndex[j] = list[i].Name
					sAnimationId[j] = list[i].BaseId
					j += 1
				EndIf
			EndWhile
		ElseIf idxAnimationTypes == 1
			sAnimationIndex = New String[3]
			sAnimationIndex[0] = "$ZazAP_AnimHornyDesc01"
			sAnimationIndex[1] = "$ZazAP_AnimHornyDesc02"
			sAnimationIndex[2] = "$ZazAP_AnimHornyDesc03"
		EndIf

		If (idxAnimationIndex >= sAnimationIndex.Length) || (sAnimationIndex[idxAnimationIndex] == "")
			idxAnimationIndex = 0
		EndIf
		oidAnimationIndex = CreateMenuOption("$ZazAP_AnimationIndex", idxAnimationIndex, sAnimationIndex, 0, "$ZazAP_AnimationIndexDesc")
		AddEmptyOption()

		If bCanIdle
			sSelectedAnimationEvent = Main.GetAnimationName(iActor1BindType, idxAnimationTypes, idxAnimationIndex + 1)
			CreateTextOption("$ZazAP_AnimationName", sSelectedAnimationEvent, "Animation that will play.")
			AddEmptyOption()
		EndIf
		If bCanSexLab
			String selectedSexLabId = sAnimationId[idxAnimationIndex]
			SelectedBaseEntry = SexLab.GetEntryById(selectedSexLabId)

			sSelectedSexLabActor1Base = Main.GetSexLabAnimationName(SelectedBaseEntry, iActor1BindType)
			sSelectedSexLabActor2Base = Main.GetSexLabAnimationName(SelectedBaseEntry, iActor2BindType)

			CreateTextOption("$ZazAP_AnimationName", selectedSexLabId, "$ZazAP_AnimationNameDesc")
			CreateTextOption("$ZazAP_AnimationActor1Base", sSelectedSexLabActor1Base, "$ZazAP_AnimationActorBaseDesc")
			CreateTextOption("$ZazAP_AnimationActor2Base", sSelectedSexLabActor2Base, "$ZazAP_AnimationActorBaseDesc")
			AddEmptyOption()
		EndIf
		
		AddHeaderOption("$ZazAP_AnimationHelpHeader")
		oidAnimationHelp = CreateTextOption("$ZazAP_AnimationHelpButton", "", "")
		
		oidPlayIdleAnimation = -1
		oidPlaySexLabAnimation = -1

		; Show options for both actors
		SetCursorPosition(1)
		AddHeaderOption("$ZazAP_AnimationControlHeader")
		If bCanIdle
			oidPlayIdleAnimation = CreateTextOption("$ZazAP_AnimationRun", "", "$ZazAP_AnimationRunDesc")
			AddEmptyOption()
		EndIf
		If bCanSexLab
			oidPlaySexLabAnimation = CreateTextOption("$ZazAP_AnimationRun", "", "$ZazAP_AnimationRunDesc")
			AddEmptyOption()
		EndIf

		oidFilterActor1 = CreateToggleOption("$ZazAP_AnimationFilterActor1", bFilterActor1, True, "$ZazAP_AnimationFilterActorDesc")
		oidFilterActor2 = CreateToggleOption("$ZazAP_AnimationFilterActor2", bFilterActor2, True, "$ZazAP_AnimationFilterActorDesc")
		AddEmptyOption()

		ShowActorStatus(kActor1)
		ShowActorStatus(kActor2)
	EndIf
EndFunction

Function RestartAllQuests()
	zbfPlayerControl[] zbfControls = Main.PlayerControlRegs ; Save all registrations, since these happen at startup

	SexLab.Stop()
	Main.Stop()

	SexLab.Start()
	Main.Start()
	
	Main.PlayerControlRegs = zbfControls ; Restore registrations
EndFunction

Event OnOptionMenuAccept(Int aiOption, Int aiIndex)
	If aiOption == oidAnimationTypes
		Parent.OnOptionMenuAccept(aiOption, aiIndex)
		ForcePageReset()

	ElseIf aiOption == oidAnimationIndex
		Parent.OnOptionMenuAccept(aiOption, aiIndex)
		ForcePageReset()

	Else
		Parent.OnOptionMenuAccept(aiOption, aiIndex)
	EndIf
EndEvent

Int[] iMariaList
Int iMariaIndex = 0

Event OnOptionSelect(Int aiOption)
	iMariaList = New Int[11]
	iMariaList[0] = 1
	iMariaList[1] = 2
	iMariaList[2] = 3
	iMariaList[3] = 4
	iMariaList[4] = 5
	iMariaList[5] = 6
	iMariaList[6] = 7
	iMariaList[7] = 8
	iMariaList[8] = 9
	iMariaList[9] = 90
	iMariaList[10] = 100

	iMariaList = New Int[2]
	iMariaList[0] = 1
	iMariaList[1] = 8

	If aiOption == oidRegisterSexLab
		SetOptionFlags(oidRegisterSexLab, a_flags = OPTION_FLAG_DISABLED, a_noUpdate = False)
		SexLab.RegisterForSexLab()
		ForcePageReset()

	ElseIf aiOption == oidReleaseAi
		Main.ReleaseAllAiRefs()
		bForceAi = False
		ForcePageReset()

	ElseIf aiOption == oidResetControls
		Game.EnablePlayerControls()
		ForcePageReset()

	ElseIf aiOption == oidForceAi
		Parent.OnOptionSelect(aiOption)
		If bForceAi
			Main.RetainAi()
		Else
			Main.ReleaseAi()
		EndIf
		ForcePageReset()

	ElseIf aiOption == oidFilterActor1
		Parent.OnOptionSelect(aiOption)
		ForcePageReset()

	ElseIf aiOption == oidFilterActor2
		Parent.OnOptionSelect(aiOption)
		ForcePageReset()

	ElseIf aiOption == oidRebuildBaseAnimations
		SexLab.RebuildBaseAnimations()
		ForcePageReset()

	ElseIf aiOption == oidAnimationHelp
		ShowMessage("$ZazAP_AnimationHelp", a_withCancel = False)

	ElseIf aiOption == oidTestButton
		SexLab.CreateThreadAuto(Game.GetPlayer(), Game.GetCurrentCrosshairRef() As Actor).StartThread()
		ForceCloseMenu()

	ElseIf aiOption == oidDebugLogging
		Parent.OnOptionSelect(aiOption)
		SexLab.iDebugLevel = 2 * (bDebugLogging As Int)
		Main.iDebugLevel = 2 * (bDebugLogging As Int)
		iDebugLevel = 2 * (bDebugLogging As Int)

	ElseIf aiOption == oidPlayIdleAnimation
		Debug.SendAnimationEvent(Game.GetPlayer(), sSelectedAnimationEvent)
		Debug.MessageBox("Menu will now close.\n" + sSelectedAnimationEvent + " will start playing.")
		ForceCloseMenu()

	ElseIf aiOption == oidPlaySexLabAnimation
		Debug.MessageBox("Menu will now close.\n" + SelectedBaseEntry.BaseId + " will start playing.")
		SexLab.PlayAnimationHelper(SelectedBaseEntry, Game.GetPlayer(), Game.GetCurrentCrosshairRef() As Actor, sSelectedSexLabActor1Base, sSelectedSexLabActor2Base)
		ForceCloseMenu()

	ElseIf aiOption == oidRestart
		Log("OnOptionSelect", "Restarting quests. Sending ForceUpdatEvent.")
		ForceUpdateEvent(CurrentVersion, CurrentVersion)
		ForcePageReset()

	Else
		Parent.OnOptionSelect(aiOption)
	EndIf
EndEvent

Int Property iDebugLevel Auto Hidden
Int iForce = -1
Int iError = 0
Int iWarning = 1
Int iInfo = 2
String sFilePrefix = "zbfConfig"
Function Log(String asMethod, String asMessage, Int aiLevel = 2, Bool abCondition = True)
	If abCondition && (aiLevel <= iDebugLevel)
		Debug.Trace(sFilePrefix + " (" + asMethod + "): " + asMessage)
	EndIf
EndFunction
