Scriptname _00E_Phasmalist_Workbench extends ObjectReference  
; script that is attached to all phasmalist workbenches and manages their gui and functions

Message Property illegalTrinket Auto
{Message objects whose title is the message that is displayed when the player tries to summon an apparition but wears no phasmalist trinket object}
Message Property reallyDespectralize Auto
_FS_Phasmalist_ControlQuest Property phasmalistControlQuest Auto
ObjectReference Property spectralizerContainer Auto
{the container items that should be spectralized are put in; should be the same for all workbenches}

ObjectReference Property _00E_Phasmalist_DespectralizingContainerReference Auto

Keyword Property _00E_Phasmalist_CraftingWorkbench_NPCMarker Auto
Actor Property PlayerREF Auto
Message Property _00E_Theriantrophist_CantCraftMSG Auto
Race Property _00E_Theriantrophist_PlayerWerewolfRace Auto
GlobalVariable Property _00E_Phasmalist_TankMode Auto
Static Property _00E_NPCMarkerBlue Auto

Bool bApparitionPrepared = False
bool bApparitionSummoned = False

String Property CRAFTING_MENU = "Crafting Menu" AutoReadOnly
String Property CONTAINER_MENU = "ContainerMenu" AutoReadOnly


;=====================================================================================
;              							EVENTS
;=====================================================================================

Event OnInit()
	BlockActivation()
EndEvent

Event OnLoad()
	; Failsafes
	GoToState("")
	bApparitionPrepared = False
	bApparitionSummoned = False
	UnregisterForAllMenus()
EndEvent

Event OnActivate(ObjectReference akActionRef)
	If akActionRef == PlayerREF
		GoToState("Waiting")

		If _00E_PlayerhousingMaster.ReferenceCanBeActivated(Self)
			If PlayerREF.GetRace() == _00E_Theriantrophist_PlayerWerewolfRace
				_00E_Theriantrophist_CantCraftMSG.Show()
			Else
				ShowMainMenu()
				Return
			EndIf
		EndIf

		GoToState("")
	Else
		Activate(akActionRef, true)
	EndIf
EndEvent

State Waiting
	Event OnActivate(ObjectReference akActionRef)
		; Do nothing
	EndEvent
EndState


;=====================================================================================
;              						PHASMALISM MENU
;=====================================================================================

; Summons the apparition and places it in the tank
Function PrepareApparition()
	If bApparitionPrepared == False
		ObjectReference tankMarkerRef = GetTankMarker()
		If bApparitionPrepared == False
			bApparitionPrepared = True
			_00E_Phasmalist_TankMode.SetValue(1)

			bApparitionSummoned = (phasmalistControlQuest.IsApparitionSpawned() == False)
			If tankMarkerRef 
				phasmalistControlQuest.SummonApparition(tankMarkerRef, True)
				Utility.Wait(0.1)
			ElseIf bApparitionSummoned ; Summon apparition to the player?
				phasmalistControlQuest.SummonApparition(PlayerREF, False)
			Else
				Actor akApparition = phasmalistControlQuest.GetApparitionRef()
				If akApparition.GetDistance(PlayerREF) > 512.0
					phasmalistControlQuest.TeleportApparitionToPlayer(False, True)
				EndIf
			EndIf
		EndIf
	EndIf
EndFunction

Function ResetApparitionOnInventoryChange()
	If bApparitionPrepared
		ObjectReference tankMarkerRef = GetTankMarker()
		Actor akApparition = phasmalistControlQuest.GetApparitionRef()
		If akApparition
			akApparition.Disable()
			Utility.Wait(0.05)
			akApparition.Enable()
			If tankMarkerRef
				akApparition.MoveTo(tankMarkerRef)
			EndIf
			Utility.Wait(0.1)
		EndIf
	EndIf
EndFunction

; Releases the apparition from the tank
Function ReleaseApparition()
	If bApparitionPrepared
		bApparitionPrepared = False
		_00E_Phasmalist_TankMode.SetValue(0)

		phasmalistControlQuest.UnsummonApparition()
		If bApparitionSummoned == False
			phasmalistControlQuest.SummonApparition(PlayerREF, False, True)
		EndIf
	EndIf
EndFunction

Function ShowMainMenu()
	If phasmalistControlQuest == None
		phasmalistControlQuest = _FS_Phasmalist_ControlQuest.getControlQuest()
	EndIf
	
	While _ShowMainMenu() == True
		; Repeat while _ShowMainMenu returns True
	EndWhile
EndFunction

