Scriptname FWSystem extends Quest  
import FWUtility

;--------------------------------------------------------------------------------
; Quest Objectives / Beeing Female States
;--------------------------------------------------------------------------------
;  0 -  3		Zyklus
;  4 -  8		Normal pregnancy
;  9 - 19		<reserved>
; 20 - 39		Pregnant from other mod
; 40 - 49		<none>
; 50 - 69		<reserved - thought about abortus states>
; 70 - 89		<none>
; 90 - 99		Being female / Being male (/ Being child / Being creature / ...)


FWSaveLoad property Data auto
FWAddOnManager property Manager auto
FWSystemConfig property cfg auto
FWTextContents property Content auto
SexLabFramework Property SexLab Auto
sslThreadLibrary Property Lib Auto
FWController property Controller auto
FWBabyItemList Property BabyItemList Auto
Globalvariable property ModEnabled auto
Globalvariable property CloakingSpellEnabled auto
FWChildSettings property ChildSettings auto
Imagespacemodifier property MenuImageSpace auto

FWStateWidget property StateWidget auto
FWContraceptionWidget property ContraceptionWidget auto
FWBabyHealthWidget property BabyHealthWidget auto
FWWidgetController property WidgetController auto
FWPantyWidget property PantyWidget auto

int Property lastStage auto hidden
float EggTravelingDuration_Percentage = 0.7
int PlayerBleedOut

float property Version auto
float _version

armor property Sanitary_Napkin_Normal auto
armor property Sanitary_Napkin_Bloody auto

ImageSpaceModifier property DefaultBlur auto
Activator Property MaraShrineObject Auto ; God of love and marriage
Activator Property ArkayShrineObject Auto ; God of birth and death

Spell Property BeeingFemaleSpell Auto
Spell Property BeeingMaleSpell Auto
FWAbilityBeeingFemale Property Player Auto hidden
FWAbilityBeeingMale Property PlayerMale Auto hidden

ImageSpaceModifier Property AbortusImod  Auto
ImageSpaceModifier Property AbortusFever Auto
Imagespacemodifier property iModPainLow auto
Imagespacemodifier property iModPainMiddle auto
Imagespacemodifier property iModPainHigh auto

Faction property ForbiddenFaction auto
Faction property FollowerFaction = none auto
Faction property ChildFollowerFaction auto ; Reserved for Current Follower
Faction property ChildFollowerFaction2 = none auto ; Reserved for Potential Follower
Faction property ChildFollowerFaction3 = none auto ; Reserved for HearthFires Adopting
Faction property ChildFollowerFaction4 = none auto ; Free
Faction property ChildFollowerFaction5 = none auto ; Free
Faction property ParentFaction auto
int property ChildFollowerFactionRank = 0 auto
int property ChildFollowerFactionRank2 = 0 auto
int property ChildFollowerFactionRank3 = 0 auto
int property ChildFollowerFactionRank4 = 0 auto
int property ChildFollowerFactionRank5 = 0 auto

spell[] Property StatCycleID_List Auto
spell Property StatMenstruationCycle Auto
spell Property StatPregnancyCycle Auto

spell property BeeingFemaleInfoSpell auto
spell property InfectionSpell auto
spell property FeverSpell auto

spell property Effect_Mittelschmerz auto
spell property Effect_MenstruationCramps auto
spell property Effect_Vorwehen auto
spell property Effect_Eroeffnungswehen auto
spell property Effect_Presswehen auto
spell property Effect_Nachwehen auto

spell property Effect_VaginalBloodLow auto
spell property Effect_VaginalBloodHigh auto
spell property Effect_VaginalBloodBig auto
spell property Effect_BreastMilk1 auto
spell property Effect_BreastMilk2 auto
spell property Effect_BreastMilk3 auto

Armor Property AmnioticFluid Auto
Armor Property VaginalBleeding Auto

book[] Property PlayerBooks Auto
Scroll[] property StartUpScrolls auto
FormList Property BadSpellList Auto
MagicEffect[] property BabyHealingMagicEffects auto

spell property ChaurusBreeder = none Auto hidden
bool property EstrusActive = false Auto hidden
armor property DeviceBelt = none auto hidden
bool property DeviceActive = false auto hidden
bool property HearthFiresActive = false auto hidden

formlist property Pill_Items auto
MagicEffect property Pill_Effect auto
float property MaxContraception = 98.0 AutoReadOnly hidden
float property MaxContraceptionTime = 2.0 AutoReadOnly hidden
LeveledItem[] property PillStor_Types auto

formlist property WashOut_List auto
MagicEffect property WashOut_Effect auto

soulgem property BabyGem auto

race[] property MountableRace auto

int lastStage=-1

Int Property MSG_All = 0 AutoReadOnly hidden 		; Only when set to 'All Messages'
Int Property MSG_Debug = 1 AutoReadOnly hidden		; Send a debug message
Int Property MSG_High = 2 AutoReadOnly hidden		; High Information Level
Int Property MSG_Low = 3 AutoReadOnly hidden		; Low Information Level
Int Property MSG_Immersive = 4 AutoReadOnly hidden	; Imersive Messaage
Int Property MSG_Error = 5 AutoReadOnly hidden		; Important error message
Int Property MSG_Always = 99 AutoReadOnly hidden	; This message will be shown always


int[] property CheatAddFather auto hidden
int property MaxBabyPregnantWith = 6 autoreadonly hidden

FWAbilityBeeingFemale[] property FWCached auto hidden
int FWCacheID=0
int FWCacheMax = 15

Quest property ChildFinder auto

;--------------------------------------------------------------------------------
; Quest Functions
;--------------------------------------------------------------------------------
event OnInit()
	initArrays()
	giveStartupSpells()
	giveStartupItems()
	initDrinkStor()
	OnGameLoad()
endEvent

; Here the last 15 NPCs are stored
function RegisterFWCache(FWAbilityBeeingFemale FW_MagicEffect)
	if FWCacheMax==0
		FWCached=new FWAbilityBeeingFemale[15]
		FWCacheMax=FWCached.length
	endif
	int i=FWCacheID
	int j=0
	while j<FWCacheMax
		if FWCached[j]==FW_MagicEffect
			return
		endif
		j+=1
	endWhile
	FWCacheID = (FWCacheID + 1) % FWCacheMax
	FWCached[i]=FW_MagicEffect
endfunction

; Here you can gain access to a cached BeeingFemaleSpell
FWAbilityBeeingFemale function getBeeingFemaleSpell(actor woman)
	return none
	int j=0
	while j<FWCacheMax
		if FWCached[j].ActorRef==woman
			return FWCached[j]
		endif
		j+=1
	endWhile
	return none
endfunction


; After registration, NPCs may use this potion
function RegisterFluid(potion Fluid)
	int c=Fluid.GetNumEffects()
	while c>0
		c-=1
		if Fluid.GetNthEffectMagicEffect(c)==Pill_Effect && Pill_Items.HasForm(Fluid)==false
			Pill_Items.AddForm(Fluid)
		endif
		if Fluid.GetNthEffectMagicEffect(c)==WashOut_Effect && WashOut_List.HasForm(Fluid)==false
			WashOut_List.AddForm(Fluid)
		endif
	endWhile
endFunction

float function IrregulationChance(actor woman, int state_number)
	return cfg.irregulationChance * Manager.IrregulationChance(woman, state_number)
endFunction

float function IrregulationValue(actor woman, int state_number)
	float max = Manager.IrregulationValue(woman, state_number)
	float min = 1.0
	if max>1.5
		max = 1.5
	endif
	if max<=0
		return 1.0
	elseif max<1
		min = max
		max = FWUtility.MaxFloat(0.3, 1 / max)
	else
		min = FWUtility.MaxFloat(0.3, 1 / max)
	endif
	if min<max
		return Utility.RandomFloat(min,max)
	else
		return Utility.RandomFloat(max,min)
	endif
endFunction

