2021-10-05 22:15:58 +00:00
Scriptname _00E_Phasmalist_ApparationAlias extends ReferenceAlias
2021-10-05 22:59:59 +00:00
{ OBSOLETE. Left for backward save compatibility. See _00E_Phasmalist_NewApparitionAlias. }
2021-10-05 22:15:58 +00:00
; on Abilities/_00E_A3_PhasmalistApparation
; script that controls the apparation stats calculation and initialization. Additionally, it is responsible for the control of the apparation communication while it is summoned
; we prefer to place new actors instead of using only one actor
; due to the problem of keeping track of all apparations,
; which might create memory leaks because of persistence;
; Additionally, temporary or accidental changes do not cumulate
; and lead to problems
; balancing data
float Property apparationManaRate = 1 AutoReadOnly Hidden
float Property playerStatsMultiplier = 0.20 AutoReadOnly Hidden
float Property playerConjSkillMultiplier = 0.10 AutoReadOnly Hidden
float Property playerEnchSkillMultiplier = 0.15 AutoReadOnly Hidden
float Property fArcaneFeverLevel01 = 7.00 AutoReadOnly Hidden
float Property fArcaneFeverLevel02 = 6.00 AutoReadOnly Hidden
float Property fArcaneFeverLevel03 = 5.00 AutoReadOnly Hidden
int Property fArcaneFeverModWarrior = -1 AutoReadOnly Hidden
int Property fArcaneFeverModRanger = 0 AutoReadOnly Hidden
int Property fArcaneFeverModHybrid = 0 AutoReadOnly Hidden
int Property fArcaneFeverModMage = 1 AutoReadOnly Hidden
int Property ghostlyMageBoostDestructionPowerMod1 = 7 AutoReadOnly Hidden
int Property ghostlyMageBoostDestructionPowerMod2 = 15 AutoReadOnly Hidden
int Property ghostlyMageBoostDestructionPowerMod3 = 25 AutoReadOnly Hidden
int Property ghostlyMageBoostMagicka1 = 15 AutoReadOnly Hidden
int Property ghostlyMageBoostMagicka2 = 40 AutoReadOnly Hidden
int Property ghostlyMageBoostMagicka3 = 75 AutoReadOnly Hidden
int Property ghostlyRangerBoostArchery1 = 7 AutoReadOnly Hidden
int Property ghostlyRangerBoostArchery2 = 17 AutoReadOnly Hidden
int Property ghostlyRangerBoostArchery3 = 30 AutoReadOnly Hidden
int Property ghostlyRangerBoostCritChance1 = 7 AutoReadOnly Hidden
int Property ghostlyRangerBoostCritChance2 = 15 AutoReadOnly Hidden
int Property ghostlyRangerBoostCritChance3 = 25 AutoReadOnly Hidden
int Property ghostlyWarriorBoostMelee1 = 7 AutoReadOnly Hidden
int Property ghostlyWarriorBoostMelee2 = 17 AutoReadOnly Hidden
int Property ghostlyWarriorBoostMelee3 = 30 AutoReadOnly Hidden
int Property ghostlyWarriorBoostArmorSkill1 = 7 AutoReadOnly Hidden
int Property ghostlyWarriorBoostArmorSkill2 = 17 AutoReadOnly Hidden
int Property ghostlyWarriorBoostArmorSkill3 = 30 AutoReadOnly Hidden
int Property iCallApparitionKeyCode = 34 Auto Hidden
Explosion Property enterWorldExplosion auto
Perk Property _00E_Class_Phasmalist_P04_Talent_SummonApparation auto
Perk Property _00E_Class_Phasmalist_P04_Talent_SummonApparation2 auto
Perk Property _00E_Class_Phasmalist_P04_Talent_SummonApparation3 auto
Static Property XMarker Auto
Perk Property _00E_Class_Phasmalist_P08a auto
Perk[] Property _00E_Class_Phasmalist_P05a_ABC auto ; ghostly mage
{ghostly mage perks, this array should have 3 elements for all 3 perks}
Perk[] Property _00E_Class_Phasmalist_P05b_ABC auto ; ghostly ranger
{ghostly ranger perks, this array should have 3 elements for all 3 perks}
Perk[] Property _00E_Class_Phasmalist_P05c_ABC auto ; ghostly warrior
{ghostly warrior perks, this array should have 3 elements for all 3 perks}
Location Property _00E_Dreamworld_Location auto
Keyword Property _00E_Phasmalist_NoSummonLocation auto
Message Property _00E_Phasmalist_NoSummoningMessage auto
Keyword Property _00E_Phasmalist_NoSummonLocationTown auto
Message Property _00E_Phasmalist_CurrentlyEquipped auto
Message Property _00E_Phasmalist_NoSummoningMessageTown auto
Sound Property MAGAlterationInvisibilityIn Auto
Sound Property MAGAlterationInvisibilityOut Auto
Perk Property _00E_Class_Phasmalist_P08b auto ; apparations can exist in towns
EffectShader Property _00E_Phasmalist_ApparitionShaderFXS Auto
ImageSpaceModifier Property _00E_ArkanistenfieberIMOD Auto
ImageSpaceModifier Property _00E_Phasmalist_ApparitionEnterWorldIMOD Auto
Sound Property _00E_FS_IncreaseArcaneFeverM Auto
;Sound Property _00E_FS_Phasmalist_EnterWorld_Male Auto
;Sound Property _00E_FS_Phasmalist_EnterWorld_Female Auto
_00E_GUI_ActorHealthBar Property _ActorHealthBarShower Auto
_00E_GUI_ActorHealthBar Property ActorHealthBarShower
_00E_GUI_ActorHealthBar Function Get()
If (_ActorHealthBarShower == None)
_ActorHealthBarShower = Game.GetFormFromFile(0x01024b66, "Enderal - Forgotten Stories.esm") as _00E_GUI_ActorHealthBar
EndIf
return _ActorHealthBarShower
EndFunction
EndProperty
Message Property _00E_BlitzheilungArkanistenfieber_sFeverIncreased Auto
GlobalVariable Property _00E_Phasmalist_IsApparationSummoned Auto
Keyword Property _00E_FS_Magic_Summon auto ; the apparation should not be able to learn certain spells
Keyword Property _00E_FS_Magic_Mystical auto
int currentBoostMagicka ; this is set in adjustBoost() to have the attribute set correctly in the stats calculation
_00E_Phasmalist_TrinketSC equippedTrinket
Actor Property PlayerREF Auto
Formlist Property _00E_AllAmmos Auto
; for a description, look to the function failsaveRefillOnLoad() of this script
Actor failsave_content
; functions that are called from the trinkets to keep track of the currently equipped trinket --------------------------------------------------------------------------------------------
function onTrinketEquipped(_00E_Phasmalist_TrinketSC trinket)
equippedTrinket = trinket
Endfunction
function onTrinketUnequipped(_00E_Phasmalist_TrinketSC trinket)
unsummonIfExists()
If trinket == equippedTrinket
equippedTrinket = None
EndIf
Endfunction
_00E_Phasmalist_TrinketSC function getEquippedTrinket()
return equippedTrinket
Endfunction
; summon and unsummon ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function unsummon(bool silent = false)
{Unsummons the phasmalist apparation content of this alias; should be used instead of delete()}
Actor SelfREF = self.GetActorReference()
If (!silent)
SelfREF.placeAtMe(enterWorldExplosion)
addArcaneFever()
EndIf
; empty function?
;(SelfREF.getActorBase() as _00E_Phasmalist_ApparationSC).onUnsummon(SelfREF)
SelfREF.removeAllItems((SelfREF.GetActorBase() as _00E_Phasmalist_ApparationSC).inventoryContainer, false, true)
2021-10-05 22:59:59 +00:00
SelfREF.disable()
2021-10-05 22:15:58 +00:00
_00E_Phasmalist_IsApparationSummoned.setValue(0)
_RemoveApparationHealthBar()
SelfREF.delete()
self.clear()
failsave_content = None
SendModEvent("Phasmalist_ApparationUnSummon")
Endfunction
function unsummonIfExists()
If getRef()
unsummon()
EndIf
Endfunction
; utility functions ----------------------------------------------------------------------------------------------------------------------------------------------------------
Function _RemoveApparationHealthBar()
2021-10-05 22:22:24 +00:00
ActorHealthBarShower.RemoveActors(self.getActorReference())
2021-10-05 22:15:58 +00:00
EndFunction
Function _AddApparationHealthBar()
2021-10-05 22:22:24 +00:00
ActorHealthBarShower.AddActors(self.getActorReference())
2021-10-05 22:15:58 +00:00
EndFunction
; local helper functions ---------------------------------------------------------------------------------------------------------------------------------------------------------------
function addArcaneFever()
float healthLostPercentage = 0
If self.getActorReference().isDead()
healthLostPercentage = 1
Else
healthLostPercentage = 1 - self.getActorReference().GetActorValuePercentage("health")
EndIf
int TalentLevel = _00E_TalentLibrary.GetPlayerTalentLevel(_00E_Class_Phasmalist_P04_Talent_SummonApparation, _00E_Class_Phasmalist_P04_Talent_SummonApparation2, _00E_Class_Phasmalist_P04_Talent_SummonApparation3)
float maxArcaneFeverAdd = 0
If (TalentLevel == 1)
maxArcaneFeverAdd = fArcaneFeverLevel01
ElseIf (TalentLevel == 2)
maxArcaneFeverAdd = fArcaneFeverLevel02
Else
maxArcaneFeverAdd = fArcaneFeverLevel03
EndIf
If getEquippedTrinket().type == 0
maxArcaneFeverAdd = maxArcaneFeverAdd + fArcaneFeverModWarrior
ElseIf getEquippedTrinket().type == 1
maxArcaneFeverAdd = maxArcaneFeverAdd + fArcaneFeverModRanger
ElseIf getEquippedTrinket().type == 2
maxArcaneFeverAdd = maxArcaneFeverAdd + fArcaneFeverModMage
Else
maxArcaneFeverAdd = maxArcaneFeverAdd + fArcaneFeverModHybrid
EndIf
float arcaneFeverAdd = (maxArcaneFeverAdd * healthLostPercentage) as float
If arcaneFeverAdd > 0
PlayerREF.ModAV("LastFlattered", -arcaneFeverAdd)
_00E_ArkanistenfieberIMOD.ApplyCrossFade()
_00E_FS_IncreaseArcaneFeverM.Play(PlayerREF)
_00E_BlitzheilungArkanistenfieber_sFeverIncreased.Show(arcaneFeverAdd, -1*PlayerREF.GetAV("LastFlattered"))
EndIf
Endfunction
function adjustBoosts()
adjustBoostPerk(_00E_Class_Phasmalist_P05a_ABC, "mage")
adjustBoostPerk(_00E_Class_Phasmalist_P05b_ABC, "ranger")
adjustBoostPerk(_00E_Class_Phasmalist_P05c_ABC, "warrior")
Endfunction
function addClassBoost(int level, string boostClass)
Actor referenceActor = self.getActorReference()
If boostClass == "mage"
int boostDestructionPowerMod = 0
If level == 2
boostDestructionPowerMod = ghostlyMageBoostDestructionPowerMod2
currentBoostMagicka = ghostlyMageBoostMagicka2; since magicka is boosted later again, we have to save this boost and apply it later to prevent overwriting old boosts
ElseIf level == 3
boostDestructionPowerMod = ghostlyMageBoostDestructionPowerMod3
currentBoostMagicka = ghostlyMageBoostMagicka3
Else
boostDestructionPowerMod = ghostlyMageBoostDestructionPowerMod1
currentBoostMagicka = ghostlyMageBoostMagicka1
EndIf
;referenceActor.ForceAV("DestructionPowerMod", referenceActor.GetAV("DestructionPowerMod") + boostDestructionPowerMod)
referenceActor.ModAV("DestructionPowerMod", boostDestructionPowerMod)
ElseIf boostClass == "ranger"
int boostArchery = 0
int boostCritChance = 0
If level == 2
boostArchery = ghostlyRangerBoostArchery2
boostCritChance = ghostlyRangerBoostCritChance2
ElseIf level == 3
boostArchery = ghostlyRangerBoostArchery3
boostCritChance = ghostlyRangerBoostCritChance3
Else
boostArchery = ghostlyRangerBoostArchery1
boostCritChance = ghostlyRangerBoostCritChance1
EndIf
;referenceActor.ForceAV("Marksman", referenceActor.GetAV("Marksman") + boostArchery)
referenceActor.ModAV("Marksman", boostArchery)
;referenceActor.ForceAV("CritChance", referenceActor.GetAV("CritChance") + boostCritChance)
referenceActor.ModAV("CritChance", boostCritChance)
ElseIf boostClass == "warrior"
int boostMelee = 0
int boostArmorSkill = 0
If level == 2
boostMelee = ghostlyWarriorBoostMelee2
boostArmorSkill = ghostlyWarriorBoostArmorSkill2
ElseIf level == 3
boostMelee = ghostlyWarriorBoostMelee3
boostArmorSkill = ghostlyWarriorBoostArmorSkill3
Else
boostMelee = ghostlyWarriorBoostMelee1
boostArmorSkill = ghostlyWarriorBoostArmorSkill1
EndIf
;referenceActor.ForceAV("HeavyArmor", referenceActor.GetAV("HeavyArmor") + boostArmorSkill)
referenceActor.ModAV("HeavyArmor", boostArmorSkill)
;referenceActor.ForceAV("LightArmor", referenceActor.GetAV("LightArmor") + boostArmorSkill)
referenceActor.ModAV("LightArmor", boostArmorSkill)
;referenceActor.ForceAV("MeleeDamage", referenceActor.GetAV("MeleeDamage") + boostMelee)
referenceActor.ModAV("MeleeDamage", boostMelee)
EndIf
Endfunction
function adjustBoostPerk(Perk[] perks, string boostClass)
int i = perks.length
While i > 0
i = i - 1
If PlayerREF.HasPerk(perks[i])
addClassBoost(i + 1, boostClass)
return
EndIf
EndWhile
Endfunction
function init()
initBehaviour()
initNotPersistentStats()
Actor referenceActor = self.getActorReference()
;Actor player = Game.getPlayer()
float attributeRaisePercentage = playerConjSkillMultiplier * PlayerREF.getActorValue("Conjuration") + playerEnchSkillMultiplier * PlayerREF.getActorValue("Enchanting")
attributeRaisePercentage = attributeRaisePercentage / 100 + 1
adjustBoosts()
If (PlayerREF.hasPerk(_00E_Class_Phasmalist_P08a))
float maxAttributeValue = PlayerREF.getBaseActorValue("Health")
If PlayerREF.getBaseActorValue("Magicka") > maxAttributeValue
maxAttributeValue = PlayerREF.getBaseActorValue("Magicka")
EndIf
If PlayerREF.getBaseActorValue("Stamina") > maxAttributeValue
maxAttributeValue = PlayerREF.getBaseActorValue("Stamina")
EndIf
referenceActor.ForceAV("Health", ((referenceActor.getBaseActorValue("Health") + maxAttributeValue * playerStatsMultiplier) * attributeRaisePercentage) as int)
referenceActor.ForceAV("Magicka", ((referenceActor.getBaseActorValue("Magicka") + maxAttributeValue * playerStatsMultiplier) * attributeRaisePercentage) as int + currentBoostMagicka)
referenceActor.ForceAV("Stamina", ((referenceActor.getBaseActorValue("Stamina") + maxAttributeValue * playerStatsMultiplier) * attributeRaisePercentage) as int)
Else
referenceActor.ForceAV("Health", ((referenceActor.getBaseActorValue("Health") + PlayerREF.getBaseActorValue("Health") * playerStatsMultiplier) * attributeRaisePercentage) as int)
referenceActor.ForceAV("Magicka", ((referenceActor.getBaseActorValue("Magicka") + PlayerREF.getBaseActorValue("Magicka") * playerStatsMultiplier) * attributeRaisePercentage) as int + currentBoostMagicka)
referenceActor.ForceAV("Stamina", ((referenceActor.getBaseActorValue("Stamina") + PlayerREF.getBaseActorValue("Stamina") * playerStatsMultiplier) * attributeRaisePercentage) as int)
EndIf
Endfunction
function initBehaviour()
Actor akSelf = self.getActorReference()
If akSelf.GetRelationshipRank(PlayerREF) < 3 && akSelf.GetRelationshipRank(PlayerREF) >= 0
akSelf.SetRelationshipRank(PlayerREF, 3)
EndIf
akSelf.SetPlayerTeammate()
akSelf.SetActorValue("Confidence", 4) ; the apparation should never flee
akSelf.SetActorValue("Aggression", 0) ; the apparation should not initiate combat (-> stealth playstyle)
akSelf.SetActorValue("Sneak", 100)
akSelf.SetActorValue("Invisibility", 1) ; make the apparation undetectable when sneaking (-> stealth playstyle)
akSelf.IgnoreFriendlyHits() ; make the apparation ignore friendly fire from the PC
Endfunction
function initNotPersistentStats()
Actor akSelf = self.getActorReference()
If akSelf
akSelf.getActorBase().setCombatStyle(getEquippedTrinket().getUsedCombatStyle())
akSelf.setAV("HealRate", 50)
akSelf.setAV("MagickaRate", apparationManaRate)
;failsafe since setav doesn't work sometimes
akSelf.forceAV("HealRate", 50)
akSelf.forceAV("MagickaRate", apparationManaRate)
_AddApparationHealthBar()
EndIf
Endfunction
; events -----------------------------------------------------------------------------------------------------------------------------------------------------------
function addSpells()
int index = self.getActorReference().getNumItems() - 1
While index >= 0
Form item = self.getActorReference().getNthForm(index)
If item as book && !item.hasKeyword(_00E_FS_Magic_Summon) && !item.hasKeyword(_00E_FS_Magic_Mystical)
If (item as book).getSpell()
self.getActorReference().addSpell((item as book).getSpell())
EndIf
EndIf
index = index - 1
EndWhile
Endfunction