359 lines
14 KiB
Plaintext
359 lines
14 KiB
Plaintext
Scriptname _00E_Phasmalist_ApparationAlias extends ReferenceAlias
|
|
{ OBSOLETE. Left for backward save compatibility. See _00E_Phasmalist_NewApparitionAlias. }
|
|
|
|
; 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
|
|
|
|
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)
|
|
SelfREF.disable()
|
|
_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()
|
|
HealthBarManager.Hide(self.getActorReference())
|
|
EndFunction
|
|
|
|
Function _AddApparationHealthBar()
|
|
HealthBarManager.Show(self.getActorReference())
|
|
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
|