[WIPz] Formulator.esm

Post » Tue Mar 29, 2011 7:59 pm

This is a modder's tool. Version 0.01 alpha (for developers only) is http://www.tesnexus.com/downloads/file.php?id=31755.

I finally got tired of writing variants of the same code every time I need to manage CloneForms. Let's get this done, once and for all! Version 1 will support all MagicItem types, i.e. Enchantments, Ingredients, Potions and Spells. Future versions may expand this list.

Here's how it works:

  • Call a Register function for the form type you want to work with. Either pass an existing form to duplicate, or start from a blank.
  • Use commands which mirror OBSE's to edit the form. All relevant commands will be supported.
  • Call a Finalize function which returns the fully edited form.

    Behind the scenes...
  • When you finalize, Formulator checks its database for a form which matches the one you have requested. It uses string keys which fully identify the form.
  • If a matching key is found, it verifies that the stored form is appropriate to the key. If everything checks out, you are returned a reference to the existing form.
    • If the stored form is invalid for some reason (e.g. a mod edited it directly instead of using Formulator's interface), a new key is generated for it. If no form already exists for that key (or one exists but is also invalid, recursively) the form is filed away where it belongs. If an identical form already exists, the invalid one is placed in a recycling bin.
  • If no matching key is found, Formulator checks the recycling bin. If there is an appropriate form there it is repurposed, filed, and given to you.
  • Only if all of the above has failed, Formulator creates a new CloneForm, stores it in the database, and returns it to you.


API documentation:
In this document a command which starts with "form..." applies to multiple formtypes. Replace the elipsis with the type you are working with. For instance, touse the form...Finalize command on an enchantment, call formEnchantmentFinalize.The universal commands work with all form types. Each quality lists its members,and each form type lists which qualities it possesses. Some form types alsopossess unique commands.For more information about the qualities and form types, see OBSE'sdocumentation: http://obse.silverlock.org/obse_command_doc.html----------------------- Universal Commands -----------------------(nothing) form...Register sourceForm:refBegin a Formulator work session. The form sent as an argument will be the basisfor the form you wish to create, and any other form... commands sent beforeform...Finalize will modify it. If you wish to start from a completely blankform, pass form... (e.g. formSpell) which is the editorID of Formulator'sworkspace form (and should never be used in any other context). Note thatsourceForm does not have to be the same form type you are registering: if adifferent type of form is passed, any traits shared between the two types willbe duplicated and any other traits possessed by the type you are registeringwill be set to zero or null as appropriate.(finalForm:ref) form...FinalizeEnd a Formulator work session, returning a reference to a form which matches allspecifications set since the most recent form...Register. Although Formulator'sdatabase keys fully describe a form and consistency checking is performed onevery lookup, the intention is that no form returned from Formulator is everedited directly. If you wish to make further changes, the proper method is touse form...Register again.--------------------- Quality - Edible ---------------------Members: Ingredient, Potion(nothing) form...SetIsFood isFood:bool------------------------ Quality - Inventory ------------------------Members: Ingredient, Potion(nothing) form...SetGoldValue goldValue:long(nothing) form...ModGoldValue difference:float(nothing) form...SetWeight weight:float(nothing) form...ModWeight difference:float(nothing) form...SetQuestItem isQuestItem:bool-------------------- Quality - Magic --------------------Members: Ingredient, Enchantment, Potion, Spell(nothing) form...SetAutoCalc isAutoCalc:bool(nothing) form...AddEffect effectCode:longEffect code as returned by OBSE's GetMagicEffectCode.(nothing) form...AddFullEffect effectCode:long magnitude:long area:long duration:long range:shortEffect code as returned by OBSE's GetMagicEffectCode.See OBSE's list of magic effect range codes.(nothing) form...CopyNthEffectFrom fromForm:ref whichEffect:short(nothing) form...CopyAllEffectsFrom fromForm:ref(nothing) form...RemoveNthEffect whichEffect:short(nothing) form...RemoveAllEffects(nothing) form...SetNthMagnitude magnitude:long whichEffect:short(nothing) form...ModNthMagnitude difference:float whichEffect:short(nothing) form...SetNthDuration duration:long whichEffect:short(nothing) form...ModNthDuration difference:float whichEffect:short(nothing) form...SetNthArea area:long whichEffect:short(nothing) form...ModNthArea difference:float whichEffect:short(nothing) form...SetNthRange range:short whichEffect:shortSee OBSE's list of magic effect range codes.(nothing) form...SetNthAV actorValue:long whichEffect:shortsee OBSE's list of numeric actor value codes.(nothing) form...SetNthScript script:ref whichEffect:short(nothing) form...SetNthScriptName name:string whichEffect:short(nothing) form...ModNthScriptName filter:string whichEffect:shortSee OBSE's ModName for filter format.(nothing) form...SetNthScriptSchool school:long whichEffect:shortSee OBSE's list of magic school codes.(nothing) form...SetNthScriptVisual effectCode:long whichEffect:shortEffect code as returned by OBSE's GetMagicEffectCode.(nothing) form...SetNthScriptHostile isHostile:bool whichEffect:short-------------------- Quality - Named --------------------Members: Ingredient, Potion, Spell(nothing) form...SetName name:string(nothing) form...ModName filter:stringSee OBSE's ModName for filter format.(nothing) form...AppendToName toAppend:string(nothing) form...CopyNameFrom source:ref------------------------- Quality - Scriptable -------------------------Members: Ingredient, Potion(nothing) form...SetScript script:ref(nothing) form...RemoveScript--------------------- Quality - Simple ---------------------Members: Ingredient, Potion(nothing) form...SetModel modelPath:string(nothing) form...ModModel filter:stringSee OBSE's ModName for filter format.(nothing) form...CopyModelFrom source:ref(nothing) form...SetIcon iconPath:string(nothing) form...ModIcon filter:stringSee OBSE's ModName for filter format.(nothing) form...CopyIconFrom source:ref----------------------- Type - Enchantment -----------------------Member of: Magic(nothing) formEnchantmentSetCost chargeCost:long(nothing) formEnchantmentModCost difference:float(nothing) formEnchantmentSetType enchantmentType:shortSee OBSE's list of enchantment type codes.---------------------- Type - Ingredient ----------------------Member of: Edible, Inventory, Magic, Named, Scriptable, SimpleThere are no commands unique to ingredients.------------------ Type - Potion ------------------Member of: Edible, Inventory, Magic, Named, Scriptable, SimpleThere are no commands unique to potions.----------------- Type - Spell -----------------Member of: Magic, Named(nothing) formSpellSetCost magickaCost:long(nothing) formSpellModCost difference:float(nothing) formSpellSetType spellType:shortSee OBSE's list of spell type codes.(nothing) formSpellSetHostile isHostile:bool(nothing) formSpellSetExplodesWithNoTarget explodes:bool!!! The following four commands are special. OBSE v0018 has not exposed thisdata in spell records, and while Formulator supports them, there are twolimitations. First, these properties will always be zero after formSpellRegisteris called, regardless of how they are set on the duplicated form; if you wishthem to be set, you must do so explicitly. Second, Formulator's database cannotcreate keys which reflect this data. It is up to the API user to avoid creatingtwo spells which are identical in every way except the state of these forproperties. Failure to do so may yield unintended results. !!!(nothing) formSpellSetAreaIgnoresLOS ignored:bool(nothing) formSpellSetDisallowAbsorbReflect disallowed:bool(nothing) formSpellSetImmuneToSilence immune:bool(nothing) formSpellSetScriptAlwaysApplies always:bool

User avatar
Laura-Jayne Lee
 
Posts: 3474
Joined: Sun Jul 02, 2006 4:35 pm

Post » Wed Mar 30, 2011 3:49 am

Ohhhh, sweet. I'm always eager to see how others make (script/database) resources. :)
User avatar
Alberto Aguilera
 
Posts: 3472
Joined: Wed Aug 29, 2007 12:42 am

Post » Tue Mar 29, 2011 9:57 pm

I have no idea what's this about! :D
User avatar
naomi
 
Posts: 3400
Joined: Tue Jul 11, 2006 2:58 pm

Post » Wed Mar 30, 2011 12:46 am

I'm (supposed to be) looking into something that would render this unnecessary :spotted owl:

False alarm.
User avatar
Taylor Tifany
 
Posts: 3555
Joined: Sun Jun 25, 2006 7:22 am

Post » Wed Mar 30, 2011 9:40 am

I'm (supposed to be) looking into something that could potentially render this unnecessary :spotted owl:
Not sure if this is a good thing or a bad thing..... :P
User avatar
N3T4
 
Posts: 3428
Joined: Wed Aug 08, 2007 8:36 pm

Post » Tue Mar 29, 2011 9:04 pm

I'm (supposed to be) looking into something that would render this unnecessary :spotted owl:

Some details and an ETA, perhaps?

I need this last week. (Frankly I needed this several years ago.) If you've got an OBSE plugin brewing or suchlike, let me know so I can get back to work on what I want to use this FOR, instead of working on this. ;)
User avatar
Cedric Pearson
 
Posts: 3487
Joined: Fri Sep 28, 2007 9:39 pm

Post » Wed Mar 30, 2011 10:20 am

Turns out shadeMe's project, while independently awesome and possessing great potential, does not do the same thing. Formulator continues.

And here's a switch: I'm working on documentation first! ;)

