Shadohz Posted November 8, 2020 Share Posted November 8, 2020 I have a follower that I only want to wear clothing and wield a dagger. I need a script that can control her inventory so that she removes any gear or weapons that I do not fit my requirements.Short-term objective:As I see it there's two possible methods for monitoring her equipment: 1) is to register the script on a timer and alter the gear based on armortype or 2) verify what is equipped based on changes to the NPC container event. The problem I'm having is I keep screwing up how to detect the armortype. I could use GetArmorRating to see if anything is higher than 0 but that doesn't solve my weapon problem. I can't seem to figure out how to get the HasKeyword function working with IsEquipped.Wait, dangit. Argh. Okay I think I'm having one of those epiphany moments when I start figuring something out as I ask for help. Okay "GetEquippedItemType" will allow me to address the shield and weapon problem. That problem is out of the way but I still need to figure out how to spot the best clothing to force wear on the follower.Long-term objective:Using a solution from the first what I want to do is create a generic script for public-use that will allow players to set a Combat Style (existing or new) and the NPC will only wear gear pre-defined for that class that is attached by the Actor script. So for my follower who is an alchemist, she'd only wear clothing and wield a dagger. For a witchhunter a bow and clothing, so on and so forth. Link to comment Share on other sites More sharing options...
maxarturo Posted November 8, 2020 Share Posted November 8, 2020 Start from here, there are at least 3 different ways posted that can help you start building what you want. https://forums.nexusmods.com/index.php?/topic/9113018-alternative-for-this-script-function/ * Small advice: simplify things, a big complicated script does not always mean better, better is making the complicated thing as simple as possible. Have a happy modding. Link to comment Share on other sites More sharing options...
foamyesque Posted November 8, 2020 Share Posted November 8, 2020 I don't believe your end goal is doable without SKSE -- setting things on an ActorBase for the most part requires it, and, particularly, that is true of combat styles. However, there are some things you can do without that portion. It is possible to 'lock' equipment so that it is never unequipped; this does not require SKSE, but it will also stop it from ever changing, even if other, better items are added. Some additional scripting could be done to listen for gear being added to, or removed from, their inventory, upon which you might be able to update what is equipped or not. This would unfortunately mean that they would also always have their weapon(s) equipped, which could be a problem. Checking a full inventory without SKSE is possible but very much not recommended, because it is both prone to error, visible to the user if done on an NPC/the player, and very slow. Since you can't access it directly the only way I know of is to call a RemoveAll() to another container, catch all the OnItemRemoved() events (or, have a separate script on the destination container listening for OnItemAdded() events) to build a list, and then call RemoveAll() on that container to bring them all back. With actors this will result in them being naked while the thing runs, and in all cases (especially on e.g. the player) is vulnerable to stack dumping and thus giving inaccurate results, even if the Papyrus code is exactly correct. I would strongly recommend, given your desired goal, that you consider incorporating SKSE's tools here. Link to comment Share on other sites More sharing options...
Shadohz Posted November 9, 2020 Author Share Posted November 9, 2020 Thanks maxarturo but I had already exhausted those options. That was the part of the reason I reached out looking for alternative solutions. I needed it specifically designed this way to be flexible with identifying by armor type. I knew that I could SKSE and have this done in half a day but I didn't want to use that particular method. foamyesque "I would strongly recommend..." I know that tone. I use it all the time. Thanks for the feedback and potential pitfalls. Part of my follower script is below. I tried other methods. What I intended as a last ditch attempt was to create a formlist then cycle through each possible option until there's a hit. For example for "clothing" formlist a loop would cycle until hits on a valid item in the NPC inventory. Eventually it would hit something so it's not a problem if it's only clothing where all armor rating is 0 (the value of the items is not so much a factor so no comparison needed). In the case of light armor or heavy armor value and AR comes into play and that's where I obviously run into the problem. I would basically have to prioritize all armor based on AR in the formlist and allow the loop to work it's way through until it hits something. This of course isn't the optimal choice because there are just too many armor to account for and there surely had to be a better method micro-targeting inventory changes. I saw the SKSE options and knew right away it would fix all my problems in an instant (for the functionality I wanted). Ugggh. Bethesda why couldn't you just use old DnD rules and segregate armor use based on class like every other RPG that's been out since my childhood? I'm just going to pass on this and move onto my next project. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;This is a setting that dialogue will use for determining if the cloak should be used or not ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GlobalVariable Property Clara_CloakUse Auto Event OnInit() Clara_Followquest.setstage(5) RegisterForUpdateGameTime(0.0245) EndEvent ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Event: OnUpdateGameTime ;Purpose: This event will tick/trigger ~every 15 in-game minutes. ; It will go through a variety of checks for NPC dynamic behavior ; ;Parameters: None - UpdateGameTime is just a timer for the in-game clock ;Returns: Events don't return anything ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Event OnUpdateGameTime() ;Debug.MessageBox("Test") Clara_ClaraCompanionForUpdate = ClaraRef.GetActorRef() bool NativeFile01 = Game.GetFormFromFile (0x000D62, "Clara.esp") ; Detect if Clara is loaded If (NativeFile01 == false) ; If (Clara_ClaraCompanionForUpdate == None) Debug.MessageBox("We have a Problem. Unable to detect necessary file. Performing uninstall procedure.") ;We have to unregister for updates. This check was done to make sure the game still had a NPC to work with UnregisterForUpdateGameTime() Clara_FollowQuest.Stop() ElseIf ((Clara_Followquest.GetStage()== 10) || (Clara_Followquest.GetState() > 10)) ;Perform check for Clara on Accessories logic int hoodValue = ShouldWearHood(Clara_ClaraCompanionForUpdate) int cloakLogic = Clara_CloakUse.GetValue() as INT If (cloakLogic < 2) If (hoodValue == 0) ;No Hood Time Clara_ClaraCompanionForUpdate.RemoveItem(Claras_Backpack) Clara_ClaraCompanionForUpdate.RemoveItem(Claras_CapeHoodDown) Clara_ClaraCompanionForUpdate.RemoveItem(Claras_CapeHoodUp) ; Clara_ClaraCompanionForUpdate.RemoveItem(Claras_Gloves) ; Re-equip gear If (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_HelmetInv))) Clara_ClaraCompanionForUpdate.EquipItem(Claras_HelmetInv) ElseIf (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_Boots2))) Clara_ClaraCompanionForUpdate.EquipItem(Claras_Boots2) ElseIf (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_Gloves))) Clara_ClaraCompanionForUpdate.EquipItem(Claras_Gloves) ElseIf (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_Clothes2))) Clara_ClaraCompanionForUpdate.EquipItem(Claras_Clothes2) EndIf ElseIf (hoodValue == 1) ;Remove the hooded version Clara_ClaraCompanionForUpdate.RemoveItem(Claras_CapeHoodUp) ;Handle Backpack first If (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_Backpack))) ;We need to add the hood and equip ;------Clara_ClaraCompanionForUpdate.AddItem(Claras_Backpack) Clara_ClaraCompanionForUpdate.EquipItem(Claras_Backpack) EndIf ;Handle Cape Hood Down next ; If (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_CapeHoodDown))) ; Clara_ClaraCompanionForUpdate.AddItem(Claras_CapeHoodDown) ; Clara_ClaraCompanionForUpdate.EquipItem(Claras_CapeHoodDown) ; EndIf ;Handle Gloves If (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_Gloves))) ;---------Clara_ClaraCompanionForUpdate.AddItem(Claras_Gloves) Clara_ClaraCompanionForUpdate.EquipItem(Claras_Gloves) EndIf ;Handle Clothes If (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_Clothes2))) ;--------Clara_ClaraCompanionForUpdate.AddItem(Claras_Clothes2) Clara_ClaraCompanionForUpdate.EquipItem(Claras_Clothes2) EndIf ;Handle Boots If (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_Boots2))) ;---------Clara_ClaraCompanionForUpdate.AddItem(Claras_Boots2) Clara_ClaraCompanionForUpdate.EquipItem(Claras_Boots2) EndIf ;Handle Helmet If (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_HelmetInv))) Clara_ClaraCompanionForUpdate.EquipItem(Claras_HelmetInv) EndIf ElseIf (hoodValue == 2) ;Remove the non-hooded version Clara_ClaraCompanionForUpdate.RemoveItem(Claras_CapeHoodDown) Clara_ClaraCompanionForUpdate.RemoveItem(Claras_Backpack) Clara_ClaraCompanionForUpdate.RemoveItem(Claras_HelmetInv) ;Handle Backpack first ; If (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_Backpack))) ; ;We need to add the hood and equip ; ;---------Clara_ClaraCompanionForUpdate.AddItem(Claras_Backpack) ; Clara_ClaraCompanionForUpdate.EquipItem(Claras_Backpack) ; EndIf ;Check Cape Hood Up If (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_CapeHoodUp))) ;We need to add the hood and equip ;----------Clara_ClaraCompanionForUpdate.AddItem(Claras_CapeHoodUp) Clara_ClaraCompanionForUpdate.EquipItem(Claras_CapeHoodUp) EndIf ;Handle Gloves If (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_Gloves))) ;------------Clara_ClaraCompanionForUpdate.AddItem(Claras_Gloves) Clara_ClaraCompanionForUpdate.EquipItem(Claras_Gloves) EndIf ;Handle Clothes If (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_Clothes2))) ;---------Clara_ClaraCompanionForUpdate.AddItem(Claras_Clothes2) Clara_ClaraCompanionForUpdate.EquipItem(Claras_Clothes2) EndIf ;Handle Boots If (!(Clara_ClaraCompanionForUpdate.IsEquipped(Claras_Boots2))) ;-----------Clara_ClaraCompanionForUpdate.AddItem(Claras_Boots2) Clara_ClaraCompanionForUpdate.EquipItem(Claras_Boots2) EndIf Else ;We are just eating the -1 for the Do Nothing call EndIf Elseif (cloakLogic == 2) Clara_ClaraCompanionForUpdate.RemoveItem(Claras_Backpack) Clara_ClaraCompanionForUpdate.RemoveItem(Claras_CapeHoodDown) Clara_ClaraCompanionForUpdate.RemoveItem(Claras_CapeHoodUp) Clara_ClaraCompanionForUpdate.RemoveItem(Claras_Gloves) Clara_ClaraCompanionForUpdate.RemoveItem(Claras_Clothes2) Clara_ClaraCompanionForUpdate.RemoveItem(Claras_Boots2) Clara_ClaraCompanionForUpdate.RemoveItem(Claras_HelmetInv) EndIf Link to comment Share on other sites More sharing options...
Shadohz Posted November 9, 2020 Author Share Posted November 9, 2020 It wasn't a total loss. In brainstorming I at least figured out finally had to make her stop using shields and restrict her to daggers and bows. Link to comment Share on other sites More sharing options...
dylbill Posted November 9, 2020 Share Posted November 9, 2020 (edited) Hey, as maxaturo said, keep things simple. I think you can achieve what you want without skse by using keywords and the OnObjectEquipped event. I wouldn't use a constant running Update loop, as that can be bad for performance. Here's an example script: Scriptname MyFollowerScript extends Actor Keyword Property VendorItemClothing Auto Keyword Property ArmorCuirass Auto Keyword Property WeapTypeDagger Auto Armor Property DefaultClothes Auto ObjectReference Property FollowerStorageChest Auto Form CurrentDagger Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference) If akBaseObject as Armor && akBaseObject.HasKeyword(VendorItemClothing) == false Self.UnequipItem(akBaseObject) Self.RemoveItem(akBaseObject, 1, 1, FollowerStorageChest) ; remove item and put it in chest If akBaseObject.HasKeyword(ArmorCuirass) Self.EquipItem(DefaultClothes) Endif Elseif akBaseObject as Weapon If akBaseObject.HasKeyword(WeapTypeDagger) CurrentDagger = akBaseObject Else Self.UnequipItem(akBaseObject) Self.RemoveItem(akBaseObject, 1, 1, FollowerStorageChest) ; remove item and put it in chest Self.EquipItem(CurrentDagger) Endif Elseif akBaseObject as Spell Self.UnequipItem(akBaseObject) Endif EndEvent Edited November 9, 2020 by dylbill Link to comment Share on other sites More sharing options...
Recommended Posts