[RELz] Oblivion Magic Extender v1.beta3

Post » Sat May 28, 2011 1:33 pm

For something like this, but with less one-dimensional mechanics, you should check out Fizzle -- follow the first link in my sig.

DW: Heh, that'll change a few of my default settings. I was only keeping the vanilla effectiveness mechanic in my game at all (based on fatigue rather than armor) because Fizzle doesn't affect NPCs (could, but the AI would have no idea what to do). Guess I can axe that. :)

I know about Fizzle, but the reason I think this would be useful is because Silence is so powerful. It shuts down a mage completely. It would be nice to have an intermediate effect that impedes rather than disables spellcasting.

Sounds like it should be an easy fix anyway. However the AI should then treat 100% spellcasting failure as being silenced, which it probably doesn't.
User avatar
john page
 
Posts: 3401
Joined: Thu May 31, 2007 10:52 pm

Post » Sun May 29, 2011 3:02 am

One mod that was a major inspiration to me was grmblf's http://www.tesnexus.com/downloads/file.php?id=27746. In addition to the titular spell charging mechanic, it features a scaling system of side effects (damage to attributes, mostly) to limit how much magicka a caster could spend on a spell. I've not played with Fizzle - no offense, tejon, I just wasn't aware of it - but it sounds like the principle of penalties rather than limits is the same, just with different penalties.
User avatar
David John Hunter
 
Posts: 3376
Joined: Sun May 13, 2007 8:24 am

Post » Sat May 28, 2011 2:46 pm

Finally thought of something I could request - A HasMagicEffect2 command that works with 0-duration effects like CUDI effect items (ideally, returns true if the calling ref had the magic effect active in the last frame).
User avatar
Kelly James
 
Posts: 3266
Joined: Wed Oct 04, 2006 7:33 pm

Post » Sat May 28, 2011 5:13 pm

A HasMagicEffect2 command that works with 0-duration effects like CUDI effect items

I'll see what I can do. It's not a trivial request, I'm afraid :(
User avatar
biiibi
 
Posts: 3384
Joined: Sun Apr 08, 2007 4:39 am

Post » Sat May 28, 2011 8:49 pm

I'll see what I can do. It's not a trivial request, I'm afraid :(
No worries - Off it to the back burner then.
User avatar
Jade Muggeridge
 
Posts: 3439
Joined: Mon Nov 20, 2006 6:51 pm

Post » Sun May 29, 2011 1:30 am

My understanding of magic casting time is that it is constant and set for each school of magic.

Is that correct ? I don't ever recall noticing a difference in casting time b'ween schools.

Target and touch spells take 1.5 seconds to cast. Self spells take 2.0 seconds. Readying a weapon (including fists) and holding down the block key shaves off 0.5 seconds for some reason. School has no effect on casting time.

Fixing it to 1.5 seconds with no exceptions would be a nice starting point. :P
User avatar
Charles Weber
 
Posts: 3447
Joined: Wed Aug 08, 2007 5:14 pm

Post » Sun May 29, 2011 2:19 am

Target and touch spells take 1.5 seconds to cast. Self spells take 2.0 seconds.

How did you arrive at those numbers?
User avatar
Del Arte
 
Posts: 3543
Joined: Tue Aug 01, 2006 8:40 pm

Post » Sat May 28, 2011 11:48 pm

I think he look at the Animations. At this point where the Hit Key is, the Spell is casted.
User avatar
Lou
 
Posts: 3518
Joined: Wed Aug 23, 2006 6:56 pm

Post » Sat May 28, 2011 7:05 pm

OBME alters the format of the *.esp and *.esm files by adding new chunk types to the EffectSetting record (MGEF) and various magic item records (SPEL,ENCH,INGR,ALCH,SGST). At the moment, this means that mod files *with new OBME features* are not compatible with TES4Edit.

Please let me know exactly what changes you made and I will adjust TES4Edit to support them.