function OnGameLoad()
	actor PA=Game.GetPlayer()
	UnregisterForAllModEvents()
	Utility.WaitMenuMode(4)
	RegisterForModEvent("OrgasmStart", "onSexLabOrgasm")
	RegisterForModEvent("AddActorSperm", "onAddActorSperm")
	RegisterForModEvent("AddSperm", "onAddActorSperm")
	RegisterForModEvent("BeeingFemale", "onBeeingFemaleCommand")
	ModEnabled.SetValueInt(1)
	CloakingSpellEnabled.SetValueInt(1)
	
	if SexLab == none
		Trace("SexLab was not defined - ReReg Sexlabl")
		if FixSexLab()==false
			Trace("SexLab coudln't be fixed")
		endif
	endif
	if Player!=none && PA.GetLeveledActorBase().GetSex()==1
		Player.OnGameLoad()
	elseif PlayerMale!=none && PA.GetLeveledActorBase().GetSex()==0
		PlayerMale.OnGameLoad()
	else
		ReNewSpells()
	endif
	ChildSettings.OnGameLoad()
	Manager.OnLoadGame()
	Content.LoadContent()
	
	UnregisterForUpdate()
	if cfg.UpdateInterval>=10 && cfg.UpdateIntervalEnabled==true
		RegisterForUpdate(30)
	endif
	
	int childCount = StorageUtil.FormListCount(none, "FW.Babys")
	while childCount>0
		childCount-=1
		Form frm = StorageUtil.FormListGet(none, "FW.Babys", childCount)
		if(frm as FWChildActor == none && frm as FWChildItem == none)
			StorageUtil.FormListRemoveAt(none, "FW.Babys", childCount)
		endif
	endwhile
endfunction

int curRefreshWoman
event OnUpdate()
	; Update the next woman in list
	int i=10
	actor female=none
	while i>0 && female==none
		i-=1 ; To prevent endless loops
		female = StorageUtil.FormListGet(none,"FW.SavedNPCs",curRefreshWoman) as actor
		curRefreshWoman+=1
		if curRefreshWoman> StorageUtil.FormListCount(none,"FW.SavedNPCs")
			curRefreshWoman=0
		endif
	endWhile
	if female!=none && female!=Game.GetPlayer()
		float t = Utility.GetCurrentRealTime()
		Data.Update(female)
		;Debug.Notification("Update '" + female.GetDisplayName() + "' done in: "+(Utility.GetCurrentRealTime() - t))
	endif
endEvent


function Upgrade(int oldVersion, int newVersion)
	giveStartupItems(oldVersion)
	Content.Upgrade(oldVersion, newVersion)
	ContraceptionWidget.Upgrade(oldVersion, newVersion)
	BabyHealthWidget.Upgrade(oldVersion, newVersion)
	StateWidget.Upgrade(oldVersion, newVersion)
	ChildSettings.Upgrade(oldVersion, newVersion)
	Manager.Upgrade(oldVersion, newVersion)
	Data.Upgrade(oldVersion, newVersion)
	; Upgrade all Children
	int c = StorageUtil.FormListCount(none,"FW.Babys")
	while c>0
		c-=1
		if StorageUtil.FormListGet(none,"FW.Babys", c) as FWChildActorPlayer != none
			(StorageUtil.FormListGet(none,"FW.Babys", c) as FWChildActorPlayer).Upgrade(oldVersion, newVersion)
		elseif StorageUtil.FormListGet(none,"FW.Babys", c) as FWChildActor != none
			(StorageUtil.FormListGet(none,"FW.Babys", c) as FWChildActor).Upgrade(oldVersion, newVersion)
		endif
	endWhile
	Debug.Notification("Beeing Female updated")
endFunction

function initDrinkStor()
	;int l=Pill_Items.GetSize()
	;while l>0
	;	l-=1
	;	int Level = 0
	;	int Count = 10
	;	potion pot = Pill_Items.GetAt(l) as potion
	;	if pot != none
	;		int m=pot.GetNumEffects()
	;		while m>0
	;			m-=1
	;			if pot.GetNthEffectMagicEffect(m)==Pill_Effect
	;				float mag = pot.GetNthEffectMagnitude(m)
	;				if mag>10
	;					Level = Math.Ceiling(mag / 2)
	;				endif
	;				if mag<10
	;					Count=40
	;				elseif mag <20
	;					Count=30
	;				elseif mag <30
	;					Count=20
	;				endif
	;				m=0
	;			endif
	;		endWhile
	;	endif
	;	Debug.Trace("Add "+Count+"x "+Pill_Items.GetAt(l).GetName()+" to Player")
	;	Game.GetPlayer().AddItem(Pill_Items.GetAt(l),Count)
	;endWhile

	;if PillStor_Types.length>0 && Pill_Items.GetSize()>0
	;	Debug.trace("Add "+Pill_Items.GetSize()+" Pill-Items to "+PillStor_Types.length+" store-types")
	;	int i=PillStor_Types.length
	;	while i>0
	;		i-=1
	;		int j=Pill_Items.GetSize()
	;		while j>0
	;			j-=1
	;			int Level = 0
	;			int Count = 1
	;			potion pot = Pill_Items.GetAt(j) as potion
	;			if pot != none
	;				int k=pot.GetNumEffects()
	;				while k>0
	;					k-=1
	;					if pot.GetNthEffectMagicEffect(k)==Pill_Effect
	;						float mag = pot.GetNthEffectMagnitude(k)
	;						if mag>10
	;							Level = Math.Ceiling(mag / 2)
	;						endif
	;						if mag<10
	;							Count=4
	;						elseif mag <20
	;							Count=3
	;						elseif mag <30
	;							Count=2
	;						endif
	;						k=0
	;					endif
	;				endWhile
	;			endif
	;			Debug.Trace("Add "+pot.GetName()+" to "+PillStor_Types[i].GetName()+" store on Level "+Level+" with count "+Count)
	;			PillStor_Types[i].AddForm(Pill_Items.GetAt(j),Level,Count)
	;		endWhile
	;	endwhile
	;endif
endFunction


function ReNewSpells()
	actor PA = Game.GetPlayer()
	if(PA.HasSpell(BeeingFemaleSpell))
		PA.RemoveSpell(BeeingFemaleSpell)
	endif
	if(PA.HasSpell(BeeingMaleSpell))
		PA.RemoveSpell(BeeingMaleSpell)
	endif
	giveStartupSpells()
endFunction

function giveStartupSpells()
	actor PA = Game.GetPlayer()
	; Remove spells if not neccessary
	if (PA.GetLeveledActorBase().GetSex() == 0 || cfg.RelevantPlayer==false) && PA.HasSpell(BeeingFemaleSpell)==false
		FWUtility.ActorRemoveSpell(PA,BeeingFemaleSpell)
	elseif (PA.GetLeveledActorBase().GetSex() == 1 || cfg.RelevantPlayer==false) && PA.HasSpell(BeeingMaleSpell)==false
		FWUtility.ActorRemoveSpell(PA,BeeingMaleSpell)
	endIf
	; Give spells
	if PA.GetLeveledActorBase().GetSex() == 0 && PA.HasSpell(BeeingMaleSpell)==false && cfg.RelevantPlayer==true
		FWUtility.ActorAddSpell(PA,BeeingMaleSpell)
	elseif PA.GetLeveledActorBase().GetSex() == 1 && PA.HasSpell(BeeingFemaleSpell)==false && cfg.RelevantPlayer==true
		FWUtility.ActorAddSpell(PA,BeeingFemaleSpell)
	endIf
endFunction

function giveStartupItems(int oldVersion=0)
	actor PlayerActor = Game.GetPlayer()
	if oldVersion <=2
		PlayerActor.AddItem(PlayerBooks[0],1)
		PlayerActor.AddItem(PlayerBooks[1],1)
		PlayerActor.AddItem(PlayerBooks[2],1)
		PlayerActor.AddItem(PlayerBooks[3],1)
	endif
	if oldVersion <=9
		PlayerActor.AddItem(StartUpScrolls[0],3)
		PlayerActor.AddItem(StartUpScrolls[1],1)
	endif
endFunction