Edit: See actual documentation in first post.
User avatar
Vicki Gunn
 
Posts: 3397
Joined: Thu Nov 23, 2006 9:59 am

Post » Wed Mar 30, 2011 5:13 am

Turns out shadeMe's project, while independently awesome and possessing great potential, does not do the same thing.
Strangely, the more I think about the application of temp. cloneforms, the less practical it becomes. I must be wired incorrectly or something. Regardless, I digress. The formulator looks very nice indeed. Good luck with it!

You aren't going to get me to rewrite Vector's cloneform management code though :homestar:
User avatar
Dan Scott
 
Posts: 3373
Joined: Sun Nov 11, 2007 3:45 am

Post » Tue Mar 29, 2011 7:46 pm

Strangely, the more I think about the application of temp. cloneforms, the less practical it becomes.

Dunno, I can see applications. You'd have to use a quest script to manage consistency across game loads, but if for instance you've got a weapon which changes its speed based on , it'd probably be better to use temporary forms than keep a database for floating point variants because it's very likely you'll never hit the same one twice!

You aren't going to get me to rewrite Vector's cloneform management code though

Hehe, you say that now, but wait until you're doing something with it anyway. ;) There's no doubt I'm going to wind up revising TRAP and Birthsigns Expanded to be Formulator-dependent...