Currently, TES4Edit expects the following format:
  wbRecord(MGEF, 'Magic Effect', [    wbEDID,    wbFULL,    wbDESC,    wbICON,    wbMODL,    wbStruct(DATA, 'Data', [      wbInteger('Flags', itU32, wbFlags([        {0x00000001} 'Hostile',        {0x00000002} 'Recover',        {0x00000004} 'Detrimental',        {0x00000008} 'Magnitude %',        {0x00000010} 'Self',        {0x00000020} 'Touch',        {0x00000040} 'Target',        {0x00000080} 'No duration',        {0x00000100} 'No magnitude',        {0x00000200} 'No area',        {0x00000400} 'FX persist',        {0x00000800} 'Spellmaking',        {0x00001000} 'Enchanting',        {0x00002000} 'No Ingredient',        {0x00004000} '',        {0x00008000} '',        {0x00010000} 'Use weapon',        {0x00020000} 'Use armor',        {0x00040000} 'Use creature',        {0x00080000} 'Use skill',        {0x00100000} 'Use attribute',        {0x00200000} '',        {0x00400000} '',        {0x00800000} '',        {0x01000000} 'Use actor value',        {0x02000000} 'Spray projectile type (or Fog if Bolt is specified as well)',        {0x04000000} 'Bolt projectile type',        {0x08000000} 'No hit effect'      ])),      wbFloat('Base cost'),      wbUnion('Assoc. Item', wbMGEFFAssocItemDecider, [        wbFormIDCk('Unused', [NULL]),        wbFormIDCk('Assoc. Weapon', [WEAP]),        wbFormIDCk('Assoc. Armor', [ARMO, NULL{?}]),        wbFormIDCk('Assoc. Creature', [CREA, LVLC, NPC_]),        wbInteger('Assoc. Actor Value', itS32, wbActorValueEnum)      ]),      wbInteger('Magic School', itS32, wbMagicSchoolEnum),      wbInteger('Resist value', itS32, wbActorValueEnum),      wbInteger('Unknown', itU16),      wbByteArray('Unused', 2),      wbFormIDCk('Light', [LIGH, NULL]),      wbFloat('Projectile speed'),      wbFormIDCk('Effect Shader', [EFSH, NULL]),      wbFormIDCk('Enchant effect', [EFSH, NULL]),      wbFormIDCk('Casting sound', [NULL, SOUN]),      wbFormIDCk('Bolt sound', [NULL, SOUN]),      wbFormIDCk('Hit sound', [NULL, SOUN]),      wbFormIDCk('Area sound', [NULL, SOUN]),      wbFloat('Constant Effect enchantment factor'),      wbFloat('Constant Effect barter factor')    ], cpNormal, True, nil, 10),    wbArrayS(ESCE, 'Counter Effects', wbInteger('Counter Effect', itU32, wbChar4))  ], False, nil, cpNormal, False, wbMGEFAfterLoad);  wbRecord(SPEL, 'Spell', [    wbEDID,    wbFULL,    wbStruct(SPIT, '', [      wbInteger('Type', itU32, wbEnum([        {0} 'Spell',        {1} 'Disease',        {2} 'Power',        {3} 'Lesser Power',        {4} 'Ability',        {5} 'Poison'      ])),      wbInteger('Cost', itU32),      wbInteger('Level', itU32, wbEnum([        {0} 'Novice',        {1} 'Apprentice',        {2} 'Journeyman',        {3} 'Expert',        {4} 'Master'      ])),      wbInteger('Flags', itU8, wbFlags([        {0x00000001} 'Manual Spell Cost',        {0x00000002} 'Immune to Silence 1',        {0x00000004} 'Player Start Spell',        {0x00000008} 'Immune to Silence 2',        {0x00000010} 'Area Effect Ignores LOS',        {0x00000020} 'Script Effect Always Applies',        {0x00000040} 'Disallow Spell Absorb/Reflect',        {0x00000080} 'Touch Spell Explodes w/ no Target'      ])),      wbByteArray('Unused', 3)    ], cpNormal, True),    wbEffects  ]);  wbRecord(ENCH, 'Enchantment', [    wbEDID,    wbFULL,    wbStruct(ENIT, '', [      wbInteger('Type', itU32, wbEnum([        {0} 'Scroll',        {1} 'Staff',        {2} 'Weapon',        {3} 'Apparel'      ])),      wbInteger('Charge Amount', itU32),      wbInteger('Enchant Cost', itU32),      wbInteger('Flags', itU8, wbFlags(['Manual Enchant Cost (Autocalc Off)'])),      wbByteArray('Unused', 3)    ], cpNormal, True),    wbEffects  ]);  wbRecord(INGR, 'Ingredient', [    wbEDID,    wbFULL,    wbMODL,    wbICON,    wbSCRI,    wbFloat(DATA, 'Weight', cpNormal, True),    wbStruct(ENIT, '', [      wbInteger('Value', itS32),      wbInteger('Flags', itU8, wbFlags(['No auto-calculation', 'Food item'])),      wbByteArray('Unused', 3)    ], cpNormal, True),    wbEffects  ]);  wbRecord(ALCH, 'Potion', [    wbEDID,    wbFULL,    wbMODL,    wbICON,    wbSCRI,    wbFloat(DATA, 'Weight', cpNormal, True),    wbStruct(ENIT, '', [      wbInteger('Value', itS32),      wbInteger('Flags', itU8, wbFlags(['No auto-calculation', 'Food item'])),      wbByteArray('Unused', 3)    ], cpNormal, True),    wbEffects  ]);  wbRecord(SGST, 'Sigil Stone', [    wbEDID,    wbFULL,    wbMODL,    wbICON,    wbSCRI,    wbEffects,    wbStruct(DATA, '', [      wbInteger('Uses ', itU8),      wbInteger('Value', itU32),      wbFloat('Weight')    ], cpNormal, True)  ]);  wbEffects :=    wbRStructs('Effects','Effect', [      wbEFID,      wbEFIT,      wbSCIT    ], []);  wbEFID := wbInteger(EFID, 'Magic effect name', itU32, wbChar4, cpNormal, True);  wbEFIT :=    wbStructSK(EFIT, [4, 5], '', [      wbInteger('Magic effect name', itU32, wbChar4),      wbInteger('Magnitude', itU32),      wbInteger('Area', itU32),      wbInteger('Duration', itU32),      wbInteger('Type', itU32, wbEnum(['Self', 'Touch', 'Target'])),      wbInteger('Actor Value', itS32, wbActorValueEnum)    ], cpNormal, True, nil, -1, wbEFITAfterLoad);  wbMagicSchoolEnum :=    wbEnum([      'Alteration',      'Conjuration',      'Destruction',      'Illusion',      'Mysticism',      'Restoration'    ]);  wbSCIT :=    wbRStructSK([0], 'Script effect', [      wbStructSK(SCIT, [0], 'Script effect data', [        wbFormIDCk('Script effect', [NULL, SCPT]),        wbInteger('Magic school', itU32, wbMagicSchoolEnum),        wbInteger('Visual effect name', itU32, wbChar4),        wbInteger('Flags', itU8, wbFlags(['Hostile'])),        wbByteArray('Unused', 3)      ], cpNormal, True, nil, 1),      wbFULLReq    ], []);

