Scriptname SuH_Main extends Quest  

SuH_Fun property _f auto
SuH_Status property _s auto

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

;ent/ MODupdate
Function MODupdate()
	if _s.IsRunning() == False
		Debug.MessageBox(": Succubus Heart :\n!!! FATAL ERROR !!!\nMod failed to initiate properly, please load and try initiating again. \n If you're updating from before 5.0 please install 4.6 first! Load your save and create a new save with 4.6 installed, then 5.0 will initiate properly.(Check ReadMe for more info)")
	endIf
	;ent/ Always Run
	if _s.SuH_MODversion < 4008002
		_s.InitProperties()
	endIf
	if _s.SuH_MODversion < 4007000
		_f.InitProperties()
	endIf
	; NOTE : Succubus Heart MUST reset the player Dynamic Effect spell on each load because Skyrim doesn't store spell values properly between saves
	_s.PlayerRef.RemoveSpell(_s.SuH_dyna_player)
	_s.PlayerRef.AddSpell(_s.SuH_dyna_player, false)
	if _s.SuH_actor_activepet != none
		_s.SuH_actor_activepet.RemoveSpell(_s.SuH_spell_pet)
		_s.SuH_actor_activepet.AddSpell(_s.SuH_spell_pet)
	endIf
	; NOTE : Re-remove Status Regen that's disabled, Skyrim resets them to default when loading a save
	if _s.SuH_SETdisablehealthrecovery > 0.0
		_s.playerRef.SetActorValue("HealRate", 0)
	endIf
	if _s.SuH_SETdisablemagickarecovery > 0.0
		_s.playerRef.SetActorValue("MagickaRate", 0)
	endIf
	if _s.SuH_SETdisablestaminarecovery > 0.0
		_s.playerRef.SetActorValue("StaminaRate", 0)
	endIf
	;end/
	;ent/ Initial Set-Up
	if _s.SuH_MODversion < 100
		_s.SexLab.TrackFaction(_s.SuH_tracker,"NPCtracker")
		RegisterForModEvent("NPCtracker_Added","anim_NPC_Added")
		RegisterForModEvent("NPCtracker_Start","anim_NPC_Start")
		RegisterForModEvent("NPCtracker_Orgasm","anim_NPC_Orgasm")
		RegisterForModEvent("NPCtracker_End","anim_NPC_End")
		RegisterForModEvent("PlayerTrack_Added","anim_PC_Added")
		RegisterForModEvent("PlayerTrack_Start","anim_PC_Start")
		RegisterForModEvent("PlayerTrack_Orgasm","anim_PC_Orgasm")
		RegisterForModEvent("PlayerTrack_End","anim_PC_End")
	endIf
	;end/
	;ent/ Previous Patches
	if _s.SuH_MODversion < 4007000
		_s.playerRef.AddSpell(_s.SuH_spell_nightsembrace)
		_s.PlayerRef.AddSpell(_s.SuH_spell_selfpleasure)
		_s.playerRef.AddSpell(_s.SuH_spell_teliRealm)
		_s.playerRef.AddSpell(_s.SuH_spell_sexualenrage)
		_s.playerRef.AddSpell(_s.SuH_spell_sexualentice)
		_s.PlayerRef.AddSpell(_s.SuH_spell_petself)
		_s.PlayerRef.AddSpell(_s.SuH_spell_pettarget)
		
		_s.SuH_petactorbases = new ActorBase[25]
		_s.SuH_petlevels = new int[25]
		_s.SuH_petxps = new int[25]
		_s.SuH_craftforms = new form[50]
	endIf
	if _s.SuH_MODversion < 4008000
		_s.SuH_petnames = new string[25]
		_s.SuH_MODversion = 4008000
	endIf
	;end/
	;Current Patch
	if _s.SuH_MODversion < 4009000
		_s.SuH_MODversion = 4009000
		debug.Notification("Succubus Heart : This is a DEV Build and will have some issues.")
		debug.Notification("Succubus Heart : Please report any issues you find!")
		debug.Notification("Succubus Heart : 4.9 DEV Installed")
	endIf
endFunction
;end/

Event OnInit()
	InitProperties()
endEvent

