Scriptname SuH_SuQuest extends Quest

SuH_Fun property _f auto
SuH_Status property _s auto

int drainMessage
int desireDelay
int sdDelay
int petDelay
int sexstackDelay
int spermstackDelay
int milkstackDelay
int savingessenseDelay
int formalbeautyDelay
int violenceDelay
int masochistDelay
int regalglowarmor
bool nowincombat

Event OnInit()
	InitProperties()
endEvent

Function InitProperties()
	_f = Game.GetFormFromFile(0x814, "Succubus Heart.esp") as SuH_Fun
	_s = Game.GetFormFromFile(0x16E496, "Succubus Heart.esp") as SuH_Status
endFunction

Function ModStart()
	_s.PlayerRef.AddSpell(_s.SuH_dyna_player, FALSE) ; Add dynamic player script
	RegisterForSingleUpdate(5.0) ; Tick in 5 seconds, giving time to initialize other scripts
endFunction

Event OnUpdate()
	dynamicScriptApply()
	deathOverrideCalc()
	desireCalc()
	regalGlowCalc()
	soulPetCalc()
	SoulForgeCalc()
	;stackDecay()
	savingEssenseCalc()
	violenceCalc()
	masochistCalc()
	overcapCalc()
	if _s.playerRef.IsInCombat()
		if nowincombat == false
			nowincombat = true
			formalBeautyCalc()
		endIf
	else
		nowincombat = false
	endIf
	
	if _s.SuH_SETadvancedchecking
		disableRecoveryCalc()
	endIf
	
	;if _f.SuH_SETrecoverbleed.GetValue()
	;	If PlayerRef.IsBleedingOut() == True
	;		PlayerRef.RestoreAV("Health", 100)
	;	endIf
	;endIf
	RegisterForSingleUpdate(1.0) ; Tick in 1 seconds
endEvent

;Dynamics
function dynamicScriptApply()
	If _s.PlayerRef.HasSpell(_s.SuH_dyna_ability) ; If dynamic script is applying
		_s.PlayerRef.RemoveSpell(_s.SuH_dyna_ability) ; Remove dynamic run script
	else ; if dynamic script is not applying
		_s.PlayerRef.AddSpell(_s.SuH_dyna_ability, FALSE) ; AddSpell dynamic run script
	endIf
endFunction

;Death Override Calculations
function deathOverrideCalc()
	if _s.SuH_CHKsdinact == 4
		_f.SDrespawn()
	else
		if _s.SuH_CHKsdinact > 0 || _s.PlayerRef.IsBleedingOut() == True
			if _s.SuH_SETspecialdeath > 0
				_s.PlayerRef.SetNoBleedoutRecovery(true)
				if _s.SuH_CHKcsprocessing > 0
					_s.SuH_CHKsdinact = 1
				else
					_s.SuH_CHKsdinact = 2
				endIf
			else
				_s.PlayerRef.SetNoBleedoutRecovery(false)
			endIf
		endIf
		if _s.SuH_CHKsdinact == 2
			sdDelay += 1
			if sdDelay >= _s.SuH_SETcsbleedoutdelay
				_f.SDrespawn()
				sdDelay = 0
			endIf
		else
			sdDelay = 0
		endIf
	endIf
	; Place return point when leaving/entering interiors
	if _s.playerRef.GetWorldSpace() != _s.SuH_worldspace
		if _s.playerRef.GetWorldSpace() != _s.SuH_sd_returnpointcell.GetWorldSpace()
			_s.SuH_sd_returnpointcell.MoveTo(_s.PlayerRef)
		endIf
	endIf
endFunction

;Desire Calculations
function desireCalc()
	desireDelay += 1
	if desireDelay > 4
		_s.SuH_PCSdesire += _s.SuH_PCSdesiregain
		if _s.SuH_PCSdesire >= _s.SuH_SETdesirecap && _s.SuH_SETdesiredrain > 0
			if drainMessage == 0
				debug.notification("Succubus Heart : Desire has begun to drain status!")
				drainMessage = 1
			endIf
			float h = _s.PlayerRef.GetBaseActorValue("health")
			float m = _s.PlayerRef.GetBaseActorValue("magicka")
			float s = _s.PlayerRef.GetBaseActorValue("stamina")
			float x = 0.0
			if h > 10.0
				_s.PlayerRef.SetActorValue("health", h - 1.0)
				x += 1.0
			endIf
			if m > 10.0
				_s.PlayerRef.SetActorValue("magicka", m - 1.0)
				x += 1.0
			endIf
			if s > 10.0
				_s.PlayerRef.SetActorValue("stamina", s - 1.0)
				x += 1.0
			endIf
			_s.SuH_PCSforce += Math.Floor(x)
		endIf
		desireDelay = 0
	endIf
