ScriptName aaaKimachuuReturningPotion Extends ActiveMagicEffect

Actor Property aaaKimachuuReturningPotionCRef Auto
Faction Property PlayerFaction Auto
FormList Property aaaKimachuuReturningPotionFL Auto
FormList Property aaaKimachuuReturningPotionExistFL Auto
Message Property aaaKimachuuReturningPotionMes01 Auto
Message Property aaaKimachuuReturningPotionMesL Auto
Message Property aaaKimachuuReturningPotionMesS Auto
ObjectReference Property aaaKimachuuReturningPotionMRef Auto
Potion Property aaaKimachuuReturningPotionALCH Auto
ReferenceAlias Property playerRA Auto

Actor actSelf

Bool bRun

String strPath = "../KimachuuReturningPotion/KimachuuReturningPotion.json"
String strPathItem = "../KimachuuReturningPotion/KimachuuReturningPotionItem.json"
String strPathSpell = "../KimachuuReturningPotion/KimachuuReturningPotionSpell.json"
String strPathPerk = "../KimachuuReturningPotion/KimachuuReturningPotionPerk.json"

Import ConsoleUtil
Import JsonUtil
Import PapyrusUtil
Import PO3_SKSEFunctions

Event OnEffectStart(Actor akTarget, Actor akCaster)
	Game.DisablePlayerControls()
	If bRun == True
		Game.EnablePlayerControls()
		Debug.Notification("Currently processing.")
		Return
	EndIf
	bRun = True
	Utility.Wait(0.1)
	actSelf = akTarget
	GoToState("MainState")
EndEvent

State MainState
	Event OnBeginState()
		Int iPotion = actSelf.GetItemCount(aaaKimachuuReturningPotionALCH)
		If iPotion >= 1
			actSelf.RemoveItem(aaaKimachuuReturningPotionALCH, iPotion, True)
		EndIf
		Int iIndex = aaaKimachuuReturningPotionMes01.Show()
		If iIndex == 0 ;ロード
			GoToState("LoadState")
		ElseIf iIndex == 1 ;セーブ
			GoToState("SaveState")
		Else ;キャンセル
			Game.EnablePlayerControls()
			potionCheckFunction(actSelf)
			bRun = False
			actSelf = None
		EndIf
	EndEvent
EndState

State LoadState
	Event OnBeginState()
		Int iIndex = aaaKimachuuReturningPotionMesL.Show()
		If iIndex == 0 ;値ロード
			loadFunction(actSelf)
			GoToState("MainState")
		ElseIf iIndex == 1 ;所持品ロード
			loadItemFunction(actSelf)
			GoToState("MainState")
		ElseIf iIndex == 2 ;魔法ロード
			loadSpellFunction(actSelf)
			GoToState("MainState")
		ElseIf iIndex == 3 ;Perkロード
			loadPerkFunction(actSelf)
			GoToState("MainState")
		ElseIf iIndex == 4 ;一括ロード
			loadFunction(actSelf)
			loadItemFunction(actSelf)
			loadSpellFunction(actSelf)
			loadPerkFunction(actSelf)
			Debug.Notification("All processes have been completed.")
			GoToState("MainState")
		Else ;キャンセル
			GoToState("MainState")
		EndIf
	EndEvent
EndState

State SaveState
	Event OnBeginState()
		Int iIndex = aaaKimachuuReturningPotionMesS.Show()
		If iIndex == 0 ;値セーブ
			saveFunction(actSelf)
			GoToState("MainState")
		ElseIf iIndex == 1 ;所持品セーブ
			saveItemFunction(actSelf)
			GoToState("MainState")
		ElseIf iIndex == 2 ;魔法セーブ
			saveSpellFunction(actSelf)
			GoToState("MainState")
		ElseIf iIndex == 3 ;Perkセーブ
			savePerkFunction(actSelf)
			GoToState("MainState")
		ElseIf iIndex == 4 ;一括セーブ
			saveFunction(actSelf)
			saveItemFunction(actSelf)
			saveSpellFunction(actSelf)
			savePerkFunction(actSelf)
			Debug.Notification("All processes have been completed.")
			GoToState("MainState")
		Else ;キャンセル
			GoToState("MainState")
		EndIf
	EndEvent
EndState

