Scriptname TW_Script_Q01_ThrowQuest extends ReferenceAlias  

Import Game

;Properties
;------------------------------------------------------

FORMLIST Property ThrowingAxeList  Auto 
FORMLIST Property ThrowingAxeSpellList  Auto 
FORMLIST Property ThrowingAxeSpellHiddenList  Auto 
FORMLIST Property ThrowingAxeQuiverList Auto

FORMLIST Property ThrowingKnifeList  Auto 
FORMLIST Property ThrowingKnifeSpellList  Auto 
FORMLIST Property ThrowingKnifeSpellHiddenList  Auto 
FORMLIST Property ThrowingKnifeQuiverList Auto

FORMLIST Property ThrowingJavelinList  Auto 
FORMLIST Property ThrowingJavelinSpellList  Auto 
FORMLIST Property ThrowingJavelinSpellHiddenList  Auto 
FORMLIST Property ThrowingJavelinQuiverList Auto
FORMLIST Property ThrowingJavelinGlobalList Auto

FORMLIST Property ThrowingGrenadeList  Auto 
FORMLIST Property ThrowingGrenadeSpellList  Auto 
FORMLIST Property ThrowingGrenadeSpellHiddenList  Auto 
FORMLIST Property ThrowingGrenadeQuiverList Auto

KEYWORD Property ThrowKeywordProperty Auto
KEYWORD Property AxeKeywordProperty Auto
KEYWORD Property KnifeKeywordProperty Auto
KEYWORD Property JavelinKeywordProperty Auto
KEYWORD Property PotionKeywordProperty Auto

PERK Property PerkPairedBlades Auto
PERK Property PerkNullWeaponDamage Auto
PERK Property PerkActivateQuivers Auto

SPELL Property SpellBreakInvis Auto
;------------------------------------------------------

;Variables
;------------------------------------------------------

WEAPON WeaponEquippedRight
WEAPON WeaponEquippedLeft

SPELL ThrowingAbilityRight
SPELL ThrowingAbilityRightHidden
SPELL ThrowingAbilityLeft
SPELL ThrowingAbilityLeftHidden

AMMO ThrowingQuiver

BOOL SneakAttack
BOOL OnAttack
BOOL PairedDrop = False

GLOBALVARIABLE BaseDamage
;------------------------------------------------------

;Event is called when player equips a weapon
;--------------------------------------------------------------------------------------------------------------
Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)

	Int WeaponHand
	
	;Compares equipped weapon with list of throwing weapons.
	If !(akBaseObject.HasKeyword(ThrowKeywordProperty))
		;If weapon is not in the list then the script stops
		UnregisterAnims(akBaseObject)
		Return	
	EndIf
	
	Game.GetPlayer().RemoveItem(ThrowingQuiver, 1, true)
	
	;Checks if equipped weapon is in the right hand.
	If (Game.GetPlayer().GetEquippedWeapon() == akBaseObject)
		WeaponHand = 0
	;Checks if equipped weapon is in the left hand.
	ElseIf(Game.GetPlayer().GetEquippedWeapon(true) == akBaseObject)
		WeaponHand = 1
	EndIf

	If akBaseObject.HasKeyword(AxeKeywordProperty)
		WeaponRegister(WeaponHand, akBaseObject, ThrowingAxeList, ThrowingAxeSpellList, ThrowingAxeSpellHiddenList, ThrowingAxeQuiverList)
	ElseIf akBaseObject.HasKeyword(KnifeKeywordProperty)
		WeaponRegister(WeaponHand, akBaseObject, ThrowingKnifeList, ThrowingKnifeSpellList, ThrowingKnifeSpellHiddenList, ThrowingKnifeQuiverList)
	ElseIf akBaseObject.HasKeyword(JavelinKeywordProperty)
		WeaponRegister(WeaponHand, akBaseObject, ThrowingJavelinList, ThrowingJavelinSpellList, ThrowingJavelinSpellHiddenList, ThrowingJavelinQuiverList)
	ElseIf akBaseObject.HasKeyword(PotionKeywordProperty)
		WeaponRegister(WeaponHand, akBaseObject, ThrowingGrenadeList, ThrowingGrenadeSpellList, ThrowingGrenadeSpellHiddenList, ThrowingGrenadeQuiverList)
	EndIf

EndEvent
;--------------------------------------------------------------------------------------------------------------

