scriptName MineOreScript extends objectReference
;
;This script handles the Ore Veins and handshakes with the mining furniture
;===================================================================


sound property DrScOreOpen auto
{sound played when Ore is acquired}

formlist property mineOreToolsList auto
{Optional: Player must have at least one item from this formlist to interact}

Message Property FailureMessage Auto  
{Message to say why you can't use this without RequiredWeapon}

Message Property DepletedMessage Auto  
{Message to say that this vein is depleted}

MiscObject Property Ore Auto  
{what you get from this Ore Vein}

LeveledItem property lItemGems10 auto
{Optional: Gems that may be mined along with ore}

int Property ResourceCount = 1 Auto
{how many resources you get per drop}

int property ResourceCountTotal = 3 auto
{how many resources this has before it is depleted}

int property ResourceCountCurrent = -1 auto Hidden
{Used to track the current remaining resources}

int property StrikesBeforeCollection = 1 Auto
{how many times this is struck before giving a resource}

int property StrikesCurrent = -1 Auto hidden
{Current number of strikes}

int property AttackStrikesBeforeCollection = 3 Auto
{how many times this is struck by attacks before giving a resource}

int property AttackStrikesCurrent = -1 Auto hidden
{Current number of attack strikes}

Actor Property PlayerREF Auto

GlobalVariable Property _00E_OreVeinsMined Auto

Form[] EquippedTorches

Bool PlayerIsInFurniture = False

Bool PlayerActivationLocked = False


;===================================================================
;;EVENT BLOCK
;===================================================================

event onCellAttach()
	; debug.Trace(self + ": is running onCellAttach")
	blockActivation()
	SetNoFavorAllowed()

	If !PlayerREF ; Just in case
		PlayerREF = Game.GetPlayer()
	EndIf

	if !getLinkedRef()
		; debug.Trace(self + ": does not have a linked ref, going to depleted state")
		depleteOreDueToFailure()
	endif

	; Failsafes
	PlayerIsInFurniture = False 
	PlayerActivationLocked = False

	Int iHand = 0
	While iHand < EquippedTorches.Length
		EquippedTorches[iHand] = None
		iHand += 1
	EndWhile
endEvent

Event OnUnload()
	; Do not do here failsafes or safety measures. The event is triggered on the vein's depletion
endEvent

Function TryPlayerActivate(ObjectReference myLinkedRef)
	If PlayerIsInFurniture == False || myLinkedRef.isFurnitureInUse() == False ; Entering the furniture

		; Fail if the player is in combat
		; Yes, the furniture has a check for this built into the engine, but the furniture's code has no way to know about it,
		; so if the player IS in combat, the furniture still enters the "busy" state and does not leave it until a second try by the player or until it's unloaded.
		; The check is not a panacea for this bug, but it decreases the probability of it happening.
		; As a bonus, this early check prevents useless fail messages, forced exit from sneaking, and so on.
		If PlayerREF.IsInCombat()
			Debug.Notification(Game.GetGameSettingString("sCombatCannotActivate"))
			Return
		EndIf

		If ResourceCountCurrent == 0
			DepletedMessage.Show()
			Return
		EndIf

		If PlayerREF.GetItemCount(mineOreToolsList) < 1
			FailureMessage.Show()
			Return
		EndIf

		;USKP 1.3.0 FixStart - Deactivate sneaking before mining to prevent sneak issues.
		if PlayerREF.IsSneaking()
			PlayerREF.StartSneaking()
		EndIf
		;USKP 1.3.0 FixEnd

		EquippedTorches = New Form[2]
		If (PlayerREF as _00E_PlayerFunctions).UnequipTorches(EquippedTorches)
			Utility.Wait(0.25) ; Give some time for torch unequip animations to settle
		EndIf

		; Do combat check again (up to one third of a second may have passed since the previous check)
		If PlayerREF.IsInCombat()
			Debug.Notification(Game.GetGameSettingString("sCombatCannotActivate"))
			Return
		EndIf

		PlayerIsInFurniture = True
	EndIf

	(myLinkedRef as mineOreFurnitureScript).lastActivateRef = self
	myLinkedRef.activate(PlayerREF)

	; Give some time for the animations to warm up/settle down before we can start reacting on OnActivate again.
	; Without this the furniture (MineOreFurnitureScript) may get stuck in "reseting" state until it's unloaded.
	Utility.Wait(1)

EndFunction

event onActivate(objectReference akActivator)
	; debug.Trace(self + ": onActivate by " + akActivator)	

	ObjectReference myLinkedRef = GetLinkedRef()
	If !myLinkedRef
		Debug.Trace(self + " error: this ore does not have a linkedRef")
		Return
	EndIf

	;Actor is attempting to mine
	if akActivator as actor
		;if the actor is the player
		if akActivator == PlayerREF
			If PlayerActivationLocked == False
				PlayerActivationLocked = True
				TryPlayerActivate(myLinkedRef)
				PlayerActivationLocked = False
			EndIf
		Else
			myLinkedRef.Activate(akActivator)
		EndIf
		
	;Furniture is telling ore it has been struck	
	ElseIf akActivator == myLinkedRef
		; debug.Trace(self + ": has been activated by" + akActivator)
		ProccessStrikes()
			
	;Something unexpected has activated the ore
	Else
		; debug.Trace(self + "has been activated by: " + akActivator + " why?")
	endif

endEvent

;;;May add on hit with pickaxe here later
Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)

	; ADDED IN ENDERAL - FORGOTTEN STORIES
	
	if ResourceCountCurrent == -1
		ResourceCountCurrent = ResourceCountTotal
	EndIf
	
	_00E_FS_ForgottenStories_Functions _00E_FS_ControlQuest = Game.GetFormFromFile(0x01016E89, "Enderal - Forgotten Stories.esm") as _00E_FS_ForgottenStories_Functions
	_00E_FS_ControlQuest.TransmuteOre(akSource, self as MineOreScript, ResourceCountCurrent)
	
	; ADDED IN ENDERAL - FORGOTTEN STORIES

 	; debug.Trace(self + ": onHit - akAgressor = " + akAggressor + "; akSource = " + akSource)
	if akAggressor == PlayerREF	
		if mineOreToolsList.hasForm(akSource)			
			proccessAttackStrikes()
		endif
	endif

	
