lasere200 Posted May 20, 2016 Share Posted May 20, 2016 (edited) Hi, I'm looking to create an Auto Loot mod based on my previous version for FNV. I learned the scripting in the FNV geck as I went along and now I just can't get started with Papyrus. The way it worked in FNV is a quest enabled to run at start that would add a non-playable armor to my char that would continously run a script. This was the quest Script: scn ALEnhSInit short DoOnce Begin GameMode if DoOnce != 1 set DoOnce to 1 Player.AddItem ALEnh 1 1 ShowMessage ALEnhMInit StopQuest ALEnhQInit endif endThis is my new "code" and it's not working. Any help would be greatly appreciated Scriptname AutoLootQuestScript extends Quest Armor Property AutoLootArmor Auto Quest Property AutoLootQuest Auto Message Property AutoLootMessage Auto Event OnQuestInit() Game.GetPlayer().AddItem(AutoLootArmor, 1, true) AutoLootMessage.Show() AutoLootQuest.Stop() endEventI get this error in the debug log: error: Unable to bind script AutoLootQuestScript to AutoLootQuest (01000F9A) because their base types do not match Edited May 21, 2016 by lasere200 Link to comment Share on other sites More sharing options...
ant2888 Posted May 20, 2016 Share Posted May 20, 2016 I'm not really sure what your mod is completely doing but why not just create a quest that is attached to the player at all times. You can then attach a script to the player via ReferenceAlias and then they have a script attached to them at all times. But either way I don't know exactly what the armor will do but you'd should probably do something like that anyway. I'm not really sure about your error but to create a quest that Shows a message, Adds and item then ends you'd do the following:Create a new quest via CK (just 'right-click', 'new' over any other quests). Give it whatever ID you want and make sure "Start Game Enabled" and "Run Once" are checked then click "OK". Reopen the script (you needed to do that to auto-generate some properties) and go to Quest Stages. Right-click on the left, create a new Index then right-click in the top Log-Entry portion (with the index you created highlighted) and click "new". You can leave both the index and log empty you just need it to place a fragment.Now for the scripting part. While highlighting both the index and entry you created go to the Papyrus Fragment portion and you can put the following: Utility.wait(5) ;Bethesda's wait onLoad trigger from the SM comes up a little to fast so we put a wait Game.getPlayer().addItem(AutoLootArmor, 1, true) AutoLootMessage.show() Stop() ;you can choose to stop the quest or not. It doesn't really matter Now for the important bit. After you've put the above in the Papyrus Fragment click Properties right below it. You're going to create TWO properties. One with Type: Armor and Name: AutoLootArmor and another with Type: Message and Name: AutoLootMessage . Leave there initial values default. Now click on each one individually and pick a value, a little drop down menu will appear, then select the AutoLootArmor you created. Same for the Message. Viola run it and it should happen as soon as the player spawns into the game. If you want it to start on some specific event or prerequisite you can just add that condition in the first tab on the lower left. Before you click okay and exit out be sure that "Run on Start" is checked in the Quest Stages tab. Link to comment Share on other sites More sharing options...
lasere200 Posted May 20, 2016 Author Share Posted May 20, 2016 (edited) Thank you very much for your response. I am still trying to get it to work. The armor would run a script made of bits like this: if ALEnhGKey set KeyR to GetFirstRef 46 1 0 Label 46 if IsFormValid KeyR if (Player.GetDistance KeyR < 201) && (KeyR.GetDisabled == 0) set OREvl to 0 set OCEvl to 0 set ORe to KeyR.GetOwner set OCe to KeyR.GetParentCellOwner if ORe && (ORe != Player.GetBaseObject) && (ORe != PlayerFaction) if GetType ORe == 8 set OREvl to (ListGetFormIndex ALEnhLEvilFact ORe >= 0) endif endif if OCe && (OCe != Player.GetBaseObject) && (OCe != PlayerFaction) if GetType OCe == 8 set OCEvl to (ListGetFormIndex ALEnhLEvilFact OCe >= 0) endif endif if ((ORe == 0) && (OCe == 0)) || (ORe == Player.GetBaseObject) || (ORe == PlayerFaction) || (OCe == Player.GetBaseObject) || (OCe == PlayerFaction) || ((Seen == 0) && (OREvl || OCEvl || ALEnhGSteal)) KeyR.Activate Player 1 endif endif set KeyR to Pencil01 set KeyR to GetNextRef Goto 46 endif endifIt would cycle through refs and loot based on certain conditions. Here's the link to it http://www.nexusmods.com/newvegas/mods/42631/? I am initially looking to create a mod that automatically loots and instantly scraps to your inventory the items looted. Junk only of course, for starters. I'd be interested in seeing the script for that magnifying class used to track components. Maybe I could use that but I don't know if that's possible. Ref walking was done with NVSE so again I'm at a loss on how to move from one object to another. I feel like the scavenging is too much for anything else but the first 1-2 runs. I wish to make it more efficiet. The NV version had more features but I'm just looking to get started. Edited May 21, 2016 by lasere200 Link to comment Share on other sites More sharing options...
ant2888 Posted May 21, 2016 Share Posted May 21, 2016 Yea I've been playing with it a bit. It's not really my mod but I'll give you the code I came up with. Scriptname ScavengeItems extends Actor Form property TYPETOFIND auto mandatory float property distanceToLook = 50.0 auto Form property ScavangerArmor auto const bool property isEquipped = false auto Event OnItemEquipped(Form akBaseObject, ObjectReference akReference) if ScavangerArmor == akBaseObject isEquipped = true checkForJunk() endif endEvent Function checkForJunk() while isEquipped ObjectReference[] junkNearme = FindAllReferencesWithKeyword(TYPETOFIND, distanceToLook) ;The line above is pretty much just what you need to figure out. debug.MessageBox(""+junkNearme) if junkNearme.length !=0 || junkNearme != none int i = 0 while i < junkNearme.length if junkNearme[i].GetBaseObject() == TYPETOFIND AddItem(junkNearMe, 1, false) junkNearme[i].delete() endif i = i +1 endWhile endif Utility.wait(1) endwhile endFunction Event OnItemUnEquipped(Form akBaseObject, ObjectReference akReference) if ScavangerArmor == akReference isEquipped = false endif endEvent I have this script running off the player (which is a BIG nono for compatibility issues) but you can figure out how to manipulate it through ReferenceAlias'. With more time looking at it I could probably get it but this should probably get you on your way. (It's a little messy since it was only meant to just debug a bit). Link to comment Share on other sites More sharing options...
lasere200 Posted May 21, 2016 Author Share Posted May 21, 2016 (edited) Thank you very much. Seems to me that the variants of FindClosestReference and FindAllReferences only return "none". Function checkForJunk() while isEquipped ObjectReference junkNearme = Game.FindClosestReferenceOfType (TYPETOFIND, 0.0, 0.0, 0.0, distanceToLook) if junkNearme != None debug.MessageBox(""+junkNearme) Utility.wait(1) endif endwhile endFunctionset TYPETOFIND to a MiscObject like OilCan01 and no messages around Oil Cans Maybe I'm not using them correctly. EDIT: I got it to work :D I was wrong about FindAllReferences because I did it with FindAllReferencesOfType and a form list. Looking into using the keyword variant now to keep lists small. Thank you so much. Edited May 21, 2016 by lasere200 Link to comment Share on other sites More sharing options...
ant2888 Posted May 22, 2016 Share Posted May 22, 2016 No problem :). Let me know if you ever release it! Link to comment Share on other sites More sharing options...
lasere200 Posted May 22, 2016 Author Share Posted May 22, 2016 (edited) I just can't understand this no matter how much I google: Function AutoLoot() while isEquipped ObjectReference[] junkNearme = FindAllReferencesWithKeyword(AutoLootKeyword, AutoLootRange) if junkNearme.length != 0 || junkNearme != none int i = 0 while i < junkNearme.length AddItem(junkNearMe[i], 1, false) junkNearMe[i].Delete() debug.MessageBox(""+i +junkNearme.length) Utility.wait(1) i = i + 1 endWhile endif endwhile endFunction FindAllReferencesWithKeyword continues to find the deleted references. So the objects are removed from the game world but as far as FindAllReferencesWithKeyword is concerned the references are still there. If junkNearme is in a container it will add the item to my inventory but it will not remove it from the container. I guess this is normal since i'm not using RemoveItem but what I don't understand is why is it doing this only once. I mean the object is still in the container and is still found by FindAllReferencesWithKeyword. Shouldn't it spam me with the object? Does junkNearMe.Delete() somehow work if the ref is in a container without removing the item? I just don't get it. I've tried junkNearMe.Activate(Game.GetPlayer()) instead of Add and Remove but it continuously adds the items to my Inventory. The references are still there after activation even though the item is not and get continuously activated. Edited May 22, 2016 by lasere200 Link to comment Share on other sites More sharing options...
ThoraldGM Posted May 22, 2016 Share Posted May 22, 2016 A couple of guesses here, could be spot on or hideously wrong: - The found reference after the first loop is the item in your inventory, not the one you deleted from the crate. If you're just getting a list of nearby ObjectRefs, how do you know for sure what container they are in? Or that the Widget in loop 2+ is the same instance from the first loop? - The crate popup shows the item listed because it's showing available forms in addition to references. Items "may or may not exist" when inside a crate. I think I read that in OnItemAdded page for a similar project (my Scavver NPC, who loots via find/acquire procedures). - Or... the crate popup list is some kind of swf menu that doesn't update (shows cached view) because the swf (if that's even what it is) doesn't know you "reached in" and plucked the item by script. I'm still in the process of exploring the "items in a crate may be forms or references" angle. Something about persistent items, but not sure what that term really means yet. You should list the FindAllReferencesWithKeyword results in a debug trace and check your log to see if the loop is finding/editing your inventory in addition to your surroundings. Edit: Also, the wiki examples prefix the array with Game.GetPlayer() : http://www.creationkit.com/fallout4/index.php?title=FindAllReferencesWithKeyword_-_ObjectReference Link to comment Share on other sites More sharing options...
ThoraldGM Posted May 22, 2016 Share Posted May 22, 2016 New reply so you don't get ninja'd, since we are both here. If you don't specify player, I suspect function wouldn't know where to look/radius from. Link to comment Share on other sites More sharing options...
lasere200 Posted May 22, 2016 Author Share Posted May 22, 2016 (edited) Thank you for your answer. I realized that the Item in the Container isn't added at all so at least that's consistent in the sense that my script does not affect containers for now, at all. Basically I've added my keyword to 3 items Oil can, Duct Tape and Coffee Pot. So these are the only items that get found. In Sanctuary, near the workshop and in the house where the workshop is are 2 Oil Cans, 1 Coffee Pot and 1 Duct Tape. There's another Duct Tape in the Toolbox by the weapons bench. I do not think it's finding items in my Inventory because of the "debug.MessageBox(""+junkNearme.length)". The length of the array generated by the FindAllReferencesWithKeyword is always the summed up value of how many references USED to be in range where you are standing. This is what's so crazy. If I use Activate instead of Add the item spam happens only in range of where the reference used to be. If I step away, the spamming of activate on the invisible/ghost reference stops. I hope that made sense. Something else strange to a beginner like me: If I use JunkNearme.Delete() after Add like in my code above, even though the reference still gets detected where the item used to be, it works. If I use it after Activate it doesn't and the Activate spams continues at the ref's last location filling my inventory up. So I guess the ObjectReferences persist somehow, but I don't get it. EDIT: Also it seems that FindAllReferencesWithKeyword does not detect refs in containers. Edited May 22, 2016 by lasere200 Link to comment Share on other sites More sharing options...
Recommended Posts