function initArrays()
	; Cheat Father
	CheatAddFather = new int[27]
	CheatAddFather[0] =0x13475 	; Alvor Nord
	CheatAddFather[1] =0xAE779 	; Badnir Nord
	CheatAddFather[2] =0x1334C 	; Balimund Nord
	CheatAddFather[3] =0x1338A 	; Borkul Orc
	CheatAddFather[4] =0x20040 	; Deekus Argonian
	CheatAddFather[5] =0x1403E 	; Derkeethus Argonian
	CheatAddFather[6] =0x13284 	; GulumEi Argonian
	CheatAddFather[7] =0x661AD 	; Adeber Breton
	CheatAddFather[8] =0x13B69 	; Ainethach Breton
	CheatAddFather[9] =0x13353 	; Dravin DarkElf
	CheatAddFather[10]=0x13370 	; Indaryn DarkElf
	CheatAddFather[11]=0x85D44 	; Orini Dral DarkElf
	CheatAddFather[12]=0x7D679 	; Linwe HighElf
	CheatAddFather[13]=0x34D99 	; Muril HighElf
	CheatAddFather[14]=0x39250 	; Tandil HighElf
	CheatAddFather[15]=0xD6AD8 	; Aquilius Aeresius Imperial
	CheatAddFather[16]=0x1BB5D 	; Gallus Imperial
	CheatAddFather[17]=0x1995B 	; Olur Orc
	CheatAddFather[18]=0x3BC26 	; Yamarz Orc
	CheatAddFather[19]=0x1B3B5 	; Enis Redgurd
	CheatAddFather[20]=0x1C3AB 	; Nazir Redgurd
	CheatAddFather[21]=0x13B9E 	; Elrindir WoodElf
	CheatAddFather[22]=0x1C19C 	; Enthir WoodElf
	CheatAddFather[23]=0x13480 	; Faendal WoodElf
	CheatAddFather[24]=0x1B1CF 	; Dro'marash Khajiit
	CheatAddFather[25]=0x4D12B 	; J'datharr Khajiit
	CheatAddFather[26]=0x13298 	; Mazaka Khajiit
	
	FWCached=new FWAbilityBeeingFemale[15]
	FWCacheMax=FWCached.length
endFunction


; How to use
; FemaleActor.SendModEvent("BeeingFemale", "AddContraception", 100) ; This adds contraception to the woman
; FemaleActor.SendModEvent("BeeingFemale", "AddSperm", MaleActor.GetFormID()) ; This will add sperm to the woman
; FemaleActor.SendModEvent("BeeingFemale", "WashOutSperm", 100) ; This will wash out 100% sperm
; FemaleActor.SendModEvent("BeeingFemale", "ChangeState", 3) ; This will change the state to 'Menstruation'
; FemaleActor.SendModEvent("BeeingFemale", "InfoBox", 100) ; This will open the info window with all informations
; FemaleActor.SendModEvent("BeeingFemale", "DamageBaby", 30) ; This will make 30 damage to the baby
; FemaleActor.SendModEvent("BeeingFemale", "HealBaby", 60) ; This will heal the baby with 60 Health points
Event onBeeingFemaleCommand(string hookName, string argString, float argNum, form sender)
	if hookName=="BeeingFemale" && (sender as Actor)!=none
		Debug.Notification("BF Event called!")
		Debug.Notification("A: " + argString + " V:" + argNum)
		actor a = (sender as Actor)
		int iNum = argNum as int
		int validateF = IsValidateFemaleActor(a)
		int validateM = IsValidateMaleActor(a)
		if argString=="AddContraception" && argNum>0.0 && validateF
			Controller.AddContraception(a, argNum)
		elseif argString=="AddSperm" && argNum>0.0 && validateF
			form f1 = Game.GetForm(argNum as int)
			if f1
				actor f2 = f1 as Actor
				if f2
					Controller.AddSperm(a, f2, 1.0)
				endif
			endif
		elseif argString=="WashOutSperm" && argNum>0 && validateF
			Controller.WashOutSperm(a,2,argNum)
		elseif argString=="ChangeState" && iNum>=0 && iNum <9 && validateF
			Controller.ChangeState(a, iNum)
		elseif argString=="InfoBox"
			Controller.showRankedInfoBox(a,iNum)
		elseif argString=="DamageBaby" && validateF
			Controller.DamageBaby(a,argNum)
		elseif argString=="HealBaby" && validateF
			Controller.DamageBaby(a,argNum)
		endif
	endif
endEvent


; How to use:
; actor denor (= the person who came inside)
; actor woman (= the woman who conceive sperm)
; man.SendModEvent("AddSperm","", woman.GetFormID())
Event onAddSperm(string hookName, string argString, float argNum, form sender)
	actor man
	actor woman
	if (Sender as Actor)!=none
		; Man
		if (Sender as Actor).GetLeveledActorBase().GetSex()==0 && IsValidateMaleActor(Sender as Actor)>0
			man = sender as Actor
		elseif (Sender as Actor).GetLeveledActorBase().GetSex()==1 && SexLab.Config.AllowFFCum==true && IsValidateFemaleActor(Sender as Actor)>0
			man = sender as Actor
		endif
	endif
	if (Game.GetForm(argNum as int) as Actor !=none)
		; Woman
		if IsValidateFemaleActor(Game.GetForm(argNum as int) as Actor)>0
			woman = Game.GetForm(argNum as int) as Actor
		endif
	endif
	
	bool bCanAdd=true
	if woman==none
		bCanAdd=false
	endif
	if man==none
		bCanAdd=false
	endif
	if DeviceActive==true
		if woman.IsEquipped(DeviceBelt)==true
			bCanAdd=false
		endif
	endif
	if bCanAdd==true
		Controller.AddSperm(woman,man)
	endif
endEvent

Event onAddActorSperm(string hookName, Actor Woman, Actor Donor)
	actor w
	actor m
	if Donor!=none
		; Man
		if Donor.GetLeveledActorBase().GetSex()==0 && IsValidateMaleActor(Donor)>0
			m = Donor
		elseif Donor.GetLeveledActorBase().GetSex()==1 && SexLab.Config.AllowFFCum==true && IsValidateFemaleActor(Donor)>0
			m = Donor
		endif
	endif
	if (Woman!=none)
		; Woman
		if IsValidateFemaleActor(Woman)>0
			w = Woman
		endif
	endif
	bool bCanAdd=true
	if woman==none
		bCanAdd=false
	endif
	if m==none
		bCanAdd=false
	endif
	if DeviceActive==true
		if woman.IsEquipped(DeviceBelt)==true
			bCanAdd=false
		endif
	endif
	if bCanAdd==true
		Controller.AddSperm(w,m)
	endif
endEvent

