Scriptname RaceMenuPluginBeast extends RaceMenuBase

bool Property BEAST_ENABLED = true AutoReadOnly ; Set this to false to rebuild if you don't want beast features

string Property NINODE_TAIL01 = "TailBone01" AutoReadOnly
string Property NINODE_TAIL02 = "TailBone02" AutoReadOnly
string Property NINODE_TAIL03 = "TailBone03" AutoReadOnly
string Property NINODE_TAIL04 = "TailBone04" AutoReadOnly
string Property NINODE_TAIL05 = "TailBone05" AutoReadOnly

;XPMSE Specific
string Property NINODE_TAIL01_CME = "CME TailBone01" AutoReadOnly
string Property NINODE_TAIL02_CME = "CME TailBone02" AutoReadOnly
string Property NINODE_TAIL03_CME = "CME TailBone03" AutoReadOnly
string Property NINODE_TAIL04_CME = "CME TailBone05" AutoReadOnly
string Property NINODE_TAIL_PELVIS = "CME Tail Pelvis [Pelv]" AutoReadOnly
string Property NINODE_TAIL_SPINE = "CME Tail Spine [Spn0]" AutoReadOnly
string Property NINODE_TAIL_SPINE1 = "CME Tail Spine1 [Spn1]" AutoReadOnly
string Property NINODE_TAIL_LEFT_THIGH = "CME Tail L Thigh [LThg]" AutoReadOnly
string Property NINODE_TAIL_RIGHT_THIGH = "CME Tail R Thigh [RThg]" AutoReadOnly

;Callbacks Table
string Property CALLBACK_TAIL_01_SCALE = "XPMSEChangeTail01Size" AutoReadOnly
string Property CALLBACK_TAIL_02_SCALE = "XPMSEChangeTail02Size" AutoReadOnly
string Property CALLBACK_TAIL_03_SCALE = "XPMSEChangeTail03Size" AutoReadOnly
string Property CALLBACK_TAIL_04_SCALE = "XPMSEChangeTail04Size" AutoReadOnly
string Property CALLBACK_TAIL_05_SCALE = "XPMSEChangeTail05Size" AutoReadOnly
string Property CALLBACK_TAIL_POSX = "XPMSEChangeTailPosX" AutoReadOnly
string Property CALLBACK_TAIL_POSY = "XPMSEChangeTailPosY" AutoReadOnly
string Property CALLBACK_TAIL_POSZ = "XPMSEChangeTailPosZ" AutoReadOnly

; If you are making your own scaling mod, use your own key name
string Property MOD_OVERRIDE_KEY = "RMBPlugin" AutoReadOnly

;Arrays
float[] _tail_position

string Property CATEGORY_BEASTS = "rsm_beast" AutoReadOnly

; NiOverride version data
int Property NIOVERRIDE_VERSION = 3 AutoReadOnly
int Property NIOVERRIDE_SCRIPT_VERSION = 2 AutoReadOnly

bool _versionValid = false

Event OnCategoryRequest()
	AddCategory(CATEGORY_BEASTS, "$CATEGORY BEAST")
EndEvent

Event OnStartup()
	parent.OnStartup()

	int nioverrideVersion = SKSE.GetPluginVersion("NiOverride")
	int nioverrideScriptVersion = NiOverride.GetScriptVersion()

	; Check NiOverride version, disable most features if this fails
	if nioverrideVersion >= NIOVERRIDE_VERSION && nioverrideScriptVersion >= NIOVERRIDE_SCRIPT_VERSION
		_versionValid = true
	Else
		_versionValid = false
	Endif
EndEvent

; Add Custom sliders here
Event OnSliderRequest(Actor target, ActorBase targetBase, Race actorRace, bool isFemale)
	If BEAST_ENABLED
		If NetImmerse.HasNode(target, NINODE_TAIL01, false) && NetImmerse.HasNode(target, NINODE_TAIL01_CME, false)
			AddSliderEx("$Tail01", CATEGORY_BEASTS, CALLBACK_TAIL_01_SCALE, 0.60, 1.40, 0.01, GetNodeScale(target, isFemale, NINODE_TAIL01))
		Endif
		If NetImmerse.HasNode(target, NINODE_TAIL02, false) && NetImmerse.HasNode(target, NINODE_TAIL02_CME, false)
			AddSliderEx("$Tail02", CATEGORY_BEASTS, CALLBACK_TAIL_02_SCALE, 0.60, 1.40, 0.01, GetNodeScale(target, isFemale, NINODE_TAIL02))
		Endif
		If NetImmerse.HasNode(target, NINODE_TAIL03, false) && NetImmerse.HasNode(target, NINODE_TAIL03_CME, false)
			AddSliderEx("$Tail03", CATEGORY_BEASTS, CALLBACK_TAIL_03_SCALE, 0.60, 1.40, 0.01, GetNodeScale(target, isFemale, NINODE_TAIL03))
		Endif
		If NetImmerse.HasNode(target, NINODE_TAIL04, false) && NetImmerse.HasNode(target, NINODE_TAIL04_CME, false)
			AddSliderEx("$Tail04", CATEGORY_BEASTS, CALLBACK_TAIL_04_SCALE, 0.60, 1.40, 0.01, GetNodeScale(target, isFemale, NINODE_TAIL04))
		Endif
		If NetImmerse.HasNode(target, NINODE_TAIL05, false)
			AddSliderEx("$Tail05", CATEGORY_BEASTS, CALLBACK_TAIL_05_SCALE, 0.60, 1.40, 0.01, GetNodeScale(target, isFemale, NINODE_TAIL05))
		Endif
		If NetImmerse.HasNode(target, NINODE_TAIL_PELVIS, false) && NetImmerse.HasNode(target, NINODE_TAIL_SPINE, false) && NetImmerse.HasNode(target, NINODE_TAIL_SPINE1, false) && NetImmerse.HasNode(target, NINODE_TAIL_LEFT_THIGH, false) && NetImmerse.HasNode(target, NINODE_TAIL_RIGHT_THIGH, false)
			_tail_position = GetNodePosition(target, isFemale, NINODE_TAIL_PELVIS)
			AddSliderEx("$Tail Pos X", CATEGORY_BEASTS, CALLBACK_TAIL_POSX, -10.00, 10.00, 0.01, _tail_position[0])
			AddSliderEx("$Tail Pos Y", CATEGORY_BEASTS, CALLBACK_TAIL_POSY, -10.00, 10.00, 0.01, _tail_position[1])
			AddSliderEx("$Tail Pos Z", CATEGORY_BEASTS, CALLBACK_TAIL_POSZ, -10.00, 10.00, 0.01, _tail_position[2])
		Endif
	Endif