Bool Function _ShowMainMenu()
	UIExtensions.initMenu("UIWheelMenu")
	UIExtensions.SetMenuPropertyIndexBool("UIWheelMenu", "optionEnabled", 0, true)
	UIExtensions.SetMenuPropertyIndexBool("UIWheelMenu", "optionEnabled", 4, true)
	UIExtensions.SetMenuPropertyIndexBool("UIWheelMenu", "optionEnabled", 5, true)
	UIExtensions.SetMenuPropertyIndexBool("UIWheelMenu", "optionEnabled", 1, true)
	UIExtensions.SetMenuPropertyIndexBool("UIWheelMenu", "optionEnabled", 6, true)
	UIExtensions.SetMenuPropertyIndexBool("UIWheelMenu", "optionEnabled", 2, true)
	
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionText", 0, "$Create_Talisman")
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionLabelText", 0, "$Create_Talisman")
	
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionText", 4, "$Equip")
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionLabelText", 4, "$Equip")
	
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionText", 5, "$Adapt_Combat_Style")
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionLabelText", 5, "$Adapt_Combat_Style")
	
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionText", 1, "$View_Attributes")
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionLabelText", 1, "$View_Attributes")
	
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionText", 6, "$Currently_Equipped")
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionLabelText", 6, "$Currently_Equipped")
	
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionText", 2, "$Quit")
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionLabelText", 2, "$Quit")
	
	Int iChoice = UIExtensions.OpenMenu("UIWheelMenu")
	If iChoice == 0
		RegisterForMenu(CRAFTING_MENU)
		phasmalistControlQuest.AddEnchantmentItem()
		ReleaseApparition()
		if ! self.IsFurnitureInUse()
			self.SendModEvent("Enderal_StartCreateTalisman")
		endif
		self.activate(PlayerREF, true)
		GoToState("")

	ElseIf iChoice == 1
		If ValidateEquippedTrinket()
			PrepareApparition()
			phasmalistControlQuest.ShowApparitionStats()
			Utility.Wait(0.1)
		EndIf
		Return True

	ElseIf iChoice == 4
		If ValidateEquippedTrinket()
			PrepareApparition()
			Return ShowEquipApparitionMenu()
		Else
			Return True
		EndIf

	ElseIf iChoice == 5
		If ValidateEquippedTrinket()
			PrepareApparition()
			phasmalistControlQuest.GetEquippedTrinket().ChooseApparitionCombatStyle()
			ResetApparitionOnInventoryChange()
		EndIf
		Return True

	ElseIf iChoice == 6
		If ValidateEquippedTrinket()
			PrepareApparition()
			phasmalistControlQuest.ShowApparitionEquipment()
			Utility.Wait(0.1)
		EndIf
		Return True

	Else ; Quit
		ReleaseApparition()
		self.SendModEvent("Enderal_FinishSpectralizing")
		GoToState("")

	EndIf

	Return False
Endfunction

Bool Function ValidateEquippedTrinket()
	If phasmalistControlQuest.IsTrinketEquipped() == False
		illegalTrinket.Show()
		Return False
	EndIf
	Return True
EndFunction

Event OnMenuClose(String MenuName)
	If MenuName == CRAFTING_MENU
		UnregisterForAllMenus()
		phasmalistControlQuest.RemoveEnchantmentItem()
	EndIf
EndEvent

Bool Function ShowEquipApparitionMenu()
	UIExtensions.initMenu("UIWheelMenu")
	UIExtensions.SetMenuPropertyIndexBool("UIWheelMenu", "optionEnabled", 0, true)
	UIExtensions.SetMenuPropertyIndexBool("UIWheelMenu", "optionEnabled", 1, true)
	UIExtensions.SetMenuPropertyIndexBool("UIWheelMenu", "optionEnabled", 4, true)

	
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionText", 0, "$Spectralize")
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionLabelText", 0, "$Spectralize")
	
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionText", 1, "$Despectralize")
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionLabelText", 1, "$Despectralize")
	
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionText", 4, "$Quit")
	UIExtensions.SetMenuPropertyIndexString("UIWheelMenu", "optionLabelText", 4, "$Quit")
	
	Int iChoice = UIExtensions.OpenMenu("UIWheelMenu")
	If iChoice == 0
		self.SendModEvent("Enderal_StartSpectralizing")
		GoToState("Spectralize")
		Return False
	ElseIf iChoice == 1
		GoToState("Despectralize")
		Return False
	Else
		Return True
	EndIf
EndFunction