User avatar
Javier Borjas
 
Posts: 3392
Joined: Tue Nov 13, 2007 6:34 pm

Post » Sun May 29, 2011 1:14 am

How did you arrive at those numbers?

Metronome. :D SirTroy's method is good too, though!
User avatar
Stacyia
 
Posts: 3361
Joined: Mon Jul 24, 2006 12:48 am

Post » Sat May 28, 2011 5:40 pm

A new 'hotfix', for lack of a better name, has been uploaded. It fixes a couple bugs related to the CS and some new bugs I inadvertently introduced in beta3.

I'll continue to release bug fixes like this until I can comfortably call the plugin stable, at which point it will become "v1.0".

I'd appreciate any help with testing I can get - especially compatibility with other mods. If you have a little free time and feel like contributing, please do your d*amnedest to break this mod (it helps if you also send me results, of course).

Please let me know exactly what changes you made and I will adjust TES4Edit to support them.
Wow. I'm ... well, "honored" might be too patronizing, but you get the idea. Working on this without TES4Edit has been like loosing a limb.

Anyway, I've uploaded the details of the file format changes to the http://www.tesnexus.com/downloads/file.php?id=31981, under "Miscellaneous".
There are a couple things I should mention directly, though:
  • Oblivion generally doesn't care what order the chunks are in, but there are exceptions. The most important is that all the chunks pertaining to an effect item must appear together, without other recognized chunks separating them. However, unrecognized chunks (like those that might be added by other mods) are ignored anyway, so these may be interspersed anywhere.
  • Some fields - those that held actor values or effect-specific data like script formIDs - have been 'expanded' to contain arbitrary 32-bit integers. It's important not to truncate them or 'force' them into an enumeration.
  • New chunks may be added for Effect Items & Effect Settings in future versions (i.e. 2.0 or later).


