484 lines
16 KiB
Plaintext
484 lines
16 KiB
Plaintext
Scriptname _00E_Theriantrophist_PlayerAsWerewolf extends ReferenceAlias
|
|
; Main script of the theriantrophist system; this alias contains the player during the transformation
|
|
; and while he is in werewolf form.
|
|
; this script is responsible for stats calculation, controlling the player as werewolf and propagation
|
|
; events/control signals to chymikum activemagiceffect scripts etc.
|
|
|
|
_00E_Theriantrophist_TransformStorage Property EquipementStorage Auto
|
|
_00E_Theriantrophist_WolfAttributes Property WolfAttributes Auto
|
|
_FS_TheriantrophistControlQuest Property ControlQuest Auto
|
|
|
|
Spell Property _00E_Theriantrophist_WolfFormSP Auto
|
|
{the spell that visually transforms the player}
|
|
GlobalVariable Property _00E_Theriantrophist_IsTransformed Auto
|
|
|
|
Perk Property _00E_Class_Theriantrophist_P06b_BeastInstinct Auto
|
|
{the perk that gives the player life detection when in wolf form}
|
|
Spell Property _00E_Theriantrophist_DetectLifeBaseSP Auto
|
|
{the life detection spell given if the player has the beast instinct perk}
|
|
Perk Property _00E_Class_Theriantrophist_P09b_Disguise Auto
|
|
Perk Property _00E_Class_Theriantrophist_P09c_AetherBlood Auto
|
|
|
|
Perk Property _00E_Class_Theriantrophist_P06c_Nightwolf_01 Auto
|
|
Perk Property _00E_Class_Theriantrophist_P06c_Nightwolf_02 Auto
|
|
Perk Property _00E_Class_Theriantrophist_P06c_Nightwolf_03 Auto
|
|
|
|
Idle Property WerewolfSneakStart Auto
|
|
Idle Property WerewolfSneakStop Auto
|
|
Weapon Property _00E_Theriantrophist_Claws Auto
|
|
|
|
Keyword Property _00E_Theriantrophist_NoTransformLocation Auto
|
|
Keyword Property _00E_Theriantrophist_NoTransformLocationTown Auto
|
|
Message Property _00E_Theriantrophist_ForceTransformBackMessage Auto
|
|
Message Property _00E_Theriantrophist_ForceTransformBackMessageTown Auto
|
|
GlobalVariable Property _00E_FS_Theriantrophist_AllowTemporaryTransform Auto
|
|
|
|
Spell Property _00E_FS_Affinity_AbBrute Auto
|
|
Spell Property _00E_FS_Affinity_AbDrifter Auto
|
|
Spell Property _00E_FS_Affinity_AbDruid Auto
|
|
Spell Property _00E_FS_Affinity_AbNightwolf Auto
|
|
Spell Property _00E_FS_Affinity_AbRavager Auto
|
|
Spell Property _00E_FS_Affinity_AbScourge Auto
|
|
Spell Property _00E_FS_Affinity_AbSoulcaller Auto
|
|
|
|
Spell Property _00E_FS_Affinity_ScourgeOfTheWilds_TitanSP Auto
|
|
|
|
Armor Property _00E_FS_Theriantrophist_Skin_Brute Auto
|
|
Armor Property _00E_FS_Theriantrophist_Skin_Drifter Auto
|
|
Armor Property _00E_FS_Theriantrophist_Skin_Druid Auto
|
|
Armor Property _00E_FS_Theriantrophist_Skin_Nightwolf Auto
|
|
Armor Property _00E_FS_Theriantrophist_Skin_Ravager Auto
|
|
Armor Property _00E_FS_Theriantrophist_Skin_Soulcaller Auto
|
|
Armor Property _00E_FS_Theriantrophist_Skin_Scourge Auto
|
|
|
|
Shout Property _00E_A1_Theriantrophist_TransformBack Auto
|
|
WordOfPower Property _00E_FS_Theriantrophist_TransformBack_Word01 Auto
|
|
|
|
Quest Property FS_NQ11 Auto
|
|
|
|
float fPlayerScale = 1.0
|
|
|
|
; Achievement
|
|
GlobalVariable Property _00E_AchievementsEnabled Auto
|
|
bool bTransformAchievementUnlocked = false
|
|
|
|
; Balancing data
|
|
Float Property AlchemyPercentage = 0.03 Autoreadonly Hidden
|
|
{all werewolf attributes are boosted by this percentage for each alchemy skill point the player has}
|
|
Float Property StaminaPercentage = 0.005 Autoreadonly Hidden
|
|
{all werewolf attributes are boosted by this percentage for each attribute point over 90 the player has; the atrribute is stamina per default, but may be switched to mana if the player has the special perk}
|
|
Float Property BaseDamageResist = 10 Autoreadonly Hidden
|
|
{without extra perks and stuff, the werewolf has this amount of damage resist, i.e. this percentage of every damage point is prevented}
|
|
Float Property BaseDamagePerSkillLevelInEquippedSpellsSchool = 0.33 Autoreadonly Hidden
|
|
{the base claw damage of the werewolf (damage before the boost factor is applied) uses the DPS of equipped weapons, or the player skill level in the magic school of an equipped spell.
|
|
This skill level is multiplied with BaseDamagePerSkillLevelInEquippedSpellsSchool and treated as a DPS value of a weapon after that}
|
|
|
|
Float Property BalancingDamageMalusPercent = 33 Autoreadonly Hidden
|
|
{the claw damage of the wolf is decreased by this percentage for balancing purposes}
|
|
Float Property BalancingHealthMalusPercent = 85 Autoreadonly Hidden
|
|
{the health of the wolf is decreased by this percentage for balancing purposes}
|
|
Float Property BalancingStaminaMalusPercent = 75 Autoreadonly Hidden
|
|
{the stamina of the wolf is decreased by this percentage for balancing purposes}
|
|
Float Property BoostFactorInfluenceOnArmor = 11 Autoreadonly Hidden
|
|
{the boost factor multiplied with this value is the wolf armor bonus for balancing purposes}
|
|
|
|
|
|
_00E_Theriantrophist_Chymikum[] RegisteredChymikums
|
|
bool Sneaking = false
|
|
|
|
Function Transform(int duration)
|
|
|
|
bool bWasParalyzed
|
|
Actor player = self.getActorReference()
|
|
while player.GetAV("Paralysis") == 1
|
|
bWasParalyzed = true
|
|
Utility.Wait(1)
|
|
endwhile
|
|
|
|
If bWasParalyzed
|
|
Utility.Wait(6)
|
|
EndIf
|
|
|
|
fPlayerScale = player.GetScale()
|
|
EquipementStorage.saveEquippedItems()
|
|
float preTransformDmgResist = player.GetAV("damageResist")
|
|
_00E_Theriantrophist_WolfFormSP.setNthEffectDuration(0, duration)
|
|
_00E_Theriantrophist_WolfFormSP.Cast(player)
|
|
WolfAttributes.SetInWolfForm(true)
|
|
player.additem(_00E_Theriantrophist_Claws, abSilent = true)
|
|
player.equipItem(_00E_Theriantrophist_Claws, abSilent = true)
|
|
_Init(preTransformDmgResist)
|
|
gotoState("Transfomed")
|
|
_TeachTransformBackTalent()
|
|
|
|
If !bTransformAchievementUnlocked && _00E_AchievementsEnabled.GetValueInt() == 1
|
|
bTransformAchievementUnlocked = true
|
|
Game.UnlockAchievement("END_WEREWOLF_01")
|
|
EndIf
|
|
|
|
If FS_NQ11.GetStage() == 15 || FS_NQ11.GetStage() == 17
|
|
FS_NQ11.SetObjectiveCompleted(20)
|
|
EndIf
|
|
|
|
EndFunction
|
|
|
|
Function TransformBack()
|
|
|
|
If _00E_FS_Affinity_ScourgeOfTheWilds_TitanSP == None
|
|
_00E_FS_Affinity_ScourgeOfTheWilds_TitanSP = Game.GetFormFromFile(0x0102F19E, "Enderal - Forgotten Stories.esm") as Spell
|
|
EndIf
|
|
|
|
MagicEffect _00E_FS_Affinity_ScourgeOfTheWilds_TitanME = Game.GetFormFromFile(0x0102F19F, "Enderal - Forgotten Stories.esm") as MagicEffect
|
|
|
|
Actor PlayerREF = self.getActorReference()
|
|
|
|
If PlayerREF.dispelSpell(_00E_FS_Affinity_ScourgeOfTheWilds_TitanSP)
|
|
while PlayerREF.getscale() > fPlayerScale
|
|
Utility.Wait(0.05)
|
|
endwhile
|
|
EndIf
|
|
PlayerREF.dispelSpell(_00E_Theriantrophist_WolfFormSP)
|
|
|
|
Endfunction
|
|
|
|
Function OnWolfFormSpellEnd()
|
|
gotoState("")
|
|
Actor wolf = self.getActorReference()
|
|
self.clear()
|
|
wolf.removeSpell(_00E_Theriantrophist_DetectLifeBaseSP)
|
|
wolf.removeItem(_00E_Theriantrophist_Claws, 100, abSilent = true)
|
|
WolfAttributes.SetInWolfForm(false)
|
|
EquipementStorage.equipeItems()
|
|
_DispelAllChymikums()
|
|
EndFunction
|
|
|
|
Function TransformBackIfTransformed()
|
|
if (IsTransformed())
|
|
TransformBack()
|
|
EndIf
|
|
Endfunction
|
|
|
|
Bool Function IsTransformed()
|
|
return self.getActorReference() != None
|
|
Endfunction
|
|
|
|
Function _TeachTransformBackTalent()
|
|
if !Game.getPlayer().HasSpell(_00E_A1_Theriantrophist_TransformBack)
|
|
Game.getPlayer().addShout(_00E_A1_Theriantrophist_TransformBack)
|
|
Game.unlockWord(_00E_FS_Theriantrophist_TransformBack_Word01)
|
|
Endif
|
|
Endfunction
|
|
|
|
Function _UpdateChymikumTransformed()
|
|
Int i = 0
|
|
while (i < RegisteredChymikums.length)
|
|
if (RegisteredChymikums[i] != None)
|
|
RegisteredChymikums[i].OnWolfFormStart()
|
|
EndIf
|
|
i += 1
|
|
EndWhile
|
|
Endfunction
|
|
|
|
Function _UpdateChymikumTransformedBack()
|
|
Int i = 0
|
|
while (i < RegisteredChymikums.length)
|
|
if (RegisteredChymikums[i] != None)
|
|
RegisteredChymikums[i].OnWolfFormFinish()
|
|
EndIf
|
|
i += 1
|
|
EndWhile
|
|
Endfunction
|
|
|
|
Function _DispelAllChymikums()
|
|
Int i = 0
|
|
while (i < RegisteredChymikums.length)
|
|
if (RegisteredChymikums[i] != None)
|
|
RegisteredChymikums[i].Dispel()
|
|
EndIf
|
|
i += 1
|
|
EndWhile
|
|
Endfunction
|
|
|
|
Function RegisterChymikum(_00E_Theriantrophist_Chymikum value)
|
|
if (RegisteredChymikums.length != 5)
|
|
RegisteredChymikums = new _00E_Theriantrophist_Chymikum[5]
|
|
EndIf
|
|
Int index = RegisteredChymikums.Find(None)
|
|
RegisteredChymikums[index] = value
|
|
Endfunction
|
|
|
|
Function UnRegisterChymikum(_00E_Theriantrophist_Chymikum value)
|
|
Int index = RegisteredChymikums.Find(value)
|
|
if index != -1
|
|
RegisteredChymikums[index] = None
|
|
EndIf
|
|
Endfunction
|
|
|
|
Int Function CalcRegisteredChymikumCount()
|
|
Int i = 0
|
|
Int count = 0
|
|
while (i < RegisteredChymikums.length)
|
|
if (RegisteredChymikums[i] != None)
|
|
count += 1
|
|
EndIf
|
|
i += 1
|
|
EndWhile
|
|
return count
|
|
EndFunction
|
|
|
|
_00E_Theriantrophist_Chymikum Function CalcNthRegisteredChymikum(Int index)
|
|
Int i = 0
|
|
While i < RegisteredChymikums.length
|
|
if RegisteredChymikums[i] != None
|
|
if index == 0
|
|
return RegisteredChymikums[i]
|
|
Endif
|
|
index = index - 1
|
|
EndIf
|
|
i += 1
|
|
Endwhile
|
|
return None
|
|
EndFunction
|
|
|
|
Function _Init(float preTransformDmgResist)
|
|
_InitStats(preTransformDmgResist)
|
|
Actor player = self.getActorReference()
|
|
if (player.hasPerk(_00E_Class_Theriantrophist_P06b_BeastInstinct))
|
|
player.addSpell(_00E_Theriantrophist_DetectLifeBaseSP, false)
|
|
Endif
|
|
Endfunction
|
|
|
|
Function _InitStats(float preTransformDmgResist)
|
|
Actor player = self.getActorReference()
|
|
Float boostAttribute = player.getAV("stamina") - 90
|
|
if player.hasPerk(_00E_Class_Theriantrophist_P09c_AetherBlood) && player.getAV("magicka") - 88 > boostAttribute
|
|
boostAttribute = player.getAV("magicka") - 88
|
|
EndIf
|
|
|
|
; damage, health and stamina in werewolf form are boosted by this factor
|
|
Float boostFactor = 1 + player.getAV("alchemy") * AlchemyPercentage + boostAttribute * StaminaPercentage
|
|
Float boostFactorLifeStamina = 1 + player.getAV("alchemy") * AlchemyPercentage
|
|
|
|
float fHealthMod = player.getBaseAV("health") * boostFactorLifeStamina * (1 - BalancingHealthMalusPercent / 100.0)
|
|
float fStaminaMod = player.getBaseAV("stamina") * boostFactorLifeStamina * (1 - BalancingStaminaMalusPercent / 100.0)
|
|
|
|
WolfAttributes.ModWolfHealth(fHealthMod)
|
|
WolfAttributes.ModWolfStamina(fStaminaMod)
|
|
|
|
float fClawDamage = boostFactor * _CalcWeaponSpellStrength(player) * (1 - BalancingDamageMalusPercent / 100.0)
|
|
float ClawDamageBonus = player.GetAV("LastBribedIntimidated")
|
|
WolfAttributes.ForceWolfUnarmedDmg(fClawDamage + ClawDamageBonus)
|
|
|
|
float fDamageResistBonus = BoostFactorInfluenceOnArmor * boostFactor
|
|
float fDamageResist = preTransformDmgResist + fDamageResistBonus
|
|
|
|
WolfAttributes.ForceWolfDamageResist(fDamageResist)
|
|
WolfAttributes.ForceWolfSpeedMult(100)
|
|
|
|
EndFunction
|
|
|
|
Float Function _CalcWeaponSpellStrength(Actor player)
|
|
|
|
Float result = EquipementStorage.getWeaponDamageSpeed()
|
|
|
|
if (EquipementStorage.isEquippedItemRightSpell())
|
|
result += _GuessPlayerSkillInSpellSchool(player, EquipementStorage.getEquippedSpellRight()) * BaseDamagePerSkillLevelInEquippedSpellsSchool
|
|
EndIf
|
|
|
|
if (EquipementStorage.isEquippedItemLeftSpell())
|
|
result += _GuessPlayerSkillInSpellSchool(player, EquipementStorage.getEquippedSpellLeft()) * BaseDamagePerSkillLevelInEquippedSpellsSchool
|
|
EndIf
|
|
|
|
return result
|
|
|
|
EndFunction
|
|
|
|
Float Function _GuessPlayerSkillInSpellSchool(Actor player, Spell s)
|
|
String guessedSchool = s.getNthEffectMagicEffect(0).getAssociatedSkill()
|
|
return player.getAV(guessedSchool)
|
|
EndFunction
|
|
|
|
Int Function _CalcNumberOfPerksPlayerHas(Perk[] perks)
|
|
Actor player = self.getActorReference()
|
|
Int i = perks.length
|
|
Int perkCount = 0
|
|
while (i > 0)
|
|
i = i - 1
|
|
if (player.hasPerk(perks[i]))
|
|
perkCount += 1
|
|
EndIf
|
|
Endwhile
|
|
return perkCount
|
|
Endfunction
|
|
|
|
Function UpdateChymikumsLoadGame()
|
|
Int i = 0
|
|
while (i < RegisteredChymikums.length)
|
|
if (RegisteredChymikums[i] != None)
|
|
RegisteredChymikums[i].OnPlayerLoadGame()
|
|
EndIf
|
|
i += 1
|
|
EndWhile
|
|
EndFunction
|
|
|
|
Function UpdateChymikumOnCombatHit(Actor target)
|
|
Int i = 0
|
|
while (i < RegisteredChymikums.length)
|
|
if (RegisteredChymikums[i] != None)
|
|
RegisteredChymikums[i].OnCombatHit(target)
|
|
EndIf
|
|
i += 1
|
|
EndWhile
|
|
Endfunction
|
|
|
|
bool function CanBeTransformed(Location loc)
|
|
if loc && loc.hasKeyword(_00E_Theriantrophist_NoTransformLocation) && _00E_FS_Theriantrophist_AllowTemporaryTransform.GetValueInt() != 1
|
|
return false
|
|
elseif loc && loc.hasKeyword(_00E_Theriantrophist_NoTransformLocationTown) && !Game.getPlayer().hasPerk(_00E_Class_Theriantrophist_P09b_Disguise) && _00E_FS_Theriantrophist_AllowTemporaryTransform.GetValueInt() != 1
|
|
return false
|
|
endif
|
|
return true
|
|
Endfunction
|
|
|
|
Function _ReapplySkins()
|
|
|
|
Actor player = self.getActorReference()
|
|
ActorBase playerbase = player.GetActorBase()
|
|
|
|
if player.HasSpell(_00E_FS_Affinity_AbBrute)
|
|
playerbase.SetSkin(_00E_FS_Theriantrophist_Skin_Brute)
|
|
elseif player.HasSpell(_00E_FS_Affinity_AbDrifter)
|
|
playerbase.SetSkin(_00E_FS_Theriantrophist_Skin_Drifter)
|
|
elseif player.HasSpell(_00E_FS_Affinity_AbDruid)
|
|
playerbase.SetSkin(_00E_FS_Theriantrophist_Skin_Druid)
|
|
elseif player.HasSpell(_00E_FS_Affinity_AbNightwolf)
|
|
playerbase.SetSkin(_00E_FS_Theriantrophist_Skin_Nightwolf)
|
|
elseif player.HasSpell(_00E_FS_Affinity_AbRavager)
|
|
playerbase.SetSkin(_00E_FS_Theriantrophist_Skin_Ravager)
|
|
elseif player.HasSpell(_00E_FS_Affinity_AbScourge)
|
|
playerbase.SetSkin(_00E_FS_Theriantrophist_Skin_Scourge)
|
|
elseif player.HasSpell(_00E_FS_Affinity_AbSoulcaller)
|
|
playerbase.SetSkin(_00E_FS_Theriantrophist_Skin_Soulcaller)
|
|
else
|
|
playerbase.SetSkin(playerbase.GetRace().GetSkin())
|
|
endif
|
|
player.QueueNiNodeUpdate()
|
|
EndFunction
|
|
|
|
Function _FixNotTransformedPlayerSkin()
|
|
Actor player = Game.GetPlayer()
|
|
player.getActorBase().SetSkin(player.GetRace().GetSkin())
|
|
player.QueueNiNodeUpdate()
|
|
EndFunction
|
|
|
|
Event OnLocationChange(Location akOldLoc, Location akNewLoc)
|
|
if !CanBeTransformed(akNewLoc)
|
|
if akNewLoc.hasKeyword(_00E_Theriantrophist_NoTransformLocationTown)
|
|
_00E_Theriantrophist_ForceTransformBackMessageTown.show()
|
|
else
|
|
_00E_Theriantrophist_ForceTransformBackMessage.show()
|
|
endif
|
|
RegisterForSingleUpdate(6)
|
|
Endif
|
|
Endevent
|
|
|
|
Event OnUpdate()
|
|
if !CanBeTransformed(self.GetRef().GetCurrentLocation())
|
|
TransformBackIfTransformed()
|
|
Endif
|
|
EndEvent
|
|
|
|
Function OnPlayerLoadGame()
|
|
WolfAttributes.renewNotPersistentStats()
|
|
UpdateChymikumsLoadGame()
|
|
If Game.GetPlayer().IsOnMount() == false
|
|
_FixNotTransformedPlayerSkin()
|
|
EndIf
|
|
Endfunction
|
|
|
|
State Transfomed
|
|
|
|
Event OnBeginState()
|
|
_00E_Theriantrophist_IsTransformed.setValue(1)
|
|
_UpdateChymikumTransformed()
|
|
RegisterForControl("Sneak")
|
|
SendModEvent("Theriantrophist_Transformed")
|
|
Sneaking = false
|
|
AddInventoryEventFilter(_00E_Theriantrophist_Claws)
|
|
Endevent
|
|
|
|
Event OnEndState()
|
|
if (Sneaking)
|
|
self.getActorReference().playIdle(WerewolfSneakStop)
|
|
WolfAttributes.SetTemporarilyWolfSpeedMultMod(0)
|
|
Sneaking = false
|
|
ControlQuest.GetAffinityControl().OnSneak(false)
|
|
Endif
|
|
_UpdateChymikumTransformedBack()
|
|
_00E_Theriantrophist_IsTransformed.setValue(0)
|
|
SendModEvent("Theriantrophist_TransformedBack")
|
|
UnRegisterForControl("Sneak")
|
|
Endevent
|
|
|
|
Function OnPlayerLoadGame()
|
|
WolfAttributes.renewNotPersistentStats()
|
|
UpdateChymikumsLoadGame()
|
|
RegisterForControl("Sneak")
|
|
_ReapplySkins()
|
|
Endfunction
|
|
|
|
Event OnControlDown(string control)
|
|
If Sneaking
|
|
self.getActorReference().playIdle(WerewolfSneakStop)
|
|
WolfAttributes.SetTemporarilyWolfSpeedMultMod(0)
|
|
Sneaking = false
|
|
ControlQuest.GetAffinityControl().OnSneak(false)
|
|
Else
|
|
self.getActorReference().playIdle(WerewolfSneakStart)
|
|
|
|
Actor akplayer = self.GetActorReference()
|
|
|
|
if akplayer.HasPerk(_00E_Class_Theriantrophist_P06c_Nightwolf_01)
|
|
WolfAttributes.SetTemporarilyWolfSpeedMultMod(-55)
|
|
elseif akplayer.HasPerk(_00E_Class_Theriantrophist_P06c_Nightwolf_02)
|
|
WolfAttributes.SetTemporarilyWolfSpeedMultMod(-50)
|
|
elseif akplayer.HasPerk(_00E_Class_Theriantrophist_P06c_Nightwolf_03)
|
|
WolfAttributes.SetTemporarilyWolfSpeedMultMod(-40)
|
|
else
|
|
WolfAttributes.SetTemporarilyWolfSpeedMultMod(-60)
|
|
endif
|
|
|
|
Sneaking = true
|
|
ControlQuest.GetAffinityControl().OnSneak(true)
|
|
EndIf
|
|
EndEvent
|
|
|
|
Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
|
|
if (akBaseObject != _00E_Theriantrophist_Claws) || akBaseObject.GetType() == 119
|
|
self.getActorReference().UnequipItem(akBaseObject)
|
|
self.getActorReference().equipItem(_00E_Theriantrophist_Claws, abSilent = true)
|
|
Endif
|
|
Endevent
|
|
|
|
Event OnObjectUnequipped(Form akBaseObject, ObjectReference akReference)
|
|
if (akBaseObject == _00E_Theriantrophist_Claws)
|
|
self.getActorReference().equipItem(_00E_Theriantrophist_Claws, abSilent = true)
|
|
Endif
|
|
Endevent
|
|
|
|
Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
|
|
if (akBaseItem != _00E_Theriantrophist_Claws)
|
|
return
|
|
Endif
|
|
If !akDestContainer
|
|
akItemReference.delete()
|
|
self.getActorReference().addItem(_00E_Theriantrophist_Claws, abSilent = true)
|
|
self.getActorReference().equipItem(_00E_Theriantrophist_Claws, abSilent = true)
|
|
Else
|
|
akDestContainer.removeItem(_00E_Theriantrophist_Claws)
|
|
self.getActorReference().addItem(_00E_Theriantrophist_Claws, abSilent = true)
|
|
self.getActorReference().equipItem(_00E_Theriantrophist_Claws, abSilent = true)
|
|
Endif
|
|
EndEvent
|
|
EndState
|