;ent/ NPC Anim Start
Function anim_NPC_Start(form ActorRef, int threadId)
	actor char = ActorRef as actor ; Get Actor
	char.addSpell(_s.SuH_sex_inact, false) ; Add InAct spell tag
	if _s.SuH_SETclearactor > 0
		char.ClearExtraArrows()
	endIf
	; if _f.SuH_SETessentialacts.GetValue()
		; if char.GetActorBase().IsEssential()
			;do nothing
		; else
			; char.GetActorBase().setEssential() ; Make character essential
			; char.addSpell(SuH_stat_essential) ; Add Essential spell tag
		; endIF
	; endIf
	if char.IsInFaction(_s.SuH_petfaction)
		sslThreadController Thread = _s.SexLab.GetController(threadId)
		actor[] animActor = _s.SexLab.HookActors(threadId)
		actor animVictim = _s.SexLab.HookVictim(threadId)
		string petID = "none" ; Capture pet
		; If Segment Needs to be here (Check Pet to apply spell effects to other actors)
		int i = 0
		int pact = 0
		int nact = 0
		; Calculate pet spell effect (on Others) and tally actors
		While i < animActor.Length
			if animActor[i] != char
				if animActor[i] == _s.PlayerRef
					pact = 1
				else
					nact += 1
				endIf
			endIf
			;_f.spellPET(petID, animActor[i])
			i+= 1
		endWhile
		; Calculate pet spell effect (On Pet)
		if animVictim != none
			if char == animVictim
				if pact != 0
					char.AddSpell(_s.SuH_sex_petpvictim)
				else
					char.AddSpell(_s.SuH_sex_petnvictim)
				endIf
			else
				if pact != 0
					char.AddSpell(_s.SuH_sex_petpattacker)
				else
					char.AddSpell(_s.SuH_sex_petnattacker)
				endIf
			endIf
		else
			if pact != 0
				char.AddSpell(_s.SuH_sex_petpconsent)
			else
				char.AddSpell(_s.SuH_sex_petnconsent)
			endIf
		endIf
	endIf
endFunction
;end/