Warudder, if you read this, hopefully it will help with CBash as well.
User avatar
KRistina Karlsson
 
Posts: 3383
Joined: Tue Jun 20, 2006 9:22 pm

Post » Sat May 28, 2011 9:30 pm

Ah, that will prove quite useful. Thanks!
User avatar
alicia hillier
 
Posts: 3387
Joined: Tue Feb 06, 2007 2:57 am

Post » Sun May 29, 2011 1:31 am

Oblivion generally doesn't care what order the chunks are in, but there are exceptions. The most important is that all the chunks pertaining to an effect item must appear together, without other recognized chunks separating them. However, unrecognized chunks (like those that might be added by other mods) are ignored anyway, so these may be interspersed anywhere.
While the game engine might generally not care too much about the record order, TES4Edit does. So please make sure to define a canonical order, and stick to it.

Some fields - those that held actor values or effect-specific data like script formIDs - have been 'expanded' to contain arbitrary 32-bit integers. It's important not to truncate them or 'force' them into an enumeration.
For these cases, especially when a field can contain a FormID that needs to be mapped, you need to make sure that I have a bit flag clearly indicating if it's a FormID or not, BEFORE the relevant field.

New chunks may be added for Effect Items & Effect Settings in future versions (i.e. 2.0 or later).
Whole new subrecords are not an issue.

Now, one thing I already noticed when I had a quick look at your example .esp's is that whatever you are doing with the MGEF.EDID field is quite ugly. EDID is supposed to contain a string. Originally, even though for MGEF's, it's always 4 characters in length, it's still always a valid string of upper case characters ('A'..'Z', '0'..'9'). I don't really know what you are writing into that field, it's clearly binary data. And it's also not a repeat of the FormID either which was my first thought.

If it is supposed to be a FormID which gets mapped correctly on load, then please store it in the same format as all FormID fields, and please set me a bit in the record flags (I think there are plenty of bits unused there still) to indicate that this MGEF record is one of "yours".

In general that would be a very good idea, a bit in the record header which is set for all records that are on OBME specific format. That way I can clearly distinguish between records in your format and records in the original TES4 format.

Last but not least, your format description seems to be missing exact specification for the bits in all flags/bitmask fields.
User avatar
Liv Brown
 
Posts: 3358
Joined: Wed Jan 31, 2007 11:44 pm

Post » Sat May 28, 2011 8:30 pm

please make sure to define a canonical order, and stick to it.

OBME, like Oblivion, always writes chunks in the same order. All I meant - and I apologize for this in advance - is that at some point in the future new chunks will be added to some of the records.

whatever you are doing with the MGEF.EDID field is quite ugly.

I agree about it being ugly. Unfortunately, I can't claim credit for it. Internally, the contents of the EDID field are used as the 'magic effect code' (I think the term was introduced by obse?) that uniquely identifies magic effects. It is not a formID, nor is it really an editorID - internally, it's just a 32-bit number. For the original effects this was the editorID, or at least the same bit pattern. With new effects being added, it is too restrictive to limit effect codes to case-insensitive 4-letter strings. New magic effect codes are arbitrary 32-bit numbers, and their editorIDs are stored in a separate chunk. I realize new effect codes are difficult to print, since they can't necessarily be interpreted as strings.

In general that would be a very good idea, a bit in the record header which is set for all records that are on OBME specific format. That way I can clearly distinguish between records in your format and records in the original TES4 format.