Function saveFunction(Actor act01)
	Debug.Notification("Stat: Please wait a moment.")
	string[] strArrayF = new string[22]
	strArrayF[0] = "health"
	strArrayF[1] = "magicka"
	strArrayF[2] = "stamina"
	strArrayF[3] = "oneHanded"
	strArrayF[4] = "twoHanded"
	strArrayF[5] = "marksman"
	strArrayF[6] = "block"
	strArrayF[7] = "smithing"
	strArrayF[8] = "heavyArmor"
	strArrayF[9] = "lightArmor"
	strArrayF[10] = "pickpocket"
	strArrayF[11] = "lockpicking"
	strArrayF[12] = "sneak"
	strArrayF[13] = "alchemy"
	strArrayF[14] = "speechcraft"
	strArrayF[15] = "alteration"
	strArrayF[16] = "conjuration"
	strArrayF[17] = "destruction"
	strArrayF[18] = "illusion"
	strArrayF[19] = "restoration"
	strArrayF[20] = "enchanting"
	strArrayF[21] = "carryweight"

	SetIntValue(strPath, "level", act01.GetLevel())
	SetIntValue(strPath, "perk", Game.GetPerkPoints())

	Int iSize = strArrayF.Length
	While iSize > 0
		iSize -= 1
		SetFloatValue(strPath, strArrayF[iSize], act01.GetBaseActorValue(strArrayF[iSize]))
	EndWhile

	aaaKimachuuReturningPotionRA scrRun = playerRA as aaaKimachuuReturningPotionRA
	scrRun.fCW = act01.GetActorValue("carryweight")

	If Save(strPath)
		Debug.Notification("Stat: Save completed.")
	Else
		Debug.Notification("ERROR. Save failed.")
	EndIf
EndFunction

Function loadFunction(Actor act01)
	If !JsonExists(strPath)
		Debug.Notification("Json file not found.")
		Return
	EndIf

	Debug.Notification("Stat: Please wait a moment.")
	string[] strArrayF = new string[22]
	strArrayF[0] = "health"
	strArrayF[1] = "magicka"
	strArrayF[2] = "stamina"
	strArrayF[3] = "oneHanded"
	strArrayF[4] = "twoHanded"
	strArrayF[5] = "marksman"
	strArrayF[6] = "block"
	strArrayF[7] = "smithing"
	strArrayF[8] = "heavyArmor"
	strArrayF[9] = "lightArmor"
	strArrayF[10] = "pickpocket"
	strArrayF[11] = "lockpicking"
	strArrayF[12] = "sneak"
	strArrayF[13] = "alchemy"
	strArrayF[14] = "speechcraft"
	strArrayF[15] = "alteration"
	strArrayF[16] = "conjuration"
	strArrayF[17] = "destruction"
	strArrayF[18] = "illusion"
	strArrayF[19] = "restoration"
	strArrayF[20] = "enchanting"
	strArrayF[21] = "carryweight"

	SetSelectedReference(act01)
	Int iLevel = GetIntValue(strPath, "level", 1)
	ExecuteCommand("SetLevel " + iLevel)

	Int iPerk = GetIntValue(strPath, "perk", 0)
	If iPerk > 127
		Game.SetPerkPoints(127)
	Else
		Game.SetPerkPoints(iPerk)
	EndIf

	Int iSize = strArrayF.Length
	While iSize > 0
		iSize -= 1
		act01.SetActorValue(strArrayF[iSize], GetFloatValue(strPath, strArrayF[iSize]))
	EndWhile

	aaaKimachuuReturningPotionRA scrRun = playerRA as aaaKimachuuReturningPotionRA
	scrRun.fCW = act01.GetActorValue("carryweight")

	Debug.Notification("Stat: Load completed.")
EndFunction