EndEvent

Event OnSliderChanged(string callback, float value)
	bool isFemale = _targetActorBase.GetSex() as bool
	If _versionValid
		If callback == CALLBACK_TAIL_01_SCALE
			SetNodeScale(_targetActor, isFemale, NINODE_TAIL01, value)
			SetNodeScale(_targetActor, isFemale, NINODE_TAIL01_CME, value)
		ElseIf callback == CALLBACK_TAIL_02_SCALE
			SetNodeScale(_targetActor, isFemale, NINODE_TAIL02, value)
			SetNodeScale(_targetActor, isFemale, NINODE_TAIL02_CME, value)
		Elseif callback == CALLBACK_TAIL_03_SCALE
			SetNodeScale(_targetActor, isFemale, NINODE_TAIL03, value)
			SetNodeScale(_targetActor, isFemale, NINODE_TAIL03_CME, value)
		Elseif callback == CALLBACK_TAIL_04_SCALE
			SetNodeScale(_targetActor, isFemale, NINODE_TAIL04, value)
			SetNodeScale(_targetActor, isFemale, NINODE_TAIL04_CME, value)
		Elseif callback == CALLBACK_TAIL_05_SCALE
			SetNodeScale(_targetActor, isFemale, NINODE_TAIL05, value)
		Elseif callback == CALLBACK_TAIL_POSX || callback == CALLBACK_TAIL_POSY || callback == CALLBACK_TAIL_POSZ
			If callback == CALLBACK_TAIL_POSX
				_tail_position[0] = value
			ElseIf callback == CALLBACK_TAIL_POSY
				_tail_position[1] = value
			ElseIf callback == CALLBACK_TAIL_POSZ
				_tail_position[2] = value
			EndIf
			SetNodePosition(_targetActor, isFemale, NINODE_TAIL_PELVIS, _tail_position)
			SetNodePosition(_targetActor, isFemale, NINODE_TAIL_SPINE, _tail_position)
			SetNodePosition(_targetActor, isFemale, NINODE_TAIL_SPINE1, _tail_position)
			SetNodePosition(_targetActor, isFemale, NINODE_TAIL_LEFT_THIGH, _tail_position)
			SetNodePosition(_targetActor, isFemale, NINODE_TAIL_RIGHT_THIGH, _tail_position)
		Endif
	Endif		
EndEvent

Function SetNodeScale(Actor akActor, bool isFemale, string nodeName, float value)
	If value != 1.0
		NiOverride.AddNodeTransformScale(akActor, false, isFemale, nodeName, MOD_OVERRIDE_KEY, value)
		NiOverride.AddNodeTransformScale(akActor, true, isFemale, nodeName, MOD_OVERRIDE_KEY, value)
	Else
		NiOverride.RemoveNodeTransformScale(akActor, false, isFemale, nodeName, MOD_OVERRIDE_KEY)
		NiOverride.RemoveNodeTransformScale(akActor, true, isFemale, nodeName, MOD_OVERRIDE_KEY)
	Endif
	NiOverride.UpdateNodeTransform(akActor, false, isFemale, nodeName)
	NiOverride.UpdateNodeTransform(akActor, true, isFemale, nodeName)
EndFunction

Function SetNodePosition(Actor akActor, bool isFemale, string nodeName, float[] values)
	If values[0] != 0.0 || values[1] != 0.0 || values[2] != 0.0
		NiOverride.AddNodeTransformPosition(akActor, false, isFemale, nodeName, MOD_OVERRIDE_KEY, values)
		NiOverride.AddNodeTransformPosition(akActor, true, isFemale, nodeName, MOD_OVERRIDE_KEY, values)
	Else
		NiOverride.RemoveNodeTransformPosition(akActor, false, isFemale, nodeName, MOD_OVERRIDE_KEY)
		NiOverride.RemoveNodeTransformPosition(akActor, true, isFemale, nodeName, MOD_OVERRIDE_KEY)
	Endif
	NiOverride.UpdateNodeTransform(akActor, false, isFemale, nodeName)
	NiOverride.UpdateNodeTransform(akActor, true, isFemale, nodeName)
EndFunction

float Function GetNodeScale(Actor akActor, bool isFemale, string nodeName)
	return NiOverride.GetNodeTransformScale(akActor, false, isFemale, nodeName, MOD_OVERRIDE_KEY)
EndFunction

float[] Function GetNodePosition(Actor akActor, bool isFemale, string nodeName)
	return NiOverride.GetNodeTransformPosition(akActor, false, isFemale, nodeName, MOD_OVERRIDE_KEY)
EndFunction