I hadn't thought of that. I'll try to implement this in a hotfix very soon.

when a field can contain a FormID that needs to be mapped, you need to make sure that I have a bit flag clearly indicating if it's a FormID or not, BEFORE the relevant field.
Last but not least, your format description seems to be missing exact specification for the bits in all flags/bitmask fields.

'XXX field is a formID' flags are doable, in general. Making sure that they come before the field in question, though, is very difficult. It will require some rearranging of the chunks and an additional chunk for each Effect Item. Would it be possible, for the time being, to treat the 'Param' fields on OBME-formatted records as just 32-bit numbers?

Apologies about the bitmasks, I did indeed leave a lot unsaid.
  • bits for mgefFlags are enumerated in the file as 'Vanilla EffectSetting flags'. Some bits are being phased out by OBME, meaning that they are or will be ignored.
  • bits for mgefFlagOverrides are enumerated in the file as "EffectSetting Flags Overriden by OBME". Bits not enumerated are ignored, for the time being.
  • bits for efixFlags are the same as the undeprecated effect setting flags, combined with the new obme flags.
  • bits for the efixOverrideMask are the same as the efixFlags under the mask 0xF8DFC40F. Other significant override bits are
    OverrideEfixParam         = 0x00000010OverrideSchool            = 0x00000020OverrideName              = 0x00000040OverrideVFXCode           = 0x00000080OverrideBaseCost          = 0x00000100OverrideResistAV          = 0x00000200OverrideIcon              = 0x00000800

The reason I didn't enumerate those last two is that, unlike Oblivion, OBME is still a work in progress. I don't plan on changing these enumerations, but something may come up and force me to it - for example, flags to mark fields as formIDs may have to be squeezed in somewhere. I honestly think it might be better to treat the new OBME bitmask fields as simple 32-bit numbers, at least until the plugin has a few major versions under it's belt. I suppose people might complain, but in the end it will make life simpler for all of us.
User avatar
SEXY QUEEN
 
Posts: 3417
Joined: Mon Aug 13, 2007 7:54 pm

Post » Sat May 28, 2011 6:29 pm

[quote name='JRoush' date='04 August 2010 - 02:26 AM' timestamp='1280852767' post='16234606']OBME, like Oblivion, always writes chunks in the same order. All I meant - and I apologize for this in advance - is that at some point in the future new chunks will be added to some of the records.[/quote]New subrecords being added is not a problem (but it will obviously require additions to the record definitions when that happens). What would be a problem is if the same record (type) occurs with the same subrecord (types) but in different orders.

[quote name='JRoush' date='04 August 2010 - 02:26 AM' timestamp='1280852767' post='16234606']I agree about it being ugly. Unfortunately, I can't claim credit for it. Internally, the contents of the EDID field are used as the 'magic effect code' (I think the term was introduced by obse?) that uniquely identifies magic effects. It is not a formID, nor is it really an editorID - internally, it's just a 32-bit number. For the original effects this was the editorID, or at least the same bit pattern. With new effects being added, it is too restrictive to limit effect codes to case-insensitive 4-letter strings. New magic effect codes are arbitrary 32-bit numbers, and their editorIDs are stored in a separate chunk. I realize new effect codes are difficult to print, since they can't necessarily be interpreted as strings.[/quote]How "arbitrary" is arbitrary? How are you going to guarantee that there are no collisions when multiple different plugins define new MGEF's? I figured the only thing that's really unique would be the FormIDs of the MGEF records *AFTER* mapping them from file specific to global FormIDs.

I don't know how deep you have wormed your way into the original engine (too lazy to read your source, sorry) but assuming you can hook into the original code which reads the EDID field for MGEFs I would have then checked if the record header has the OBME flag, if yes, ignore the EDID and use the (remapped, global) FormID of the record as if you had just read these 4 bytes out of the EDID field. And in that case you can keep the EDID field to really contain the EditorID.

References to MGEFs are limited to only a few different places as far as I can tell (besides any you might have added in your new structures):
  • EFID subrecord
  • 1st field in EFIT subrecord
  • 3rd field in SCIT subrecord
  • array elements in ESCE subrecord