Function saveItemFunction(Actor obj01)
	ClearAll(strPathItem)
	aaaKimachuuReturningPotionFL.Revert()
	aaaKimachuuReturningPotionExistFL.Revert()
	obj01.SetAlpha(0.0)
	Debug.Notification("Item: Please wait a moment.")
	aaaKimachuuReturningPotionCRef.MoveTo(obj01)
	Int iItemN = obj01.GetNumItems()
	Int cIndex = 0
	Int rIndex = 0
	While cIndex < iItemN
		Int iType = obj01.GetNthForm(cIndex).GetType()
		Int iQItem = obj01.GetItemCount(obj01.GetNthForm(cIndex))
		If iQItem > 0
			FormListAdd(strPathItem, "items", obj01.GetNthForm(cIndex), True)
		EndIf
		If iType == 26 || iType == 41
			If obj01.IsEquipped(obj01.GetNthForm(cIndex))
				aaaKimachuuReturningPotionFL.AddForm(obj01.GetNthForm(cIndex))
			EndIf
			ObjectReference objItemRef = obj01.DropObject(obj01.GetNthForm(cIndex), 1)
			If aaaKimachuuReturningPotionExistFL.HasForm(objItemRef.GetBaseObject())
				iItemN += 1
			EndIf
			If objItemRef.GetEnchantment() != none
				SetIntValue(strPathItem, "enchantment" + rIndex, 1)
				IntListAdd(strPathItem, "quantity", 1, True)
				SetFloatValue(strPathItem, "currentcharge" + rIndex, objItemRef.GetItemCharge())
				SetFloatValue(strPathItem, "maxcharge" + rIndex, objItemRef.GetItemMaxCharge())
				Int iNumEffects = objItemRef.GetEnchantment().GetNumEffects()
				While iNumEffects > 0
					iNumEffects -= 1
					FormListAdd(strPathItem, "magiceffects" + rIndex, objItemRef.GetEnchantment().GetNthEffectMagicEffect(iNumEffects), true)
					FloatListAdd(strPathItem, "magnitude" + rIndex, objItemRef.GetEnchantment().GetNthEffectMagnitude(iNumEffects), true)
					IntListAdd(strPathItem, "area" + rIndex, objItemRef.GetEnchantment().GetNthEffectArea(iNumEffects), true)
					IntListAdd(strPathItem, "duration" + rIndex, objItemRef.GetEnchantment().GetNthEffectDuration(iNumEffects), true)
				EndWhile
				SetStringValue(strPathItem, "names" + rIndex, objItemRef.GetDisplayName())
			Else
				SetIntValue(strPathItem, "enchantment" + rIndex, 0)
				IntListAdd(strPathItem, "quantity", 1, true)
				SetStringValue(strPathItem, "names" + rIndex, objItemRef.GetDisplayName())
			EndIf
			SetFloatValue(strPathItem, "health" + rIndex, objItemRef.GetItemHealthPercent())
			aaaKimachuuReturningPotionExistFL.AddForm(objItemRef.GetBaseObject())
			objItemRef.Activate(aaaKimachuuReturningPotionCRef)
		Else
			If iType > 0
				IntListAdd(strPathItem, "quantity", obj01.GetItemCount(obj01.GetNthForm(cIndex)), true)
			EndIf
			cIndex += 1
		EndIf
		rIndex += 1
	EndWhile

	While aaaKimachuuReturningPotionCRef.GetNumItems() > 0
		ObjectReference objItemRef = aaaKimachuuReturningPotionCRef.DropObject(aaaKimachuuReturningPotionCRef.GetNthForm(0), 1)
		objItemRef.SetActorOwner(obj01.GetActorBase())
		objItemRef.Activate(obj01)
	EndWhile

	aaaKimachuuReturningPotionCRef.MoveTo(aaaKimachuuReturningPotionMRef)
	Int iSize = aaaKimachuuReturningPotionFL.GetSize()
	Armor armTemp
	While iSize > 0
		iSize -= 1
		armTemp = aaaKimachuuReturningPotionFL.GetAt(iSize) As Armor
		If armTemp != None
			obj01.EquipItem(armTemp, False, False)
		EndIf
	EndWhile
	obj01.SetAlpha(1.0)
	Utility.Wait(0.1)

	If Save(strPathItem)
		Debug.Notification("Item: Save completed.")
	Else
		Debug.Notification("ERROR. Save failed.")
	EndIf
	armTemp = None
EndFunction