endFunction

;Regal Glow Calculations
function regalGlowCalc()
	int RGarmor = _s.SuH_rank_regalglow
	if RGarmor > 0
		int bodySlot = 0x00000004
		Armor bodyArmor = _s.playerRef.GetWornForm(bodySlot) as Armor
		;if bodyArmor == _f.SuH_armor_regalglow ;Regal Glow Active Already
		if (bodyArmor) ;Body Armor Found
			regalglowarmor = 0
			_s.playerRef.UnequipItem(_s.SuH_armor_regalglow, abSilent=true)
		elseif _s.playerRef.IsEquipped(_s.SuH_armor_regalglow) ;Regal Glow Active Already
			if RGarmor != regalglowarmor
				bodyArmor.SetArmorRating( Math.Floor(1 + (RGarmor * (_s.SuH_PCSmpoint * 0.05))) )
				_s.playerRef.UnequipItem(_s.SuH_armor_regalglow, abSilent=true)
				_s.playerRef.equipitem(_s.SuH_armor_regalglow, false, true)
				regalglowarmor = RGarmor
			endIf
		else ;no body armor
			_s.playerRef.equipitem(_s.SuH_armor_regalglow, false, true)
			_s.SuH_armor_regalglow.SetArmorRating(RGarmor)
			_s.playerRef.UnequipItem(_s.SuH_armor_regalglow, abSilent=true)
			_s.playerRef.equipitem(_s.SuH_armor_regalglow, false, true)
			regalglowarmor = RGarmor
		endIf
	endIf
endFunction

;Formal Beauty Calculations
	; Stack Effects
		; Sex Stacks = Health
		; Sperm Stacks = Magicka
		; Milk Stacks = Stamina
function formalBeautyCalc()
	int fb = _s.SuH_rank_formalbeauty
	if fb > 0
		int d = _s.SuH_PCSdpoint
		float recovery = 1 + (fb * (d * 0.05))
		float x = _s.PlayerRef.GetBaseActorValue("health")
		float y = _s.PlayerRef.GetActorValue("health")
		if x > y
			x -= y
			int consume = Math.Ceiling(x / recovery)
			if consume > _s.SuH_PCSstacksex
				if _s.SuH_PCSstacksex > 0
					if consume > _s.SuH_PCSstackmaxsex
						consume = _s.SuH_PCSstackmaxsex
					else
						consume = _s.SuH_PCSstacksex
					endIf
				else
					consume = 0
				endIf
			endIf
			if consume != 0
				_s.playerRef.RestoreActorValue("health", recovery * consume)
				consume -= _s.SuH_rank_formalbeauty2
				if consume < 1
					consume = 1
				endIf
				_s.SuH_PCSstacksex = ( Math.Floor(_s.SuH_PCSstacksex - consume) )
			endIf
		endIf
		x = _s.PlayerRef.GetBaseActorValue("magicka")
		y = _s.PlayerRef.GetActorValue("magicka")
		if x > y
			x -= y
			int consume = Math.Ceiling(x / recovery)
			if consume > _s.SuH_PCSstacksperm
				if _s.SuH_PCSstacksperm > 0
					if consume > _s.SuH_PCSstackmaxsperm
						consume = _s.SuH_PCSstackmaxsperm
					else
						consume = _s.SuH_PCSstacksperm
					endIf
				else
					consume = 0
				endIf
			endIf
			if consume != 0
				_s.playerRef.RestoreActorValue("magicka", recovery * consume)
				consume -= _s.SuH_rank_formalbeauty2
				if consume < 1
					consume = 1
				endIf
				_s.SuH_PCSstacksperm = Math.Floor(_s.SuH_PCSstacksperm - consume)
			endIf
		endIf
		x = _s.PlayerRef.GetBaseActorValue("stamina")
		y = _s.PlayerRef.GetActorValue("stamina")
		if x > y
			x -= y
			int consume = Math.Ceiling(x / recovery)
			if consume > _s.SuH_PCSstackmilk
				if _s.SuH_PCSstackmilk > 0
					if consume > _s.SuH_PCSstackmaxmilk
						consume = _s.SuH_PCSstackmaxmilk
					else
						consume = _s.SuH_PCSstackmilk
					endIf
				else
					consume = 0
				endIf
			endIf
			if consume != 0
				_s.playerRef.RestoreActorValue("stamina", recovery * consume)
				consume -= _s.SuH_rank_formalbeauty2
				if consume < 1
					consume = 1
				endIf
				_s.SuH_PCSstackmilk = Math.Floor(_s.SuH_PCSstackmilk - consume)
			endIf
		endIf
	endIf