The last only occurs in MGEF records, and the first three only in ALCH, ENCH, INGR, SGST and SPEL records. All of which you already must have hooked into the reading/writing code.

If possible, when reading/writing any of these records with the OBME flag in the record header, you could generally treat these fields as being FormIDs (performing the appropriate file specific <-> global mapping). Or, if you really can't look up the object representing the stock MGEFs using their FormIDs, first check if the field contains one of the know magic values, otherwise treat it as a FormID (there is a slight change for a collision between the magic values and known a real FormID in that case though, and it would make my code more complicated...).

[quote name='JRoush' date='04 August 2010 - 02:26 AM' timestamp='1280852767' post='16234606']I hadn't thought of that. I'll try to implement this in a hotfix very soon.[/list]Alternatively, but I don't know how the engine reacts to any subrecord before the EDID subrecord, you could put a marker subrecord (size=0) with a signature of OBME at the beginning of any record in OBME format that you write.

[quote name='JRoush' date='04 August 2010 - 02:26 AM' timestamp='1280852767' post='16234606']'XXX field is a formID' flags are doable, in general. Making sure that they come before the field in question, though, is very difficult. It will require some rearranging of the chunks and an additional chunk for each Effect Item. Would it be possible, for the time being, to treat the 'Param' fields on OBME-formatted records as just 32-bit numbers?[/quote]Sure I can, but that means that if you load any file which contains a FormID in one of these fields, then do something which adds or removes a master or changes the order of the masters and then save the module, you've just trashed it. Any FormID must always be reliably identified as such so that it can be appropriately remapped if there are any changes to the list of masters for the containing module. I don't know yet how this is currently handled, but this is also very important for the actor value fields where you are now storing FormIDs (but at least here I can clearly distinguish between the 2 because no user defineable record can be smaller then 00000800, so there is no possible overlap between valid FormIDs and AVs).

As far as the original TES4 format goes, there is only what I call the 'Assoc. Item' field in MGEF.DATA, which can contain either a FormID, or an ActorValue, or be unused, depending on the Flags coming BEFORE that field in the DATA subrecord.

[quote name='JRoush' date='04 August 2010 - 02:26 AM' timestamp='1280852767' post='16234606']Apologies about the bitmasks, I did indeed leave a lot unsaid.
....
The reason I didn't enumerate those last two is that, unlike Oblivion, OBME is still a work in progress. I don't plan on changing these enumerations, but something may come up and force me to it - for example, flags to mark fields as formIDs may have to be squeezed in somewhere. I honestly think it might be better to treat the new OBME bitmask fields as simple 32-bit numbers, at least until the plugin has a few major versions under it's belt. I suppose people might complain, but in the end it will make life simpler for all of us.[/quote]I can do that, but only in so far as I don't need them to identify if a specific field contains a FormID or not.
User avatar
Manuel rivera
 
Posts: 3395
Joined: Mon Sep 10, 2007 4:12 pm

Post » Sat May 28, 2011 5:05 pm

How are you going to guarantee that there are no collisions when multiple different plugins define new MGEF's?

I did originally plan to switch entirely to formIDs as you describe. I changed my mind on the grounds that several built-in effects do not have formids defined by default - any mod that defines them will give them a different formid. In addition, effect codes are already used extensively by existing OBSE functions.

Most importantly, magic effects are were never intended to be 'resolved' with load order - they are implicitly static. Changing them based on load order works fine wherever OBME has a hand, but it can and will break some existing scripts. For this reason it is essential to allow mod authors to use unchanging magic effect codes if they so choose - an impossibility when using ordinary formids.

This is a topic that was discussed at some length in previous threads, and considered very carefully by yours truly. The "solution" was 'dynamic effect codes', which are discussed in the obme Features pdf. In short they encode a mod index in the lowest byte. This scheme has it's drawbacks, but is the best & simplest I've found to date.

