Jump to content
  • Announcements

    • AndalayBay

      Orphan Attachments   07/31/2018

      I have been doing some housekeeping lately and I've noticed that I had a lot of orphaned attachments. Attachments get orphaned when the PM or post is deleted without removing the attachment first. Deleting a PM or post does not delete the attachment and the file or image remain on the server. I'd like to ask all members to go through their attachments and delete any attachments you don't need anymore or those that have been orphaned. Where can I get a list of my attachments? Click on your display name in the upper right corner of the forums and pick "My Attachments" from the drop-down list. How can I tell an attachment is orphaned? If the PM has been deleted, you'll see a message like this in your attachment list: Unfortunately there is no message if the post has been deleted, so please check your old posts. We do purge old birthday threads every once in a while. Also some hosted projects have been shut down, so you may have orphaned attachments on one of those locations. Thanks!
saebel

OBSE Plugin / Array Processing C++ Expert Assistance Needed

Recommended Posts

Recreating the master each game load seems like a reasonable approach.

Found the defs in Commandtable:

#define COMMAND_ARGS	ParamInfo * paramInfo, void * arg1, TESObjectREFR * thisObj, UInt32 arg3, Script * scriptObj, ScriptEventList * eventList, double * result, UInt32 * opcodeOffsetPtr
#define PASS_COMMAND_ARGS paramInfo, arg1, thisObj, arg3, scriptObj, eventList, result, opcodeOffsetPtr

The problem is when doing this in your own code, all the objects have to be defined there as well for anything to work. ParamInfo TESObjectREFR, and all the rest. 

Share this post


Link to post
Share on other sites
2 hours ago, Schtearn said:

Recreating the master each game load seems like a reasonable approach.

Found the defs in Commandtable:


#define COMMAND_ARGS	ParamInfo * paramInfo, void * arg1, TESObjectREFR * thisObj, UInt32 arg3, Script * scriptObj, ScriptEventList * eventList, double * result, UInt32 * opcodeOffsetPtr
#define PASS_COMMAND_ARGS paramInfo, arg1, thisObj, arg3, scriptObj, eventList, result, opcodeOffsetPtr

The problem is when doing this in your own code, all the objects have to be defined there as well for anything to work. ParamInfo TESObjectREFR, and all the rest. 

Yup.  That's all part of the overall problem.  Getting the initial master array ID is not a problem.  It's when your start digging down into the nested arrays.

Also, I took a look at the plugin example that returned the array ID.  What it's doing is using a console print of the result, which is an Oblivion function.  And unfortunately, the function is not exposed.  It is basically the exact same technique I am using in my script to get the array ID in the first place.  But it doesn't actually return the array ID within the .dll in any usable form, because it's a "void" function.  So I can't even convert it into a string within the .dll.

Seriously - why the hell is this so f'ing hard.  Yeesh.

Share this post


Link to post
Share on other sites

Actually, I take it back.  I think you may be on to something with the "AssignCommandResult".  I messed around with it a little bit in a new command function that either retrieves or creates a new array for the master array.  I was able to extract the array ID from the "result" portion before the command ended.  So that's good news.  My concern though is whether it will work in a nested function, and will that mess something else up in the greater scheme of things?

Share this post


Link to post
Share on other sites
Posted (edited)

Yeah, I was just trying to illustrate the process and give you some ideas.

4 hours ago, saebel said:

One possible idea that may be the next best thing to ar_Erase is to create a "cloned array", but skip cloning the key/value pairs that are supposed to be dropped, and then replace the original array with the cloned array.  The original array will no longer be referenced, so OBSE will remove it when it handles it's garbage collection routines.

So for example, let's say I have StringMap1 with three key/value pairs ([modA:data],[modB:data],[modC:data]).

I then create a new OBSE StringMap1clone.

I create a loop that cycles through StringMap1.  It grabs the key of each value pair, and tests to see if the mod is in the active load order.  If it is, it copies the key/value pair over to the clone.  If it isn't, then it is skipped.

In this example, let's assume ModB is no longer active.  When the loop finishes, the clone would only have the ModA and ModC key/value pairs.  The original array would then be replaced by the clone.  Something like that should be able to work for the lower tier items when removing invalid/deleted refs, data groups, or specific data keys from the data sets.

I'm not sure about replacing the master array though.  That could be problematic.  But it occurs to me that the array ID of the master array is stored in a game setting global.  So potentially I could swap out that ID with the new one created by the clone (which should be capturable).  I might also be able to use that ID to tap into the EraseElements function.  I haven't tried that yet though.

That's what I do when I use arrays. I was going to suggest just wiping the array and forgot to say that in my post last night. I think that would be your best option and it shouldn't take long.

Edit: I didn't see Schtearn's reply, but I'd still be inclined to recreate the array on each game load.

Edited by AndalayBay

Share this post


Link to post
Share on other sites
Posted (edited)

Also, maybe take a look at ArrayVarMap::RemoveReference and ArrayVarMap:GetKeyType. Those could be invaluable to your plugin.

If this is running in the dll, it should iterate quicker than the oblivion script over your keys, even if it is stupidly analyzing all of them. It should return kDataType_Array once it hits on your subarray key, no?

RemoveReference can simply take the ref id and referring mod index as args (double and uint8, respectively.)
Wish I knew enough to write the code/pseudocode for you, but I'm retarded. Lol

Edited by darkrumbleking

Share this post


Link to post
Share on other sites
5 hours ago, darkrumbleking said:

Also, maybe take a look at ArrayVarMap::RemoveReference and ArrayVarMap:GetKeyType. Those could be invaluable to your plugin.

If this is running in the dll, it should iterate quicker than the oblivion script over your keys, even if it is stupidly analyzing all of them. It should return kDataType_Array once it hits on your subarray key, no?

RemoveReference can simply take the ref id and referring mod index as args (double and uint8, respectively.)
Wish I knew enough to write the code/pseudocode for you, but I'm retarded. Lol

Unfortunately, I haven't been able to figure out how to tap into the ArrayVarMap data.  It's not the same class/structure as the OBSEArrayInterface.  That same section has the code for removing elements from an array, assuming I know the array ID.

Share this post


Link to post
Share on other sites

I thought since you're writing C++ you have a lot more power. Call the functions anyways, if you specify that they're from another namespace, so long as they're public and not private it should work right?
If you didnt want to resolve the name every time maybe you'd write 
using ArrayVarMap::RemoveReference

Share this post


Link to post
Share on other sites
On 6/15/2018 at 7:05 PM, darkrumbleking said:

I thought since you're writing C++ you have a lot more power. Call the functions anyways, if you specify that they're from another namespace, so long as they're public and not private it should work right?
If you didnt want to resolve the name every time maybe you'd write 
using ArrayVarMap::RemoveReference

I have tried many different ways of calling the functions, and it has failed to compile every time.  I've tried resolving the errors by including various additional dependencies, and it just ended up causing more errors.

I really need someone who knows what they are doing to look at my code.  This is beyond my skill set.  And I also don't have time to try and wrestle with it anymore.

If no one can, it's fine, because the scripted solutions work.  It's just a shame that I can't overcome this one small limitation.

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

×