Reworked hidden stashes to a ContainerController quest alias instead of attached script

This commit is contained in:
Eddoursul 2024-01-13 15:58:46 +01:00
parent 68c68c6a3e
commit 5dc76239c8
5 changed files with 312 additions and 278 deletions

BIN
SleightOfHand quest.esp Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,312 @@
Scriptname _00E_SleightOfHandAlias extends ReferenceAlias Hidden
; This script sets up the sleight of hand loot of a chest upon activating it
;=====================================================================================
; EVENTS
;=====================================================================================
event OnInit()
RegisterForMenu("ContainerMenu")
RegisterForMenu("LootMenu")
endevent
event OnPlayerLoadGame()
RegisterForMenu("ContainerMenu")
RegisterForMenu("LootMenu")
endevent
event OnUpdate()
if lastContainer && UI.IsMenuOpen("LootMenu") && lastContainer == Game.GetCurrentCrosshairRef()
OpenHiddenSlot(lastContainer, true)
endif
endevent
event OnMenuOpen(String MenuName)
if MenuName == "LootMenu"
UnregisterForUpdate()
; Even when QuickLoot RE does not show up, it still sends open and close menu events
; To determine if QuickLoot is open, we check it 0.1 seconds later
ObjectReference lootMenuRef = Game.GetCurrentCrosshairRef()
if ! lootMenuRef
return
endif
Container baseContainer = lootMenuRef.GetBaseObject() as Container
if ! baseContainer || lootMenuRef.IsActivationBlocked() || _00E_ChestsWithHiddenSlots.Find(baseContainer) == -1
return
endif
lastContainer = lootMenuRef
; Clears previous request automatically
RegisterForSingleUpdate(0.1)
return
endif
if MenuName == "ContainerMenu"
ObjectReference currentContainer = EnderalFunctions.GetCurrentContainer()
if ! currentContainer || currentContainer as Actor
return
endif
if currentContainer == containterToFill
; Opened hidden container
Utility.Wait(0.1)
; Move unclaimed items to the original container
containterToFill.RemoveAllItems(lastContainer, true, true)
lastContainer = None
containterToFill = None
return
endif
if _00E_ChestsWithHiddenSlots.Find(currentContainer.GetBaseObject()) == -1
return
endif
OpenHiddenSlot(currentContainer)
endif
endevent
event OnMenuClose(String MenuName)
if MenuName == "LootMenu"
UnregisterForUpdate()
lastContainer = None
endif
endevent
;=====================================================================================
; FUNCTIONS
;=====================================================================================
function OpenHiddenSlot(ObjectReference currentContainer, bool bLootMenu = false)
if ! SetUpHiddenSlot(currentContainer)
return
endif
UILockpickingCylinderTurnM.Play(PlayerREF)
messageToShow.Show()
if bLootMenu
containterToFill.RemoveAllItems(currentContainer, true, true)
else
; Open hidden container after the original one closes
Utility.Wait(0.1)
If IsOwned(currentContainer)
containterToFill.SetFactionOwner(SleightOfHandOwnerFaction)
Else
containterToFill.SetFactionOwner(none)
Endif
lastContainer = currentContainer
containterToFill.Activate(PlayerREF, True)
endif
If containterToFill == _00E_FS_SleightOfHand_HiddenSlot_BigSlotREF
_00E_EPHandler.GiveEP(_00E_BigHiddenSlotExpReward.GetValue() as int)
If _00E_HiddenSlotAchievementUnlocked.GetValueInt() == 0
UIEnchantingLearnEffectM.Play(PlayerREF)
_00E_HiddenSlotAchievementUnlocked.SetValueInt(1)
Steam.UnlockAchievement("END_HIDDEN_SLOT_01")
EndIf
EndIf
endfunction
bool function SetUpHiddenSlot(ObjectReference aContainer)
if aContainer.GetItemCount(_00E_HiddenSlotChecked)
return false
endif
aContainer.AddItem(_00E_HiddenSlotChecked, 1, true)
if ! DoesContainerHaveHiddenSlot()
return false
EndIf
messageToShow = GetSlotMessage()
int iHiddenSlotTier = GetHiddenSlotTier()
int iFormlistIndexOffset = 8*(iHiddenSlotTier - 1)
int iFormlistIndex
if messageToShow == _00E_FS_SleightOfHand_HiddenSlot_sSmallSlotFound
containterToFill = _00E_FS_SleightOfHand_HiddenSlot_SmallSlotREF
iFormlistIndex = Utility.RandomInt(0, 2) + iFormlistIndexOffset
Elseif messageToShow == _00E_FS_SleightOfHand_HiddenSlot_sMediumSlotFound
containterToFill = _00E_FS_SleightOfHand_HiddenSlot_MediumSlotREF
iFormlistIndex = Utility.RandomInt(3, 5) + iFormlistIndexOffset
Elseif messageToShow == _00E_FS_SleightOfHand_HiddenSlot_sBigSlotFound
containterToFill = _00E_FS_SleightOfHand_HiddenSlot_BigSlotREF
iFormlistIndex = Utility.RandomInt(6, 7) + iFormlistIndexOffset
EndIf
Formlist hiddenSlotFormlist = _00E_FS_HiddenSlotRewardFormlists.GetAt(iFormlistIndex) as Formlist
AddItemsToContainer(hiddenSlotFormlist, iFormlistIndexOffset, iHiddenSlotTier)
return true
EndFunction
Function AddItemsToContainer(Formlist itemsToAdd, int iFormlistIndexOffset, int iHiddenSlotTier)
containterToFill.RemoveAllItems()
if containterToFill == _00E_FS_SleightOfHand_HiddenSlot_BigSlotREF
if ! itemsToAdd.HasForm(_00E_FS_SleightOfHand_HiddenSlotUsedMarker)
itemsToAdd.AddForm(_00E_FS_SleightOfHand_HiddenSlotUsedMarker)
Else
int iFormlistIndex = Utility.RandomInt(3, 5) + iFormlistIndexOffset
itemsToAdd = _00E_FS_HiddenSlotRewardFormlists.GetAt(iFormlistIndex) as Formlist
messageToShow = _00E_FS_SleightOfHand_HiddenSlot_sMediumSlotFound
EndIf
EndIf
int iIndex = itemsToAdd.GetSize() - 1
while iIndex >= 0
Form formToAdd = itemsToAdd.GetAt(iIndex)
if formToAdd == Gold001
containterToFill.AddItem(itemsToAdd.GetAt(iIndex), iHiddenSlotTier*5)
Else
containterToFill.AddItem(itemsToAdd.GetAt(iIndex), 1)
EndIf
iIndex -= 1
endwhile
EndFunction
bool Function DoesContainerHaveHiddenSlot()
float fHiddenSlotChance = Utility.RandomInt(0, 100)
int iPlayerPickpocketSkill = PlayerREF.GetActorValue("Pickpocket") as Int
; raised the divider from 2 to 2.5, maybe we should raise it even further
; otherwise too much loot might be given away
float fPlayerChance = iPlayerPickpocketSkill/2.5
If fPlayerChance < 15
fPlayerChance = 15
EndIf
return (fHiddenSlotChance <= fPlayerChance)
EndFunction
int Function GetHiddenSlotTier()
int iPlayerLevel = PlayerLevel.GetValueInt()
if iPlayerLevel >= iTierCap_1 && iPlayerLevel < iTierCap_2
Return 1
Elseif iPlayerLevel >= iTierCap_2 && iPlayerLevel < iTierCap_3
Return 2
Elseif iPlayerLevel >= iTierCap_3 && iPlayerLevel < iTierCap_4
Return 3
Elseif iPlayerLevel >= iTierCap_4 && iPlayerLevel < iTierCap_5
Return 4
Else
Return 5
EndIf
EndFunction
Message Function GetSlotMessage()
; This calculates whether the hidden slot will be filled with a small, a regular, or a rare reward
int iSlotSize = Utility.RandomInt(1, 100)
if iSlotSize <= iBigSlotChance && PlayerREF.GetActorValue("Pickpocket") >= 75
return _00E_FS_SleightOfHand_HiddenSlot_sBigSlotFound
Elseif (iSlotSize > iBigSlotChance) && (iSlotSize <= (iMediumSlotChance + iBigSlotChance)) && PlayerREF.GetActorValue("Pickpocket") >= 50
return _00E_FS_SleightOfHand_HiddenSlot_sMediumSlotFound
Else
return _00E_FS_SleightOfHand_HiddenSlot_sSmallSlotFound
EndIf
EndFunction
bool Function IsOwned(ObjectReference aContainer)
If aContainer.GetActorOwner()
return true
EndIf
Cell ContainerParentCell = aContainer.GetParentCell()
return ContainerParentCell.GetActorOwner() || ContainerParentCell.GetFactionOwner()
EndFunction
;=====================================================================================
; PROPERTIES
;=====================================================================================
; These integers determine at which levels player can access the different tiers
int iTierCap_1 = 0
int iTierCap_2 = 15
int iTierCap_3 = 25
int iTierCap_4 = 35
int iTierCap_5 = 45
; These integers determine the likelihood of the different slot sizes
int iSmallSlotChance = 50
int iMediumSlotChance = 35
int iBigSlotChance = 15
; This formlist will be filled with the formlist containing the items that will actually be added into the container
Message messageToShow
ObjectReference lastContainer
ObjectReference containterToFill
Actor Property PlayerRef Auto
GlobalVariable Property PlayerLevel Auto
GlobalVariable Property _00E_HiddenSlotAchievementUnlocked Auto
GlobalVariable Property _00E_BigHiddenSlotExpReward Auto
; These REFs simply provide the containers that will be filled when finding a secret slot
ObjectReference Property _00E_FS_SleightOfHand_HiddenSlot_SmallSlotREF Auto
ObjectReference Property _00E_FS_SleightOfHand_HiddenSlot_MediumSlotREF Auto
ObjectReference Property _00E_FS_SleightOfHand_HiddenSlot_BigSlotREF Auto
MiscObject Property Gold001 Auto
MiscObject Property _00E_FS_SleightOfHand_HiddenSlotUsedMarker Auto
MiscObject Property _00E_HiddenSlotChecked Auto
Sound Property UILockpickingCylinderTurnM Auto
Sound Property UIEnchantingLearnEffectM Auto
Message Property _00E_FS_SleightOfHand_HiddenSlot_sSmallSlotFound Auto
Message Property _00E_FS_SleightOfHand_HiddenSlot_sMediumSlotFound Auto
Message Property _00E_FS_SleightOfHand_HiddenSlot_sBigSlotFound Auto
; This contains all formlists with items for the rewards.For every tier, there are nine different treasures to be found, three in small and medium category, two in big.
FormList Property _00E_FS_HiddenSlotRewardFormlists Auto
FormList Property _00E_ChestsWithHiddenSlots Auto
Faction Property SleightOfHandOwnerFaction Auto

