Jump to content

How to define a base object to be used in a script in a text file


Surilindur

Recommended Posts

I was wondering if it is possible to define a reference to a base object in an external file, an .ini file, for example, that only contains text. The idea would be to allow the user to define a base object to copy stats and mesh paths from to another object using some OBSE functions. The stats and other things will only be copied once when a savegame is loaded. I have tried something like the following:

 

Create an .ini file with the following line:

set ExampleQuest.BaseHelmet to X

Where I have tried to replace the X with both FormIDs (the ones like 00000ABC) and EditorIDs (like HelmetMadeOfCheese). The quest has a script that runs the batch script (the .ini) and it has something like the following in it:

ScriptName ExampleQuestScript

ref BaseHelmet

Begin GameMode

    If GetGameLoaded
        RunBatchScript "Data\Example.ini"
    EndIf

    Call ExampleFnChangeThings BaseHelmet

End

It now runs the function every time the quest is updated, as I am only testing it. Also, the GetGameLoaded section will be expanded a lot and moved to a different function. Perhaps combined with the stat and other changing function. But at least the idea can be seen... The function looks a bit like that:

ScriptName ExampleFnChangeThings

ref BaseHelmet

Begin Function { BaseHelmet }

    CopyMaleBipedPath BaseHelmet TargetHelmet

End

Where TargetHelmet is a base record or object... the ones created in the Construction Set. For some reason, I cannot get the 'external' base record definition to work. It works if I set the BaseHelmet in the quest script, for example. Like that:

    set BaseHelmet to ElvenHelmet

I would like to make it possible for the user to define the base objects to copy mesh paths and stats from to a new set of armour without editing the actual plugin. But is it impossible?

Link to comment
Share on other sites

For some reason I think so but the truth is I don't know.

I made a quick test but couldn't make it happen.

 

Could you update this thread when/if you'll figure things out? I might need to do something similar in the future.

Link to comment
Share on other sites

Yes! I managed to make it work last night. The solution was to use the StringToRef command of Pluggy (the OBSE plugin). Also, this thread here - and especially the first suggestion by QQuix - was helpful.

 

So both OBSE and Pluggy are required for this thing to work. The way I managed to set it up was about this:

 

Create an .ini file with the following in it:

; Print DebugPrint?
set QuestName.Debug to 1

; Define the item (using FormID)
set QuestName.FormIDString to sv_Construct "00036343"

The item must to be defined using its FormID. That one in the example is glass cuirass, but it does not really matter what the item or something else is. That depends only on what is done with it once it has been successfully turned into a ref. I think.

 

The .ini file can then be 'read' by a quest script, for example. The quest script (attached to a quest with EditorID of 'QuestName') could be something like that:

ScriptName QuestNameScript

float fQuestDelayTime      ; Quest update interval
short Debug                ; Print DebugPrint?

String_var FormIDString    ; FormID as OBSE string
Long FormIDPluggyThing     ; FormID as Pluggy string or something else 'pluggy'
Ref ItemRef                ; The 'ready-to-use' reference

Begin GameMode

    If ( GetGameLoaded )

        If FileExists "Data\NameOfTheINI.ini"
            RunBatchScript "Data\NameOfTheINI.ini"
        Else
            MessageBox "Could not find NameOfTheINI.ini in Data folder!"
        EndIf

        If Debug == 0
            SetDebugMode 0
        Else
            SetDebugMode 1
        EndIf

        ; Create the Pluggy string thingy
        set FormIDPluggyThing to CreateString -1 0 1 1

        ; Make the OBSE string a Pluggy string so that it can be use by StringToRef
        SetString FormIDPluggyThing $FormIDString

        ; Use StringToRef on the Pluggy string thingy to make it a Ref
        set ItemRef to StringToRef FormIDPluggyThing

        ; Print the name of the item in the ref to console for debug purposes
        DebugPrint, "QuestName: ItemRef set to %n", "ItemRef"

    EndIf

End

So that sets ItemRef to the item defined in the .ini file (with its FormID) once when the game is loaded. That is not exactly the way I used it, but it should be a basic example from which to get the idea and adapt it to whatever purpose you want to use it for.

 

Hopefully that helps a little. Now I can try to finish my little project and release it - if I can get the rest of it to work. :)

Link to comment
Share on other sites

Thanks for the update!

Aw, I wish we could avoid the pluggy...Some people have said that it's a bit buggy but maybe I remember wrongly... (or it was but got fixed?) Oh well, better than nothing!

 