;ent/ NPC Anim Orgasm
Function anim_NPC_Orgasm(form ActorRef, int threadId)
	sslThreadController Thread = _s.SexLab.GetController(threadId) ; Get Thread
	actor char = ActorRef as actor ; Get Actor (We'll exclude char from results)
	actor[] animActor = _s.SexLab.HookActors(threadId) ; Create Actor Array
	int pact = 0
	; Hand out sex drops
	if animActor.Length > 1 ; If multiple actors are present
		; Check for player
		int i = 0 ; Set array position to 0
		While i < animActor.Length
			if animActor[i] != char
				if animActor[i] == _s.PlayerRef
					pact = 1
				endIf
			endIf
			i += 1
		endWhile
		int charGender = _s.SexLab.GetGender(char) ; Get char gender
		if charGender == 0 || charGender == 2 ; If char is male or male creature
			i = 0 ; Set array position to 0
			while i < animActor.Length
				if animActor[i] != char
					animActor[i].AddItem(_s.SuH_ing_sperm, 2, true) ; Give actor 2 items
					animActor[i].EquipItem(_s.SuH_ing_sperm, false, true) ; Use 1 item
				endIf
				i += 1
			endWhile
		elseIf charGender == 1 || charGender == 3 ; If char is female or female creature
			i = 0 ; Set array position to 0
			while i < animActor.Length
				if animActor[i] != char
					animActor[i].AddItem(_s.SuH_ing_milk, 2, true)
					animActor[i].EquipItem(_s.SuH_ing_milk, false, true)
				endIf
				i += 1
			endWhile
		endIf
	else ; If actor is alone
		int charGender = _s.SexLab.GetGender(char) ; Get char gender
		if charGender == 0 || charGender == 2 ; If char is male or male creature
			char.AddItem(_s.SuH_ing_sperm, 2, true)
			char.EquipItem(_s.SuH_ing_sperm, false, true)
		elseIf charGender == 1 || charGender == 3 ; If char is female or female creature
			int i = 0 ; Set array position to 0
			char.AddItem(_s.SuH_ing_milk, 2, true)
			char.EquipItem(_s.SuH_ing_milk, false, true)
		endIf
	endIf
	; Pet orgasm calculation
	if char.IsInFaction(_s.SuH_petfaction)
		_s.SuH_sex_petorgasm.cast(char, char)
	endIf
	; Player Included Proc
	if pact == 1
		if char.GetRelationshipRank(_s.PlayerRef) >= 3
			_f.perkcalc("allyorgasm")
		endIf
	endIf
endFunction
;end/

;ent/ NPC Anim End
Function anim_NPC_End(form ActorRef, int threadId)
	actor char = ActorRef as actor ; Get Actor
	; Remove sex effects
	char.RemoveSpell(_s.SuH_sex_PCmastery)
	char.RemoveSpell(_s.SuH_sex_PCtraining)
	char.RemoveSpell(_s.SuH_sex_PCsubmit)
	char.RemoveSpell(_s.SuH_sex_NPCattacker)
	char.RemoveSpell(_s.SuH_sex_NPCconsent)
	char.RemoveSpell(_s.SuH_sex_NPCvictim)
	char.RemoveSpell(_s.SuH_sex_petspell)
	char.RemoveSpell(_s.SuH_sex_inact)
	if char.hasSpell(_s.SuH_stat_essential) ; if char has essential spell tag
		char.GetActorBase().setEssential(FALSE) ; Remove essential
		char.removeSpell(_s.SuH_stat_essential) ; Remove essential spell tag
	endIf
	if char.IsInFaction(_s.SuH_petfaction)
		char.removeSpell(_s.SuH_sex_petpconsent)
		char.removeSpell(_s.SuH_sex_petnconsent)
		char.removeSpell(_s.SuH_sex_petpattacker)
		char.removeSpell(_s.SuH_sex_petnattacker)
		char.removeSpell(_s.SuH_sex_petpvictim)
		char.removeSpell(_s.SuH_sex_petnvictim)
	endIf
	if _s.SuH_SETcombatseduction > 0
		char.AddSpell(_s.SuH_sex_CScd, false)
	endIf
	if char.HasSpell(_s.SuH_CHAinvact)
		char.RemoveSpell(_s.SuH_CHAinvact)
		char.GetActorBase().setEssential(false)
	endIf
	actor[] animActor = _s.SexLab.HookActors(threadId) ; Create Actor Array
	int pact = 0
	int i = 0 ; Set array position to 0
	While i < animActor.Length
		if animActor[i] != char
			if animActor[i] == _s.PlayerRef
				pact = 1
			endIf
		endIf
		i += 1
	endWhile
	if pact == 1 ; If play involved
		if _s.SuH_SETallowdrainkill > 0
			float x = char.GetActorValue("Health")
			if x < 1.0
				char.DamageActorValue("Health", 1.0)
				_f.perkcalc("killdrain")
			elseIf _s.SuH_SETalwaysdrainkill > 0
				char.DamageActorValue("Health", 9999999999)
				_f.perkcalc("killdrain")
			endIf
		endIf
	endIf
endFunction
;end/

;ent/ PC Anim Added
Function anim_PC_Added(form ActorRef, int threadId)
	actor char = ActorRef as actor ; Get Actor (Looking for player)
	if char == _s.PlayerRef
		if _s.SuH_SETcalmaura > 0
			char.AddSpell(_s.SuH_dyna_calmaura, false)
		endIf
		If _s.PlayerRef.IsBleedingOut() == True
			_s.SuH_CHKsdinact = 1
			Utility.Wait(0.1)
			_s.PlayerRef.SetNoBleedoutRecovery(false)
			_s.PlayerRef.RestoreActorValue("Health", 100)
		endIf
	endIf
endFunction
;end/

;ent/ PC Anim Start
Function anim_PC_Start(form ActorRef, int threadId)
	sslThreadController Thread = _s.SexLab.GetController(threadId) ; Get Thread
	actor[] animActor = _s.SexLab.HookActors(threadId) ; Create Actor Array
	actor char = ActorRef as actor ; Get Actor (Looking for player)
	char.AddSpell(_s.SuH_sex_inact, false) ; Add InAct spell tag
	char.AddSpell(_s.SuH_sex_inact, false) ; Add InAct spell tag
	if _s.SuH_SETclearactor > 0
		char.ClearExtraArrows()
	endIf
	if char == _s.PlayerRef && animActor.Length > 1 ; If actor is player then execute and distribute effect spells
		; if _f.SuH_SETcalmaura.GetValue()
			; char.AddSpell(SuH_dyna_calmaura, false)
		; endIf
		; If PlayerRef.IsBleedingOut() == True
			; _f.SuH_CHKsdinact.SetValue(1)
			; PlayerRef.SetNoBleedoutRecovery(false)
			; PlayerRef.RestoreActorValue("Health", 100)
		; endIf
		; if _f.SuH_SETactmessage.GetValue()
			; debug.MessageBox("Act Started")
		; endIf
		actor victim = _s.SexLab.HookVictim(threadId) ; Get Victim
		int i = 0 ;Set array position to 0
		while i < animActor.Length ; Scan through all actors and apply effects
			if animActor[i] == _s.PlayerRef ; If character is the PC
				if _s.PlayerRef == victim ; If PC is victim
					_s.PlayerRef.AddSpell(_s.SuH_sex_PCsubmit, false) ; Add Submit Effect
				elseif victim != none ; If PC is aggressor
					_s.PlayerRef.AddSpell(_s.SuH_sex_PCmastery, false) ; Add Mastery Effect
				else ; If PC is consent
					_s.PlayerRef.AddSpell(_s.SuH_sex_PCtraining, false) ; Add Training Effect
				endIf
			else ; If character is an NPC
				if animActor[i] == victim ; If NPC is a victim
					if animActor[i].IsInFaction(_s.SuH_ignoreabsorb)
					else
						animActor[i].AddSpell(_s.SuH_sex_NPCvictim, false) ; Add Victim Effect
					endIf
					_f.seducedNPCSet(animActor[i], "aggressive", 0)
				elseif victim != none ; If NPC is aggressor
					if animActor[i].IsInFaction(_s.SuH_ignoreabsorb)
					else
						animActor[i].AddSpell(_s.SuH_sex_NPCattacker, false) ; Add Attacker Effect
					endIf
					_f.seducedNPCSet(animActor[i], "aggressive", 0)
				else ; If NPC is consent
					if animActor[i].IsInFaction(_s.SuH_ignoreabsorb)
					else
						animActor[i].AddSpell(_s.SuH_sex_NPCconsent, false) ; Add Consent Effect
					endIf
					_f.seducedNPCSet(animActor[i], "consent", 0)
				endIf
			endIf
			i+=1
		endWhile
	endIf
endFunction
;end/

;ent/ PC Anim Orgasm
Function anim_PC_Orgasm(form ActorRef, int threadId)
	actor char = ActorRef as actor ; Get Actor (We'll exclude char from results)
	sslThreadController Thread = _s.SexLab.GetController(threadId) ; Get Thread
	actor[] animActor = _s.SexLab.HookActors(threadId) ; Create Actor Array
	if char == _s.PlayerRef
		_f.XPcalc("PCorgasm")
		_f.perkcalc("orgasm")
	endIf
	; Hand out sex drops
	if animActor.Length > 1 ; If multiple actors are present	
		; Apply player/character specific effects
		if char == _s.PlayerRef
			_f.XPcalc("PCorgasm")
			; Devious Partner 2 Effect (Stamina to Gold)
			int x = _s.SuH_rank_deviouspartner2
			if x > 0
				int y = Math.Floor(1 + (x * (_s.SuH_PCSmpoint * 0.2)))
				_s.playerRef.AddItem(_s.Gold001, y, true)
			endIf
			_f.perkcalc("orgasm")
		endIf
		int charGender = _s.SexLab.GetGender(char) ; Get char gender
		if charGender == 0 || charGender == 2 ; If char is male or male creature
			int i = 0 ; Set array position to 0
			while i < animActor.Length
				if animActor[i] != char
					animActor[i].AddItem(_s.SuH_ing_sperm, 2, true) ; Give actor 2 items
					animActor[i].EquipItem(_s.SuH_ing_sperm, false, true) ; Use 1 item
				endIf
				i += 1
			endWhile
		elseIf charGender == 1 || charGender == 3 ; If char is female or female creature
			int i = 0 ; Set array position to 0
			while i < animActor.Length
				if animActor[i] != char
					animActor[i].AddItem(_s.SuH_ing_milk, 2, true)
					animActor[i].EquipItem(_s.SuH_ing_milk, false, true)
				endIf
				i += 1
			endWhile
		endIf
		; Calculate rare drop chance and handout
		if char == _s.PlayerRef
			int i = 0
			while i < animActor.Length
				if animActor[i] != char
					int ran = Utility.RandomInt(0,99) + _s.SuH_rank_perfectorgasm as int
					if ran >= 94
						int rare = Utility.RandomInt(0,2)
						if rare == 0
							char.AddItem(_s.SuH_ing_vitalitystone, 1, true)
							if char == _s.PlayerRef ; Notify player of rare drop
								debug.Notification("Succubus Heart - RARE DROP - Vitality Stone")
							endIf
						elseif rare == 1
							char.AddItem(_s.SuH_ing_empowermentstone, 1, true)
							if char == _s.PlayerRef
								debug.Notification("Succubus Heart - RARE DROP - Empowerment Stone")
							endIf
						elseif rare == 2
							char.AddItem(_s.SuH_ing_specialtystone, 1, true)
							if char == _s.PlayerRef
								debug.Notification("Succubus Heart - RARE DROP - Specialty Stone")
							endIf
						endIf
					endIf
				endIf
				i += 1
			endWhile
			; Apply Perfect Orgasm's Death Drop Bonus Passive
			int perforg2 = _s.SuH_rank_perfectorgasm2
			if perforg2 > 0
				int m = perforg2*5
				int ranD = Utility.RandomInt(1,100)
				if ranD <= m
					int ran = Utility.RandomInt(0,49)
					if ran < 14
						_s.playerRef.AddItem(_s.SuH_ing_soulofforce, 1, false)
					elseIf ran < 28
						_s.playerRef.AddItem(_s.SuH_ing_soulofexperience, 1, false)
					elseIf ran < 41
						_s.playerRef.AddItem(_s.SuH_ing_soulofdesire, 1, false)
					elseIf ran < 44
						_s.playerRef.AddItem(_s.SuH_ing_souloflife, 1, false)
					elseIf ran < 47
						_s.playerRef.AddItem(_s.SuH_ing_soulofmagic, 1, false)
					elseIf ran < 50
						_s.playerRef.AddItem(_s.SuH_ing_soulofpower, 1, false)
					endIf
				endIf
			endIf
		endIf
	else ; If actor is alone
		int charGender = _s.SexLab.GetGender(char) ; Get char gender
		if charGender == 0 || charGender == 2 ; If char is male or male creature
			char.AddItem(_s.SuH_ing_sperm, 2, true)
			char.EquipItem(_s.SuH_ing_sperm, false, true)
		elseIf charGender == 1 || charGender == 3 ; If char is female or female creature
			int i = 0 ; Set array position to 0
			char.AddItem(_s.SuH_ing_milk, 2, true)
			char.EquipItem(_s.SuH_ing_milk, false, true)
		endIf
	endIf
	
endFunction
;end/

;ent/ PC Anim End
Function anim_PC_End(form ActorRef, int threadId)
	actor char = ActorRef as actor ; Get Actor
	; Remove sex effects
	char.RemoveSpell(_s.SuH_sex_PCmastery)
	char.RemoveSpell(_s.SuH_sex_PCtraining)
	char.RemoveSpell(_s.SuH_sex_PCsubmit)
	char.RemoveSpell(_s.SuH_sex_NPCattacker)
	char.RemoveSpell(_s.SuH_sex_NPCconsent)
	char.RemoveSpell(_s.SuH_sex_NPCvictim)
	char.RemoveSpell(_s.SuH_sex_petspell)
	char.RemoveSpell(_s.SuH_sex_inact)
	char.RemoveSpell(_s.SuH_dyna_calmaura)
	if char == _s.PlayerRef
		; Give Sex Stack
		_s.SuH_PCSstacksex = Math.Floor(_s.SuH_PCSstacksex + _s.SuH_rank_valuestacker + 1)
		;Self Stacker
		int selfstacker = _s.SuH_rank_selfstacker
		if selfstacker != 0
			int pg = _s.SexLab.GetGender(char)
			if pg == 1 ;female
				_s.SuH_PCSstackmilk = Math.Floor(_s.SuH_PCSstackmilk + 1)
			else ;male
				_s.SuH_PCSstacksperm = Math.Floor(_s.SuH_PCSstacksperm + 1)
			endIf
		endIf
		if _s.SuH_CHKsdinact > 0
			_f.SDrespawn()
		endIf
		if _s.SuH_SETcombatseduction > 0
			char.AddSpell(_s.SuH_sex_CScd, false)
		endIf
		_s.SuH_com_absorbvisuals.cast(_s.playerRef, _s.playerRef)
	; Kill if HP is lower than 1 and Kill Drain is enabled
	elseif _s.SuH_SETallowdrainkill > 0
		if char.HasSpell(_s.SuH_CHAinvact)
			char.RemoveSpell(_s.SuH_CHAinvact)
			char.GetActorBase().setEssential(false)
		endIf
		float x = char.GetBaseActorValue("Health")
		if x < 1.0
			char.DamageActorValue("Health", 1.0)
		elseIf _s.SuH_SETalwaysdrainkill > 0
			char.DamageActorValue("Health", 9999999999)
		endIf
		if _s.SuH_SETcombatseduction > 0
			char.AddSpell(_s.SuH_sex_CScd, false)
		endIf
	endIf
endFunction
;end/