;Detects when an object has been un-equipped
;--------------------------------------------------------------------------------------------------------------
Event OnObjectUnequipped(Form akBaseObject, ObjectReference akReference)
	
	;If the unequipped weapon is not a throwing weapon then ignore
	If !(akBaseObject.HasKeyword(ThrowKeywordProperty))
		Return
	EndIf
	
	;If the removed weapon is the weapon equipped from the right hand
	If (akBaseObject == WeaponEquippedRight)
		;The variables of the equipped weapons and spells are reverted to null and animations are unregistered
		if (Utility.IsInmenumode())
			Utility.WaitMenumode(0.5)
		else
			Utility.Wait(0.5)
		endif
		If !(Game.GetPlayer().GetEquippedWeapon(False) == WeaponEquippedRight)
			UnregisterForAnimationEvent(game.GetPlayer(), "WeaponSwing")	
			WeaponEquippedRight = None	
			ThrowingAbilityRight = None
			ThrowingAbilityRightHidden = None
			Game.getPlayer().RemoveItem(ThrowingQuiver, 1, true)
		Endif
	EndIf
	
	If  (akBaseObject == WeaponEquippedLeft)
		if (Utility.IsInmenumode())
			Utility.WaitMenumode(0.5)
		else
			Utility.Wait(0.5)
		endif
		if !(Game.GetPlayer().GetEquippedWeapon(True) == WeaponEquippedLeft)
			UnregisterForAnimationEvent(game.GetPlayer(), "WeaponLeftSwing")
			WeaponEquippedLeft = None 
			ThrowingAbilityLeft = None	
			ThrowingAbilityLeftHidden = None
			Game.getPlayer().RemoveItem(ThrowingQuiver, 1, true)
		Endif
	endif
	
EndEvent
;--------------------------------------------------------------------------------------------------------------

;Event is called when player causes an animation event
;--------------------------------------------------------------------------------------------------------------
Event OnAnimationEvent(ObjectReference akSource, string asEventName)
	
	Int Hand
	ObjectReference TempWeapon

	;If the player did not cause the animation event then ignore
	If ! (akSource == game.GetPlayer())
		Return
	EndIf	
	
	If SneakAttack == True
		Return
	EndIf
	
	OnAttack = True
	
	;If the animation event is a right hand swing
	If (asEventName == "WeaponSwing")
		Hand = 0
		WeaponThrow(WeaponEquippedRight, 0, 0)	
	;If the animation event is a left hand swing
	ElseIf (asEventName == "WeaponLeftSwing")
		Hand = 1
		WeaponThrow(WeaponEquippedLeft, 1, 0)
	Else
		OnAttack = False
	EndIf
	
	If Game.GetPlayer().IsSneaking()
		SneakAttack = True
		RegisterForSingleUpdate(0.3)
	EndIf
	
	If OnAttack == True
		If Hand == 0
			Game.GetPlayer().DropObject(WeaponEquippedRight, 1)
			If (WeaponEquippedRight.HasKeyword(KnifeKeywordProperty)) && (Game.GetPlayer().HasPerk(PerkPairedBlades))
				WeaponThrow(WeaponEquippedRight, 0, 0)
				OnAttack = True
				Game.GetPlayer().DropObject(WeaponEquippedRight, 1)
			EndIf
		ElseIf Hand == 1
			Game.GetPlayer().DropObject(WeaponEquippedLeft, 1)
			If (WeaponEquippedLeft.HasKeyword(KnifeKeywordProperty)) && (Game.GetPlayer().HasPerk(PerkPairedBlades))
				WeaponThrow(WeaponEquippedLeft, 1, 0)
				OnAttack = True
				Game.GetPlayer().DropObject(WeaponEquippedLeft, 1)
			EndIf
		EndIf
	EndIf

EndEvent
;--------------------------------------------------------------------------------------------------------------

;Detects in an object has been removed from the player
;--------------------------------------------------------------------------------------------------------------
Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)

	If (OnAttack == True)
			akItemReference.DisableNoWait()	
			akItemReference.delete()		
			
			If (akBaseItem == WeaponEquippedRight)
				OnAttack = False
				WeaponEquippedRight = akBaseItem as Weapon
			ElseIf (akBaseItem == WeaponEquippedLeft)
				OnAttack = False
				WeaponEquippedLeft = akBaseItem as Weapon
			EndIf	
	EndIf
EndEvent

Event OnUpdate()
	SneakAttack = False
EndEvent

