zede5 Posted January 9, 2020 Share Posted January 9, 2020 Hi, so I'm a new modder working on my first mod. When it is finished, the mod will basically link chests and categorize items put into linked chests.The player will then be able to put filters on each chest to set what type of items are in it. The problem I am running into has to do with optimization. The system I'm using in the mod is one where there is one "master chest" which holds all items in the system of linked chests until one of them is opened, at which time items corresponding to the filters put on the opened chest are transferred from the master chest to the open chest. However, the way I am sorting items is using an if/then tree that triggers using an OnItemAdded event attached to the master chest. What I am trying to do is create a filter so that all the items that have already been sorted will skip the OnItemAdded event on the master chest. At first I thought I could use the InventoryEventFilter function to do this, but upon reading exactly what the function did, I found that it actually does the exact opposite of what I need. I have a formlist of all the items I don't want to trigger the OnItemAdded event, whereas the InventoryEventFilter function needs a formlist of what items it does want to trigger the event. The only idea I have had so far is to somehow create a formlist of every item the player encounters, then remove all the items that get sorted, but I haven't been able to make it work , and I also feel like it is not a very good solution. So do any of y'all know of a function or something that will fit what I need? Link to comment Share on other sites More sharing options...
ReDragon2013 Posted January 9, 2020 Share Posted January 9, 2020 (edited) You didn't post any script or part of that. Maybe next sample code is useful. xyzMasterContainerScript Scriptname xyzMasterContainerScript extends ObjectReference ; https://forums.nexusmods.com/index.php?/topic/8301788-reversing-inventoryeventfilter-function/ ObjectReference PROPERTY container00 auto ; any other item ObjectReference PROPERTY container01 auto ; Weapons ObjectReference PROPERTY container02 auto ; Armor ObjectReference PROPERTY container03 auto ; Ingredients ObjectReference PROPERTY container04 auto ; Potions ObjectReference PROPERTY container05 auto ; Books ;ObjectReference[] PROPERTY myContainerList auto ; instead of single objectRef properties you could use an array to hold all of them ; myContainerList[0] = container00 ; myContainerList[1] = container01 ; .. ; myContainerList[?] = container?? ; -- EVENTs -- 3 EVENT OnInit() Debug.Trace(self+" OnInit() - has been reached..") ; info only ENDEVENT EVENT OnActivate(ObjectReference akActionRef) IF (akActionRef == Game.GetPlayer() as ObjectReference) ELSE RETURN ; - STOP - masterchest not player activated ENDIF ;--------------------- ; now player transfers some item to self "the masterchest" ; which are immediately transfered to categorized containers Utility.Wait(0.25) ; transfer menu has been closed by player, time to do other things ; like message choice to open a sub container menu ENDEVENT ;EVENT OnItemRemoved(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) ;ENDEVENT EVENT OnItemAdded(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) IF (akBaseItem as Weapon) self.RemoveItem(akBaseItem, aiItemCount, TRUE, container01) ; myContainerList[1] RETURN ; - STOP - ENDIF ;--------------------- IF (akBaseItem as Armor) self.RemoveItem(akBaseItem, aiItemCount, TRUE, container02) RETURN ; - STOP - ENDIF ;--------------------- IF (akBaseItem as Ingredient) self.RemoveItem(akBaseItem, aiItemCount, TRUE, container03) RETURN ; - STOP - ENDIF ;--------------------- IF (akBaseItem as Potion) self.RemoveItem(akBaseItem, aiItemCount, TRUE, container04) RETURN ; - STOP - ENDIF ;--------------------- IF (akBaseItem as Book) self.RemoveItem(akBaseItem, aiItemCount, TRUE, container05) RETURN ; - STOP - ENDIF ;--------------------- self.RemoveItem(akBaseItem, aiItemCount, TRUE, container00) ; myContainerList[0] ; some more item classes ;IF (akBaseItem as MiscObject) ;IF (akBaseItem as Scroll) ;IF (akBaseItem as Key) ; samples for keyword sorting ;IF akBaseItem.HasKeyword(VendorItemSoulGem) ; [KYWD:000937A3] Soulgems ;IF akBaseItem.HasKeyword(VendorItemOreIngot) ; [KYWD:000914EC] Ingots ;IF akBaseItem.HasKeyword(VendorItemRecipe) ; [KYWD:000F5CB0] Receipes ;IF akBaseItem.HasKeyword(VendorItemSpellTome) ; [KYWD:000937A5] SpellTomes ;IF akBaseItem.HasKeyword(WeapMaterialSilver) ; [KYWD:0010AA1A] Silver Weapons ;IF akBaseItem.HasKeyword(WeapMaterialFalmer) ; [KYWD:000C5C03] Falmer Weapons and Shields ENDEVENT no formlist required and its avoid using of AddInventoryEventFilter() Edited January 9, 2020 by ReDragon2013 Link to comment Share on other sites More sharing options...
zede5 Posted January 9, 2020 Author Share Posted January 9, 2020 First of all, thank you for the response! I had thought of that approach of storing items in presorted chests at first when I started the mod. The problem is that I have a super specific sorting system- almost 30 options, and I plan to add ones that the player can customize as well. Not all the categories use keywords to categorize items, and there are also cases where an item may be in two or more different categories, such as garlic being both in alchemy ingredients and cooking ingredients. I'll gladly post the script, I think you'll see the problem once I post it. Fair warning, its pretty long :b Scriptname CLC_MasterChest extends ReferenceAlias {Script to apply to master chest (chest that items are stored in by default)} EffectShader Property EnchShockFXShader Auto Actor Property PlayerREF Auto Message Property CLC_UnlinkMessage Auto Quest Property CLC_AliasStorage Auto FormList Property CLC_1HandedWeaponFormList Auto FormList Property CLC_2HandedWeaponFormList Auto FormList Property CLC_AlchIngredientFormList Auto FormList Property CLC_ArrowFormList Auto FormList Property CLC_BookFormList Auto FormList Property CLC_ClothingFormList Auto FormList Property CLC_ClutterFormList Auto FormList Property CLC_CookingIngredientsFormList Auto FormList Property CLC_FoodFormList Auto FormList Property CLC_GemFormList Auto FormList Property CLC_HealthPotionFormList Auto FormList Property CLC_HeavyArmorFormList Auto FormList Property CLC_IngotFormList Auto FormList Property CLC_JewelryFormList Auto FormList Property CLC_KeyFormList Auto FormList Property CLC_LightArmorFormList Auto FormList Property CLC_MagickaPotionFormList Auto FormList Property CLC_MiscPotionFormList Auto FormList Property CLC_MiscFormList Auto FormList Property CLC_OreFormList Auto FormList Property CLC_PoisonFormList Auto FormList Property CLC_ScrollFormList Auto FormList Property CLC_SoulGemFormList Auto FormList Property CLC_SpellTomeFormList Auto FormList Property CLC_StaffWeaponFormList Auto FormList Property CLC_StaminaPotionFormList Auto FormList Property CLC_BowFormList Auto FormList Property CLC_NoteFormList Auto FormList Property CLC_UnsortedFormList Auto FormList Property CLC_ValuablesFormList Auto FormList Property CLC_SortedFormList Auto FormList Property CLC_TrueUnsortedFormList Auto Keyword Property ArmorHeavy Auto Keyword Property ArmorLight Auto Keyword Property ArmorJewelry Auto Keyword Property ArmorClothing Auto Keyword Property VendorItemAnimalHide Auto Keyword Property VendorItemAnimalPart Auto Keyword Property VendorItemArmor Auto Keyword Property VendorItemArrow Auto Keyword Property VendorItemBook Auto Keyword Property VendorItemClothing Auto Keyword Property VendorItemClutter Auto Keyword Property VendorItemFood Auto Keyword Property VendorItemFoodRaw Auto Keyword Property VendorItemGem Auto Keyword Property VendorItemIngredient Auto Keyword Property VendorItemJewelry Auto Keyword Property VendorItemKey Auto Keyword Property VendorItemOreIngot Auto Keyword Property VendorItemPoison Auto Keyword Property VendorItemPotion Auto Keyword Property VendorItemScroll Auto Keyword Property VendorItemSoulGem Auto Keyword Property VendorItemSpellTome Auto Keyword Property VendorItemStaff Auto Keyword Property VendorItemWeapon Auto Keyword Property WeapTypeBattleaxe Auto Keyword Property WeapTypeBow Auto Keyword Property WeapTypeDagger Auto Keyword Property WeapTypeGreatsword Auto Keyword Property WeapTypeMace Auto Keyword Property WeapTypeStaff Auto Keyword Property WeapTypeSword Auto Keyword Property WeapTypeWarAxe Auto Keyword Property WeapTypeWarhammer Auto MagicEffect Property AlchFortifyHealRate Auto MagicEffect Property AlchFortifyHealth Auto MagicEffect Property AlchFortifyMagicka Auto MagicEffect Property AlchFortifyMagickaRate Auto MagicEffect Property AlchFortifyStamina Auto MagicEffect Property AlchFortifyStaminaRate Auto MagicEffect Property AlchRestoreHealth Auto MagicEffect Property AlchRestoreMagicka Auto MagicEffect Property AlchRestoreStamina Auto MagicEffect Property AlchRestoreHealthAll Auto MagicEffect Property AlchRestoreMagickaAll Auto MagicEffect Property AlchRestoreStaminaAll Auto Event OnActivate(ObjectReference akActionRef) Debug.Notification("Linked Chest") EndEvent Auto State Unlinked Event OnClose(ObjectReference akActionRef) EnchShockFXShader.Play(Self.GetRef(), -1) GoToState("Linked") EndEvent EndState State Linked Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) ;;Armor If akBaseItem.GetType() == 26 If akBaseItem.HasKeyword(ArmorHeavy) CLC_HeavyArmorFormList.AddForm(akBaseItem) ElseIf akBaseItem.HasKeyword(ArmorLight) CLC_LightArmorFormList.AddForm(akBaseItem) ElseIf akBaseItem.HasKeyword(ArmorClothing) CLC_ClothingFormList.AddForm(akBaseItem) ElseIf akBaseItem.HasKeyword(ArmorJewelry) CLC_JewelryFormList.AddForm(akBaseItem) EndIf ;;Weapons ElseIf (akBaseItem.GetType() == 41) || (akBaseItem.GetType() == 42) If akBaseItem.HasKeyword(WeapTypeBattleaxe) || akBaseItem.HasKeyword(WeapTypeGreatsword) || akBaseItem.HasKeyword(WeapTypeWarhammer) CLC_2HandedWeaponFormList.AddForm(akBaseItem) ElseIf akBaseItem.HasKeyword(WeapTypeBow) CLC_BowFormList.AddForm(akBaseItem) ElseIf akBaseItem.HasKeyword(WeapTypeDagger) || akBaseItem.HasKeyword(WeapTypeSword) || akBaseItem.HasKeyword(WeapTypeMace) || akBaseItem.HasKeyword(WeapTypeWarAxe) CLC_1HandedWeaponFormList.AddForm(akBaseItem) ElseIf akBaseItem.HasKeyword(WeapTypeStaff) || akBaseItem.HasKeyword(VendorItemStaff) CLC_StaffWeaponFormList.AddForm(akBaseItem) ElseIf akBaseItem.HasKeyword(VendorItemArrow) || (akBaseItem.GetType() == 42) CLC_ArrowFormList.AddForm(akBaseItem) EndIf ;;Ingredients ElseIf (akBaseItem.GetType() == 30) CLC_AlchIngredientFormList.AddForm(akBaseItem) If akBaseItem.HasKeyword(VendorItemFoodRaw) CLC_CookingIngredientsFormList.AddForm(akBaseItem) EndIf ;;Books ElseIf (akBaseItem.GetType() == 27) If akBaseItem.HasKeyword(VendorItemSpellTome) CLC_SpellTomeFormList.AddForm(akBaseItem) ElseIf (akBaseItem.GetWeight() == 0) CLC_NoteFormList.AddForm(akBaseItem) ElseIf akBaseItem.HasKeyword(VendorItemBook) CLC_BookFormList.AddForm(akBaseItem) EndIf ;;SoulGems ElseIf (akBaseItem.GetType() == 52) CLC_SoulGemFormList.AddForm(akBaseItem) ;;Scrolls ElseIf (akBaseItem.GetType() == 23) CLC_ScrollFormList.AddForm(akBaseItem) ;;MiscItems ElseIf (akBaseItem.GetType() == 32) If akBaseItem.HasKeyword(VendorItemSoulGem) CLC_SoulGemFormList.AddForm(akBaseItem) ElseIf akBaseItem.HasKeyword(VendorItemGem) CLC_GemFormList.AddForm(akBaseItem) ElseIf akBaseItem.HasKeyword(VendorItemOreIngot) If StringUtil.Find(akBaseItem.GetName(), "Ore") || StringUtil.Find(akBaseItem.GetName(), "Stalhrim") CLC_OreFormList.AddForm(akBaseItem) Else CLC_IngotFormList.AddForm(akBaseItem) EndIf ElseIf (akBaseItem.GetGoldValue() >= 250) CLC_ValuablesFormList.AddForm(akBaseItem) ElseIf akBaseItem.HasKeyword(VendorItemClutter) CLC_ClutterFormList.AddForm(akBaseItem) Else CLC_MiscFormList.AddForm(akBaseItem) EndIf ElseIf (akBaseItem.GetType() == 45) CLC_KeyFormList.AddForm(akBaseItem) ;;Potions and food ElseIf (akBaseItem.GetType() == 46) If (akBaseItem as Potion).IsFood() If akBaseItem.HasKeyword(VendorItemFoodRaw) CLC_CookingIngredientsFormList.AddForm(akBaseItem) EndIf If akBaseItem.HasKeyword(VendorItemFood) CLC_FoodFormList.AddForm(akBaseItem) EndIf ElseIf (akBaseItem as Potion).IsPoison() || akBaseItem.HasKeyword(VendorItemPoison) CLC_PoisonFormList.AddForm(akBaseItem) Else MagicEffect[] PotionEffects PotionEffects = (akBaseItem as Potion).GetMagicEffects() If PotionEffects.Find(AlchFortifyHealth) || PotionEffects.Find(AlchFortifyHealRate) || PotionEffects.Find(AlchRestoreHealth) || PotionEffects.Find(AlchRestoreHealthAll) CLC_HealthPotionFormList.AddForm(akBaseItem) EndIf If PotionEffects.Find(AlchFortifyStamina) || PotionEffects.Find(AlchFortifyStaminaRate) || PotionEffects.Find(AlchRestoreStamina) || PotionEffects.Find(AlchRestoreStaminaAll) CLC_StaminaPotionFormList.AddForm(akBaseItem) EndIf If PotionEffects.Find(AlchFortifyMagicka) || PotionEffects.Find(AlchFortifyMagickaRate) || PotionEffects.Find(AlchRestoreMagicka) || PotionEffects.Find(AlchRestoreMagickaAll) CLC_MagickaPotionFormList.AddForm(akBaseItem) EndIf Int p = 0 While p <= ((akBaseItem as Potion).GetNumEffects() - 1) If !(PotionEffects[p] == AlchFortifyHealth || PotionEffects[p] == (AlchFortifyHealRate) || PotionEffects[p] == (AlchRestoreHealth) || PotionEffects[p] == (AlchRestoreHealthAll) || PotionEffects[p] == (AlchFortifyStamina) || PotionEffects[p] == (AlchFortifyStaminaRate) || PotionEffects[p] == (AlchRestoreStamina) || PotionEffects[p] == (AlchRestoreStaminaAll) || PotionEffects[p] == (AlchFortifyMagicka) || PotionEffects[p] == (AlchFortifyMagickaRate) || PotionEffects[p] == (AlchRestoreMagicka) || PotionEffects[p] == (AlchRestoreMagickaAll)) CLC_MiscPotionFormList.AddForm(akBaseItem) EndIf p += 1 EndWhile EndIf Else CLC_UnsortedFormList.AddForm(akBaseItem) EndIf CLC_SortedFormList.AddForm(akBaseItem) CLC_TrueUnsortedFormList.RemoveAddedForm(akBaseItem) ;;Self.AddInventoryEventFilter(CLC_TrueUnsortedFormList) EndEvent EndState Link to comment Share on other sites More sharing options...
ReDragon2013 Posted January 10, 2020 Share Posted January 10, 2020 (edited) The script was not long, imho very poor structured. At this moment I do not know what are you really want to do here.Nevertheless a bit rewritten for better understanding.. compiled not yet CLC_MasterChest Scriptname CLC_MasterChest extends ReferenceAlias {Script to apply to master chest} ; chest that items are stored in by default ; https://forums.nexusmods.com/index.php?/topic/8301788-reversing-inventoryeventfilter-function/ Quest PROPERTY CLC_AliasStorage auto ; !? Message PROPERTY CLC_UnlinkMessage auto ; !? EffectShader PROPERTY EnchShockFXShader auto ; effect shader to play while sorting FormList PROPERTY CLC_PlayerItemList auto ; empty formlist has to be created by CK and filled here ; -- EVENTs -- 4 + "Done" EVENT OnInit() Debug.Trace(" OnInit() - has been reached.. " +self) ENDEVENT ;========================================== state Done ;========= EVENT OnActivate(ObjectReference akActionRef) ENDEVENT EVENT OnItemAdded(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) ENDEVENT EVENT OnItemRemoved(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) ENDEVENT ;======= endState ;EVENT OnClose(ObjectReference akActionRef) ;ENDEVENT EVENT OnActivate(ObjectReference akActionRef) IF (akActionRef == Game.GetPlayer() as ObjectReference) ELSE RETURN ; - STOP - not player activated ENDIF ;--------------------- Debug.Notification("Activation.. linked chest") Utility.Wait(0.25) gotoState("Done") ; ### STATE ### do not interrupt sorting myF_PlayFX(TRUE) float f = Utility.GetCurrentGameTime() ; for debugging *** myF_SortByList() f = Utility.GetCurrentGameTime() - f ; *** edited 13th January *** Debug.Trace("Sorting in " +f+ " sec") ; for debugging *** myF_PlayFX(False) gotoState("") ; ### STATE ### formlist sorting finished ENDEVENT EVENT OnItemAdded(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) IF (CLC_PlayerItemList.Find(akBaseItem) < 0) CLC_PlayerItemList.AddForm(akBaseItem) ENDIF ENDEVENT EVENT OnItemRemoved(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) int i = akSourceContainer.GetItemCount(akBaseItem) - aiItemCount IF (i <= 0) CLC_PlayerItemList.RemoveAddedForm(akBaseItem) ENDIF ENDEVENT ; -- FUNCTIONs -- 4 + 11 = 15 ;---------------------------- FUNCTION myF_PlayFX(Bool bOK) ;---------------------------- ; https://www.creationkit.com/index.php?title=Play_-_EffectShader ; wiki tells us: "The effects created by this function stack, so using it ; multiple times without stopping may cause frame rate issues." objectReference oRef = self.GetReference() IF ( oRef ) IF (bOK) EnchShockFXShader.Play(oRef, -1) ; play shader FX (no time out) ELSE EnchShockFXShader.Stop(oRef) ; stop shader FX ENDIF ENDIF ENDFUNCTION ;-------------------------------------- Bool FUNCTION myF_HasKW(Form fm, Int i) ; internal helper to shrink amount of properties ;-------------------------------------- RETURN fm.HasKeyword(Game.GetForm(i) as Keyword) ENDFUNCTION ;---------------------------- FUNCTION myF_RevertAllLists() ;---------------------------- ; ??? CLC_UnknownFormList.Revert() ; weapon CLC_BowFormList.Revert() CLC_StaffWeaponFormList.Revert() CLC_2HandedWeaponFormList.Revert() CLC_1HandedWeaponFormList.Revert() ; ammo CLC_ArrowFormList.Revert() ; key CLC_KeyFormList.Revert() ; Ingredient CLC_AlchIngredientFormList.Revert() CLC_CookingIngredientsFormList.Revert() ; Potion CLC_FoodFormList.Revert() CLC_PoisonFormList.Revert() ; Scroll CLC_ScrollFormList.Revert() ; Armor CLC_ShieldFormList.Revert() CLC_HeavyArmorFormList.Revert() CLC_LightArmorFormList.Revert() CLC_JewelryFormList.Revert() CLC_ClothingFormList.Revert() ; Book CLC_SpellTomeFormList.Revert() CLC_ReceipeFormList.Revert() CLC_SkillBookWizardFormList.Revert() CLC_NoteFormList.Revert() CLC_BookFormList.Revert() ; MiscObject CLC_SoulGemFormList.Revert() CLC_GemFormList.Revert() CLC_OreFormList.Revert() CLC_IngotFormList.Revert() CLC_ValuablesFormList.Revert() CLC_ClutterFormList.Revert() CLC_MiscFormList.Revert() ; Potion CLC_HealthPotionFormList.Revert() CLC_MagickaPotionFormList.Revert() CLC_StaminaPotionFormList.Revert() CLC_MiscPotionFormList.Revert() ENDFUNCTION ;------------------------ FUNCTION myF_SortByList() ;------------------------ myF_RevertAllLists() ; just an approach, can be handled much better int i = CLC_PlayerItemList.GetSize() WHILE (i) ; WHILE (i > 0) i = i - 1 form fm = CLC_PlayerItemList.GetAt(i) IF (fm as Weapon) myF_Add41(fm) ELSEIF (fm as Ammo) myF_Add42(fm) ELSEIF (fm as Key) myF_Add45(fm) ELSEIF (fm as Potion) myF_Add46(fm) ; potions and food ELSEIF (fm as Scroll) myF_Add23(fm) ELSEIF (fm as Armor) myF_Add26(fm) ELSEIF (fm as Book) myF_Add27(fm) ELSEIF (fm as Ingredient) myF_Add30(fm) ELSEIF (fm as MiscObject) myF_Add32(fm) ; miscItems and soulgems ELSE myF_Add00(fm) ; *** edited 13th January *** ENDIF ENDWHILE ENDFUNCTION FormList PROPERTY CLC_UnknownFormList auto Keyword Property VendorItemAnimalHide Auto ; VendorItemAnimalHide [KYWD:000914EA] Keyword Property VendorItemAnimalPart Auto ; VendorItemAnimalPart [KYWD:000914EB] Keyword Property VendorNoSale Auto ; VendorNoSale [KYWD:000FF9FB] ;-------------------------- FUNCTION myF_Add00(Form fm) ;-------------------------- ;IF fm.HasKeyword(VendorItemClothing) ; VendorItemClothing [KYWD:0008F95B] ; CLC_ClothingFormList.AddForm(fm) ;ELSE CLC_UnknownFormList.AddForm(fm) ;ENDIF ENDFUNCTION FormList PROPERTY CLC_BowFormList auto FormList PROPERTY CLC_StaffWeaponFormList auto FormList PROPERTY CLC_2HandedWeaponFormList auto FormList PROPERTY CLC_1HandedWeaponFormList auto ;-------------------------- FUNCTION myF_Add41(Form fm) ; (akBaseItem.GetType() == 41) ;-------------------------- IF myF_HasKW(fm, 0x0001E715) ; [KYWD:0001E715] fm.HasKeyword(WeapTypeBow) CLC_BowFormList.AddForm(fm) RETURN ; - STOP - bows and crossbows ENDIF ;--------------------- ; [KYWD:0001E716] fm.HasKeyword(WeapTypeStaff) IF myF_HasKW(fm, 0x0001E716) || myF_HasKW(fm, 000937A4) ; [KYWD:000937A4] fm.HasKeyword(VendorItemStaff) CLC_StaffWeaponFormList.AddForm(fm) RETURN ; - STOP - any kind of magic staff ENDIF ;--------------------- fm.HasKeyword(WeapTypeBattleaxe) || fm.HasKeyword(WeapTypeGreatsword) || fm.HasKeyword(WeapTypeWarhammer) IF myF_HasKW(oRef, 0x0006D932) || myF_HasKW(oRef, 0x0006D931) || myF_HasKW(oRef, 0x0006D930) CLC_2HandedWeaponFormList.AddForm(fm) RETURN ; - STOP - any kind of 2H-Weapon ENDIF ;--------------------- ;IF fm.HasKeyword(WeapTypeDagger) || fm.HasKeyword(WeapTypeSword) || fm.HasKeyword(WeapTypeMace) || fm.HasKeyword(WeapTypeWarAxe) CLC_1HandedWeaponFormList.AddForm(akBaseItem) ;ENDIF ENDFUNCTION FormList PROPERTY CLC_ArrowFormList auto ;-------------------------- FUNCTION myF_Add42(Form fm) ; (akBaseItem.GetType() == 42) ;-------------------------- ;IF fm.HasKeyword(VendorItemArrow) ; VendorItemArrow [KYWD:000917E7] CLC_ArrowFormList.AddForm(fm) ;ENDIF ENDFUNCTION FormList PROPERTY CLC_KeyFormList auto ;-------------------------- FUNCTION myF_Add45(Form fm) ; (akBaseItem.GetType() == 45) ;-------------------------- CLC_KeyFormList.AddForm(fm) ENDFUNCTION FormList PROPERTY CLC_AlchIngredientFormList auto FormList PROPERTY CLC_CookingIngredientsFormList auto ;-------------------------- FUNCTION myF_Add30(Form fm) ; (akBaseItem.GetType() == 30) ;-------------------------- IF myF_HasKW(fm, 0x000A0E56) ; [KYWD:000A0E56] fm.HasKeyword(VendorItemFoodRaw) CLC_CookingIngredientsFormList.AddForm(fm) RETURN ; - STOP - for cooking ENDIF ;--------------------- ;IF fm.HasKeyword(VendorItemIngredient) ; VendorItemIngredient [KYWD:0008CDEB] CLC_AlchIngredientFormList.AddForm(fm) ;ENDIF ENDFUNCTION FormList PROPERTY CLC_FoodFormList auto FormList PROPERTY CLC_PoisonFormList auto ;-------------------------- FUNCTION myF_Add46(Form fm) ; (akBaseItem.GetType() == 46) ;-------------------------- IF myF_HasKW(fm, 0x000A0E56) ; [KYWD:000A0E56] fm.HasKeyword(VendorItemFoodRaw) CLC_CookingIngredientsFormList.AddForm(fm) RETURN ; - STOP - ENDIF ;--------------------- IF myF_HasKW(fm, 0x0008CDEA) ; [KYWD:0008CDEA] fm.HasKeyword(VendorItemFood) CLC_FoodFormList.AddForm(fm) RETURN ; - STOP - ENDIF ;--------------------- IF fm.IsFood() ; SKSE required !!! CLC_FoodFormList.AddForm(fm) RETURN ; - STOP - ENDIF ;--------------------- IF myF_HasKW(fm, 0x0008CDED) ; [KYWD:0008CDED] fm.HasKeyword(VendorItemPoison) CLC_PoisonFormList.AddForm(fm) RETURN ; - STOP - ENDIF ;--------------------- IF fm.IsPoison() ; SKSE required !!! CLC_PoisonFormList.AddForm(fm) RETURN ; - STOP - ENDIF ;--------------------- myF_AddPotion2EffectList(fm) ; SKSE required !!! ENDFUNCTION FormList PROPERTY CLC_ScrollFormList auto ;-------------------------- FUNCTION myF_Add23(Form fm) ; (akBaseItem.GetType() == 23) ;-------------------------- CLC_ScrollFormList.AddForm(fm) ENDFUNCTION FormList PROPERTY CLC_ShieldFormList auto FormList PROPERTY CLC_HeavyArmorFormList auto FormList PROPERTY CLC_LightArmorFormList auto FormList PROPERTY CLC_JewelryFormList auto FormList PROPERTY CLC_ClothingFormList auto ;-------------------------- FUNCTION myF_Add26(Form fm) ; (akBaseItem.GetType() == 26) ;-------------------------- IF myF_HasKW(fm, 0x000965B2) ; [KYWD:000965B2] fm.HasKeyword(ArmorShield) CLC_ShieldFormList.AddForm(fm) RETURN ; - STOP - shields ENDIF ;--------------------- IF myF_HasKW(fm, 0x0006BBD2) ; [KYWD:0006BBD2] fm.HasKeyword(ArmorHeavy) CLC_HeavyArmorFormList.AddForm(fm) RETURN ; - STOP - heavy armor ENDIF ;--------------------- IF myF_HasKW(fm, 0x0006BBD3) ; [KYWD:0006BBD3] fm.HasKeyword(ArmorLight) CLC_LightArmorFormList.AddForm(fm) RETURN ; - STOP - light armor ENDIF ;--------------------- IF myF_HasKW(fm, 0x0006BBE9) ; [KYWD:0006BBE9] fm.HasKeyword(ArmorJewelry) CLC_JewelryFormList.AddForm(fm) RETURN ; - STOP - jewelry ENDIF ;--------------------- ;IF fm.HasKeyword(ArmorClothing) ; ArmorClothing [KYWD:0006BBE8] CLC_ClothingFormList.AddForm(fm) ;ENDIF ENDFUNCTION FormList PROPERTY CLC_SpellTomeFormList auto FormList PROPERTY CLC_ReceipeFormList auto FormList PROPERTY CLC_SkillBookWizardFormList auto FormList PROPERTY CLC_NoteFormList auto FormList PROPERTY CLC_BookFormList auto ;-------------------------- FUNCTION myF_Add27(Form fm) ; (akBaseItem.GetType() == 27) ;-------------------------- IF myF_HasKW(fm, 0x000937A5) ; [KYWD:000937A5] fm.HasKeyword(VendorItemSpellTome) CLC_SpellTomeFormList.AddForm(fm) RETURN ; - STOP - spelltome ENDIF ;--------------------- IF myF_HasKW(fm, 0x000F5CB0) ; [KYWD:000F5CB0] fm.HasKeyword(VendorItemRecipe) CLC_ReceipeFormList.AddForm(fm) RETURN ; - STOP - receipe ENDIF ;--------------------- IF myF_HasKW(fm, 0x000A0E62) ; [KYWD:000A0E62] fm.HasKeyword(GiftWizardSpecial) CLC_SkillBookWizardFormList.AddForm(fm) RETURN ; - STOP - wizard skillbook ENDIF ;--------------------- IF (fm.GetWeight() == 0.0) ; SKSE required !!! CLC_NoteFormList.AddForm(fm) RETURN ; - STOP - note ENDIF ;--------------------- ;IF fm.HasKeyword(VendorItemBook) ; VendorItemBook [KYWD:000937A2] CLC_BookFormList.AddForm(fm) ;ENDIF ENDFUNCTION FormList PROPERTY CLC_SoulGemFormList auto FormList PROPERTY CLC_GemFormList auto FormList PROPERTY CLC_OreFormList auto FormList PROPERTY CLC_IngotFormList auto FormList PROPERTY CLC_ValuablesFormList auto FormList PROPERTY CLC_ClutterFormList auto FormList PROPERTY CLC_MiscFormList auto ;-------------------------- FUNCTION myF_Add32(Form fm) ; (akBaseItem.GetType() == 32) || (akBaseItem.GetType() == 52) ;-------------------------- IF myF_HasKW(fm, 0x000937A3) ; [KYWD:000937A3] fm.HasKeyword(VendorItemSoulGem) CLC_SoulGemFormList.AddForm(fm) RETURN ; - STOP - soulgems 52 ENDIF ;--------------------- IF myF_HasKW(fm, 0x000914ED) ; [KYWD:000914ED] fm.HasKeyword(VendorItemGem) CLC_GemFormList.AddForm(fm) RETURN ; - STOP - gems ENDIF ;--------------------- IF myF_HasKW(fm, 0x000914EC) ; [KYWD:000914EC] fm.HasKeyword(VendorItemOreIngot) IF StringUtil.Find(fm.GetName(), "Ore") || StringUtil.Find(fm.GetName(), "Stahlrim") ; SKSE required !!! ; it works for the English language only !!! CLC_OreFormList.AddForm(fm) ELSE CLC_IngotFormList.AddForm(fm) ENDIF RETURN ; - STOP - ENDIF ;--------------------- IF (fm.GetGoldValue() >= 250) ; SKSE required !!! CLC_ValuablesFormList.AddForm(fm) RETURN ; - STOP - ENDIF ;--------------------- IF myF_HasKW(fm, 0x000914E9) ; [KYWD:000914E9] fm.HasKeyword(VendorItemClutter) CLC_ClutterFormList.AddForm(fm) RETURN ; - STOP - ENDIF ;--------------------- CLC_MiscFormList.AddForm(fm) ; any other miscItem ENDFUNCTION FormList PROPERTY CLC_HealthPotionFormList auto FormList PROPERTY CLC_MagickaPotionFormList auto FormList PROPERTY CLC_StaminaPotionFormList auto FormList PROPERTY CLC_MiscPotionFormList auto ;----------------------------------------- FUNCTION myF_AddPotion2EffectList(Form fm) ; internal helper ;----------------------------------------- magicEffect[] b = fm.GetMagicEffects() ; SKSE required !!! bool bOK IF b.Find(a[0]) || b.Find(a[1]) || b.Find(a[2]) || b.Find(a[3]) CLC_HealthPotionFormList.AddForm(fm) bOK = TRUE ENDIF IF b.Find(a[4]) || b.Find(a[5]) || b.Find(a[6]) || b.Find(a[7]) CLC_StaminaPotionFormList.AddForm(fm) bOK = TRUE ENDIF IF b.Find(a[8]) || b.Find(a[9]) || b.Find(a[10]) || b.Find(a[11]) CLC_MagickaPotionFormList.AddForm(fm) bOK = TRUE ENDIF IF ( bOK ) ELSE CLC_MiscPotionFormList.AddForm(fm) ENDIF ENDFUNCTION MagicEffect[] PROPERTY a auto ; fill by CK with next effects ;;; MagicEffect PROPERTY AlchFortifyHealth auto ; a[0] ;;; MagicEffect PROPERTY AlchFortifyHealRate auto ;;; MagicEffect PROPERTY AlchRestoreHealth auto ;;; MagicEffect PROPERTY AlchRestoreHealthAll auto ; a[3] ;;; MagicEffect PROPERTY AlchFortifyStamina auto ; a[4] ;;; MagicEffect PROPERTY AlchFortifyStaminaRate auto ;;; MagicEffect PROPERTY AlchRestoreStamina auto ;;; MagicEffect PROPERTY AlchRestoreStaminaAll auto ; a[7] ;;; MagicEffect PROPERTY AlchFortifyMagicka auto ; a[8] ;;; MagicEffect PROPERTY AlchFortifyMagickaRate auto ;;; MagicEffect PROPERTY AlchRestoreMagicka auto ;;; MagicEffect PROPERTY AlchRestoreMagickaAll auto ; a[11] Edited January 13, 2020 by ReDragon2013 Link to comment Share on other sites More sharing options...
SurfsideNaturals Posted January 11, 2020 Share Posted January 11, 2020 The script was not long, imho very poor structured. At this moment I do not know what are you really want to do here.Nevertheless a bit rewritten for better understanding.. compiled not yet Hey ReDragon, 1. I noticed you used Game.GetPlayer() in your script. That function is tied to the frame rates of the game so it can be quite slow. In most cases when it is used it is not noticeable. This function gets you the player and is very fast. Game.GetFormFromFile(0x00000014, "Skyrim.esm") As ObjectReference ; Player https://www.creationkit.com/index.php?title=Category:Non-delayed_Native_Function 2. I noticed you used Utility.Wait(0.25) in your script. Using that in a menu can create some very bizarre behaviors. It is best to be avoided if you can. It will not fire in menu so any functions below it will not start until the chest is closed and the player is no longer in menu. It is used for this purpose if you must have your script start after the menu has closed. That may be why you are using it here. There is a trick for working with chests and moving things around. You can BlockActivation() on the chest and then after the scripts have run you use this ( Activate(Game.GetPlayer(), true) ) to active the chest so all of the moved items show up in the menu or don't. Your script is amazing and I hope these suggestions are helpful. It would take me a week to write a script like that. Link to comment Share on other sites More sharing options...
maxarturo Posted January 11, 2020 Share Posted January 11, 2020 (edited) To anyone that might be interested... 1) If the "Game.GetPlayer()" will be call only once then there isn't too much of a problem. If its is going to be call multiple times in the same script (slowing down the script execution), then you can call it once and then store it. Example: Event OnActivate(ObjectReference akActionRef) If akActionRef == Game.GetPlayer() Actor AC = akActionRef as Actor AC.DamageActorValue(...) AC.AddItem(...) ... EndIf EndEvent 2) There is an other workaround to this: Self.setDestroyed(True) And when it has finish doing its thing Self.setDestroyed(False) Objects that have the flag "setDestroyed(True)" cannot be interacted by the Player or anyone else, they appear normal ingame and they will not show the "E Activate" text when near it, setting it to "False" will revert the object to its normal state. Edited January 11, 2020 by maxarturo Link to comment Share on other sites More sharing options...
foamyesque Posted January 13, 2020 Share Posted January 13, 2020 To anyone that might be interested... 1) If the "Game.GetPlayer()" will be call only once then there isn't too much of a problem.If its is going to be call multiple times in the same script (slowing down the script execution), then you can call it once and then store it. Example:Event OnActivate(ObjectReference akActionRef) If akActionRef == Game.GetPlayer() Actor AC = akActionRef as Actor AC.DamageActorValue(...) AC.AddItem(...) ...EndIfEndEvent 2) There is an other workaround to this:Self.setDestroyed(True)And when it has finish doing its thingSelf.setDestroyed(False) Objects that have the flag "setDestroyed(True)" cannot be interacted by the Player or anyone else, they appear normal ingame and they will not show the "E Activate" text when near it, setting it to "False" will revert the object to its normal state. That point 2 is interesting! I've been using perks to do that. Link to comment Share on other sites More sharing options...
ReDragon2013 Posted January 13, 2020 Share Posted January 13, 2020 (edited) Thank you for interrest and posting background infos.. "SurfsideNaturals" 1. Game.GetPlayer() vs. Game.GetForm()Your approach (as follow) is not really thread safe. I had some strange CTD by using Game.GetForm(0x14). ; yours IF (akActionRef == Game.GetFormFromFile(0x00000014, "Skyrim.esm") As ObjectReference) ELSE RETURN ; - STOP - ENDIF ;; same as IF (akActionRef == Game.GetForm(0x14) as ObjectReference) ELSE RETURN ; - STOP - ENDIF ;; same as IF (Game.GetForm(0x14) == akActionRef as Form) ELSE RETURN ; - STOP - ENDIF ;; same as IF (akActionRef.GetFormID() == 0x14) ELSE RETURN ; - STOP - ENDIF My first choice is next code, because it is absolutely thread safe. IF (akActionRef == Game.GetGetPlayer() as ObjectReference) ELSE RETURN ; - STOP - ENDIF or this IF (Game.GetGetPlayer() == akActionRef as Actor) ELSE RETURN ; - STOP - ENDIF 2. OnClose()The issue with OnClose() event is that it triggers only when the activated object finishes its closing animation.But in fact most of the Skyrim containers do not have such animation so OnClose() won't never initiate here.That is the reason why I am using OnActivate() event with Utility.Wait(0.25) in the script. It never fails.---maxarturo, if next is really working.. thank you for sharing this information :smile:2) "There is an other workaround to this:" EVENT OnActivate(ObjectReference akActionRef) self.SetDestroyed(TRUE) Utility.Wait(0.25) ; and when it has finish doing its thing self.SetDestroyed(False) ENDEVENT Edited January 13, 2020 by ReDragon2013 Link to comment Share on other sites More sharing options...
SurfsideNaturals Posted January 13, 2020 Share Posted January 13, 2020 (edited) Thank you for interrest and posting background infos.. "SurfsideNaturals" Hey ReDragon, Game.GetForm() is known to be very buggy. We have never had any issues with Game.GetFormFromFile() and we run large array functions with it. Never any CTDs. https://www.creationkit.com/index.php?title=GetFormFromFile_-_Game If you are using it to get NPCs you need to make sure they are flagged persistent or loaded or the function will fail. basically any object ref that you would call a function on needs to be persistent or loaded. Give it a try in some of your scripts and get back to us. 2. If you use utility.wait in a menu it will cause some events to fire more than once. If your functions must run on close you have to use it. We know of no other way. Edited January 13, 2020 by SurfsideNaturals Link to comment Share on other sites More sharing options...
maxarturo Posted January 13, 2020 Share Posted January 13, 2020 (edited) foamyesque & ReDragon2013 And of course anyone else interested in this. I've been using "SetDestroyed()" to the death in my project, it's very reliable. I have found only one bug with it, or more like a "malfunction". Explanation of the issue: - If the "Activator A" calls on itself Event OnCellAttach() Self.SetDestroyed(True) ..... EndEvent - And then "Activator B" calls on "Activator A" Event SomeEvent() Activator A.SetDestryed(False) .... EndEvent It will not work, the "SetDestroyed(True / False)" must be called by the same Object that called the "OnCellAttach()" event on itself. Other than that, i haven't found any other issues with it. Edited January 13, 2020 by maxarturo Link to comment Share on other sites More sharing options...
Recommended Posts