Function loadItemFunction(Actor obj01)
	If !JsonExists(strPathItem)
		Debug.Notification("Json file not found.")
		Return
	EndIf

	Debug.Notification("Item: Please wait a moment.")
	aaaKimachuuReturningPotionCRef.MoveTo(obj01)
	Int iItemN = FormListCount(strPathItem, "items")
	Int cIndex = 0
	While cIndex < iItemN
		Form forItem = FormListGet(strPathItem, "items", cIndex)
		Int iType = forItem.GetType()
		If iType == 26 || iType == 41
			aaaKimachuuReturningPotionCRef.AddItem(forItem, 1)
			ObjectReference objItemRef = aaaKimachuuReturningPotionCRef.DropObject(forItem, 1)
			objItemRef.SetItemHealthPercent(GetFloatValue(strPathItem, "health" + cIndex, 0.0))
			If objItemRef.GetEnchantment() != none
				objItemRef.SetFactionOwner(PlayerFaction)
				objItemRef.Activate(aaaKimachuuReturningPotionCRef)
			Else
				Bool bEnchantment = GetIntValue(strPathItem, "enchantment" + cIndex, 0)
				If bEnchantment
					Int iNumEffects = FormListCount(strPathItem, "magiceffects" + cIndex)
					Int iEffectCurIndex = 0
					MagicEffect[] meEffects = ResizeMEArrayFunction(iNumEffects)
					Float[] fMagnitudes = ResizeFloatArrayFunction(iNumEffects)
					Int[] iAreas = ResizeIntArrayFunction(iNumEffects)
					Int[] iDurations = ResizeIntArrayFunction(iNumEffects)
					While iEffectCurIndex < iNumEffects
						meEffects[iEffectCurIndex] = FormListGet(strPathItem, "magiceffects" + cIndex, iEffectCurIndex) As MagicEffect
						fMagnitudes[iEffectCurIndex] = FloatListGet(strPathItem, "magnitude" + cIndex, iEffectCurIndex)
						iAreas[iEffectCurIndex] = IntListGet(strPathItem, "area" + cIndex, iEffectCurIndex)
						iDurations[iEffectCurIndex] = IntListGet(strPathItem, "duration" + cIndex, iEffectCurIndex)
						iEffectCurIndex += 1
					EndWhile
					objItemRef.CreateEnchantment(GetFloatValue(strPathItem, "maxcharge" + cIndex, 0.0), meEffects, fMagnitudes, iAreas, iDurations)
					objItemRef.SetItemCharge(GetFloatValue(strPathItem, "currentcharge" + cIndex, 0.0))
				EndIf

				String strBaseName = objItemRef.GetBaseObject().GetName()
				If StringUtil.Find(GetStringValue(strPathItem, "names" + cIndex, ""), strBaseName) != -1
					objItemRef.SetDisplayName(strBaseName, false)
				Else
					objItemRef.SetDisplayName(GetStringValue(strPathItem, "names" + cIndex, ""), False)
				EndIf
				objItemRef.SetFactionOwner(PlayerFaction)
				objItemRef.Activate(aaaKimachuuReturningPotionCRef)
			EndIf
		Else
			obj01.AddItem(FormListGet(strPathItem, "items", cIndex), IntListGet(strPathItem, "quantity", cIndex), true)
			aaaKimachuuReturningPotionCRef.RemoveItem(FormListGet(strPathItem, "items", cIndex), IntListGet(strPathItem, "quantity", cIndex), true)
		EndIf
		cIndex += 1
	EndWhile

	While aaaKimachuuReturningPotionCRef.GetNumItems() > 0
		ObjectReference objItemRef = aaaKimachuuReturningPotionCRef.DropObject(aaaKimachuuReturningPotionCRef.GetNthForm(0), 1)
		objItemRef.SetActorOwner(obj01.GetActorBase())
		objItemRef.Activate(obj01)
	EndWhile

	Utility.Wait(0.1)
	aaaKimachuuReturningPotionCRef.MoveTo(aaaKimachuuReturningPotionMRef)
	Debug.Notification("Item: Load completed.")
EndFunction

Function saveSpellFunction(Actor obj01)
	ClearAll(strPathSpell)
	Debug.Notification("Spell: Please wait a moment.")
	Int iSpellN = obj01.GetSpellCount()
	Int cIndex = 0
	Spell curSpell
	While cIndex < iSpellN
		curSpell = obj01.GetNthSpell(cIndex)
		Int iMEType = GetSpellType(curSpell)
		If iMEType == 0 || iMEType == 2 || iMEType == 3
			FormListAdd(strPathSpell, "spells", obj01.GetNthSpell(cIndex), True)
		EndIf
		cIndex += 1
	EndWhile

	If Save(strPathSpell)
		Debug.Notification("Spell: Save completed.")
	Else
		Debug.Notification("ERROR. Save failed.")
	EndIf

	curSpell = None
EndFunction

Function loadSpellFunction(Actor obj01)
	If !JsonExists(strPathSpell)
		Debug.Notification("Json file not found.")
		Return
	EndIf

	Debug.Notification("Spell: Please wait a moment.")
	Int iSpellN = FormListCount(strPathSpell, "spells")
	Int cIndex = 0
	Spell curSpell
	While cIndex < iSpellN
		curSpell = FormListGet(strPathSpell, "spells", cIndex) As Spell
		If !obj01.HasSpell(curSpell)
			obj01.AddSpell(curSpell, False)
		EndIf
		cIndex += 1
	EndWhile
	Debug.Notification("Spell: Load completed.")

	curSpell = None
