luthienanarion Posted April 2, 2014 Share Posted April 2, 2014 Well, five hours later I have a working NVSE plugin function. The function code: bool Cmd_GetLoadedType_Execute(COMMAND_ARGS) { *result = 0; int type = 0; BGSListForm* list = NULL; if(!ExtractArgsEx(EXTRACT_ARGS_EX, &list, &type)) return true; if(list) list->list.RemoveAll(); if(list && type) { // Some types are handled in specific DataHandler lists. if(type == 7) for(tList<TESClass>::Iterator iter = g_data->Get()->classList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), TESClass, TESForm), eListEnd); else if(type == 8) for(tList<TESFaction>::Iterator iter = g_data->Get()->factionList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), TESFaction, TESForm), eListEnd); else if(type == 9) for(tList<BGSHeadPart>::Iterator iter = g_data->Get()->headPartList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), BGSHeadPart, TESForm), eListEnd); else if(type == 10) for(tList<TESHair>::Iterator iter = g_data->Get()->hairList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), TESHair, TESForm), eListEnd); else if(type == 11) for(tList<TESEyes>::Iterator iter = g_data->Get()->eyeList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), TESEyes, TESForm), eListEnd); else if(type == 12) for(tList<TESRace>::Iterator iter = g_data->Get()->raceList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), TESRace, TESForm), eListEnd); else if(type == 13) for(tList<TESSound>::Iterator iter = g_data->Get()->soundList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), TESSound, TESForm), eListEnd); else if(type == 19) for(tList<EnchantmentItem>::Iterator iter = g_data->Get()->enchantmentItemList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), EnchantmentItem, TESForm), eListEnd); else if(type == 20) for(tList<SpellItem>::Iterator iter = g_data->Get()->spellItemList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), SpellItem, TESForm), eListEnd); else if(type == 49) for(tList<BGSNote>::Iterator iter = g_data->Get()->noteList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), BGSNote, TESForm), eListEnd); else if(type == 51) for(tList<BGSProjectile>::Iterator iter = g_data->Get()->projectileList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), BGSProjectile, TESForm), eListEnd); else if(type == 53) for(tList<TESWeather>::Iterator iter = g_data->Get()->weatherList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), TESWeather, TESForm), eListEnd); else if(type == 65) for(tList<TESWorldSpace>::Iterator iter = g_data->Get()->worldSpaceList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), TESWorldSpace, TESForm), eListEnd); else if(type == 71) for(tList<TESQuest>::Iterator iter = g_data->Get()->questList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), TESQuest, TESForm), eListEnd); else if(type == 81) for(tList<BGSExplosion>::Iterator iter = g_data->Get()->explosionList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), BGSExplosion, TESForm), eListEnd); else if(type == 83) for(tList<TESImageSpace>::Iterator iter = g_data->Get()->imageSpaceList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), TESImageSpace, TESForm), eListEnd); else if(type == 84) for(tList<TESImageSpaceModifier>::Iterator iter = g_data->Get()->imageSpaceModList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), TESImageSpaceModifier, TESForm), eListEnd); else if(type == 85) for(tList<BGSListForm>::Iterator iter = g_data->Get()->listFormList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), BGSListForm, TESForm), eListEnd); else if(type == 86) for(tList<BGSPerk>::Iterator iter = g_data->Get()->perkList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), BGSPerk, TESForm), eListEnd); else if(type == 91) for(tList<BGSCameraShot>::Iterator iter = g_data->Get()->cameraShotList.Begin(); !iter.End(); ++iter) list->AddAt(DYNAMIC_CAST(iter.Get(), BGSCameraShot, TESForm), eListEnd); else { // Other types are in the objects list. BoundObjectListHead* objects = g_data->Get()->boundObjectList; TESBoundObject* object = objects->first; while(object != objects->last) { object = object->next; if(object->GetTypeID() == type) list->AddAt(DYNAMIC_CAST(object, TESBoundObject, TESForm), eListEnd); } } } return true; } You pass a form list and a type code, and it fills the list with all items of that type from all loaded plugins. Here's the script I tested it with: short count short index ref varref string_var typefile begin gamemode if getgamerestarted set count to 0 while count < 200 getloadedtype testList count if listgetcount testList set index to 0 let typefile := "typedumps\" + $count + ".txt" con_scof $typefile while index < listgetcount testList set varref to listgetnthform testList index printc "[%i] %n" varref varref let index += 1 loop endif set count to count + 1 loop endif end ; gamemode Note that iterating through the form list and printing its contents is the longest part of the loop, and the GetLoadedType function is quite fast; type 32 (statics) took a minute to dump 9,686 forms, but there shouldn't be a reason to add all statics to a form list. Here are the resulting text files: http://www.mediafire.com/download/ki4taxaxxk1854i Expect to see this added to my NVSE plugin (link in sig). Link to comment Share on other sites More sharing options...
matortheeternal Posted April 2, 2014 Share Posted April 2, 2014 (edited) Yes but the reason I wondered if it could be done in game via script, was to automate the process of adding the items to containers to be accessed by the player regardless of what load order they were using. While it is certainly less time consuming to use TES/FNV Edit to do such a task, I would still have to create and fill all the containers by hand. It just seems impractical either way to do so in a timely manner. Hand editing would take just as long or longer to do than letting a script run in game to do it, which luthienanarion has already demonstrated takes a completely unreasonable amount of time to execute even with just the base game. Perhaps later on when I have the ability to make plugins for NVSE I could make something which could do so in a reasonable amount of time in game. Of course if someone would like to take the idea who already has the skill and know how to do, then I wouldn't complain about it and actually would be quite happy if they did. Seems like a lot of work though for a "cheat", and I doubt anyone else besides me would actually bother with it. I think this was more an exercise in "what if" :smile: A TES5Edit script can easily fill containers automatically. What are you smoking? One script - a minute - your entire load order - random (or selected) containers filled as per your specifications. Roughly: unit userscript; uses mteFunctions; var slObjects: TStringList; slContainers: TStringList; function Initialize: integer; begin slObjects := TStringList.Create; slContainers := TStringList.Create; end; function Process(e: IInterface): integer; var s: string; begin s := Signature(e); // only process armor, weap, ingr or misc records, because those are the only // records that can be added to a container safely if (s <> 'ARMO') and (s <> 'WEAP') and (s <> 'INGR') and (s <> 'MISC') then exit; slObjects.AddObject(Name(e), TObject(e)); end; function Finalize: integer; var containerfile, cont, items, item: IInterface; i, j: integer; begin containerfile := SelectFile('Select the file you want to use for the new/modified container...'); // terminate script if containerfile not assigned if not Assigned(containerfile) then exit; // build containers list cont := GroupBySignature(containerfile, 'CONT'); if not Assigned(cont) then begin Add(containerfile, cont, True); cont := GroupBySignature(containerfile, 'CONT'); Add(cont, 'CONT', True); end; for i := 0 to ElementCount(cont) - 1 do begin slContainers.AddObject(Name(ElementByIndex(cont, i)), TObject(ElementByIndex(cont, i))); end; // some kind of UI for selecting one or more containers to add the items to // OptionsForm; // loop through containers and add all selected items to them. for i := 0 to slContainers.Count - 1 do begin cont := ObjectToElement(slContainers.Objects[i]); for j := 0 to slObjects.Count - 1 do begin items := ElementByPath(cont, 'Items'); if not Assigned(items) then Add(cont, 'Items', True); item := ElementAssign(items, HighInteger, nil, false); seev(item, 'CNTO\Item', slObjects[j]); seev(item, 'CNTO\Count', '1'); end; end; end; end. This doesn't have an options form coded yet but I could easily code it when I have a bit more time on my hands. Also see http://www.nexusmods.com/skyrim/mods/49373/? Edited April 2, 2014 by matortheeternal Link to comment Share on other sites More sharing options...
RoyBatterian Posted April 2, 2014 Author Share Posted April 2, 2014 @luthienanarion: You, are awesome. BTW where to find nvse source? @matortheeternal: Thanks for posting the example, I am still very much a noob with scripting for both the games and fnv/tes edit. That's very useful for me to create chests for a mod of my own which supports my particular load order. The solution which I was seeking however was a generic approach that anyone, modder or not could use with no fuss by making the functionality into a mod that you can just dump in game. luthienanarion seems to have made a solution to that dilemma too. This community really is as cool as many say it is. Cheers Link to comment Share on other sites More sharing options...
matortheeternal Posted April 2, 2014 Share Posted April 2, 2014 @luthienanarion: You, are awesome. BTW where to find nvse source? @matortheeternal: Thanks for posting the example, I am still very much a noob with scripting for both the games and fnv/tes edit. That's very useful for me to create chests for a mod of my own which supports my particular load order. The solution which I was seeking however was a generic approach that anyone, modder or not could use with no fuss by making the functionality into a mod that you can just dump in game. luthienanarion seems to have made a solution to that dilemma too. This community really is as cool as many say it is. Cheers It is a generic approach that anyone can use. Proof of concept that TES5Edit scripts can be used by anyone:http://www.nexusmods.com/skyrim/mods/37981 Link to comment Share on other sites More sharing options...
luthienanarion Posted April 2, 2014 Share Posted April 2, 2014 NVSE's source code is included in the download, in the "src" folder. The included project files are for Visual C++ 2005 or 2008. Keep in mind that you'll have to install the DirectX SDK and add its libraries to the build path in order to compile it. I'll release my plugin's source when I finish up version 3; it could stand to be cleaned up a little. On the subject of *Edit scripts, I definitely could use some good source examples. I never learned PASCAL having jumped straight from BASIC to C++ when I was a kid. I'll check out your automation scripts, Mator. Link to comment Share on other sites More sharing options...
RoyBatterian Posted April 2, 2014 Author Share Posted April 2, 2014 @matortheeternal: I think you misunderstand my original idea, the last thing I would do when creating a mod is to FORCE people to use an FNVEdit script in order to set the mod up for themselves. The fact that many users can't even install a mod with NMM without having their hand held, it just makes my head spin with the amount of posts that I would get and complaints for doing such a thing. @luthienanarion: uff... old man moment yes I see the source in the folder now. I never bothered with BASIC, abstracts always annoyed me (and still do) so I went straight to assembly. I regret that now as everything is in higher level languages... Link to comment Share on other sites More sharing options...
matortheeternal Posted April 3, 2014 Share Posted April 3, 2014 @matortheeternal: I think you misunderstand my original idea, the last thing I would do when creating a mod is to FORCE people to use an FNVEdit script in order to set the mod up for themselves. The fact that many users can't even install a mod with NMM without having their hand held, it just makes my head spin with the amount of posts that I would get and complaints for doing such a thing. Go big or go home. Edit Scripts are extremely powerful and to say that the community isn't intelligent enough to use them so you should never make a mod with them is terrible. The number of people who are actually that incapable are few, they just stick out like sore thumbs so we think there's more of them than there really are. Besides, they can learn. Link to comment Share on other sites More sharing options...
luthienanarion Posted April 3, 2014 Share Posted April 3, 2014 Ugh, that reminds me of the time I learned Java in order to make a SkyProc patcher. I'm glad I passed that project on to someone else so that they can play tech-support. I've updated my NVSE plugin with the GetLoadedType function, so feel free to pull forms from other plugins like there's no tomorrow. Link to comment Share on other sites More sharing options...
RoyBatterian Posted April 3, 2014 Author Share Posted April 3, 2014 @matortheeternal: It's not that they are incapable, it's that they are LAZY, myself included. @luthienanarion: yay, downloading =] Link to comment Share on other sites More sharing options...
Recommended Posts