Scriptname _00E_Playerhousing_MannequinControl extends Actor  

import utility

Actor Property PlayerREF Auto

Bool bIsInPlacementMode = False
Bool bActivationBlocked = False


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

Event OnCellLoad()
	If bIsInPlacementMode == False
		ResetOnLoad()
	EndIf
EndEvent

Event OnLoad()
	If bIsInPlacementMode
		ResetOnLoad()
	EndIf
EndEvent

Event OnActivate(ObjectReference TriggerRef)
	If TriggerRef == PlayerREF && _00E_PlayerhousingMaster.ReferenceCanBeActivated(self) && bActivationBlocked == False
		bActivationBlocked = True

		ConvertArmorSlots() ; Version update

		OpenInventory(True)
		ResetPosition()
		Wait(0.1)
		EnableAI(False)

		bActivationBlocked = False
	EndIf
EndEvent

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
	If (akBaseItem as Armor)
		If TryRegisterAddedArmor(akBaseItem)
			EquipItem(akBaseItem)
		Else
			;Turn it back if the mannequin has one of these already, or if all the slots are full.
			RemoveItem(akBaseItem, aiItemCount, True, PlayerREF)
		EndIf
	Else
		RemoveItem(akBaseItem, aiItemCount, True, PlayerREF)
	EndIf
EndEvent

Event OnObjectUnequipped(Form akBaseObject, ObjectReference akReference)
	If (akBaseObject as Armor)
		UnregisterRemovedArmor(akBaseObject)
	EndIf
EndEvent


;=====================================================================================
;              					ARMOR SLOTS TRACKING
;=====================================================================================

Form Property ArmorSlot01 Auto Hidden ; Obsolete. Left for version updates on older saves.
Form Property ArmorSlot02 Auto Hidden ; Obsolete. Left for version updates on older saves.
Form Property ArmorSlot03 Auto Hidden ; Obsolete. Left for version updates on older saves.
Form Property ArmorSlot04 Auto Hidden ; Obsolete. Left for version updates on older saves.
Form Property ArmorSlot05 Auto Hidden ; Obsolete. Left for version updates on older saves.
Form Property ArmorSlot06 Auto Hidden ; Obsolete. Left for version updates on older saves.
Form Property ArmorSlot07 Auto Hidden ; Obsolete. Left for version updates on older saves.
Form Property ArmorSlot08 Auto Hidden ; Obsolete. Left for version updates on older saves.
Form Property ArmorSlot09 Auto Hidden ; Obsolete. Left for version updates on older saves.
Form Property ArmorSlot10 Auto Hidden ; Obsolete. Left for version updates on older saves.

Form[] ArmorSlots
Bool bConvertedArmorSlots = False

Function ConvertArmorSlots()
	If bConvertedArmorSlots
		Return
	EndIf
	bConvertedArmorSlots = True

	ArmorSlots = New Form[10]

	Int index = _ConvertArmorSlot(0, ArmorSlot01)
	index = _ConvertArmorSlot(index, ArmorSlot02)
	index = _ConvertArmorSlot(index, ArmorSlot03)
	index = _ConvertArmorSlot(index, ArmorSlot04)
	index = _ConvertArmorSlot(index, ArmorSlot05)
	index = _ConvertArmorSlot(index, ArmorSlot06)
	index = _ConvertArmorSlot(index, ArmorSlot07)
	index = _ConvertArmorSlot(index, ArmorSlot08)
	index = _ConvertArmorSlot(index, ArmorSlot09)
	index = _ConvertArmorSlot(index, ArmorSlot10)

	ArmorSlot01 = None
	ArmorSlot02 = None
	ArmorSlot03 = None
	ArmorSlot04 = None
	ArmorSlot05 = None
	ArmorSlot06 = None
	ArmorSlot07 = None
	ArmorSlot08 = None
	ArmorSlot09 = None
	ArmorSlot10 = None
EndFunction

Int Function _ConvertArmorSlot(Int index, Form armorItem)
	If armorItem && ArmorSlots.Find(armorItem) < 0
		ArmorSlots[index] = armorItem
		index += 1
	EndIf

	Return index
EndFunction

Bool Function TryRegisterAddedArmor(Form armorItem)
	; First check to see if this is already in a slot
	If ArmorSlots.Find(armorItem) >= 0
		Return False
	EndIf
		
	; Now find an emtpy slot to put it in, if there is one.
	Int i = 0
	While i < ArmorSlots.Length
		If ArmorSlots[i] == None
			ArmorSlots[i] = armorItem
			Return True
		EndIf

		i += 1
	EndWhile
	
	; Nope. No room left.
	Return False
EndFunction

Function UnregisterRemovedArmor(Form armorItem)
	;This loop will also clear duplicates that might have been generated.
	Int i = 0
	While i < ArmorSlots.Length
		If ArmorSlots[i] == armorItem
			ArmorSlots[i] = None
		EndIf
		i += 1
	EndWhile
EndFunction

Function ReequipAllArmor()
	UnequipAll()

	Int i = 0
	While i < ArmorSlots.Length
		If ArmorSlots[i]
			EquipItem(ArmorSlots[i])
		EndIf
		i += 1
	EndWhile
EndFunction


;=====================================================================================
;              							FUNCTIONS
;=====================================================================================

Float forceX
Float forceY
Float forceZ
Float forceAngleX
Float forceAngleY
Float forceAngleZ

Bool bPosisionValidated = False

Function ResetPosition()
	If bPosisionValidated == False
		bPosisionValidated = True

		If forceX == 0 && forceY == 0 && forceZ == 0
			Float fAngleZ = PlayerREF.GetAngleZ()
			Float fDistanceFromPlayer = 100.0

			forceX = PlayerREF.GetPositionX() + fDistanceFromPlayer * Math.sin(fAngleZ)
			forceY = PlayerREF.GetPositionY() + fDistanceFromPlayer * Math.cos(fAngleZ)
			forceZ = PlayerREF.GetPositionZ()
		EndIf
	EndIf

	SetPosition(forceX, forceY, forceZ)
	SetAngle(forceAngleX, forceAngleY, forceAngleZ)
EndFunction

Function ResetOnLoad()
	ConvertArmorSlots() ; Version update

	BlockActivation()

	EnableAI(True)
	If bIsInPlacementMode == False
		ResetPosition()
	EndIf
	ReequipAllArmor()
	EnableAI(False)
EndFunction

Function StartPlacement()
	bIsInPlacementMode = True
EndFunction

Function FinishPlacement()
	bIsInPlacementMode = False

	Disable()

	forceX = GetPositionX()
	forceY = GetPositionY()
	forceZ = GetPositionZ()
	forceAngleX = GetAngleX()
	forceAngleY = GetAngleY()
	forceAngleZ = GetAngleZ()

	bPosisionValidated = True

	Enable()

	_00E_Func_WaitForRef.WaitForReferenceToLoad(self)
	ResetOnLoad()
EndFunction