Event onSexLabOrgasm(string hookName, string argString, float argNum, form sender)
	Trace("[SexLabOrgasmEvent]")
	Trace("0. Precheck")
	if(SexLab==none)
		Trace("   SexlLab is not defined - try to fix")
		if(FixSexLab()==false)
			Trace("   Unable to fix SexLab")
			Trace("[/SexLabOrgasmEvent]")
			return
		endif
	endif
	Trace("1. Check for ThreadController")
	sslThreadController ssl_controller = self.SexLab.HookController(argString)
	if ssl_controller==none
		Trace("   Error: No sslThreadController found")
		Trace("[SexLabOrgasmEvent]")
		return
	endif
	Trace("2. Check for BaseAnimation")
	sslBaseAnimation animation = ssl_controller.Animation
	if animation==none
		Trace("   Error: No sslBaseAnimation found")
		Trace("[SexLabOrgasmEvent]")
		return
	endif
	
	Trace("4. Check for Relevant animation")
	Bool relevantAnimation = false
	if(animation.HasTag("Vaginal"))
		relevantAnimation = true
		Trace("   Animation was vaginal")
	endif
	if animation.HasTag("Anal")
		Trace("   Animation was anal")
		if Utility.RandomInt(1,100)<=cfg.NoVaginalCumChance
			Trace("   Continue using anal sperm")
			relevantAnimation=true
		endif
	endif
	If self.cfg.CreatureSperm && (! relevantAnimation)
		Trace("   Check for Tags")
		if(animation.HasTag("Creature") && animation.HasTag("Bestiality") && (! animation.HasTag("Oral")) && (animation.HasTag("Missionary") || animation.HasTag("Doggystyle") || animation.HasTag("Holding") || animation.HasTag("MMMMF") || animation.HasTag("MMMF") || animation.HasTag("MMF")))
			Trace("   Tags are allowed")
			relevantAnimation=true
		else
			Trace("   Tags were forbidden")
			relevantAnimation=false
		endif
	EndIf
	
	If relevantAnimation
		Trace("5. Animation is relevant")
		float amount = 1.0
		int c= animation.PositionCount
		Actor Female = none
		actor Male = none
		actor tmpActor
		int i = 0
		
		Trace("   "+c+" actors are involved")
		while i<c
			;tmpActor = ssl_controller.GetActor(i)
			tmpActor = ssl_controller.Positions[i]
			if Female==none && tmpActor!=none && tmpActor.GetLeveledActorBase().GetSex() == 1
				Female = tmpActor
			elseif Male==none && tmpActor!=none && tmpActor.GetLeveledActorBase().GetSex() == 0
				Male = tmpActor
			endIf
			if Female!=none && Male!=none
				i=c
			else
				i+=1
			endIf
		endWhile
		
		; Check for female sperm
		if (! Male && SexLab.Config.AllowFFCum==true)
			Trace("   Male was none - Check FF sperm")
			i = 0
			while i<c
				;tmpActor = ssl_controller.GetActor(i)
				tmpActor = ssl_controller.Positions[i]
				if Male==none && tmpActor!=none && tmpActor!=Female && tmpActor.GetLeveledActorBase().GetSex() == 1
					Male = tmpActor
				endIf
				if Male!=none
					i=c
				else
					i+=1
				endIf
			endwhile
		endIf
		
		if (! Male)
			Trace("   Male is none - Exit")
			Trace("[/SexLabOrgasmEvent]")
			return
		endif
		If (! Female)
			Trace("   Female was none - Try get victim")
			Female = ssl_controller.GetVictim()
		EndIf
		
		bool bCondom = CheckForCondome(Female, Male)
		
		If Female && Male && bCondom==false
			Trace("6. Male and Female are relevant for now")
			
			if Male.getLeveledActorBase().GetSex()==0
				if IsValidateMaleActor(Male)<0
					Trace("   Male is not a validate Male Actor: "+IsValidateMaleActor(Male))
					Trace("[/SexLabOrgasmEvent]")
					return
				endif
			else
				if IsValidateFemaleActor(Male)<0
					Trace("   Male is not a validate Female Actor: "+IsValidateFemaleActor(Male))
					Trace("[/SexLabOrgasmEvent]")
					return
				endif
			endif
			if Female.getLeveledActorBase().GetSex()==0
				if IsValidateMaleActor(Female)<0
					Trace("   Female is not a validate Male Actor: "+IsValidateMaleActor(Female))
					Trace("[/SexLabOrgasmEvent]")
					return
				endif
			else
				if IsValidateFemaleActor(Female)<0
					Trace("   Female is not a validate Female Actor: "+IsValidateFemaleActor(Female))
					Trace("[/SexLabOrgasmEvent]")
					return
				endif
			endif
			
			if DeviceActive==true
				Trace("7. Check for Device")
				if Female.IsEquipped(DeviceBelt)==true
					Trace("   A Device-Belt was detected")
					Trace("[/SexLabOrgasmEvent]")
					return
				else
					Trace("   No device was detected")
				endif
			endif
			
			Trace("8. Add sperm")
			
			Trace("   Raise AddOn Event 'OnCameInside'")
			Manager.OnCameInside(Female,Male)
			
			If Female.HasSpell(self.BeeingFemaleSpell)==false && IsValidateFemaleActor(Female)>0
				Trace("   Female doesn't had BF Spell - apply spell")
				FWUtility.ActorAddSpell(Female,BeeingFemaleSpell)
			endif
			
			If self.cfg.MaleVirilityRecovery > 0.0
				float virility = FWUtility.ClampFloat(self.SexLab.DaysSinceLastSex(Male) / self.cfg.MaleVirilityRecovery, 0.02, 1.0)
				amount = Utility.RandomFloat(virility * 0.75, virility*1.1)
				if amount>1.0
					amount=1.0
				endif
				Trace("   Base Sperm-Amount is " + amount)
			EndIf
			
			amount = Manager.getSpermAmount(Female,Male,amount)
			Trace("   Calculated Sperm-Amount is " + amount)
			
			if Female.HasSpell(BeeingFemaleSpell)==false
				Trace("   Female still don't got the BF Spell - ignore and continue")
				Message( FWUtility.StringReplace( Content.NoBeeingFemaleSpell , "{0}",Female.GetLeveledActorBase().GetName()), MSG_Immersive)
			endif
			
			If Male == Game.GetPlayer()
				;self.Message("You came inside " + Female.GetLeveledActorBase().GetName() + ".", self.MSG_Immersive)
				Message( FWUtility.StringReplace( Content.YouCameInsideNPC , "{0}",Female.GetLeveledActorBase().GetName()), MSG_Immersive)
			ElseIf Female == Game.GetPlayer()
				;self.Message(Male.GetLeveledActorBase().GetName() + " came inside you.", self.MSG_Immersive)
				Message( FWUtility.StringReplace( Content.NPCCameInsideYou , "{0}",Male.GetLeveledActorBase().GetName()), MSG_Immersive)
			Else
				;self.Message(Male.GetLeveledActorBase().GetName() + " came inside " + Female.GetLeveledActorBase().GetName() + ".", self.Msg_High)
				string[] astring = new string[2]
				astring[0] = Male.GetLeveledActorBase().GetName()
				astring[1] = Female.GetLeveledActorBase().GetName()
				Message( FWUtility.ArrayReplace(Content.NPCCameInsideNPC,astring), self.Msg_High)
			EndIf
			
			if amount>0.0
				Trace("   Finaly add " + amount + " sperm from "+Male.GetLeveledActorBase().GetName() + " to " +Female.GetLeveledActorBase().GetName())
				self.Controller.AddSperm(Female,Male, amount)
				Trace("[/SexLabOrgasmEvent]")
			endif
		EndIf
	else
		Trace("5. Animation is NOT relevant")
		Trace("[/SexLabOrgasmEvent]")
	EndIf
endEvent

function InfoMenuBlur()
	RegisterForModEvent("InfoMenuClosed","onInfoMenuClosed")
	MenuImageSpace.Apply()
endFunction
Event onInfoMenuClosed(string hookName, string argString, float argNum, form sender)
	MenuImageSpace.Remove()
	UnregisterForModEvent("InfoMenuClosed")
endEvent


bool function setObjective(int ID)
	;if Game.GetPlayer().GetLeveledActorBase().GetSex() == 0
	;	ID = 99
	;	lastStage = ID
	;elseif isObjectiveDisplayed(99)
	;	SetObjectiveDisplayed(99, false)
	;endIf
	;if lastStage != ID
	;	if isObjectiveDisplayed(lastStage)
	;		SetObjectiveDisplayed(lastStage, abDisplayed = False)
	;	endIf
	;	if cfg.Messages < 3
	;		SetStage(ID)
	;		SetObjectiveDisplayed(ID, true, true)
	;		if isObjectiveDisplayed(98)
	;			SetObjectiveDisplayed(98, false)
	;		endif
	;		if isObjectiveDisplayed(99)
	;			SetObjectiveDisplayed(99, false)
	;		endif
	;	elseif (! isObjectiveDisplayed(98))
	;		SetStage(98)
	;		SetObjectiveDisplayed(98, true, true)
	;	endIf
	;	lastStage = ID
	;	return true
	;else
	;	return false
	;endIf
endFunction

function refreshObjective()
	;SetObjectiveDisplayed(0, abDisplayed = False)
	;SetObjectiveDisplayed(1, abDisplayed = False)
	;SetObjectiveDisplayed(2, abDisplayed = False)
	;SetObjectiveDisplayed(3, abDisplayed = False)
	;SetObjectiveDisplayed(4, abDisplayed = False)
	;SetObjectiveDisplayed(5, abDisplayed = False)
	;SetObjectiveDisplayed(6, abDisplayed = False)
	;SetObjectiveDisplayed(7, abDisplayed = False)
	;SetObjectiveDisplayed(8, abDisplayed = False)
	;SetObjectiveDisplayed(20, abDisplayed = False) ; Pregnant by other mod
	;SetObjectiveDisplayed(21, abDisplayed = False) ; Pregnant by chaurus
	;SetObjectiveDisplayed(98, abDisplayed = False) ; Being a woman
	;SetObjectiveDisplayed(99, abDisplayed = False) ; Being a man
	
	;if Game.GetPlayer().GetLeveledActorBase().GetSex() == 0
		;SetStage(99)
		;SetObjectiveDisplayed(99, true, true) ; Male Quest
	;else
	;	if cfg.Messages <= 3
			;SetStage(lastStage)
			;SetObjectiveDisplayed(lastStage, true, true)
	;	else
			;SetStage(98)
			;SetObjectiveDisplayed(98)
	;	endIf
	;endIf
endFunction

;--------------------------------------------------------------------------------
; General Functions
;--------------------------------------------------------------------------------

function Trace(string msg, actor a = none)
	;If cfg.Messages <= 1 && a==none
	;	Debug.Trace(msg)
	;elseIf cfg.Messages <= 0 && a!=none
	;	Debug.Trace("[" + a.GetLeveledActorBase().GetName() + "] "+msg)
	;endif
endFunction

