ArgusSCCT Posted March 21, 2014 Posted March 21, 2014 Does anyone know if NVSE has any commands to see if an NPC has an specific item? I need to make a script that detects if an NPC has any sort of power armor, if the NPC has an item then the script would proceed to add some other items to that NPC's inventory. EDIT: Anything works actually, I'm updating a mod called Powered Power Armor, and I need a way to add the PA mods to NPCs who use power armor, the old way PPA used to do it is overly complex and creates an unnecessary dependency on another plugin. The problem is that if I add this normally into factions then the dudes without power armor will get these PA mods. If I create a leveled item with PA and the PA mods themselves, maybe that could work but I also want it to be more random on the selection of which PA mods each random NPC may get.
zippy57 Posted March 21, 2014 Posted March 21, 2014 Run GetItemCount and check for a FormList containing every piece of power armor instead of an individual item. As an added bonus, this method can allow you to let users specify custom armors as power armor in case they've added some new content.
ArgusSCCT Posted March 21, 2014 Posted March 21, 2014 That will do, I also don't want a script to be constantly running and checking every NPC in a cell, the mod itself is already sort of heavy on the scripts.
zippy57 Posted March 21, 2014 Posted March 21, 2014 I don't think you can really prevent that since you have to check them to see if they've been checked before. The alternative would be to slap a script with an OnLoad block on every relevant NPC, but that would probably cause a lot of incompatibilities. I suggest not worrying about it since it's very unlikely you'll be able to make a script that takes longer than a frame to complete. I've only heard of that happening once, and that situation involved moving around ten+ NPCs and doing all sorts of calls and whatnot; if you're just doing inventory stuff you should be fine. Also, I use PPA so let me know when you've got an update out.
ArgusSCCT Posted March 22, 2014 Posted March 22, 2014 I don't think you can really prevent that since you have to check them to see if they've been checked before. The alternative would be to slap a script with an OnLoad block on every relevant NPC, but that would probably cause a lot of incompatibilities. I suggest not worrying about it since it's very unlikely you'll be able to make a script that takes longer than a frame to complete. I've only heard of that happening once, and that situation involved moving around ten+ NPCs and doing all sorts of calls and whatnot; if you're just doing inventory stuff you should be fine. Also, I use PPA so let me know when you've got an update out. It might take a while, its my second time scripting in Fallout, I've scripted with Java and other languages on more complex stuff but the scripts in the mod are really messed up, they're very messy and hard to understand and I've found they have all kinds of redundancies. For now, what I've done is axing Inventory Access.esm, which was the way it distributed PA and PA mods to NPCs. As far as I'm aware, the only faction to which the mod added PA was the Legion. I'm planning on making an array that contains most of the PA mods, a few leveled items for Legion PA and a script that delivers those PA mods randomly to factions that use PA like the Brotherhood and the Enclave(provided you've got a mod that spawns them in the game anyway). My only unknown is that I don't know if things can be added to a leveled item(GECK website says' they're leveled lists, so I assume they can be treated as such) through script which is what I want to do with the Legion, so that if a Legion NPC has armor added, then he'll have 1 or 2 PA mods added to his inventory. Hopefully this works like I'm thinking it does, I'm also not quite sure if there's a random function to pick out the elements in the array. I don't want to rely on Inventory Access to get this done, it added stuff in a clever way but in a more complex way that it should have been, plus PPA only referenced it in one instance.
zippy57 Posted March 22, 2014 Posted March 22, 2014 Actually, the "random function to pick out the elements in an array" is known as a leveled item/list. You can add to a leveled list (AddItemToLeveledList) but I'm not sure why you'd want to.
ArgusSCCT Posted March 22, 2014 Posted March 22, 2014 Actually, the "random function to pick out the elements in an array" is known as a leveled item/list. You can add to a leveled list (AddItemToLeveledList) but I'm not sure why you'd want to. Yeah but doesn't NVSE 4 beta3 put arrays in? What I want to do is to put PA's mods in there, have the script pick one out randomly and then add it to the factions that use PA. Unless there's a better way to do it, which I can't think off and I don't want to have to resort to checking the containers in a cell like PPA did before. Any reason not to use AddItemToLeveledList? I was planning to add it randomly with that.
DoctaSax Posted March 22, 2014 Author Posted March 22, 2014 I think what you're talking about is probably holding PPA items in arrays, and pick from them to add to levelled lists rather than adding them to the lists in the geck, in order to avoid bashing/merging of those lists? Edit: unless you plan to use maps or stringmaps, there's strictly speaking no need for arrays in that case, you could populate from formlists with a while loop or something. This has the added advantage that other mods could add their items to them with BuildRef + AddFormToFormList.
zippy57 Posted March 22, 2014 Posted March 22, 2014 Leveled lists are arrays where the item is randomly chosen. There's no need to code a method to do that from scratch. How to you plan to add it to "the factions"? The Legion alone have almost a hundred leveled lists NPCs can use. And this is the reason you shouldn't use AddItemToLeveledList: "Once altered using this function, it will persist in the save game data. It can not be undone."
ArgusSCCT Posted March 22, 2014 Posted March 22, 2014 I think what you're talking about is probably holding PPA items in arrays, and pick from them to add to levelled lists rather than adding them to the lists in the geck, in order to avoid bashing/merging of those lists? Edit: unless you plan to use maps or stringmaps, there's strictly speaking no need for arrays in that case, you could populate from formlists with a while loop or something. This has the added advantage that other mods could add their items to them with BuildRef + AddFormToFormList. Yes that's what I want to do. I'm pretty new at this language and there is some stuff about it that is kind of unusual. Leveled lists are arrays where the item is randomly chosen. There's no need to code a method to do that from scratch. How to you plan to add it to "the factions"? The Legion alone have almost a hundred leveled lists NPCs can use. And this is the reason you shouldn't use AddItemToLeveledList: "Once altered using this function, it will persist in the save game data. It can not be undone." Yeah, I know about that limitation, but then again who'd remove a mod like this mid game anyway? But yeah, I'd like to avoid it. I was planning on using the legions armor lists, mainly CondLegionArmorVeteran and CondLegionArmorPrime. I'm sure the Brotherhood has its own similar lists. My issue with the mods PPA adds is that if I just throw everything at one leveled list, then it'll spawn PPA mods in places it doesn't have to. SInce you're telling me it adds it randomly anyway, I think its probably best if I make some leveled items with the armors I want to add to the legion, I guess if an NPC gets said leveled item, then I'll be able to avoid those mods spawning to NPCs that don't use PA. However, there is one issue with this, conflicts, I'm trying to make the mod as conflict free as I can, since it was one of the issues that it has, I want it to work with mods like FOOK and PN, hopefully without having to make patches for those mods.
zippy57 Posted March 22, 2014 Posted March 22, 2014 You're most likely to run into one of two issue regarding the permanence: Either someone plays with the mod for a while and decides they don't want it or you need to change something to fix an issue. As for adding the items to the lists, that's simply not going to work. Leveled lists randomly select an item. If you add your mods to that list, then when the NPCs spawn with the mod in their inventories they'll be naked because it chose the mod instead of their armor. So this leaves you with two options: You either add to NPC inventories in the GECK or in-game. While you can add in the GECK, I strongly suggest against it for a number of reasons. First, many users don't merge/bash their plugins. Second, even if they do it's a "dumb" process; I've had NPCs spawn with eight sets of armor because it doesn't know any better and just smashes them all together. Some users go through and make a plugin just to fix the dumb stuff the bash does, but again most won't. Third, in general you should override base-game records only when absolutely necessary, as other mods are likely expecting them to be unchanged. Checking every NPC in-game is probably your best bet in terms of compatibility and the performance hit from it should be negligible, as not only would it not fall into the three problems above but would also work for NPCs added by mods.
ArgusSCCT Posted March 22, 2014 Posted March 22, 2014 Alright, if checking NPCs is the best way to go, then I will do that. However I'll need a little more explaining on how to do that. I sort of get the idea of the GetItemCount with the FormList, I think there's one called AllPowerArmor or NVAllPowerArmor and it has everything in there, you also mentioned that I'd be able to add in PA from other mods. That would work out great since, there's some custom PAs in PPA, plus a new one I'm going to add in.
zippy57 Posted March 22, 2014 Posted March 22, 2014 Well first you should make sure you're adding your new armors to the vanilla power armor lists using ListAddForm to allow compatibility with other mods that do things with power armor. Next make a form list with every one of your mods. Create a new Misc. Item and flag it Non-Playable, then place it in the list as well. Now make your leveled list(s). You can balance based on PC level here and if you want to you can make different lists for different factions. If you do, don't forget to make a generic list in case an NPC doesn't fit into any of them. If you want a chance for no mod to spawn, add that Non-Playable item you made. You'll need to scan every NPC in the player's current cell. Run GetFirstRef and add the result to a form list. Then make a loop and use GetNextRef to continue adding to the list. Precede the function calls with an if statement that makes sure there are refs left (usually just "if actor" after "set actor to GetNextRef") to check and put a nice delay on it as you shouldn't need to be running this every frame anyway. When you have your NPC(s) start with a GetItemCount check against your mod form list. If they have something on that list you don't need to do anything. Next check against the Power Armor form lists (if you want to get really fancy you could try to run IsPowerArmor against all the armor items in their inventories, but it's probably not worth the effort). If they don't have power armor, add the Non-Playable item so they fail the first check next time. If they're still here, AddItem one of your leveled lists depending on the faction.
ArgusSCCT Posted March 24, 2014 Posted March 24, 2014 EDIT: Nevermind, I found a way to do it, I just hope GetInFaction really does what it says. I was expectiong something with a name like IsInFaction or something like that.
Odessa Posted April 6, 2014 Posted April 6, 2014 This code: ref rActor Begin GameMode if ListGetFormIndex SexoutListBannedActor rActor != -1 || ListGetFormIndex SexoutSLActorDataIsReserved rActor != -1 ; Pass endif End Compiles fine, but if I use compiling override (_GameMode), I get "Warning: Invalid expression for parameter 2, expected form" ... "Could not parse this line". Why is this? * the real script I want to use override for has a reason for it (arrays), the above is just a simple example that gives the same error
DoctaSax Posted April 6, 2014 Author Posted April 6, 2014 Try adding a few more parentheses, maybe, or rephrase like -1 != ListGetFormIndex etc. CO can be finnicky like that.
mojodajojo Posted April 7, 2014 Posted April 7, 2014 I have two New Vegas installs and I attached a dixie cup to each. I attached a string to each cup and I'm not seeing any effects. Edit: This was a stupid waste of space that I shouldn't have posted here. My apologies.
movomo Posted May 19, 2015 Posted May 19, 2015 I have a kind of general scripting question... I'm trying to figure out the number of occupied slots of an arbitrary apparel item. The GetBipedSlotMask function returns those slots as a long integer flag number. This can be any combination of possible slots. 1002 if it's single slot or 110012 if it's multiple slots for example. So basically I'm trying to figure out how many digits in the given number are 1, not 0. If it's 1, that slot is occupied by the equipment, if 0 then not occupied. Specifically the slot numbers I'm interested in are as follows: 2 0000000000000010 4 0000000000000100 8 0000000000001000 16 0000000000010000 32 0000000000100000 64 0000000001000000 128 0000000010000000 256 0000000100000000 8192 0100000000000000 32768 1000000000000000 I wrote two versions of the same thing to do this, but I'm not sure which one is more efficient. The first one iterates over integers between 0 and 16, make a nth power of 2 and compare it to the original slot number with bitwise AND. The second one is, do a bitwise right-left shift, thusly dividing the previous slot number by 2 - truncate - multiply by 2. Then compare this to the untouched previous slot number. If they are not the same (odd number) that slot is occupied, if same (even number) not occupied. Let slot_cur := (GetBipedSlotMask cur_base) & 41470 if 0 == slot_cur continue endif Let num_slots := 0 ; * 1 * Let iter2 := 0 while 16 > (iter2 += 1) if eval ((2^iter2) & slot_cur) Let num_slots += 1 endif loop ; OR ; * 2 * while slot_cur if (slot_cur >> 1 << 1) == slot_cur Let num_slots += 1 endif Let slot_cur := slot_cur >> 1 loop I wrote the second one because I thought bitwise shift would be more efficient (becuase it's computer), is that correct? Would there be any way to do this more nicely?
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now