Edit: I've got to give some praise to the OBSE team right now. The string and array handling in recent versions is tremendously convenient, and Formulator has over 150 scripts now because I'm creating a user function for everything that's at least two lines long and might get used twice, and anything I might want to re-implement in the future. I've actually written very little code as yet, but I've got all these scripts with their function blocks defined so I can use them elsewhere without even having implemented them yet... it's like Hippo, Scruggs and Ian snuck in and replaced my CS with a functional development environment!
User avatar
mimi_lys
 
Posts: 3514
Joined: Mon Apr 09, 2007 11:17 am

Post » Wed Mar 30, 2011 4:23 am

Dunno, I can see applications. You'd have to use a quest script to manage consistency across game loads, but if for instance you've got a weapon which changes its speed based on , it'd probably be better to use temporary forms than keep a database for floating point variants because it's very likely you'll never hit the same one twice!
Yeah, I came across that one during my cogitations. Come to think of it, I was probably looking at from a narrow angle.

Hehe, you say that now, but wait until you're doing something with it anyway. ;) There's no doubt I'm going to wind up revising TRAP and Birthsigns Expanded to be Formulator-dependent...
Be that as it may, it's quite unlikely that I'll refactor Vector's code to use this. My manager does its job wonderfully as it is, creating, updating and recycling disease records as needed. What's more, it can keep track of clones b'ween clean saves.

... it's like Hippo, Scruggs and Ian snuck in and replaced my CS with a functional development environment!
http://www.gamesas.com/index.php?/topic/1082282-discussion-cs-script-editor-wish-list/page__view__findpost__p__15766768__fromsearch__1.
User avatar
Sheila Esmailka
 
Posts: 3404
Joined: Wed Aug 22, 2007 2:31 am

Post » Wed Mar 30, 2011 11:48 am

What's more, it can keep track of clones b'ween clean saves.

But will it share those clones with other mods? Eh? Eh? ;)

Heh, I already do nearly all of my scripting (i.e., except the compile) in Notepad++... which, BTW, I'm pretty sure is BSD-licensed or similar (I know of at least one commercial development environment which integrates it); perhaps they've got some code you can snatch!
User avatar
chinadoll
 
Posts: 3401
Joined: Tue Aug 22, 2006 5:09 am

Post » Wed Mar 30, 2011 7:04 am

But will it share those clones with other mods? Eh? Eh? ;)
Huh! No, but that's mostly only because the need isn't there [in Vector].

Heh, I already do nearly all of my scripting (i.e., except the compile) in Notepad++... which, BTW, I'm pretty sure is BSD-licensed or similar (I know of at least one commercial development environment which integrates it); perhaps they've got some code you can snatch!
My editor is written in managed code unlike Scintilla (NPP's editor component), which is written in native. Actually, I've been kicking myself a lot lately for not picking up one of the better established editor libraries when I started.
User avatar
Justin Bywater
 
Posts: 3264
Joined: Tue Sep 11, 2007 10:44 pm

Post » Wed Mar 30, 2011 4:15 am

All the guts are in place for the database. Nothing has been tested yet, but at least it all compiles. ;) Gonna take a break, then wrap the OBSE commands for formPotion and take this baby for a test-drive.

As mentioned earlier, OBSE doesn't recognize five out of six checkboxes for spells. This has caused some problems. For one thing, I can't let spells be recycled: you might get one that's immune to silence and not know it, etc. Additionally, while the database keys include properties reflecting all those values, they are always listed as zero. Until this can be remedied, it's up to the API user to avoid creating two spells that are identical in every way except one of those checkboxes. This is unlikely in the first place, and the worst thing that can happen is that a few FormIDs pile up in the recycling bin (without any effect in-game).

