enderalse/source/scripts/_00e_theriantrophist_alchemycontrol.psc

492 lines
18 KiB
Plaintext

Scriptname _00E_Theriantrophist_AlchemyControl extends ReferenceAlias
import EnderalLib
;=====================================================================================
; PROPERTIES
;=====================================================================================
Keyword Property _00E_Theriantrophist_DarkBloodEffect Auto
Keyword Property _00E_Theriantrophist_Effect Auto
Keyword Property _00E_Theriantrophist_ChymikumLife Auto
{the perk that allows the player to drink theriantrophist potions}
Actor Property PlayerREF Auto
Perk Property _00E_Class_Theriantrophist_P01_WerewolfBlood Auto
Message Property _00E_Theriantrophist_ReallyWantToBrewPotion Auto
Message Property _00E_FS_Theriantrophist_PotionFortified Auto
MagicEffect Property _00E_Theriantrophist_NoEffect Auto
Perk Property _00E_Class_Theriantrophist_P03_GreyAlchemist_01 Auto
Perk Property _00E_Class_Theriantrophist_P03_GreyAlchemist_02 Auto
Perk Property _00E_Class_Theriantrophist_P03_GreyAlchemist_03 Auto
MagicEffect Property _00E_Theriantrophist_AlchChymikum_FireClaws Auto
MagicEffect Property _00E_Theriantrophist_AlchChymikum_Armor Auto
MagicEffect Property _00E_Theriantrophist_AlchChymikum_Damage Auto
MagicEffect Property _00E_Theriantrophist_AlchChymikum_FrostClaws Auto
MagicEffect Property _00E_Theriantrophist_AlchChymikum_Health Auto
MagicEffect Property _00E_Theriantrophist_AlchChymikum_ShockClaws Auto
MagicEffect Property _00E_Theriantrophist_AlchChymikum_Speed Auto
MagicEffect Property _00E_Theriantrophist_AlchChymikum_Stamina Auto
MagicEffect Property _00E_AlchReduceArcaneFever Auto
MagicEffect Property _00E_AlchRestoreMagicka Auto
MagicEffect Property _00E_AlchRestoreStamina Auto
MagicEffect Property AlchFortifyHealth Auto
MagicEffect Property AlchFortifyHealRate Auto
MagicEffect Property AlchFortifyMagicka Auto
MagicEffect Property AlchFortifyMagickaRate Auto
MagicEffect Property AlchFortifyStamina Auto
MagicEffect Property AlchFortifyStaminaRate Auto
MagicEffect Property AlchInvisibillity Auto
MagicEffect Property AlchWaterbreathing Auto
MagicEffect Property AlchResistFire Auto
MagicEffect Property AlchResistFrost Auto
MagicEffect Property AlchResistMagic Auto
MagicEffect Property AlchResistShock Auto
MagicEffect Property AlchFortifyAlchemy Auto
MagicEffect Property AlchFortifyAlteration Auto
MagicEffect Property AlchFortifyBarter Auto
MagicEffect Property AlchFortifyBlock Auto
MagicEffect Property AlchFortifyCarryWeight Auto
MagicEffect Property AlchFortifyConjuration Auto
MagicEffect Property AlchFortifyDestruction Auto
MagicEffect Property AlchFortifyEnchanting Auto
MagicEffect Property AlchFortifyHeavyArmor Auto
MagicEffect Property AlchFortifyIllusion Auto
MagicEffect Property AlchFortifyLightArmor Auto
MagicEffect Property AlchFortifyLockpicking Auto
MagicEffect Property AlchFortifyMarksman Auto
MagicEffect Property AlchFortifyOneHanded Auto
MagicEffect Property AlchFortifyPersuasion Auto
MagicEffect Property AlchFortifyPickpocket Auto
MagicEffect Property AlchFortifySmithing Auto
MagicEffect Property AlchFortifySneak Auto
MagicEffect Property AlchFortifyTwoHanded Auto
MagicEffect Property AlchRestoreMagicka Auto
MagicEffect Property AlchRestoreStamina Auto
Int Property GreyAlchemist2PotionDurationLimitInSeconds = 180 Autoreadonly Hidden
{The potion duration of all werewolf potions is limited to this amount if the player has the first and second perk grey alchemist}
Int Property GreyAlchemist1PotionDurationLimitInSeconds = 120 Autoreadonly Hidden
{The potion duration of all werewolf potions is limited to this amount if the player has the first perk grey alchemist}
Int Property NoAlchemistPotionDurationLimitInSeconds = 90 Autoreadonly Hidden
{The potion duration of all werewolf potions is limited to this amount if the player has not the perk grey alchemist}
_00E_FS_NQ11_Functions Property FS_NQ11 Auto
Int Property RenamedPotions Hidden
Int Function Get()
Int result = JMap.getObj(JDB.root(), "EnderalFS.RenamedPotions")
if (result == 0)
result = JFormMap.object()
JMap.setObj(JDB.root(), "EnderalFS.RenamedPotions", result)
EndIf
return result
EndFunction
EndProperty
Int Property ModelChangedPotions Hidden
Int Function Get()
Int result = JMap.getObj(JDB.root(), "EnderalFS.ModelChangedPotions")
If (result == 0)
result = JFormMap.object()
JMap.setObj(JDB.root(), "EnderalFS.ModelChangedPotions", result)
EndIf
return result
EndFunction
EndProperty
bool bDoneDarkBlood = false
bool bDoneChymikum = false
int PotionsMixedOnLastTest = 0 ; OBSOLETE AFTER 1.5.3.0. Needed for version update
int criticalSectionProcesses = 0 ; OBSOLETE AFTER 1.5.3.0. Needed for version update
;=====================================================================================
; FUNCTIONS
;=====================================================================================
Function _UpdatePotion(Potion item, Int count, Bool bIsInCraftingMode)
Int i
MagicEffect[] potionEffects = item.GetMagicEffects()
Int nPotionEffects = potionEffects.Length
Bool bIsTheriantrophistPotion = item.HasKeyword(_00E_Theriantrophist_Effect)
MagicEffect firstTheriantrophistEffect = None
If bIsTheriantrophistPotion && bIsInCraftingMode ; FRESHLY BREWN THERIANTROPHIST POTION
PlayerREF.removeItem(item, count, abSilent = true)
Bool bRemoveTheriantrophistEffects = False
If !PlayerREF.hasPerk(_00E_Class_Theriantrophist_P01_WerewolfBlood)
If _00E_Theriantrophist_ReallyWantToBrewPotion.Show() != 1
bRemoveTheriantrophistEffects = True
EndIf
EndIf
MagicEffect[] newEffects = new MagicEffect[10]
Float[] newMagnitudes = new Float[10]
Int[] newAreas = new Int[10]
Int[] newDurations = new Int[10]
Int nNewEffects = 0
If bRemoveTheriantrophistEffects
i = 0
While i < nPotionEffects && nNewEffects < newEffects.Length
If potionEffects[i].HasKeyword(_00E_Theriantrophist_Effect) == False
newEffects[nNewEffects] = potionEffects[i]
newMagnitudes[nNewEffects] = item.getNthEffectMagnitude(i)
newAreas[nNewEffects] = item.getNthEffectArea(i)
newDurations[nNewEffects] = item.getNthEffectDuration(i)
nNewEffects += 1
EndIf
i += 1
EndWhile
If nNewEffects == 0
newEffects[nNewEffects] = _00E_Theriantrophist_NoEffect
nNewEffects += 1
EndIf
Else
Int maxDuration = NoAlchemistPotionDurationLimitInSeconds
Int durationBonus = PlayerREF.GetAV("Variable02") as Int
If PlayerREF.hasPerk(_00E_Class_Theriantrophist_P03_GreyAlchemist_03)
maxDuration = -1 ; no duration mali are required
ElseIf PlayerREF.hasPerk(_00E_Class_Theriantrophist_P03_GreyAlchemist_02)
maxDuration = GreyAlchemist2PotionDurationLimitInSeconds
ElseIf PlayerREF.hasPerk(_00E_Class_Theriantrophist_P03_GreyAlchemist_01)
maxDuration = GreyAlchemist1PotionDurationLimitInSeconds
Endif
i = 0
While i < nPotionEffects && nNewEffects < newEffects.Length
newEffects[nNewEffects] = potionEffects[i]
newMagnitudes[nNewEffects] = item.getNthEffectMagnitude(i)
newAreas[nNewEffects] = item.getNthEffectArea(i)
newDurations[nNewEffects] = item.getNthEffectDuration(i)
If newEffects[nNewEffects].HasKeyword(_00E_Theriantrophist_Effect)
If firstTheriantrophistEffect == None
firstTheriantrophistEffect = newEffects[nNewEffects]
EndIf
If maxDuration >= 0 && newDurations[nNewEffects] > maxDuration
newDurations[nNewEffects] = maxDuration
EndIf
If durationBonus > 0
newDurations[nNewEffects] = newDurations[nNewEffects] + durationBonus
EndIf
EndIf
nNewEffects += 1
i += 1
EndWhile
If durationBonus > 0
_00E_FS_Theriantrophist_PotionFortified.Show(durationBonus)
EndIf
EndIf
Potion newPotion = EnderalLib.CreatePotion(newEffects, newMagnitudes, newAreas, newDurations, nNewEffects)
If JFormMap.hasKey(RenamedPotions, newPotion) == False
_RenamePotion(newPotion, newEffects, nNewEffects, bRemoveTheriantrophistEffects)
_SetPotionModel(newPotion, firstTheriantrophistEffect, newEffects[0])
EndIf
PlayerREF.addItem(newPotion, count, abSilent = true)
If bRemoveTheriantrophistEffects == False
_UpdateNQ11(newPotion)
EndIf
ElseIf bIsTheriantrophistPotion && bIsInCraftingMode == False ; OLD THERIANTROPHIST POTION
i = 0
While i < nPotionEffects && !firstTheriantrophistEffect
If potionEffects[i].HasKeyword(_00E_Theriantrophist_Effect)
firstTheriantrophistEffect = potionEffects[i]
EndIf
i += 1
EndWhile
_RenamePotion(item, potionEffects, nPotionEffects, False)
_SetPotionModel(item, firstTheriantrophistEffect, potionEffects[0])
_UpdateNQ11(item)
Else ; COMMON POTION
_RenamePotion(item, potionEffects, nPotionEffects, True)
_SetPotionModel(item, None, potionEffects[0])
EndIf
EndFunction
Function _RenamePotion(Potion p, MagicEffect[] potionEffects, Int nPotionEffects, Bool bCommonPotion)
String name = ""
If bCommonPotion
If p.isPoison()
name = Game.GetGameSettingString("sCreatedPoisonNamePrefix")
Else
name = Game.GetGameSettingString("sCreatedPotionNamePrefix")
Endif
EndIf
Int nEffectsAdded = 0
Int i = 0
While i < nPotionEffects && nEffectsAdded < 2
If nEffectsAdded > 0
name += ", "
EndIf
name += potionEffects[i].getName()
nEffectsAdded += 1
i += 1
EndWhile
JFormMap.setStr(RenamedPotions, p, name)
p.setName(name)
EndFunction
Function _SetPotionModel(Potion p, MagicEffect firstTheriantrophistEffect, MagicEffect firstEffect)
string modelName
string modelPath = ""
If firstTheriantrophistEffect
If firstTheriantrophistEffect == _00E_Theriantrophist_AlchChymikum_FireClaws
modelName = "ChymikumFire"
ElseIf firstTheriantrophistEffect == _00E_Theriantrophist_AlchChymikum_Armor
modelName = "ChymikumArmor"
ElseIf firstTheriantrophistEffect == _00E_Theriantrophist_AlchChymikum_Damage
modelName = "ChymikumDamage"
ElseIf firstTheriantrophistEffect == _00E_Theriantrophist_AlchChymikum_FrostClaws
modelName = "ChymikumFrost"
ElseIf firstTheriantrophistEffect == _00E_Theriantrophist_AlchChymikum_Health
modelName = "ChymikumLife"
ElseIf firstTheriantrophistEffect == _00E_Theriantrophist_AlchChymikum_ShockClaws
modelName = "ChymikumShock"
ElseIf firstTheriantrophistEffect == _00E_Theriantrophist_AlchChymikum_Speed
modelName = "ChymikumSpeed"
ElseIf firstTheriantrophistEffect == _00E_Theriantrophist_AlchChymikum_Stamina
modelName = "ChymikumStamina"
Else
modelName = "DarkBloodPotion"
Endif
modelPath = "meshes\\enderal\\forgottenstories\\theriantrophist\\" + modelName + ".nif"
ElseIf firstEffect && p.isPoison() == False
If firstEffect == _00E_AlchReduceArcaneFever
modelPath = "Meshes\\Clutter\\Quest\\MS12WhitePhialRepaired.nif"
ElseIf firstEffect == _00E_AlchRestoreMagicka || firstEffect == AlchRestoreMagicka
modelPath = "Meshes\\Clutter\\Potions\\PotionMagickaLesser.nif"
ElseIf firstEffect == _00E_AlchRestoreStamina || firstEffect == AlchRestoreStamina
modelPath = "Meshes\\Clutter\\Potions\\PotionStaminaLesser.nif"
ElseIf firstEffect == AlchFortifyHealth
modelPath = "Meshes\\Clutter\\Potions\\PotionFortifyHealthLesser.nif"
ElseIf firstEffect == AlchFortifyHealRate
modelPath = "Meshes\\Clutter\\Potions\\PotionFortifyHealRateLesser.nif"
ElseIf firstEffect == AlchFortifyMagicka
modelPath = "Meshes\\Clutter\\Potions\\PotionMagickaExtra.nif"
ElseIf firstEffect == AlchFortifyMagickaRate
modelPath = "Meshes\\Clutter\\Potions\\PotionFortifyMagiRateLesser.nif"
ElseIf firstEffect == AlchFortifyStamina
modelPath = "Meshes\\Clutter\\Potions\\PotionFortifyStaminaLesser.nif"
ElseIf firstEffect == AlchFortifyStaminaRate
modelPath = "Meshes\\Clutter\\Potions\\PotionFortifyStamRateLesser.nif"
ElseIf firstEffect == AlchInvisibillity || firstEffect == AlchWaterbreathing
modelPath = "Meshes\\Clutter\\Potions\\PotionInvisibiltyLesser.nif"
ElseIf firstEffect == AlchResistFire
modelPath = "Meshes\\Clutter\\Potions\\PotionResistFire50.nif"
ElseIf firstEffect == AlchResistFrost
modelPath = "Meshes\\Clutter\\Potions\\PotionResistFrost50.nif"
ElseIf firstEffect == AlchResistMagic
modelPath = "Meshes\\Clutter\\Potions\\PotionResistMagicka50.nif"
ElseIf firstEffect == AlchResistShock
modelPath = "Meshes\\Clutter\\Potions\\PotionResistShock50.nif"
ElseIf firstEffect == AlchFortifyAlchemy || firstEffect == AlchFortifyAlteration || firstEffect == AlchFortifyBarter || firstEffect == AlchFortifyBlock
modelPath = "Meshes\\Clutter\\Potions\\PotionFortifySkill01.nif"
ElseIf firstEffect == AlchFortifyCarryWeight || firstEffect == AlchFortifyConjuration || firstEffect == AlchFortifyDestruction || firstEffect == AlchFortifyEnchanting
modelPath = "Meshes\\Clutter\\Potions\\PotionFortifySkill01.nif"
ElseIf firstEffect == AlchFortifyHeavyArmor || firstEffect == AlchFortifyIllusion || firstEffect == AlchFortifyLightArmor || firstEffect == AlchFortifyLockpicking
modelPath = "Meshes\\Clutter\\Potions\\PotionFortifySkill01.nif"
ElseIf firstEffect == AlchFortifyMarksman || firstEffect == AlchFortifyOneHanded || firstEffect == AlchFortifyPersuasion || firstEffect == AlchFortifyPickpocket
modelPath = "Meshes\\Clutter\\Potions\\PotionFortifySkill01.nif"
ElseIf firstEffect == AlchFortifySmithing || firstEffect == AlchFortifySneak || firstEffect == AlchFortifyTwoHanded
modelPath = "Meshes\\Clutter\\Potions\\PotionFortifySkill01.nif"
EndIf
EndIf
If modelPath != ""
p.SetWorldModelPath(modelPath)
JFormMap.setStr(ModelChangedPotions, p, modelPath)
EndIf
EndFunction
Function _UpdateNQ11(Potion newPotion)
If (bDoneChymikum && bDoneDarkBlood) || FS_NQ11.IsRunning() == False
Return
EndIf
Bool bUpdateNQ11 = False
If newPotion.HasKeyword(_00E_Theriantrophist_ChymikumLife) && FS_NQ11.GetStage() >= 10 && !bDoneChymikum
bDoneChymikum = True
bUpdateNQ11 = True
EndIf
If newPotion.HasKeyword(_00E_Theriantrophist_DarkBloodEffect) && FS_NQ11.GetStage() >= 10 && !bDoneDarkBlood
bDoneDarkBlood = True
bUpdateNQ11 = True
EndIf
If bUpdateNQ11 && FS_NQ11.GetStage() < 17
FS_NQ11.ShowTutorial(2)
If bDoneChymikum && bDoneDarkBlood
_SetNewStageNQ11(17)
ElseIf bDoneChymikum
_SetNewStageNQ11(15)
ElseIf bDoneDarkBlood
_SetNewStageNQ11(16)
EndIf
EndIf
EndFunction
Function _SetNewStageNQ11(Int newStage)
If newStage > FS_NQ11.GetStage()
FS_NQ11.SetStage(newStage)
EndIf
EndFunction
;=====================================================================================
; EVENTS
;=====================================================================================
Event OnItemAdded(Form baseItem, int count, ObjectReference itemRef, ObjectReference source)
Potion item = baseItem as Potion
If item
Bool bIsInCraftingMode = UI.IsMenuOpen("Crafting Menu")
; Ignore not-custom potions (with FormID not starting with 0xFF) or already registered potions
If (Math.LogicalAnd(item.GetFormID(), 0xFF000000) == 0xFF000000) && JFormMap.hasKey(RenamedPotions, item) == False
_UpdatePotion(item, count, bIsInCraftingMode)
EndIf
EndIf
EndEvent
Event OnItemRemoved(Form baseItem, int count, ObjectReference itemRef, ObjectReference dest)
; Probably a potion is consumed
Potion item = baseItem as Potion
if item && dest == None
; we want to prevent that all potions that have been brewed are collected in this list
; and cause performance issues. So we risk that we loose track of them by removing them
; from this list. In this case, the name will be the old vanilla skyrim one
if (PlayerREF.getItemCount(item) == 0)
JFormMap.removeKey(RenamedPotions, item)
JFormMap.removeKey(ModelChangedPotions, item)
Endif
Endif
EndEvent
Int curScriptVersion = 0
Int Property LATEST_SCRIPT_VERSION = 3 AutoReadOnly
Event OnInit()
curScriptVersion = LATEST_SCRIPT_VERSION
EndEvent
Function _UpdateToVersion3()
Potion p
Int i
Int potionArrayID = JFormMap.allKeys(RenamedPotions)
JFormMap.clear(RenamedPotions)
JFormMap.clear(ModelChangedPotions)
; Update already cached potions
Int nPotions = JArray.count(potionArrayID)
i = 0
While i < nPotions
p = JArray.getForm(potionArrayID, i, None) as Potion
If p && Math.LogicalAnd(p.GetFormID(), 0xFF000000) == 0xFF000000
_UpdatePotion(p, 1, False)
EndIf
i += 1
EndWhile
; Update potions in the player's inventory
Int nItems = PlayerREF.GetNumItems()
i = 0
While i < nItems
p = PlayerREF.GetNthForm(i) as Potion
If p && Math.LogicalAnd(p.GetFormID(), 0xFF000000) == 0xFF000000 && JFormMap.hasKey(RenamedPotions, p) == False
_UpdatePotion(p, 1, False)
EndIf
i += 1
EndWhile
Debug.Trace("_00E_Theriantrophist_AlchemyControl: _UpdateToVersion3 done")
EndFunction
Event OnPlayerLoadGame()
Bool bRestoreNamesModels = True
; Version update
If curScriptVersion < LATEST_SCRIPT_VERSION
Int oldScriptVersion = curScriptVersion
curScriptVersion = LATEST_SCRIPT_VERSION
If oldScriptVersion < 3
_UpdateToVersion3()
bRestoreNamesModels = False
EndIf
EndIf
; Fix 1.5.3.0 _IsSelfBrewnPotion stuck in permanent Wait loop.
; It may take a looong time
If criticalSectionProcesses > 0
RegisterForSingleUpdate(0.1)
EndIf
; Restore names and models
If bRestoreNamesModels
Potion k
Int potionNames = RenamedPotions
k = JFormMap.nextKey(potionNames, previousKey = None, endKey = None) as Potion
while k != None
k.setName(JFormMap.getStr(potionNames, k))
k = JFormMap.nextKey(potionNames, k, endKey = None) as Potion
endwhile
Int potionModels = ModelChangedPotions
k = JFormMap.nextKey(potionModels, previousKey = None, endKey = None) as Potion
while k != None
k.SetWorldModelPath(JFormMap.getStr(potionModels, k))
k = JFormMap.nextKey(potionModels, k, endKey = None) as Potion
endwhile
EndIf
EndEvent
Event OnUpdate()
; Fix 1.5.3.0 _IsSelfBrewnPotion stuck in permanent Wait loop.
If criticalSectionProcesses <= 0
Utility.WaitMenuMode(0.1) ; Wait a bit more, just in case
If criticalSectionProcesses <= 0
;Debug.Notification("Unfucked _IsSelfBrewnPotion")
Return
EndIf
EndIf
PotionsMixedOnLastTest = Game.QueryStat("Potions Mixed") + Game.QueryStat("Poisons Mixed")
criticalSectionProcesses = 0
RegisterForSingleUpdate(0.1)
EndEvent