State Spectralize
	Event OnBeginState()
		Actor akApparition = phasmalistControlQuest.GetApparitionRef()
		If akApparition
			String sApparitionName = akApparition.GetDisplayName()
			phasmalistControlQuest.spectralizeContainer.ForceRefTo(spectralizerContainer)
			spectralizerContainer.SetDisplayName(sApparitionName)
			spectralizerContainer.Activate(PlayerREF)
			RegisterForMenu(CONTAINER_MENU)
			; rest is done in OnMenuClosed
		Else
			GoToState("Waiting")
			ShowMainMenu()
		EndIf
	EndEvent

	Event OnMenuClose(String MenuName)
		UnregisterForAllMenus()

		Actor akApparition = phasmalistControlQuest.GetApparitionRef()
		If akApparition && phasmalistControlQuest.spectralizeContainer.evaluateAndClose(akApparition)
			ResetApparitionOnInventoryChange()
			phasmalistControlQuest.OnPlayerItemSpectralized()
		EndIf
		phasmalistControlQuest.spectralizeContainer.clear()
		self.SendModEvent("Enderal_FinishSpectralizing")
		GoToState("Waiting")
		ShowMainMenu()
	EndEvent
EndState

State Despectralize
	Event OnBeginState()
		Actor akApparition = phasmalistControlQuest.GetApparitionRef()
		If akApparition
			reallyDespectralize.show()
			
			; changed to this to "fix" the stolen flag on items
			If _00E_Phasmalist_DespectralizingContainerReference == None
				_00E_Phasmalist_DespectralizingContainerReference = Game.GetFormFromFile(0x0102F5AB, "Enderal - Forgotten Stories.esm") as ObjectReference
			EndIf
			
			akApparition.RemoveAllItems(_00E_Phasmalist_DespectralizingContainerReference, False, True)
			phasmalistControlQuest.despectralizeContainerAlias.ForceRefTo(_00E_Phasmalist_DespectralizingContainerReference)
			_00E_Phasmalist_DespectralizingContainerReference.SetDisplayName(akApparition.GetDisplayName())
			_00E_Phasmalist_DespectralizingContainerReference.Activate(PlayerREF)
			
			RegisterForMenu(CONTAINER_MENU)
			; rest is done in onMenuClosed
		Else
			GoToState("Waiting")
			ShowMainMenu()
		EndIf
	EndEvent
	
	Event OnMenuClose(String MenuName)
		UnregisterForAllMenus()

		phasmalistControlQuest.despectralizeContainerAlias.clear()
		_00E_Phasmalist_DespectralizingContainerReference.RemoveAllItems(phasmalistControlQuest.GetApparitionRef(), false, true)
		ResetApparitionOnInventoryChange()

		gotoState("Waiting")
		ShowMainMenu()
	EndEvent
EndState


;=====================================================================================
;              						PLACEABLE WORKBENCH
;=====================================================================================

ObjectReference PlaceableTankMarkerRef = None

Float Property FAST_TRANSLATION_SPEED = 1000000.0 AutoReadOnly

ObjectReference Function GetTankMarker()
	If PlaceableTankMarkerRef
		Return PlaceableTankMarkerRef
	EndIf

	Return GetlinkedRef(_00E_Phasmalist_CraftingWorkbench_NPCMarker)
EndFunction

Function StartPlacement()
	If PlaceableTankMarkerRef
		PlaceableTankMarkerRef.Disable()
	EndIf
EndFunction

Function OnPickUp()
	If PlaceableTankMarkerRef
		PlaceableTankMarkerRef.Disable()
		PlaceableTankMarkerRef.Delete()
		PlaceableTankMarkerRef = None
	EndIf
EndFunction

Function FinishPlacement()
	If PlaceableTankMarkerRef == None
		PlaceableTankMarkerRef = PlaceAtMe(_00E_NPCMarkerBlue, abInitiallyDisabled = True)
	Else
		PlaceableTankMarkerRef.Disable()
	EndIf

	; (Re)position the marker
	Float fOffsetX = -116.0
	Float fOffsetY = 5.0 ; 54 ; 22.4
	Float fOffsetZ = 20.0
	Float fOffsetAngleZ = 136.0

	Float fWorkbenchAngleZ = GetAngleZ()

	Float cosZ = Math.Cos(fWorkbenchAngleZ)
	Float sinZ = Math.Sin(fWorkbenchAngleZ)
	Float mx = GetPositionX() + fOffsetY * sinZ + fOffsetX * cosZ
	Float my = GetPositionY() + fOffsetY * cosZ - fOffsetX * sinZ
	Float mz = GetPositionZ() + fOffsetZ

	PlaceableTankMarkerRef.MoveTo(self)

	PlaceableTankMarkerRef.Enable()

	_00E_Func_WaitForRef.WaitForReferenceToLoad(PlaceableTankMarkerRef)

	PlaceableTankMarkerRef.TranslateTo(mx, my, mz, 0, 0, fWorkbenchAngleZ + fOffsetAngleZ, FAST_TRANSLATION_SPEED, FAST_TRANSLATION_SPEED)


	; PlaceableTankMarkerRef.SetPosition(mx, my, mz)
	; PlaceableTankMarkerRef.SetAngle(0, 0, fWorkbenchAngleZ + fOffsetAngleZ)

EndFunction