2024-01-13 19:15:35 +00:00
Scriptname _00E_ContainerController extends ReferenceAlias Hidden
2024-01-13 14:58:46 +00:00
; This script sets up the sleight of hand loot of a chest upon activating it
;=====================================================================================
; EVENTS
;=====================================================================================
event OnInit()
RegisterForMenu("ContainerMenu")
RegisterForMenu("LootMenu")
2024-01-14 03:15:47 +00:00
PlayerREF.AddPerk(_00E_LockpickingReqPerk)
2024-01-13 14:58:46 +00:00
endevent
event OnPlayerLoadGame()
2024-01-13 19:15:35 +00:00
lastContainer = None
bLmHasGold = false
bLmHasSlot = false
2024-01-13 14:58:46 +00:00
RegisterForMenu("ContainerMenu")
RegisterForMenu("LootMenu")
2024-01-14 03:15:47 +00:00
if ! PlayerREF.HasPerk(_00E_LockpickingReqPerk)
PlayerREF.AddPerk(_00E_LockpickingReqPerk)
endif
2024-01-13 14:58:46 +00:00
endevent
event OnUpdate()
2024-01-13 19:15:35 +00:00
ObjectReference currentContainer = lastContainer
lastContainer = None
if ! currentContainer
return
endif
if UI.IsMenuOpen("LootMenu") && currentContainer == Game.GetCurrentCrosshairRef()
if bLmHasGold
IncrementGold(currentContainer)
endif
if bLmHasSlot
OpenHiddenSlot(currentContainer, true)
endif
2024-01-13 14:58:46 +00:00
endif
endevent
event OnMenuOpen(String MenuName)
if MenuName == "LootMenu"
; 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
2024-01-13 19:15:35 +00:00
lastContainer = None
UnregisterForUpdate()
2024-01-13 14:58:46 +00:00
ObjectReference lootMenuRef = Game.GetCurrentCrosshairRef()
if ! lootMenuRef
return
endif
2024-01-25 19:41:41 +00:00
if ! ( lootMenuRef.GetBaseObject() as Container ) || lootMenuRef.IsLocked() || lootMenuRef.IsActivationBlocked() || lootMenuRef.GetActorOwner() == Player
2024-01-13 14:58:46 +00:00
return
endif
2024-01-25 19:41:41 +00:00
2024-01-13 19:15:35 +00:00
bLmHasGold = lootMenuRef.GetItemCount(Gold001) >= 5
bLmHasSlot = false
2024-01-14 03:15:47 +00:00
if bLmHasGold || _00E_ChestsWithHiddenSlots.HasForm(lootMenuRef.GetBaseObject())
2024-01-13 19:15:35 +00:00
if ! bLmHasGold
bLmHasSlot = true
endif
if ! IsProcessed(lootMenuRef)
lastContainer = lootMenuRef
; Clears previous request automatically
RegisterForSingleUpdate(0.1)
endif
endif
2024-01-13 14:58:46 +00:00
return
endif
if MenuName == "ContainerMenu"
ObjectReference currentContainer = EnderalFunctions.GetCurrentContainer()
2024-01-25 19:41:41 +00:00
if ! currentContainer || currentContainer as Actor || currentContainer.GetActorOwner() == Player || currentContainer.GetParentCell() != PlayerREF.GetParentCell()
2024-01-13 14:58:46 +00:00
return
endif
2024-01-25 19:41:41 +00:00
2024-01-13 19:15:35 +00:00
if currentContainer == containerToFill
2024-01-13 14:58:46 +00:00
; Opened hidden container
Utility.Wait(0.1)
; Move unclaimed items to the original container
2024-01-13 19:15:35 +00:00
containerToFill.RemoveAllItems(lastContainer, true, true)
2024-01-13 14:58:46 +00:00
lastContainer = None
2024-01-13 19:15:35 +00:00
containerToFill = None
return
endif
bool bDoGold = currentContainer.GetItemCount(Gold001) >= 5
2024-01-14 03:15:47 +00:00
bool bDoSlot = _00E_ChestsWithHiddenSlots.HasForm(currentContainer.GetBaseObject())
2024-01-13 19:15:35 +00:00
if ! bDoGold && ! bDoSlot
2024-01-13 14:58:46 +00:00
return
endif
2024-01-13 19:15:35 +00:00
if IsProcessed(currentContainer)
2024-01-13 14:58:46 +00:00
return
endif
2024-01-13 19:15:35 +00:00
if bDoGold
IncrementGold(currentContainer)
endif
if bDoSlot
OpenHiddenSlot(currentContainer)
endif
2024-01-13 14:58:46 +00:00
endif
endevent
event OnMenuClose(String MenuName)
if MenuName == "LootMenu"
UnregisterForUpdate()
lastContainer = None
2024-01-13 19:15:35 +00:00
bLmHasGold = false
bLmHasSlot = false
2024-01-13 14:58:46 +00:00
endif
endevent
;=====================================================================================
; FUNCTIONS
;=====================================================================================
2024-01-13 19:15:35 +00:00
bool function IsProcessed(ObjectReference targetContainer)
if targetContainer.GetItemCount(_00E_HiddenSlotChecked)
return true
endif
targetContainer.AddItem(_00E_HiddenSlotChecked, 1, true)
return false
endfunction
Function IncrementGold(ObjectReference targetContainer)
int iGoldMultiplicator = _00E_GoldMult.GetValue() as int
2024-01-15 21:16:23 +00:00
if iGoldMultiplicator <= 0
2024-01-13 19:15:35 +00:00
iGoldMultiplicator = 5
endif
float fIncrementPercentage = ( PlayerREF.GetActorValue("Lockpicking") / iGoldMultiplicator ) / 100
int iGoldBuffAmount = ( targetContainer.GetItemCount(Gold001) * fIncrementPercentage ) as Int
2024-01-15 21:16:23 +00:00
if iGoldBuffAmount <= 0
2024-01-13 19:15:35 +00:00
return
endif
targetContainer.AddItem(Gold001, iGoldBuffAmount)
if iGoldBuffAmount > 1
_00E_FS_LockpickingGoldBuffMSG.Show(iGoldBuffAmount as Int)
EndIf
EndFunction
2024-01-13 14:58:46 +00:00
function OpenHiddenSlot(ObjectReference currentContainer, bool bLootMenu = false)
if ! SetUpHiddenSlot(currentContainer)
return
endif
UILockpickingCylinderTurnM.Play(PlayerREF)
messageToShow.Show()
if bLootMenu
2024-01-13 19:15:35 +00:00
containerToFill.RemoveAllItems(currentContainer, true, true)
2024-01-13 14:58:46 +00:00
else
; Open hidden container after the original one closes
Utility.Wait(0.1)
If IsOwned(currentContainer)
2024-01-13 19:15:35 +00:00
containerToFill.SetFactionOwner(SleightOfHandOwnerFaction)
2024-01-13 14:58:46 +00:00
Else
2024-01-13 19:15:35 +00:00
containerToFill.SetFactionOwner(none)
2024-01-13 14:58:46 +00:00
Endif
lastContainer = currentContainer
2024-01-13 19:15:35 +00:00
containerToFill.Activate(PlayerREF, True)
2024-01-13 14:58:46 +00:00
endif
2024-01-13 19:15:35 +00:00
If containerToFill == _00E_FS_SleightOfHand_HiddenSlot_BigSlotREF
2024-01-13 14:58:46 +00:00
_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 ! DoesContainerHaveHiddenSlot()
return false
EndIf
messageToShow = GetSlotMessage()
int iHiddenSlotTier = GetHiddenSlotTier()
int iFormlistIndexOffset = 8*(iHiddenSlotTier - 1)
int iFormlistIndex
if messageToShow == _00E_FS_SleightOfHand_HiddenSlot_sSmallSlotFound
2024-01-13 19:15:35 +00:00
containerToFill = _00E_FS_SleightOfHand_HiddenSlot_SmallSlotREF
2024-01-13 14:58:46 +00:00
iFormlistIndex = Utility.RandomInt(0, 2) + iFormlistIndexOffset
Elseif messageToShow == _00E_FS_SleightOfHand_HiddenSlot_sMediumSlotFound
2024-01-13 19:15:35 +00:00
containerToFill = _00E_FS_SleightOfHand_HiddenSlot_MediumSlotREF
2024-01-13 14:58:46 +00:00
iFormlistIndex = Utility.RandomInt(3, 5) + iFormlistIndexOffset
Elseif messageToShow == _00E_FS_SleightOfHand_HiddenSlot_sBigSlotFound
2024-01-13 19:15:35 +00:00
containerToFill = _00E_FS_SleightOfHand_HiddenSlot_BigSlotREF
2024-01-13 14:58:46 +00:00
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)
2024-01-13 19:15:35 +00:00
containerToFill.RemoveAllItems()
2024-01-13 14:58:46 +00:00
2024-01-13 19:15:35 +00:00
if containerToFill == _00E_FS_SleightOfHand_HiddenSlot_BigSlotREF
2024-01-13 14:58:46 +00:00
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
2024-01-13 19:15:35 +00:00
containerToFill.AddItem(itemsToAdd.GetAt(iIndex), iHiddenSlotTier*5)
2024-01-13 14:58:46 +00:00
Else
2024-01-13 19:15:35 +00:00
containerToFill.AddItem(itemsToAdd.GetAt(iIndex), 1)
2024-01-13 14:58:46 +00:00
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
2024-01-13 19:15:35 +00:00
ObjectReference containerToFill
bool bLmHasGold
bool bLmHasSlot
2024-01-13 14:58:46 +00:00
Actor Property PlayerRef Auto
2024-01-25 19:41:41 +00:00
ActorBase Property Player Auto
2024-01-13 14:58:46 +00:00
GlobalVariable Property PlayerLevel Auto
GlobalVariable Property _00E_HiddenSlotAchievementUnlocked Auto
GlobalVariable Property _00E_BigHiddenSlotExpReward Auto
2024-01-13 19:15:35 +00:00
; Use this to control how much the lockpicking skill increments the gold found in chest. When changing, remember to change in _00E_LootContainer.psc as well!
; Current calculation: Gold in chest*((Lockpicking/iGoldMultiplicator)/100)
GlobalVariable Property _00E_GoldMult Auto
2024-01-13 14:58:46 +00:00
; 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
2024-01-13 19:15:35 +00:00
Message Property _00E_FS_LockpickingGoldBuffMSG Auto
2024-01-14 03:15:47 +00:00
Perk Property _00E_LockpickingReqPerk Auto