Even if effect codes could be dispensed with, the EDID chunk wouldn't be able to hold the 'true' editorID. The first four characters might overlap with a built-in effect, and be mis-loaded by the vanilla engine. Given that, I don't see the harm in having an arbitrary integer in the EDID chunk - it may not be readable as a string or searchable as an editorID, but the former is purely aesthetics and the latter is outside my power to fix.

I should also note that the EDID chunk cannot be moved; it *must* be the first in the record.

if you load any file which contains a FormID in one of these fields, then do something which adds or removes a master or changes the order of the masters and then save the module, you've just trashed it

For it's part, OBME does handle this.
It is a problem for 3rd party editors, and I will attempt to add some flags that make it more straightforward. However - it will be impossible to put these flags in the same chunk as the field it describes, without altering chunk size. Is it permissible to place the flag in another chunk? Again, this isn't a restriction I'm dictating personally, but rather another limitation of the game engine.
User avatar
Doniesha World
 
Posts: 3437
Joined: Sun Jan 07, 2007 5:12 pm

Post » Sat May 28, 2011 3:38 pm

I did originally plan to switch entirely to formIDs as you describe. I changed my mind on the grounds that several built-in effects do not have formids defined by default - any mod that defines them will give them a different formid. In addition, effect codes are already used extensively by existing OBSE functions.

Most importantly, magic effects are were never intended to be 'resolved' with load order - they are implicitly static. Changing them based on load order works fine wherever OBME has a hand, but it can and will break some existing scripts. For this reason it is essential to allow mod authors to use unchanging magic effect codes if they so choose - an impossibility when using ordinary formids.

This is a topic that was discussed at some length in previous threads, and considered very carefully by yours truly. The "solution" was 'dynamic effect codes', which are discussed in the obme Features pdf. In short they encode a mod index in the lowest byte. This scheme has it's drawbacks, but is the best & simplest I've found to date.


Ok, so how do I know if a MGEF.EDID or one of the fields that references an MGEF contains a "dynamic effect code" which needs to be remapped and when it contains a static code which I need to leave alone?

And for the remapping, I assume the same rules apply as for FormIDs? so if the first byte is smaller then the count of masters of the containing module, then it is an offset into the masters list, otherwise (first byte being equal or larger then count of masters) the particular "dynamic effect code" belongs to the containing module?

For it's part, OBME does handle this.
It is a problem for 3rd party editors, and I will attempt to add some flags that make it more straightforward. However - it will be impossible to put these flags in the same chunk as the field it describes, without altering chunk size. Is it permissible to place the flag in another chunk? Again, this isn't a restriction I'm dictating personally, but rather another limitation of the game engine.
Sure, other subrecords are fine for flags as long as they are stored before the field they are describing.
User avatar
Damien Mulvenna
 
Posts: 3498
Joined: Wed Jun 27, 2007 3:33 pm

Post » Sat May 28, 2011 1:55 pm

Ok, so how do I know if a MGEF.EDID or one of the fields that references an MGEF contains a "dynamic effect code"

Dynamic effect codes are >= 0x80000000 (i.e. any code with the highest bit set is dynamic). The lowest byte of dynamic codes is resolved just like the highest byte of formIDs.

Sure, other subrecords are fine for flags as long as they are stored before the field they are describing.

I'll get to work then. Thanks very much for taking the time to look into all this.
User avatar
Chloe Mayo
 
Posts: 3404
Joined: Wed Jun 21, 2006 11:59 pm

Post » Sat May 28, 2011 4:47 pm

Dynamic effect codes are >= 0x80000000 (i.e. any code with the highest bit set is dynamic). The lowest byte of dynamic codes is resolved just like the highest byte of formIDs.

Ok, so something along the lines of (excuse the pascal):
var  edid: LongWord;begin  edid := ... load from file ...;  if edid and $80000000 = 0 then    //static code, leave alone  else    edid := (edid and $FFFFFF00) or MapFileToGlobalModIndex(edid and $000000FF);end;

Should handle your dynamic effect codes?

For display purposes of fields referencing MGEFs, if the MGEF that's being referenced contains an EDDX subrecord, I'll display that value, otherwise, if the 4 bytes only contain alpha numeric characters (a-z, A-Z, 0-9, _) I'll display the 4 characters as they are. Otherwise, I'll take the 4 bytes and turn them into an 8 character hexadecimal and display that.