bool function FixSexLab()
	if SexLab==none
		SexLab = Game.GetFormFromFile(0x00000D62, "SexLab.esm") as SexLabFramework
		if SexLab == none
			return false
		endif
	endif
	return true
endFunction

Bool Function Message(string akMessage, int aiType = 1, bool abAsBox = False)
	If cfg.Messages <= aiType
		If abAsBox && Game.GetPlayer().GetCombatState()==0 ; Messagebox only when not in cobat
			Debug.MessageBox(akMessage)
		Else
			Debug.Notification(akMessage)
		EndIf
		Return True
	EndIf
	
	Return false
EndFunction

function CheckPlayerSex()
	actor p=Game.GetPlayer()
	If p.GetLeveledActorBase().GetSex() == 0
		if Player!=none
			p.RemoveSpell(BeeingFemaleSpell)
			p.DispelSpell(BeeingFemaleSpell)
			Player=none
		endif
		if PlayerMale==none
			p.AddSpell(BeeingMaleSpell)
		endif
	elseIf p.GetLeveledActorBase().GetSex() == 1
		if PlayerMale!=none
			p.RemoveSpell(BeeingMaleSpell)
			p.DispelSpell(BeeingMaleSpell)
			PlayerMale=none
		endif
		if Player==none
			p.AddSpell(BeeingFemaleSpell)
		endif
	endif
endFunction

function raiseModEvent(string EventName, FWAbilityBeeingFemale base)
	SendModEvent("BeeingFemale",EventName, base.ActorRef.GetFormID())
endFunction

function raiseModEventA(string EventName, Actor a)
	SendModEvent("BeeingFemale",EventName, a.GetFormID())
endFunction


; Check if the given Actor is relevant
;  1 = OK Player
;  2 = OK Follower
;  3 = OK NPC
; -1 = Forbidden
; -2 = IsDead
; -3 = Is male
; -4 = Non Unique
; -5 = Player is not relevant
; -6 = Follower is not relevant
; -7 = NpcMentruation is not relevant
; -8 = Is Child
; -9 = Is Elder
; -10 = None
int function IsValidateActor(actor a)
	if a==none
		return -10
	endif
	if a.GetLeveledActorBase()==none
		return -11
	endif
	if a.GetLeveledActorBase().GetSex()==0
		return IsValidateMaleActor(a)
	elseif a.GetLeveledActorBase().GetSex()==1
		return IsValidateFemaleActor(a)
	endif
endFunction

int function IsValidateFemaleActor(actor a)
	if a==none
		return -10
	endif
	if a.GetLeveledActorBase()==none
		return -11
	endif
	if a.IsInFaction(ForbiddenFaction) || a.HasKeywordString("SexLabForbid")
		;Message("Beeing Female missed on " + a.GetLeveledActorBase().GetName() + " - Not validated (Forbidden Fraction/Sexlab Keyword)",0)
		return -1
	endIf
	if a.IsDead()
		;Message("Beeing Female missed on " + a.GetLeveledActorBase().GetName() + " - IsDead",0)
		return -2
	endIf
	if a.GetLeveledActorBase().GetSex() == 0
		return -3
	endif
	if a.GetLeveledActorBase().IsUnique()==false
		return -4
	endif
	if Game.GetPlayer() == a && cfg.RelevantPlayer==false
		;Message("Beeing Female missed on " + a.GetLeveledActorBase().GetName() + " - Player not relevant",0)
		return -5
	elseif Game.GetPlayer() != a
		if a.IsInFaction(FollowerFaction) && cfg.RelevantFollower==false
			;Message("Beeing Female missed on " + a.GetLeveledActorBase().GetName() + " - Follower not relevant",0)
			return -6
		endif
		if a.IsInFaction(FollowerFaction)==false && cfg.RelevantNPC==false
			;Message("Beeing Female missed on " + a.GetLeveledActorBase().GetName() + " - normal NPC not relevant",0)
			return -7
		endif
	endif
	Race ActorRace = a.GetLeveledActorBase().GetRace()
	String RaceName = ActorRace.GetName()+MiscUtil.GetRaceEditorID(ActorRace)
	if StringUtil.Find(RaceName, "Elder") != -1
		return -9
	endIf
	if Game.GetPlayer() == a
		return 1
	elseif a.IsInFaction(FollowerFaction)
		return 2
	else
		return 3
	endif
endFunction

; Check if the given Actor is relevant
;  1 = OK Player
;  2 = OK Follower
;  3 = OK NPC
; -1 = Forbidden
; -2 = IsDead
; -3 = Is female
; -8 = Is Child
; -10 = None
int function IsValidateMaleActor(actor a)
	if a==none
		return -10
	endif
	if a.GetLeveledActorBase()==none
		return -11
	endif
	if a.IsInFaction(ForbiddenFaction) || a.HasKeywordString("SexLabForbid")
		;Message("Beeing Female missed on " + a.GetLeveledActorBase().GetName() + " - Not validated (Forbidden Fraction/Sexlab Keyword)",0)
		return -1
	endIf
	if a.IsDead()
		;Message("Beeing Female missed on " + a.GetLeveledActorBase().GetName() + " - IsDead",0)
		return -2
	endIf
	if a.GetLeveledActorBase().GetSex() == 1
		return -3
	endif
	Race ActorRace = a.GetLeveledActorBase().GetRace()
	String RaceName = ActorRace.GetName()+MiscUtil.GetRaceEditorID(ActorRace)
	if Game.GetPlayer() == a
		return 1
	elseif a.IsInFaction(FollowerFaction)
		return 2
	else
		return 3
	endif
endFunction


function Blur(float Strength = 1.0, ImageSpaceModifier Effect = none)
	DefaultBlur.Remove()
	if Effect == none
		DefaultBlur.Apply(Strength)
	else
		Effect.Apply(Strength)
	endIf
endFunction


bool function CheckForCondome(actor Woman, actor Man)
	return Manager.CheckForCondome(Woman, Man)
endFunction


; Plaing a sexlab sound
function PlayPainSound(Actor A,float Strength=30.0)
	if A.Is3DLoaded()
		sslBaseVoice voice = SexLab.PickVoice(A)
    	;int vfxInstance = voice.Moan(A, Strength as int, true)
    	;Sound.SetInstanceVolume(vfxInstance, SexLab.Config.fVoiceVolume)
    	if voice
    		voice.Moan(A, Strength as int, true)
    	endif
    endif
endFunction

; Playing a bleed out
function PlayBleedOut(Actor A)
	if A.GetSitState() == 0 && A.IsOnMount() == false
		If A.IsWeaponDrawn()
			A.SheatheWeapon()
		EndIf
		if Game.GetPlayer() == A
			if(PlayerBleedOut == 0)
				Debug.SendAnimationEvent(A, "IdleForceDefaultState");
				Debug.SendAnimationEvent(A, "BleedOutStart");
			endif
			PlayerBleedOut += 1
		else
			Debug.SendAnimationEvent(A, "IdleForceDefaultState");
			Debug.SendAnimationEvent(A, "BleedOutStart");
		endIf
	endif
endFunction

; Stop playing bleed-out
function stopBleedOut(Actor A)
	if Game.GetPlayer() == A
		PlayerBleedOut -= 1
		if(PlayerBleedOut == 0)
			Debug.SendAnimationEvent(A, "BleedOutStop");
			Debug.SendAnimationEvent(A, "IdleForceDefaultState");
		endIf
	else
		Debug.SendAnimationEvent(A, "BleedOutStop");
		Debug.SendAnimationEvent(A, "IdleForceDefaultState");
	endIf
endFunction

function PlayerTimer(bool Enabled = true)
	if Player==none
		return
	endIf
	if Enabled==true
		Controller.Pause(Game.GetPlayer(), false)
		;Player.RegisterForUpdateGameTime(Player.UpdateDelay)
		Player.OnUpdateFunction()
	else
		;Player.UnRegisterForUpdateGameTime()
		Controller.Pause(Game.GetPlayer(), true)
	endIf
endFunction


function getUp(Actor A)
	Utility.WaitMenuMode(0)
	if A== Game.GetPlayer()
		Game.DisablePlayerControls(ablooking = True, abCamSwitch = True)
	endif
	;Game.GetPlayer().PlayIdle(WakeUp)
	Debug.SendAnimationEvent(A, "GetupBirth");
	Utility.Wait(3.5)
	Debug.SendAnimationEvent(A, "IdleForceDefaultState");
	if A== Game.GetPlayer()
		Game.EnablePlayerControls(ablooking = true, abCamSwitch = true)
	endif