View File

@ -1,278 +0,0 @@
Scriptname _00E_FS_SleightOfHand_HiddenSlotSC extends ObjectReference
; This script sets up the sleight of hand loot of a chest upon activating it
;=====================================================================================
; EVENTS
;=====================================================================================
Event OnActivate(ObjectReference akActionRef)
If !Self.IsLocked() && akActionRef == PlayerREF
If !bSetUp
SetUpHiddenSlot()
EndIf
Utility.Wait(0.5)
If bFoundTreasure && !bDone
OpenHiddenSlot()
EndIf
EndIf
EndEvent
Event OnMenuClose(String MenuName)
containterToFill.RemoveAllItems(Self as ObjectReference, true, false)
UnregisterForMenu("ContainerMenu")
EndEvent
;=====================================================================================
; FUNCTIONS
;=====================================================================================
Function OpenHiddenSlot()
bDone = True
UILockpickingCylinderTurnM.Play(PlayerREF)
messageToShow.Show()
If bOwned
containterToFill.SetFactionOwner(SleightOfHandOwnerFaction)
Else
containterToFill.SetFactionOwner(none)
Endif
RegisterForMenu("ContainerMenu")
containterToFill.Activate(PlayerREF, True)
If sTreasureSize == "Big"
UIEnchantingLearnEffectM.Play(PlayerREF)
_00E_EPHandler.GiveEP(iRewardEXPBigSlot)
If _00E_HiddenSlotAchievementUnlocked.GetValueInt() == 0
_00E_HiddenSlotAchievementUnlocked.SetValueInt(1)
Steam.UnlockAchievement("END_HIDDEN_SLOT_01")
EndIf
EndIf
EndFunction
Function SetUpHiddenSlot()
bSetUp = True
if DoesContainerHaveHiddenSlot()
bFoundTreasure = True
sTreasureSize = GetSlotSize()
iHiddenSlotTier = GetHiddenSlotTier()
iFormlistIndexOffset = 8*(iHiddenSlotTier - 1)
iFormlistIndex
if sTreasureSize == "Small"
containterToFill = _00E_FS_SleightOfHand_HiddenSlot_SmallSlotREF
iFormlistIndex = Utility.RandomInt(0, 2) + iFormlistIndexOffset
Elseif sTreasureSize == "Medium"
containterToFill = _00E_FS_SleightOfHand_HiddenSlot_MediumSlotREF
iFormlistIndex = Utility.RandomInt(3, 5) + iFormlistIndexOffset
Elseif sTreasureSize == "Big"
containterToFill = _00E_FS_SleightOfHand_HiddenSlot_BigSlotREF
iFormlistIndex = Utility.RandomInt(6, 7) + iFormlistIndexOffset
EndIf
bOwned = GetOwner()
hiddenSlotFormlist = _00E_FS_HiddenSlotRewardFormlists.GetAt(iFormlistIndex) as Formlist
AddItemsToContainer(hiddenSlotFormlist)
EndIf
EndFunction
Function AddItemsToContainer(Formlist itemsToAdd)
containterToFill.RemoveAllItems()
if sTreasureSize == "Big"
if !(itemsToAdd.HasForm(_00E_FS_SleightOfHand_HiddenSlotUsedMarker))
itemsToAdd.AddForm(_00E_FS_SleightOfHand_HiddenSlotUsedMarker)
Else
iFormlistIndex = Utility.RandomInt(3, 5) + iFormlistIndexOffset
itemsToAdd = _00E_FS_HiddenSlotRewardFormlists.GetAt(iFormlistIndex) as Formlist
messageToShow = _00E_FS_SleightOfHand_HiddenSlot_sMediumSlotFound
EndIf
EndIf
int iIndex = itemsToAdd.GetSize() - 1
while iIndex >= 0
Form formToAdd = itemsToAdd.GetAt(iIndex)
if formToAdd == Gold001
containterToFill.AddItem(itemsToAdd.GetAt(iIndex), iHiddenSlotTier*5)
Else
containterToFill.AddItem(itemsToAdd.GetAt(iIndex), 1)
EndIf
iIndex -= 1
endwhile
EndFunction
bool Function DoesContainerHaveHiddenSlot()
float fHiddenSlotChance = Utility.RandomInt(0, 100)
iPlayerPickpocketSkill = PlayerREF.GetActorValue("Pickpocket") as Int
; raised the divider from 2 to 2.5, maybe we should raise it even further
; otherwise too much loot might be given away
float fPlayerChance = iPlayerPickpocketSkill/2.5
If fPlayerChance < 15
fPlayerChance = 15
EndIf
If fHiddenSlotChance <= fPlayerChance
Return True
Else
Return False
EndIf
EndFunction
int Function GetHiddenSlotTier()
iPlayerLevel = PlayerLevel.GetValueInt()
if iPlayerLevel >= iTierCap_1 && iPlayerLevel < iTierCap_2
Return 1
Elseif iPlayerLevel >= iTierCap_2 && iPlayerLevel < iTierCap_3
Return 2
Elseif iPlayerLevel >= iTierCap_3 && iPlayerLevel < iTierCap_4
Return 3
Elseif iPlayerLevel >= iTierCap_4 && iPlayerLevel < iTierCap_5
Return 4
Else
Return 5
EndIf
EndFunction
string Function GetSlotSize()
; This calculates whether the hidden slot will be filled with a small, a regular, or a rare reward
int iSlotSize = Utility.RandomInt(1, 100)
if iSlotSize <= iBigSlotChance && PlayerREF.GetActorValue("Pickpocket") >= 75
messageToShow = _00E_FS_SleightOfHand_HiddenSlot_sBigSlotFound
Return "Big"
Elseif (iSlotSize > iBigSlotChance) && (iSlotSize <= (iMediumSlotChance + iBigSlotChance)) && PlayerREF.GetActorValue("Pickpocket") >= 50
messageToShow = _00E_FS_SleightOfHand_HiddenSlot_sMediumSlotFound
Return "Medium"
Else
messageToShow = _00E_FS_SleightOfHand_HiddenSlot_sSmallSlotFound
Return "Small"
EndIf
EndFunction
bool Function GetOwner()
ContainerParentCell = Self.GetParentCell()
If Self.GetActorOwner()
bOwned = true
EndIf
If !bOwned && ContainerParentCell.GetActorOwner()
bOwned = true
EndIf
If !bOwned && ContainerParentCell.GetFactionOwner()
bOwned = true
EndIf
Return bOwned
EndFunction
;=====================================================================================
; PROPERTIES
;=====================================================================================
bool bFoundTreasure
bool bDone
bool bSetUp
bool bOwned
int iPlayerPickpocketSkill
int iPlayerLevel
int iHiddenSlotTier
int iFormlistIndexOffset
int iFormlistIndex
int iRewardEXPBigSlot = 50
; These integers determine at which levels player can access the different tiers
int iTierCap_1 = 0
int iTierCap_2 = 15
int iTierCap_3 = 25
int iTierCap_4 = 35
int iTierCap_5 = 45
; These integers determine the likelihood of the different slot sizes
int iSmallSlotChance = 50
int iMediumSlotChance = 35
int iBigSlotChance = 15
String sTreasureSize
; This formlist will be filled with the formlist containing the items that will actually be added into the container
Formlist hiddenSlotFormlist
Message messageToShow
ObjectReference containterToFill
Cell ContainerParentCell
Actor Property PlayerREF Auto
GlobalVariable Property PlayerLevel Auto
GlobalVariable Property _00E_HiddenSlotAchievementUnlocked Auto
; These REFs simply provide the containers that will be filled when finding a secret slot
ObjectReference Property _00E_FS_SleightOfHand_HiddenSlot_SmallSlotREF Auto
ObjectReference Property _00E_FS_SleightOfHand_HiddenSlot_MediumSlotREF Auto
ObjectReference Property _00E_FS_SleightOfHand_HiddenSlot_BigSlotREF Auto
MiscObject Property Gold001 Auto
MiscObject Property _00E_FS_SleightOfHand_HiddenSlotUsedMarker Auto
Sound Property UILockpickingCylinderTurnM Auto
Sound Property UIEnchantingLearnEffectM Auto
Message Property _00E_FS_SleightOfHand_HiddenSlot_sSmallSlotFound Auto
Message Property _00E_FS_SleightOfHand_HiddenSlot_sMediumSlotFound Auto
Message Property _00E_FS_SleightOfHand_HiddenSlot_sBigSlotFound Auto
; This contains all formlists with items for the rewards.For every tier, there are nine different treasures to be found, three in small and medium category, two in big.
Formlist Property _00E_FS_HiddenSlotRewardFormlists Auto
Faction Property SleightOfHandOwnerFaction Auto