enderalse/source/scripts/_00e_theriantrophist_alchemycontrol.psc

544 lines
19 KiB
Plaintext
Raw Normal View History

Scriptname _00E_Theriantrophist_AlchemyControl extends ReferenceAlias
;=====================================================================================
; 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
FormList Property _00E_EmptyFormlist 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 curScriptVersion = 0
Int Property LATEST_SCRIPT_VERSION = 4 AutoReadOnly
bool bHasJContainers = false
;=====================================================================================
; FUNCTIONS
;=====================================================================================
Function _UpdatePotion(Potion item, Int count)
Int i
MagicEffect[] potionEffects = item.GetMagicEffects()
Int nPotionEffects = potionEffects.Length
Bool bIsTheriantrophistPotion = item.HasKeyword(_00E_Theriantrophist_Effect)
MagicEffect firstTheriantrophistEffect = None
If bIsTheriantrophistPotion && EnderalLib.IsDLLLoaded() ; FRESHLY BREWN THERIANTROPHIST POTION
Debug.Notification("Replacing 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
2021-10-05 22:46:41 +00:00
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
2021-10-05 22:59:59 +00:00
Potion newPotion = EnderalLib.CreatePotion(newEffects, newMagnitudes, newAreas, newDurations, nNewEffects)
If bHasJContainers && JFormMap.hasKey(RenamedPotions, newPotion) == False
_RenamePotion(newPotion, newEffects, nNewEffects, bRemoveTheriantrophistEffects)
_SetPotionModel(newPotion, firstTheriantrophistEffect, newEffects[0])
EndIf
GoToState("") ; skip OnItemAdded
PlayerREF.addItem(newPotion, count, abSilent = true)
GoToState("InCrafting")
If bRemoveTheriantrophistEffects == False
_UpdateNQ11(newPotion)
EndIf
return
EndIf
if bHasJContainers && JFormMap.hasKey(RenamedPotions, item) == False ; COMMON POTION
_RenamePotion(item, potionEffects, nPotionEffects, True)
_SetPotionModel(item, None, potionEffects[0])
EndIf
if bIsTheriantrophistPotion
_UpdateNQ11(item)
endif
EndFunction
Function _RenamePotion(Potion p, MagicEffect[] potionEffects, Int nPotionEffects, Bool bCommonPotion)
Debug.Notification("Renaming potion")
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
Function _UpdateInventoryFilters()
RemoveAllInventoryEventFilters()
AddInventoryEventFilter(_00E_EmptyFormlist)
Int potionNames = RenamedPotions
Form k = JFormMap.nextKey(potionNames, previousKey = None, endKey = None)
while k != None
AddInventoryEventFilter(k)
k = JFormMap.nextKey(potionNames, k, endKey = None)
endwhile
EndFunction
Function _RestorePotionAttributes()
Debug.Notification("Restoring potion names")
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
EndFunction
Function _InitAchemyControl()
;Debug.Notification("AchemyControl init")
GoToState("")
int iSKSEVer = SKSE.GetVersion()
if iSKSEVer < 2
RemoveAllInventoryEventFilters()
bHasJContainers = false
;Debug.Notification("SKSE is not loaded")
Debug.Trace("SKSE is not loaded, _00E_Theriantrophist_AlchemyControl is disabled")
return
endif
bHasJContainers = ( (SKSE.GetPluginVersion("JContainers64") != -1) || (SKSE.GetPluginVersion("JContainersVR") != -1) )
if ! bHasJContainers && ! EnderalLib.IsDLLLoaded()
; Both required components are missing, do not update version and disable everything
RemoveAllInventoryEventFilters()
UnregisterForAllMenus()
Debug.Trace("JContainers and fs.dll are not loaded, _00E_Theriantrophist_AlchemyControl is disabled.")
;Debug.Notification("JContainers and fs.dll are not loaded")
return
endif
; Version update
If curScriptVersion < LATEST_SCRIPT_VERSION
Int oldScriptVersion = curScriptVersion
curScriptVersion = LATEST_SCRIPT_VERSION
If oldScriptVersion < 4
;Debug.Notification("Updating AlchemyControl")
UnregisterForUpdate()
EndIf
EndIf
; Re-initialize everything to stay resilient to co-save deletion or corruption
if bHasJContainers
RegisterForMenu("ContainerMenu")
RegisterForMenu("InventoryMenu")
RegisterForMenu("FavoritesMenu")
;Debug.Trace("JContainers is loaded, hooking to menus")
else
RemoveAllInventoryEventFilters()
UnregisterForAllMenus()
Debug.Notification("JContainers is not loaded")
Debug.Trace("JContainers is not loaded, renaming and changing potion models is disabled")
endif
RegisterForMenu("Crafting Menu")
EndFunction
;=====================================================================================
; EVENTS
;=====================================================================================
Event OnMenuOpen(String MenuName)
If menuName == "Crafting Menu"
GoToState("InCrafting")
return
endif
if bHasJContainers
Debug.Notification("InInventory")
GoToState("InInventory")
endif
EndEvent
Event OnMenuClose(String MenuName)
GoToState("")
EndEvent
State InCrafting
Event OnBeginState()
;Debug.Notification("RemoveAllInventoryEventFilters")
RemoveAllInventoryEventFilters()
EndEvent
Event OnItemAdded(Form baseItem, int count, ObjectReference itemRef, ObjectReference source)
Debug.Notification("Added " + baseItem.GetName())
Potion item = baseItem as Potion
If item
; Ignore not-custom potions (with FormID not starting with 0xFF) or already registered potions
If (Math.LogicalAnd(item.GetFormID(), 0xFF000000) == 0xFF000000) && (!bHasJContainers || JFormMap.hasKey(RenamedPotions, item) == False)
_UpdatePotion(item, count)
EndIf
EndIf
EndEvent
Event OnEndState()
if bHasJContainers && UI.IsMenuOpen("Crafting Menu") == false
Debug.Notification("_UpdateInventoryFilters")
_UpdateInventoryFilters()
endif
EndEvent
EndState
State InInventory
Event OnItemRemoved(Form baseItem, int count, ObjectReference itemRef, ObjectReference dest)
if dest != None
return
endif
Debug.Notification("Removed " + baseItem.GetName())
; Probably a potion is consumed
Potion item = baseItem as Potion
if item
; 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)
RemoveInventoryEventFilter(baseItem)
Endif
Endif
EndEvent
EndState
Event OnInit()
curScriptVersion = LATEST_SCRIPT_VERSION
_InitAchemyControl()
EndEvent
Event OnPlayerLoadGame()
_InitAchemyControl()
if bHasJContainers
_RestorePotionAttributes()
_UpdateInventoryFilters()
endif
EndEvent