I saw your mod released, well done! :)

By the way, sorry for the late reply.

Link to comment
Share on other sites

You are welcome. And thank you.

 

I hope it would not be too buggy. It has some nice features. But I think it might also be possible define the ref using an OBSE function, although it will likely work in a different way. The thread I linked in the solution contained some kind of an example it by QQuix. Perhaps it could be used instead of the Pluggy function? I have not yet tested it to see if it is more complicated or, who knows, easier to use.

Link to comment
Share on other sites

QQuix gave you a better function: GetFormFromMod.

It allow you to obtain a ref from a string, but it's better than StringToRef. Why?

 

Because StringToRef doesn't check the mod. What you define in the string depends on the load order.

If the player change load order, StringToRef doesn't return anymore the ref you want.

 

EXAMPLE: split the string "00036343", into "00" and "036343".

The first 2 chars "00" means the reference is in the first mod in the load order (usually "Oblivion.esm" or "Nehrim.esm").

The other chars "036343" define the reference.

So StringToRef with that string check the reference "036343" in "Oblivion.esm". But what if you want to check a reference in some other mod?

You need to find the position in the load order and replace the first 2 digits. If you add, remove or sort your mods you need to repeat this for every string ==> BAD SOLUTION.

 

 

 

GetFormFromMod instead check the given mod name, so it doesn't depends on the load order.

It will find the mod in the load order automatically when you call it.

 

 

It works like this (some examples):

Let refVar1 := GetFormFromMod "ModWhereTheRefIs.esp", "05A06B"
Let refVar2 := GetFormFromMod "AnotherModWhereTheRefIs.esm", $someFormInSomeStringVar
Let refVar3 := GetFormFromMod $someModNameInSomeStringVar, "A07C36"
Let refVar4 := GetFormFromMod $someModNameInSomeStringVar, $someFormInSomeStringVar

So you don't need Pluggy, you don't need to create a complex code to create and convert the string, you can forget about the load order and it works!

Edited by forli
Link to comment
Share on other sites

PhilippePetain, in my case, just the OBSE way for it should do the trick. I don't know for your mod but now that forli's here you'll have all the help you need to pick the best for you. :)

 

Thanks forli! This will probably be useful for me too. :)

Link to comment
Share on other sites

Thank you, forli. That seems simple. Perhaps I could use it instead of StringToRef. But then the user will need to enter the name of the mod in the .ini file, as well. And that also means more code. Unless I can make it cycle through pairs of mod name strings and FormID strings. Argh. Wasted five hours yesterday trying to refine the Pluggy method. :(

 

Still, I thank you. That method shoul be easier. :)

Link to comment
Share on other sites

Cycling many fields, and even multiple "entries" is simple:

  • Declare all variables you need in a quest (in "yourQuest" declare "ModName" and "FormIDString") and declare an array.
  • Initialize an array before reading the ini.
  • Create a new function (functionRead), which will do something like this:
    scn functionRead
    Ref someRefVar
    Begin Function {}
      Let someRefVar := GetFormFromMod $yourQuest.ModName, $yourQuest.FormIDString
      If ( someRefVar )      ;the reference exists
        ar_Append yourQuest.yourArray, someRefVar
      EndIf
    End
  • Create a quest (or take a quest you only use to run some global script) and enable "allow repeat stages".
  • In this quest (yourQuest) put a new stage. Assume it's stage 10 but you can use any stage you want.
  • In the stage result script put a single line: "Call functionRead"

Now in your ini, fill all fields (in this case: yourQuest.ModName and yourQuest.FormID), followed by "SetStage yourQuest 10"
The stage will fire and so the result script, which call the function which get the reference and store it somewhere.
You can put fill the fields multiple times, each time followed by "SetStage yourQuest 10". They will be processed one by one, in the given order.

Now you have all your references in the array.

Link to comment
Share on other sites

Oops. It would seem that I forgot to thank you for the last post, forli. :) That is incredibly simple and incredibly useful. Now I can also update my other mod to use that method. And make it possible to add new faction rank requirements for even mod-added factions (and perhaps also for player's stats and such). Maybe I should have asked about these things months ago... a lot of things might have been easier. Now I can also see if a certain tiny project of mine I had to abandon earlier is possible with this new method. And then I need to see if I can somehow make it work... hmm. Perhaps some day.

 

Thank you.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...