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()
	_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
endEvent


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

Event OnUpdate()
	dynamicScriptApply()
	deathOverrideCalc()
	desireCalc()
	regalGlowCalc()
	soulPetCalc()
	;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

;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)
	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)
	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)
	endIf
endFunction