endFunction

bool Function LayDown(Actor A)
	; Check for center
	ObjectReference BedRef
	; Select a bed
	if A != none
		BedRef = Game.FindClosestReferenceOfAnyTypeInListFromRef(SexLab.Config.BedsList, A, 600.0)
	endIf
	if BedRef != none && !BedRef.IsFurnitureInUse(true)
		A.MoveTo(BedRef)
		A.SetAngle(BedRef.getAngleX(), BedRef.getAngleY(), BedRef.getAngleZ())
		Utility.Wait(1)
		Debug.SendAnimationEvent(A, "LayDownBirth");
		Utility.Wait(3.6)
		return true
	endIf
	Debug.SendAnimationEvent(A, "LayDownBirth");
	Utility.Wait(3.6)
	return false
endFunction


;--------------------------------------------------------------------------------
; Female Functions
;--------------------------------------------------------------------------------

; Does NPCs have a Menstruation cycle at all - and can become pregnant
bool function NpcMentruation()
	return true
endFunction

; Get the time the egg needs for traveling
float function getEggTravelingDuration(actor a)
	float x = getStateDuration(1,a) * EggTravelingDuration_Percentage
	if x<1.1 ; Make sure the Egg traveling is more then 1 Day
		return 1.01
	else
		return x
	endif
endFunction

bool function IsActorPregnantByChaurus(actor woman)
	if EstrusActive==true
		if ChaurusBreeder != none
			return woman.HasSpell(ChaurusBreeder)
		endif
	endif
	return false
endFunction

; Get the time in days - how long the pill will work
float function GetPillDuration(actor a)
	return 4.0 * Manager.getActorContraceptionDuration(a) ; Every 2 days
endFunction

int function calculateNumChildren(actor Woman)
	int result = 1
	float counter = 1000000.0
	float Chance = Utility.RandomFloat(0.0,counter)
	int i = 0
	float MaxBabys = cfg.MaxBabys * Manager.ActorMaxBabse(Woman)
	float MaxBabyChance = Manager.ActorMaxChance(Woman)
	if MaxBabys <1
		MaxBabys=1
	endIf
	; on a realistic base of 1 / 85 (~1.2%) following results will be
	; 1 Child    - 100.0000000000%
	; 2 Children -   1.1764705882%
	; 3 Children -   0.0138408304%
	; 4 Children -   0.0001628332%
	; 5 Children -   0.0000019156%
	; 6 Children -   0.0000000225%
	while i < 6 ; a Max of 6 children!!!!
		counter /= cfg.MultipleThreshold * MaxBabyChance ;ChanceMultipleBirth
		if counter > Chance
			result += 1
		endIf
		i += 1
	endWhile
	if result > Math.Floor(MaxBabys)
		result = Math.Floor(MaxBabys)
	endIf
	if result > MaxBabyPregnantWith
		result = MaxBabyPregnantWith
	endIf
	return result
endFunction


; Spawn the childs / adding them to the inventory
function InstantBornChilds(actor a)
	int numChilds = StorageUtil.GetIntValue(a,"FW.NumChilds",numChilds)
	if numChilds==0
		return
	endif
	float BabyHealth = StorageUtil.GetFloatValue(a,"FW.UnbornHealth",100.0)
	while numChilds>0
		numChilds-=1
		float rndHealth=Utility.RandomFloat(1,25)
		if BabyHealth>rndHealth
			SpawnChild(a, StorageUtil.FormListGet(a,"FW.ChildFather",numChilds) As Actor )
		else
			; Totgeburt
		endIf
	endWhile
	StorageUtil.FormListClear(a,"FW.ChildFather")
	StorageUtil.SetIntValue(a,"FW.NumChilds",0)
	StorageUtil.UnsetIntValue(a,"FW.Abortus")
	StorageUtil.UnsetFloatValue(a,"FW.UnbornHealth")
	StorageUtil.UnsetFloatValue(a,"FW.AbortusTime")
endFunction

; in original 2 phases:
; Follicular phase : 12 - 16 Days (contains Menstuation and Follicular)
; Luteal phase : 12 - 16 Days (contains Ovulation and Luteal)
;--------------
; so for 4 Phases:
; Follicular: arround 8 - 12 Days
; Ovulation: 3, 5 - 4  days (it takes 3 Day for egg to arrive, and there is 12 - 24 hours for sperm)
; Luteal: arround 9 - 11 Days
; Menstruation: 3 - 5 days
; 1. Trimester: 90 Days
; 2. Trimester: 90 Days
; 3. Trimester: 90 Days
; Labor-Pains around 5 - 24 hours
; Replanish As long the pregnacy takes
float function getStateDuration(int Step, actor woman)
	if Step == 0 ; Follicular phase
		return cfg.FollicularDuration * Manager.getActorDurationScale(Step,woman) * StorageUtil.GetFloatValue(woman,"FW.Irregulation",1.0);
	elseif Step == 1 ; Ovulation
		return cfg.OvulationDuration * Manager.getActorDurationScale(Step,woman) * StorageUtil.GetFloatValue(woman,"FW.Irregulation",1.0);
	elseif Step == 2 ; Luteal phase
		return cfg.LutealDuration * Manager.getActorDurationScale(Step,woman) * StorageUtil.GetFloatValue(woman,"FW.Irregulation",1.0);
	elseif Step == 3 ; Menstruation
		return cfg.MenstrualDuration * Manager.getActorDurationScale(Step,woman) * StorageUtil.GetFloatValue(woman,"FW.Irregulation",1.0);
	elseif Step == 4 ; 1. trimester 
		return cfg.Trimster1Duration * Manager.getActorDurationScale(Step,woman) * StorageUtil.GetFloatValue(woman,"FW.Irregulation",1.0);
	elseif Step == 5 ; 2. trimester 
		return cfg.Trimster2Duration * Manager.getActorDurationScale(Step,woman) * StorageUtil.GetFloatValue(woman,"FW.Irregulation",1.0);
	elseif Step == 6 ; 3. trimester 
		return cfg.Trimster3Duration * Manager.getActorDurationScale(Step,woman) * StorageUtil.GetFloatValue(woman,"FW.Irregulation",1.0);
	elseif Step == 7 ; labor pains
		return 1 ; Fix
	elseif Step == 8 ; replenish
		return cfg.ReplanishDuration * Manager.getActorDurationScale(Step,woman) * StorageUtil.GetFloatValue(woman,"FW.Irregulation",1.0);
	else
		return 0
	endIf
endFunction


; get the Belly breast scaling value
; NodeSet 0 = Belly
; NodeSet 1 = Breasts
; PhaseID 0 = 1st Trimester
; PhaseID 1 = 2nd Trimester
; PhaseID 2 = 3rd Trimester
float Function GetPhaseScale(int NodeSet, int PhaseID)
	; NodeSet 0 = Belly
	; NodeSet 1 = Breasts
	
	if cfg.VisualScalingKind==0 ; Realistic
		return FWScalingSettings.Realistic(NodeSet, PhaseID)
	elseif cfg.VisualScalingKind==1 ; Linear
		return FWScalingSettings.Linear(NodeSet, PhaseID)
	elseif cfg.VisualScalingKind==2 ; Immediately
		return FWScalingSettings.Immediately(NodeSet, PhaseID)
	elseif cfg.VisualScalingKind==3 ; Breasts
		return FWScalingSettings.Breasts(NodeSet, PhaseID)
	elseif cfg.VisualScalingKind==4 ; Belly
		return FWScalingSettings.Belly(NodeSet, PhaseID)
	elseif cfg.VisualScalingKind==5 ; Late
		return FWScalingSettings.Late(NodeSet, PhaseID)
	endif
	Return 0.0
EndFunction


; DamageType Argument:
; 	0 = Mittelschmerz
; 	1 = Menstruation
; 	2 = PMS pains
; 	3 = Labor Pains
; 	4 = Giving Birth
;	5 = Aborts
float function getDamageScale(int DamageType, actor a)
	return Manager.getActorDamageScale(DamageType,a)
endFunction

float function getPainLevel(int stateID)
	if stateID==1
		return Utility.RandomFloat(0.1,2.5)
	elseif stateID==3
		return Utility.RandomFloat(0.1,2.5)
	endif
endFunction

bool function canBecomePMS(actor woman)
	float chance = cfg.PMSChance * Manager.PMSChanceActorScale(woman)
	if Utility.RandomFloat(0.0,100.0) < chance
		return true
	else
		return false
	endIf