;Stops the detection of animation events
;--------------------------------------------------------------------------------------------------------------
Function UnregisterAnims(Form akObject)
	if (game.GetPlayer().GetEquippedWeapon() == akObject as Weapon)
		UnregisterForAnimationEvent(game.GetPlayer(), "WeaponSwing")
	endif
	if (game.GetPlayer().GetEquippedWeapon(true) == akObject as Weapon)
		UnregisterForAnimationEvent(game.GetPlayer(), "WeaponLeftSwing")
	endif
endFunction
;--------------------------------------------------------------------------------------------------------------

;Cycles through the elements in a formlist
;--------------------------------------------------------------------------------------------------------------
Int Function GetFormListIndex(FormList akFormList, Form akBaseObject) global

	Int Index = 0
	Int maxIdx = akFormList.GetSize()
	While (Index < maxIdx && (akFormList.GetAt(index) != akBaseObject))
		Index += 1
	EndWhile
	if (Index == maxIdx)
		Return -1
	else
		Return index
	endif
	
EndFunction
;--------------------------------------------------------------------------------------------------------------

;Handles the actual throwing of the weapons.
;--------------------------------------------------------------------------------------------------------------
Function WeaponThrow(Weapon ShootingWeapon, Int Hand, Int isDual)

	SPELL TempSpell
	SPELL TempSpellHidden

	WEAPON TempWeapon
	INT WeaponType
	
	If (Hand == 0)
		TempWeapon = ShootingWeapon
		TempSpell = ThrowingAbilityRight
		TempSpellHidden = ThrowingAbilityRightHidden
	Endif
	
	If (Hand == 1)
		TempWeapon = ShootingWeapon
		TempSpell = ThrowingAbilityLeft
		TempSpellHidden = ThrowingAbilityLeftHidden
	Endif

	If (TempSpellHidden && TempSpellHidden != TempSpell)
		TempSpellHidden.Cast(Game.GetPlayer())
	EndIf

	if (TempSpell)
		TempSpell.Cast(Game.GetPlayer())
		SpellBreakInvis.Cast(Game.GetPlayer())
	endif
EndFunction
;--------------------------------------------------------------------------------------------------------------

Function WeaponRegister(Int HandUse, Form BaseObject, FormList WeaponList, FormList SpellList, FormList SpellHiddenList, FormList QuiverList)

	Int IntBaseDamage

	If HandUse == 0
		;The index of the right hand equipped weapon in the form list is used to find the spell associated with
		;equipped throwing weapon. The animation event for a right swing is then registered for.
		RegisterForAnimationEvent(Game.GetPlayer(), "WeaponSwing")
		WeaponEquippedRight = game.GetPlayer().GetEquippedWeapon()

		int indexR = GetFormListIndex(WeaponList, BaseObject)
		if (indexR > -1)
			ThrowingAbilityRight = SpellList.GetAt(indexR) as Spell
			ThrowingAbilityRightHidden = SpellHiddenList.GetAt(indexR) as Spell
			Game.GetPlayer().GetEquippedWeapon().SetReach(0.0)
		else
			ThrowingAbilityRight = None
			ThrowingAbilityRightHidden = None
		endif
	ElseIf HandUse == 1	
		;The index of the left hand equipped weapon in the form list is used to find the spell associated with
		;equipped throwing weapon. The animation event for a left swing is then registered for.
		RegisterForAnimationEvent(Game.GetPlayer(), "WeaponLeftSwing")
		WeaponEquippedLeft = game.GetPlayer().GetEquippedWeapon(True)

		int indexL = GetFormListIndex(WeaponList, BaseObject)
		if (indexL > -1)
			ThrowingAbilityLeft = SpellList.GetAt(indexL) as Spell
			ThrowingAbilityLeftHidden = SpellHiddenList.GetAt(indexL) as Spell
			Game.GetPlayer().GetEquippedWeapon(True).SetReach(0.0)
		else
			ThrowingAbilityLeft = None
			ThrowingAbilityLeftHidden = None
		endif
	EndIf

	int indexQ = GetFormListIndex(WeaponList, BaseObject)
	if (indexQ > -1)
		ThrowingQuiver = QuiverList.GetAt(indexQ) as Ammo
	else
		ThrowingQuiver = None
	endif

	If (ThrowingQuiver && Game.GetPlayer().HasPerk(PerkActivateQuivers) == False)
		utility.wait(0.1)
		Game.GetPlayer().EquipItem(ThrowingQuiver, true, true)
	EndIf
	
EndFunction