diff --git a/SleightOfHand quest.esp b/SleightOfHand quest.esp new file mode 100644 index 00000000..6b1a7dd6 Binary files /dev/null and b/SleightOfHand quest.esp differ diff --git a/scripts/_00E_SleightOfHandAlias.pex b/scripts/_00E_SleightOfHandAlias.pex new file mode 100644 index 00000000..dd25ef54 Binary files /dev/null and b/scripts/_00E_SleightOfHandAlias.pex differ diff --git a/scripts/_00e_fs_sleightofhand_hiddenslotsc.pex b/scripts/_00e_fs_sleightofhand_hiddenslotsc.pex deleted file mode 100644 index 4b3bfa1c..00000000 Binary files a/scripts/_00e_fs_sleightofhand_hiddenslotsc.pex and /dev/null differ diff --git a/source/scripts/_00E_SleightOfHandAlias.psc b/source/scripts/_00E_SleightOfHandAlias.psc new file mode 100644 index 00000000..4c880f35 --- /dev/null +++ b/source/scripts/_00E_SleightOfHandAlias.psc @@ -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 diff --git a/source/scripts/_00e_fs_sleightofhand_hiddenslotsc.psc b/source/scripts/_00e_fs_sleightofhand_hiddenslotsc.psc deleted file mode 100644 index 239ee6d5..00000000 --- a/source/scripts/_00e_fs_sleightofhand_hiddenslotsc.psc +++ /dev/null @@ -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 \ No newline at end of file