EndFunction

Function savePerkFunction(Actor obj01)
	ClearAll(strPathPerk)
	Debug.Notification("Perk: Please wait a moment.")

	Form[] forPerks = Utility.CreateFormArray(2048, None)
	forPerks = GetAllForms(92, None)
	forPerks = ClearNone(forPerks)

	Int cIndexP = 0
	Perk curPerk
	String strPerkID
	While cIndexP < forPerks.Length
		curPerk = forPerks[cIndexP] As Perk
		If Game.GetPlayer().HasPerk(curPerk)
			strPerkID = GetFormEditorID(curPerk)
			StringListAdd(strPathPerk, "perks", strPerkID, True)
		EndIf
		cIndexP += 1
	EndWhile

	If Save(strPathPerk)
		Debug.Notification("Perk: Save completed.")
	Else
		Debug.Notification("ERROR. Save failed.")
	EndIf

	curPerk = None
EndFunction

Function loadPerkFunction(Actor obj01)
	If !JsonExists(strPathPerk)
		Debug.Notification("Json file not found.")
		Return
	EndIf

	Debug.Notification("Perk: Please wait a moment.")
	Int iPerkN = StringListCount(strPathPerk, "perks")
	Int cIndexP = 0
	Perk curPerk
	String strPerkID
	While cIndexP < iPerkN
		strPerkID = StringListGet(strPathPerk, "perks", cIndexP)
		curPerk = GetFormFromEditorID(strPerkID) As Perk
		If curPerk != None
			Game.GetPlayer().AddPerk(curPerk)
		EndIf
		cIndexP += 1
	EndWhile

	Debug.Notification("Perk: Load completed.")
	curPerk = None
EndFunction

Function potionCheckFunction(Actor obj01)
	If obj01.GetItemCount(aaaKimachuuReturningPotionALCH) == 0
		obj01.AddItem(aaaKimachuuReturningPotionALCH, 1, True)
	EndIf
EndFunction

Magiceffect[] Function ResizeMEArrayFunction(Int iWSize)
	If iWSize == 0 || iWSize == 1
		Return new MagicEffect[1]
	ElseIf iWSize == 2
		Return new MagicEffect[2]
	ElseIf iWSize == 3
		Return new MagicEffect[3]
	ElseIf iWSize == 4
		Return new MagicEffect[4]
	ElseIf iWSize == 5
		Return new MagicEffect[5]
	ElseIf iWSize == 6
		Return new MagicEffect[6]
	ElseIf iWSize == 7
		Return new MagicEffect[7]
	ElseIf iWSize == 8
		Return new MagicEffect[8]
	ElseIf iWSize == 9
		Return new MagicEffect[9]
	ElseIf iWSize >= 10
		Return new MagicEffect[10]
	EndIf
endFunction

Float[] Function ResizeFloatArrayFunction(Int iWSize)
	If iWSize == 0 || iWSize == 1
		Return new Float[1]
	ElseIf iWSize == 2
		Return new Float[2]
	ElseIf iWSize == 3
		Return new Float[3]
	ElseIf iWSize == 4
		Return new Float[4]
	ElseIf iWSize == 5
		Return new Float[5]
	ElseIf iWSize == 6
		Return new Float[6]
	ElseIf iWSize == 7
		Return new Float[7]
	ElseIf iWSize == 8
		Return new Float[8]
	ElseIf iWSize == 9
		Return new Float[9]
	ElseIf iWSize >= 10
		Return new Float[10]
	EndIf
endFunction

Int[] Function ResizeIntArrayFunction(Int iWSize)
	If iWSize == 0 || iWSize == 1
		Return new Int[1]
	ElseIf iWSize == 2
		Return new Int[2]
	ElseIf iWSize == 3
		Return new Int[3]
	ElseIf iWSize == 4
		Return new Int[4]
	ElseIf iWSize == 5
		Return new Int[5]
	ElseIf iWSize == 6
		Return new Int[6]
	ElseIf iWSize == 7
		Return new Int[7]
	ElseIf iWSize == 8
		Return new Int[8]
	ElseIf iWSize == 9
		Return new Int[9]
	ElseIf iWSize >= 10
		Return new Int[10]
	endIf
endFunction