endFunction

bool function canBecomePregnant(actor woman)
	float chance = cfg.ConceiveChanceNPC
	if Game.GetPlayer() == woman
		chance = cfg.ConceiveChance
	elseif woman.IsInFaction(FollowerFaction)
		chance = cfg.ConceiveChanceFollower
	endif
	chance*=Manager.PregnancyChanceActorScale(woman)
	if Utility.RandomFloat(0.0,100.0) < chance
		return true
	else
		return false
	endIf
endFunction


; Do some damage to the specific actor
; Percentage = the percentage of health, the actor will lose
; DamageType = The type of Damage (See list)
; OptionalArgument (See list)
; -----------------------------------------------------------
; Damage Type:								Optional Argument
;  0	Unknown
;  1	Mittelschmerz / Ovulation pains		strength of the pains
;  2	PMS pains							
;  3	Menstruation cramps					strength of the pains
;  4	Pregnancy 1. sickness
;  5	Pregnancy 2. sickness
;  6	Pregnancy 3. sickness
;  7	premonitory pains
;  8	first stage pains
;  9	Child-Pressing pains
; 10	bearing-down pains
; 11	afterpains
; 12	baby milk drinking pains
; 13	infection pains
; 14	abortus pains
Function doDamage(actor A, float Percentage, int DamageType, float OptionalArgument = 0.0)
	float ScaleDamage = 1.0
	bool IsPlayer = A == Game.GetPlayer()
	
	if IsPlayer
		if cfg.Difficulty == 0 ; Painless
			ScaleDamage = 0.4
		elseif cfg.Difficulty == 1 ; Easy
			ScaleDamage = 0.7
		elseif cfg.Difficulty == 3 ; Advanced
			ScaleDamage = 1.3
		elseif cfg.Difficulty == 4 ; Heavy
			ScaleDamage = 1.7
		endIf
	ElseIf cfg.NPCFeelPain
		ScaleDamage = 0.6 ; NPC got a reduced damage
	endif
	
	Percentage *=ScaleDamage
	
	Percentage=Manager.OnDoDamage(A,Percentage,DamageType,OptionalArgument)
	
	If ! IsPlayer && cfg.NPCFeelPain==false
		Percentage = 0
	elseif Percentage<1
		; At least 1% Damage (exclusive ScaleDamage)
		Percentage = 1
	elseif Percentage>50
		; A maximum of 50%
		Percentage = 50
	endif
	float efxDage=Percentage
	if !IsPlayer && Percentage>2
		efxDage = Percentage / 3
	endif
	
	Manager.OnDoDamageStart(A,Percentage, DamageType,OptionalArgument)
	
	if IsPlayer || cfg.NPCFeelPain
		int steps
		float DamageLeft = efxDage
		; In how many steps the Damage will be
		if Percentage <10
			steps = 1;
		ElseIf Percentage <20
			steps = 2;
		ElseIf Percentage <30
			steps = 3;
		ElseIf Percentage <40
			steps = 4;
		ElseIf Percentage <50
			steps = 5;
		ElseIf Percentage <60
			steps = 6;
		ElseIf Percentage <70
			steps = 7;
		ElseIf Percentage <80
			steps = 8;
		ElseIf Percentage <90
			steps = 9;
		Else
			steps = 10;
		EndIf
		
		while steps > 0
			if(DamageLeft > 10)
				A.DamageActorValue("Health", (A.GetBaseActorValue("Health") / 100) * 10)
				DamageLeft -= 10
			Else
				A.DamageActorValue("Health", (A.GetBaseActorValue("Health") / 100) * DamageLeft)
			EndIf
			Utility.Wait( 0.5 )
			steps -= 1
		Endwhile
	else
		Utility.Wait((efxDage / 10) + 1.0)
	endIf
	Utility.Wait( 3.0 )
	Manager.OnDoDamageEnd(A,Percentage, DamageType,OptionalArgument)
EndFunction

float function LutealImpregnationTime(float CurrentStatePercent)
	float res = 90 - (CurrentStatePercent * 1.66667)
	if res<0.0
		return 0.0
	else
		return res
	endif
endfunction




;--------------------------------------------------------------------------------
; Male Functions
;--------------------------------------------------------------------------------

; Returns the time male sperm can survive
float function getMaleSpermDuration(actor a)
	if a==none
		return cfg.SpermDuration
	else
		float sd = Manager.ActorMaleSpermDurationScale(a)
		if sd<=0
			return cfg.SpermDuration
		else
			return cfg.SpermDuration * sd
		endif
	endif
endFunction



;--------------------------------------------------------------------------------
; Male / Female Functions
;--------------------------------------------------------------------------------
float function GetSpermRelevance(actor female, actor male)
	float result = 1.0
	if female!=none && male!=none
		if female.HasFamilyRelationship(male)==true
			result+=0.1
		endif
		if female.HasParentRelationship(male)==true
			result-=0.15
		endif
		int relationship = female.GetRelationshipRank(male)
		result *= (relationship + 14) / 13
	endif
	return result
endfunction





;--------------------------------------------------------------------------------
; Baby Functions
;--------------------------------------------------------------------------------

function SpawnChild(Actor Mother, Actor Father)
	;Debug.Notification("1. Mother: " + Mother.GetLeveledActorBase().GetName() + " Father: " + Father.GetLeveledActorBase().GetName())
	int BabysForTheActor = StorageUtil.GetIntValue(Mother,"FW.NumBabys",0)
	StorageUtil.SetIntValue(Mother,"FW.NumBabys",BabysForTheActor + 1)
	if Mother!=Game.GetPlayer() && cfg.NPCBornChild==false
		; NPCs don't spawn babys
		return
	endif
	form Baby = none
	if cfg.BabySpawn == 0
		return;
	elseif cfg.BabySpawn == 1 ; && (Mother == Game.GetPlayer() || Father==Game.GetPlayer()) ; Only when the player is involved there will spawn actors
		Baby = SpawnChildActor(Mother, Father)
	elseif cfg.BabySpawn == 2
		Baby = SpawnChildItem(Mother, Father)
	elseif cfg.BabySpawn == 3 && BabyGem!=none
		Mother.AddItem(BabyGem)
	endif
	
	if Baby!=none
		; Here, all babys are stored
		StorageUtil.FormListAdd(none,"FW.Babys", Baby)
	endif
	
	StorageUtil.SetFloatValue(Mother,"FW.LastBornChildTime", Utility.GetCurrentGameTime())
	StorageUtil.SetFloatValue(Father,"FW.LastBornChildTime", Utility.GetCurrentGameTime())
	StorageUtil.FormListAdd(Mother,"FW.BornChildFather", Father)
	StorageUtil.FloatListAdd(Mother,"FW.BornChildTime",Utility.GetCurrentGameTime())
	Controller.UpdateParentFaction(Mother)
	Controller.UpdateParentFaction(Father)
	Manager.OnBabySpawn(Mother, Father)
endFunction

MiscObject function SpawnChildItem(Actor Mother, Actor Father)
	Int gender = Utility.RandomInt(0, 100)
	if gender < 53
		gender=0
	else
		gender=1
	endif
	MiscObject mo = BabyItemList.getBabyItem(Mother, Father,gender)
	if mo == none
		return none
	endif
	FWChilditem fwchild = mo as FWChilditem
	if fwchild != none
		string childName = getRandomChildName(gender)
		fwchild.SetName(childName)
		fwchild.SetSex(gender)
		fwchild.SetVampire(false)
		fwchild.SetParent(Mother,Father)
	endif
	
	showBornMessage(Mother, Father, gender)
	Mother.addItem(mo);
	return mo
endFunction

