ScriptName MacDIHOInit extends Quest
{Handles mod initialization and shutdown; waits for the appropriate trigger and then applies the immortality effect to the player.}

Actor Property PlayerRef auto
Book Property pImmortalDovahkiin auto
LeveledItem Property pBookLeveledItemList auto
ObjectReference Property pSpawnPoint auto
ObjectReference Property pSoulShard auto
ObjectReference Property pDeathMarkFX auto
ObjectReference Property pDeathStorage auto
ObjectReference Property pPanicStorage auto
Quest Property pUnbound auto
Quest Property pWayOfTheVoice auto
Quest Property pMacDIHOSoulBinding auto
Spell Property pImmortality auto
Spell Property pSacrifice auto
MacDIHOCommonFunctions Property Common auto

Event OnInit()
    int nDIHOInitState = Common.GetDIHOState()

    ; If mod state is uninitialized, run the initialization script
    If (nDIHOInitState == 0)
        Common.SetDIHOState(2)        ; 2 = active

        ; Some references (particularly the player) do not seem valid unless you wait a bit after the game starts
        Utility.Wait(5)

        ; Set default death behavior (gold and items taken upon death)
        Common.SetDIHOBehavior(2)

        ; By default, delayed start is off (player will become immortal after Unbound)
        Common.SetDIHODelayedStart(0)

        ; Set default polling interval (how long before each script heartbeat)
        Common.SetDIHOPollingInterval(3.0)

        ; By default, no attribute damage for lost soul shards
        Common.SetDIHOAttributeDamage(0)

        ; Add the "Immortal Dovahkiin" book to the world (one book-related levelled item list primarily used at the College of Winterhold)
        pBookLeveledItemList.AddForm(pImmortalDovahkiin as Form, 1, 1)

        ; Alert the player that the mod is initialized
        Debug.Notification("Dragon Souls, Leviathan Edition has finished initializing.")
    ElseIf(nDIHOInitState == 1)
        Common.SetDIHOState(2)        ; 2 = active
    EndIf

    ; Ensure polling interval is valid
    float fPollingInterval = Common.ValidatePollingInterval()

    ; Start the controller heartbeat
    RegisterForSingleUpdate(fPollingInterval)
EndEvent

Event OnUpdate()
    ; If mod state is set higher than 2, shut down
    If (Common.GetDIHOState() > 2)
        ModShutdown()
    Else
        ; If the intro quest is over, or if using delayed start and the player has received the Greybeard call, grant Dovahkiin immortality
        If ((pUnbound.IsCompleted() && Common.GetDIHODelayedStart() == 0) || (pWayOfTheVoice.GetCurrentStageID() >= 5))
            ; Make the player essential (i.e., player will enter unrecoverable bleedout instead of dying when health is zero)
            PlayerRef.GetActorBase().SetEssential(true)
            PlayerRef.SetNoBleedoutRecovery(true)

            ; Apply the Dovahkiin immortality effect to the player
            PlayerRef.AddSpell(pImmortality, false)

            ; Give the player the "Prayer of Sacrifice" power
            PlayerRef.AddSpell(pSacrifice, false)
			
			; Set default death behavior (gold and items taken upon death)
			Common.SetDIHOBehavior(2)
			
            ; Set the initial respawn point to wherever the player is standing upon receiving the immortality effect
            If (pSpawnPoint.GetParentCell() == pDeathStorage.GetParentCell())
                pSpawnPoint.MoveTo(PlayerRef)
            EndIf
			
            ; Prompt the player to let them know of their newfound state
            Debug.MessageBox("That dragon...my spirit echoes with its power!")
			
			Debug.MessageBox("Through the power of Akatosh, you have become immortal. Return to the site of your defeat to recover lost power and items.\n\nIf you are defeated again before reclaiming your soul, all XP and gold associated with that soul shard will be PERMANENTLY lost!")
			
			Debug.MessageBox("Held symbols of Stendarr's mercy will preserve your soul upon defeat, causing you to lose nothing.\n\nPraying at any shrine will bind your soul to that location, becoming a checkpoint should you be defeated. Offerings to Arkay will do the same, but can be performed anywhere.")
        Else
            ; Ensure polling interval is valid
            float fPollingInterval = Common.ValidatePollingInterval()

            ; Keep waiting
            RegisterForSingleUpdate(fPollingInterval)
        EndIf
    EndIf
EndEvent

Function ModShutdown()
    ; Stop soul binding quest if it is running
    If (!pMacDIHOSoulBinding.IsStopped())
        pMacDIHOSoulBinding.Stop()
    EndIf

    ; Remove the "Prayer of Sacrifice" power from the player
    PlayerRef.RemoveSpell(pSacrifice)

    ; Remove the Dovahkiin immortality effect from the player
    PlayerRef.RemoveSpell(pImmortality)

    ; Player is no longer essential
    PlayerRef.SetNoBleedoutRecovery(false)
    PlayerRef.GetActorBase().SetEssential(false)

    ; If DIHOState is set to 9, mod removal is desired: revert as much as possible
    int nDIHOState = Common.GetDIHOState()

    If (nDIHOState == 9)
        ; Revert changes to the levelled list to which we added the book
        pBookLeveledItemList.Revert()

        ; If there are any soul shards in the world, move them back to Oblivion
        pSoulShard.MoveToMyEditorLocation()
        pDeathMarkFX.MoveToMyEditorLocation()

        ; Return any items in corpse storage to the player
        pDeathStorage.RemoveAllItems(PlayerRef, true)

        ; Return any items in panic storage to the player
        pPanicStorage.RemoveAllItems(PlayerRef, true)

        ; If the player has the "Immortal Dovahkiin" book, remove it
        PlayerRef.RemoveItem(pImmortalDovahkiin, 999999999, true)

        ; Refund any attribute point damage to the player
        int nAttributeDamage = Common.GetDIHOAttributeDamageTotal()

        If (nAttributeDamage > 0)
            PlayerRef.ModActorValue("Health", nAttributeDamage)
            PlayerRef.ModActorValue("Magicka", nAttributeDamage)
            PlayerRef.ModActorValue("Stamina", nAttributeDamage)
        EndIf
    EndIf

    ; Revert state value to 1 (initialized; dormant)
    Common.SetDIHOState(1)

    ; Stop the controller quest
    If (!Self.IsStopped())
        Self.Stop()
    EndIf

    ; Give the controller quest a few seconds to finish shutting down
    Utility.Wait(5)

    ; Alert the player that shutdown is complete
    Debug.Notification("Dragon Souls, Leviathan Edition shutdown complete.")

    If (nDIHOState == 9)
        Debug.Notification("Save your game; quit Skyrim; uninstall mod.")
    Else
        Debug.Notification("Save your game; quit Skyrim; upgrade mod to latest version.")
    EndIf
 EndFunction