I'll get to work then. Thanks very much for taking the time to look into all this.
The main thing that I would need is an OBME flag in the record header of all records that contain OBME specific changes. Beyond that, for any field that can have variable content types, I would need some form of flag occuring before that field (can be in a different subrecord) in the order in which things are stored in the file.

With these things in place I should be able to implement full OBME support in TES4Edit
User avatar
Dylan Markese
 
Posts: 3513
Joined: Sat Dec 01, 2007 11:58 am

Post » Sun May 29, 2011 1:40 am

Ok, so something along the lines of :

Perfect, insofar as I understand Pascal.

For display purposes of fields referencing MGEFs, if the MGEF that's being referenced contains an EDDX subrecord, I'll display that value, otherwise, if the 4 bytes only contain alpha numeric characters (a-z, A-Z, 0-9, _) I'll display the 4 characters as they are. Otherwise, I'll take the 4 bytes and turn them into an 8 character hexadecimal and display that.
Even better than I'd hoped for. And thanks again for taking the effort.
User avatar
Annika Marziniak
 
Posts: 3416
Joined: Wed Apr 18, 2007 6:22 am

Post » Sat May 28, 2011 11:18 pm

After the last interchange I'm not sure whether Elminster still needs records flagged as to whether they're in OBME format or not; but if so, couldn't this be done once in the main .esp header rather than per record? AFAIK there is no such thing as a mod which will contain both.
User avatar
Rob Davidson
 
Posts: 3422
Joined: Thu Aug 02, 2007 2:52 am

Post » Sat May 28, 2011 4:26 pm

After the last interchange I'm not sure whether Elminster still needs records flagged as to whether they're in OBME format or not; but if so, couldn't this be done once in the main .esp header rather than per record? AFAIK there is no such thing as a mod which will contain both.
While it might not be possible to save a file in CS which has a mix of OBME format TES4 format records, there are no such limitations for any other tool used to modify or create module files. You can easily copy just individual records between modules with TES4Edit itself for a start. But also TES4Gecko and other tools. And Bashed Patches will for sure end up containing a mixture of OBME and TES4 formated records.

So yes, I think per record is the right place for such a flag. And yes, I think it would certainly be a good idea to have such a flag.
User avatar
Gavin Roberts
 
Posts: 3335
Joined: Fri Jun 08, 2007 8:14 pm

Post » Sun May 29, 2011 1:37 am

Bashed Patches will for sure end up containing a mixture of OBME and TES4 formated records.
Oh, and on that topic, "dynamic effect codes" will die a horrible death the moment the first non-OBME aware version of Bash includes anything using them in the bashed patch... same for using FormIDs in AV fields, or in general using FormIDs in any place that whatever tool is used is not aware of.
User avatar
jenny goodwin
 
Posts: 3461
Joined: Wed Sep 13, 2006 4:57 am

Post » Sat May 28, 2011 8:39 pm

Oh, and on that topic, "dynamic effect codes" will die a horrible death the moment the first non-OBME aware version of Bash includes anything using them in the bashed patch... same for using FormIDs in AV fields, or in general using FormIDs in any place that whatever tool is used is not aware of.

:(
Sadly, I don't see what can be done about that - it's not something I have much control over.
User avatar
Noraima Vega
 
Posts: 3467
Joined: Wed Jun 06, 2007 7:28 am

Post » Sun May 29, 2011 12:02 am

And Bashed Patches will for sure end up containing a mixture of OBME and TES4 formated records.

Good point.

Oh, and on that topic, "dynamic effect codes" will die a horrible death the moment the first non-OBME aware version of Bash includes anything using them in the bashed patch... same for using FormIDs in AV fields, or in general using FormIDs in any place that whatever tool is used is not aware of.

Pretty sure Bash will be OBME-friendly before OBME leaves beta. :)
User avatar
Joanne
 
Posts: 3357
Joined: Fri Oct 27, 2006 1:25 pm

PreviousNext

Return to IV - Oblivion