actor function SpawnChildActor(Actor Mother, Actor Father)
	;Debug.Notification("2. Mother: " + Mother.GetLeveledActorBase().GetName() + " Father: " + Father.GetLeveledActorBase().GetName())
	bool bIsPlayerChild = false
	if Mother==Game.GetPlayer() || Father==Game.GetPlayer()
		bIsPlayerChild = true
	endif
	Int gender = Utility.RandomInt(0, 100)
	if gender < 53
		gender=0
	else
		gender=1
	endif
	actorbase newChildBase = BabyItemList.getBabyActor(Mother, Father,gender)
	if newChildBase==none
		return none
	endif
	Actor newChild

	if(Utility.RandomInt(1, 2) == 1 || Mother==none) && Father!=none
		newChildBase.SetHairColor(Father.GetLeveledActorBase().GetHairColor()) ; Fathers hair - color
	elseif Mother!=none
		newChildBase.SetHairColor(Mother.GetLeveledActorBase().GetHairColor()) ; Mothers hair - color
	endIf
	; Face Morphs
	int i = 0
	while i < 20
		if(Utility.RandomInt(1, 2) == 1 || Mother==none) && Father!=none
			newChildBase.SetFaceMorph(Father.GetLeveledActorBase().GetFaceMorph(i), i) ; Fathers faceMorph
		elseif Mother!=none
			newChildBase.SetFaceMorph(Mother.GetLeveledActorBase().GetFaceMorph(i), i) ; Mothers faceMorph
		endIf
		i += 1
	endWhile
	
	; Create new Child
	newChild = Mother.PlaceActorAtMe(newChildBase)
	if newChild!=none
		string childName = getRandomChildName(gender)
		
		newChild.MoveTo(Mother, 50, 50, 10)
		newChild.QueueNiNodeUpdate()
		newChild.MakePlayerFriend()
	
		; Set relationship
		if Mother!=none
			newChild.SetRelationshipRank(Mother, 2)
			Mother.SetRelationshipRank(newChild, 2)
		endif
		if Father!=none
			newChild.SetRelationshipRank(Father, 2)
			Father.SetRelationshipRank(newChild, 2)
		endif
	
		if Mother == Game.GetPlayer() ||Father == Game.GetPlayer()
			; set Fraktion
			if(ChildFollowerFaction!=none)
				newChild.SetFactionRank(ChildFollowerFaction, ChildFollowerFactionRank)
			endif
			if(ChildFollowerFaction2!=none)
				newChild.SetFactionRank(ChildFollowerFaction2, ChildFollowerFactionRank2)
			endif
			if(ChildFollowerFaction3!=none)
				newChild.SetFactionRank(ChildFollowerFaction3, ChildFollowerFactionRank3)
			endif
			if(ChildFollowerFaction4!=none)
				newChild.SetFactionRank(ChildFollowerFaction4, ChildFollowerFactionRank4)
			endif
			if(ChildFollowerFaction5!=none)
				newChild.SetFactionRank(ChildFollowerFaction5, ChildFollowerFactionRank5)
			endif
			newChild.SetPlayerTeammate(true, false)
			
			; Now also set a "Other Parent" if empty
			if Mother == Game.GetPlayer()
				ChildSettings.SetOtherParentAlias(Father, true)
			else
				ChildSettings.SetOtherParentAlias(Mother, true)
			endif
		else
			newChild.SetRelationshipRank(Game.GetPlayer(),2)
		endIf
		
		if bIsPlayerChild==true
			if HearthFiresActive==true
				faction f1 = Game.GetFormFromFile(0x4290, "HearthFires.esm") as Faction
				faction f2 = Game.GetFormFromFile(0x42B0, "HearthFires.esm") as Faction
				newChild.SetFactionRank(f1,25)
				newChild.SetFactionRank(f2,1)
			endif
		endIf
		
		newChild.EnableAI(true)
		newChild.EvaluatePackage()
		FWChildActor fwchild = newChild as FWChildActor
		if fwchild != none
			; First thing for any FWChildren - set ActorValues to Start-up values
			if gender==0
				; Male values
				fwchild.SetAV("Comprehension", 5)
				fwchild.SetAV("Destruction", 10)
				fwchild.SetAV("Illusion", 10)
				fwchild.SetAV("Conjuration", 10)
				fwchild.SetAV("Restoration", 10)
				fwchild.SetAV("Alteration", 10)
				fwchild.SetAV("Block", 10)
				fwchild.SetAV("OneHanded", 10)
				fwchild.SetAV("TwoHanded", 10)
				fwchild.SetAV("Marksman", 5)
				fwchild.SetAV("Sneak", 10)
				fwchild.SetAV("Magicka", 15)
				fwchild.SetAV("CarryWeight", 35)
				fwchild.SetAV("Health", 80)
				
				fwchild.SetAV("SpeedMult", 100)
				fwchild.SetAV("HealRate", 0.6)
				fwchild.SetAV("MagickaRate", 1.4)
				fwchild.SetAV("StaminaRate", 2.8)
			else
				; Female values
				fwchild.SetAV("Comprehension", 10)
				fwchild.SetAV("Destruction", 10)
				fwchild.SetAV("Illusion", 10)
				fwchild.SetAV("Conjuration", 10)
				fwchild.SetAV("Restoration", 10)
				fwchild.SetAV("Alteration", 10)
				fwchild.SetAV("Block", 10)
				fwchild.SetAV("OneHanded", 5)
				fwchild.SetAV("TwoHanded", 5)
				fwchild.SetAV("Marksman", 10)
				fwchild.SetAV("Sneak", 10)
				fwchild.SetAV("Magicka", 35)
				fwchild.SetAV("CarryWeight", 15)
				fwchild.SetAV("Health", 80)
				
				fwchild.SetAV("SpeedMult", 95)
				fwchild.SetAV("HealRate", 0.5)
				fwchild.SetAV("MagickaRate", 1.6)
				fwchild.SetAV("StaminaRate", 2.8)
			endif
			;Debug.Notification("3. Mother: " + Mother.GetLeveledActorBase().GetName() + " Father: " + Father.GetLeveledActorBase().GetName())

			fwchild.Mother = Mother
			fwchild.Father = Father
			fwchild.Name = childName
			fwchild.Sex = gender
			fwchild.IsVampire = false
			fwchild.SetLevel(1)
			fwchild.DayOfBirth = Utility.GetCurrentGameTime()
			fwchild.Order_WaitAndPlay()
			if Father!=none
				if Father.GetLeveledActorBase().IsUnique()
					if Mother.HasFamilyRelationship(Father)==true || (Mother.GetRelationshipRank(Father)==4 && Utility.RandomInt(0,10)>7)
						fwchild.UseFathersLastName = true
					else
						fwchild.UseFathersLastName =false
					endif
				else
					fwchild.UseFathersLastName = false
				endIf
			else
				fwchild.UseFathersLastName = false
			endif
			fwchild.InitChild()
		else
			; It's not an fwchild
			newChild.setDisplayName(childName)
			newChild.setName(childName)
		endif
	endif
	showBornMessage(Mother, Father, newChild.GetLeveledActorBase().GetSex())
	return newChild
endFunction

function showBornMessage(actor Mother, actor Father, int sex)
	if Father==Game.GetPlayer()
		if sex==0
			Message( FWUtility.StringReplace( Content.NPCFatherBornHealthyBoy , "{0}",Mother.GetLeveledActorBase().GetName()), MSG_Always,true)
		else
			Message( FWUtility.StringReplace( Content.NPCFatherBornHealthyGirl , "{0}",Mother.GetLeveledActorBase().GetName()), MSG_Always,true)
		endif
		
	elseif Mother==Game.GetPlayer()
		if sex==0
			Message( Content.YouBornHealthyBoy , MSG_All,true)
		else
			Message( Content.YouBornHealthyGirl , MSG_All,true)
		endif
		
	elseif Mother.IsInFaction(FollowerFaction)
		if sex==0
			Message( FWUtility.StringReplace( Content.NPCBornHealthyBoy , "{0}",Mother.GetLeveledActorBase().GetName()), MSG_Immersive,true)
		else
			Message( FWUtility.StringReplace( Content.NPCBornHealthyGirl , "{0}",Mother.GetLeveledActorBase().GetName()), MSG_Always,true)
		endif
		
	elseif Mother!=Game.GetPlayer()
		if sex==0
			Message( FWUtility.StringReplace( Content.NPCBornHealthyBoy , "{0}",Mother.GetLeveledActorBase().GetName()), MSG_High)
		else
			Message( FWUtility.StringReplace( Content.NPCBornHealthyGirl , "{0}",Mother.GetLeveledActorBase().GetName()), MSG_Always,true)
		endif
		
	endif
endFunction

string function getRandomChildName(int sex)
	int rnd=0
	if sex==0 && BabyItemList.Male_Names.length > 0
		; Male Name
		rnd=Utility.RandomInt(0,BabyItemList.Male_Names.length - 1)
		return BabyItemList.Male_Names[rnd]
	elseif sex==1 && BabyItemList.Female_Names.length > 0
		; Female Name
		rnd=Utility.RandomInt(0,BabyItemList.Female_Names.length - 1)
		return BabyItemList.Female_Names[rnd]
	endif
	return "Baby"
endfunction