endEvent

event onReset()
	; debug.Trace(self + ": is running onReset")
	;THIS WASN'T WORKING RIGHT
	self.Reset()
	self.clearDestruction()
	self.setDestroyed(False)
	; if getLinkedRef()
		resourceCountCurrent = -1
	; else
		; depleteOreDueToFailure()
	; endif
	;USKP 1.3.0 FixStart - if ore is enabled then disable and enable to avoid becoming un-mineable upon respawn.
	if self.isEnabled()
		self.disable()
		self.enable()
	endif
	;USKP 1.3.0 FixEnd
endEvent

; Called from the linkedRef (MineOreFurnitureScript)
Function OnFurnitureExit()
	; Debug.Trace(self + ": OnFurnitureExit")
	If PlayerIsInFurniture
		PlayerIsInFurniture = False
		(PlayerREF as _00E_PlayerFunctions).ReequipTorches(EquippedTorches)
	EndIf
EndFunction

;===================================================================
;;FUNCTION BLOCK
;===================================================================

function proccessAttackStrikes()
	if AttackStrikesCurrent <= -1
		AttackStrikesCurrent = AttackStrikesBeforeCollection
	EndIf
	AttackStrikesCurrent -= 1
	
	if AttackStrikesCurrent == 0
		AttackstrikesCurrent = AttackStrikesBeforeCollection
		giveOre()
	endIf
endFunction

function proccessStrikes()
	if StrikesCurrent <= -1
		StrikesCurrent = StrikesBeforeCollection
	EndIf
	StrikesCurrent -= 1
	
	if StrikesCurrent == 0
		strikesCurrent = StrikesBeforeCollection
		giveOre()
	endIf
endFunction

function giveOre()
	ObjectReference myLinkedRef = GetLinkedRef()
	If !myLinkedRef
		Debug.Trace(self + " error: this ore does not have a linkedRef")
		Return
	EndIf

	if ResourceCountCurrent == -1
		ResourceCountCurrent = ResourceCountTotal
	EndIf
	
	if ResourceCountCurrent > 0
		ResourceCountCurrent -= 1
		; debug.Trace(self + ": ResourceCountCurrent = " + ResourceCountCurrent)
		if ResourceCountCurrent == 0
			
			; debug.Trace(self + ": ResourceCountCurrent == 0 - depleted" )
			self.damageObject(50)
			myLinkedRef.activate(self)
			DrScOreOpen.play(self)
			self.setDestroyed(true)
			; if this vein has ore and/or gems defined, give them.
			if ore
				PlayerREF.addItem(Ore, ResourceCount)
			endif
			if lItemGems10
				PlayerREF.addItem(lItemGems10)
			endif
			_00E_OreVeinsMined.SetValueInt(_00E_OreVeinsMined.GetValueInt() +1)
			DepletedMessage.Show()
			
		else
			DrScOreOpen.play(self)
			; if this vein has ore and/or gems defined, give them.
			if ore
				PlayerREF.addItem(Ore, ResourceCount)
			endif
			if lItemGems10
				PlayerREF.addItem(lItemGems10)
			endif
		endif
	elseif ResourceCountCurrent == 0
		myLinkedRef.activate(self)
		(myLinkedRef as MineOreFurnitureScript).goToDepletedState()
		DepletedMessage.Show()
	endif

EndFunction

function depleteOreDueToFailure()
	self.damageObject(50)
	;THIS WASN'T WORKING RIGHT
	self.setDestroyed(true)
	ResourceCountCurrent = 0
endFunction