The upside is, I've got everything in place to allow cleanly rebuilding the database, plus internal version tracking. When the OBSE commands are available I can sort through the bin and file anything that shouldn't have been tossed. For that matter, I could completely change the key structure in a future version, or swap from flat to nested arrays, and the worst side-effect would be a short pause on loading an old save.
User avatar
IM NOT EASY
 
Posts: 3419
Joined: Mon Aug 13, 2007 10:48 pm

Post » Wed Mar 30, 2011 9:06 am

After some crazy debugging: potions are go! :celebration: Ingredients and enchantments will be a snap. Spells will take a little extra effort because I plan to support the checkboxes which OBSE doesn't yet, maintaining the caveat that the API user is responsible for preventing two spells being duplicates except for those checkboxes.

For fun, here's the database key for a three-effect potion:
ALCH(GOLD7)(WGHT0.3)("Shock Damage"(RANG0)(MAGN14))("Damage Health"(RANG0)(MAGN3)(DRTN8))("Fire Damage"(RANG0)(MAGN2)(DRTN24))(NAME"Kapow!")(ICON"Clutter\Potions\IconPotionPoison01.dds")(MODL"Clutter\Potions\PotionPoison.NIF")

User avatar
Kari Depp
 
Posts: 3427
Joined: Wed Aug 23, 2006 3:19 pm

Post » Wed Mar 30, 2011 2:19 am

Version 0.01 alpha (for developers only) is http://www.tesnexus.com/downloads/file.php?id=31755. Only a little bit of testing so far, but the API is complete for the supported form types.

Edit: Dang it, two people got to it before I caught my completely harmless but OCD-triggering key generation error. Please re-download because I'm not going to write the database-rebuilding version upgrade code just yet. ;)
User avatar
kyle pinchen
 
Posts: 3475
Joined: Thu May 17, 2007 9:01 pm

Post » Wed Mar 30, 2011 6:18 am

Bump in the hopes that anyone but me has done any testing at all? :)
User avatar
Quick Draw
 
Posts: 3423
Joined: Sun Sep 30, 2007 4:56 am

Post » Wed Mar 30, 2011 1:48 am

Not to disparage anything you've done so far, but have you considered making this an OBSE plugin instead? This would allow you to use the game's code to compare forms instead of scripting your own. It would mean a lot of rewriting, in C++, but it still might be faster overall.

If that sounds too extreme, perhaps you can request an obse script function for comparing objects of the same type.
User avatar
Tiffany Castillo
 
Posts: 3429
Joined: Mon Oct 22, 2007 7:09 am

Post » Wed Mar 30, 2011 11:12 am

If that sounds too extreme, perhaps you can request an obse script function for comparing objects of the same type.

There is actually a virtual function on all forms that does equality comparison, but I'm not sure you would want to tie a large amount of functionality to it. You'd be at the mercy of whatever they decided to leave in/out, possible bad float comparisons, etc.
User avatar
Angela
 
Posts: 3492
Joined: Mon Mar 05, 2007 8:33 am

Post » Tue Mar 29, 2011 10:34 pm

I don't anticipate a significant performance impact during general usage (i.e. anything but a forced database rebuild, which should only ever need to be done at game load). If it turns out I'm wrong, I might consider the OBSE plug-in approach; but otherwise, I'm doing entirely too many things at once to stack "learning C++" on top of them right now.

Since this is getting bumped again, I'll mention here as well that I'm about halfway done with alpha 2, which will include: various fixes and optimizations; no more weirdness with spell checkboxes, since OBSE reads them now; support for OBME-defined magic effects (while remaining non-OBME-dependent); plus ammo, armor, clothing and weapons.
User avatar
m Gardner
 
Posts: 3510
Joined: Sun Jun 03, 2007 8:08 pm

Post » Wed Mar 30, 2011 2:57 am

Recovering the thread from the dead...
Sorry if I disturbed someone :whistling:


Looks like I could use this in the near future. Not sure if I understood all of it, but basically all I have to do is this, right?
Call form...Register
some Call form...
let myItem := Call form...Finalize



Some Questions/Requests, though:
Are new MGefs (using http://www.tesnexus.com/downloads/file.php?id=31981) supported?
Is it possible to add support for Inventory Items (Armor/Clothing/Weapons)?


Enchantments/Spells are already supported, and from a first brief look I think I got all I need. :)
User avatar
Heather beauchamp
 
Posts: 3456
Joined: Mon Aug 13, 2007 6:05 pm


Return to IV - Oblivion