endFunction

;Pet Calculations
function soulPetCalc()
	petDelay += 1
	if petDelay > 4
		_f.SoulPetPosition()
		petDelay = 0
	endIf
endFunction

;Soul Forge Calculations
function SoulForgeCalc()
	if _s.SuH_craftanaform != none
		_f.ForgeAnaXP(1)
	endIf
endFunction

;Stack Decay Function
; function stackDecay()
	; sexstackDelay += 1
	; if sexstackDelay > 299
		; int cstack = _f.SuH_PCSstacksex.GetValue() as int
		; if cstack > 0
			; _f.SuH_PCSstacksex.SetValue(cstack - 1)
		; endIf
		; sexstackDelay = 0
	; endIf
	; spermstackDelay += 1
	; if spermstackDelay > 59
		; int cstack = _f.SuH_PCSstacksperm.GetValue() as int
		; if cstack > 0
			; _f.SuH_PCSstacksperm.SetValue(cstack - 1)
		; endIf
		; spermstackDelay = 0
	; endIf
	; milkstackDelay += 1
	; if milkstackDelay > 59
		; int cstack = _f.SuH_PCSstackmilk.GetValue() as int
		; if cstack > 0
			; _f.SuH_PCSstackmilk.SetValue(cstack - 1)
		; endIf
		; milkstackDelay = 0
	; endIf
; endFunction

;Saving Essence Function
function savingEssenseCalc()
	int se = _s.SuH_rank_savingessenceCD
	if se > 0
		savingessenseDelay += 1
		int ser2 = Math.Floor(1200 - (_s.SuH_rank_savingessence2 * 60))
		if savingessenseDelay > ser2
			_s.SuH_rank_savingessenceCD = 0
			debug.Notification("Saving Essence can activate again.")
			savingessenseDelay = 0
		endIf
	else
		savingessenseDelay = 0
	endIf
endFunction

;Violence Function
function violenceCalc()
	if _s.SuH_rank_violenceCD > 0
		violenceDelay -= 1
		if violenceDelay < 1
			_s.SuH_rank_violenceCD = 0
			violenceDelay = 0
		endIf
	else
		violenceDelay = 0
	endIf
endFunction

;Masochist Function
function masochistCalc()
	if _s.SuH_rank_masochistCD > 0
		masochistDelay -= 1
		if masochistDelay < 1
			_s.SuH_rank_masochistCD = 0
			masochistDelay = 0
		endif
	else
		masochistDelay = 0
	endif
endFunction

;Disable Recovery Function
Function disableRecoveryCalc()
	if _s.SuH_SETdisablehealthrecovery > 0
		_s.playerRef.SetActorValue("HealRate", 0)
	endIf
	if _s.SuH_SETdisablemagickarecovery > 0
		_s.playerRef.SetActorValue("MagickaRate", 0)
	endIf
	if _s.SuH_SETdisablestaminarecovery > 0
		_s.playerRef.SetActorValue("StaminaRate", 0)
	endIf
endFunction

;Over Status Cap Function
Function overcapCalc()
	int plvl = _s.playerRef.GetLevel()
	int x = 0
	If _s.SuH_ORcaphealth > 0
		x = _s.SuH_ORcaphealth
	else
		x = Math.Floor((_s.SuH_PCScaphealth + (plvl * 4)) - _s.SuH_PCScaphealthdown)
	endif
	if _s.playerRef.GetBaseActorValue("Health") > x
		_s.playerRef.SetActorValue("health", _s.playerRef.GetBaseActorValue("health") - 1)
		_s.SuH_PCSforce += 1
	endIf
	If _s.SuH_ORcapmagicka > 0
		x = _s.SuH_ORcapmagicka
	else
		x = Math.Floor((_s.SuH_PCScapmagicka + (plvl * 3)) - _s.SuH_PCScapmagickadown)
	endif
	if _s.playerRef.GetBaseActorValue("magicka") > x
		_s.playerRef.SetActorValue("magicka", _s.playerRef.GetBaseActorValue("magicka") - 1)
		_s.SuH_PCSforce += 1
	endIf
	if _s.SuH_ORcapstamina > 0
		x = _s.SuH_ORcapstamina
	else
		x = Math.Floor((_s.SuH_PCScapstamina + (plvl * 3)) - _s.SuH_PCScapstaminadown)
	endif
	if _s.playerRef.GetBaseActorValue("Stamina") > x
		_s.playerRef.SetActorValue("Stamina", _s.playerRef.GetBaseActorValue("Stamina") - 1)
		_s.SuH_PCSforce += 1
	endIf
endFunction