Oblivion Mod talk:Cobl/Modding/Techniques

The UESPWiki – Your source for The Elder Scrolls since 1995
Jump to: navigation, search

Naming standards[edit]

Functions[edit]

Minor but easy issue first - Activator isn't a useful concept here. Anything that can be placed in the world and given a script can be a function (no matter how odd a functional Apparatus might be, it can be done). The major distinction is between objects and quests. I think functions should be simply F (or "Func") and quest functions should be QF (or "QFunc").

I believe these should have their own name space (and/or subspace; "Func") and should be treated differently. Functions are there for modders to use at will in their own scripts, and, more to the point, the rest of the scripts aren't!

For instance, in RUE there are only 4 functions that modders should be using in their own scripts - SetupRecipe, OpenRecipe, Init, and InitAlchemy. The rest are function activators, but they're not meant to be used by modders. Actually, unless they really know what they're doing I'd prefer they didn't, and, likewise, it'll be clearer to them that they won't get anything out of trying to use those scripts/activators. (@Wrye, I know I didn't set it up that way, but now that I've had some more time to think about it.) --Haama 17:59, 3 April 2008 (EDT)

There's no distincition between "public" and "private" in the namespace itself. In the stuff that I've done so far, I don't think that it would be useful. (Besides it can be hard to draw a clear line between what should and should not be private.) However, in your case if you have 40 scripts or so and want to clearly distinguish some of theme as public and some as private, then you might divide into cobRueA and cobRueX where 'A' is public and 'X' is private(ish). --Wrye 22:40, 6 April 2008 (EDT)
Oh yeah... But the objects that act as functions do so by being activated, right? Maybe "Activation Function" is more accurate than "Functional Activators". --Wrye 22:46, 6 April 2008 (EDT)
Err, I put too much emphasis on the object part, then (I was really thinking about FAR, but never came up with a good argument against it). I really meant that we should mark functional quests (i.e., OBSE, SI detection) with a similar key.--Haama 14:32, 8 April 2008 (EDT)
Hmmm. Consider a number of ways a quest can be used without being a quest:
  1. Quest is just a means to turn dialog on/off.
  2. Quest is just a means to turn quest markers on/off. (E.g. find your horse.)
  3. Quest is just a repository for variables.
  4. Quest is just a repository for stages that act as functions. Quest script may be nothing but a variable holder.
  5. A one frame quest script. (I.e. quest is started, runs for one frame then is done.)
  6. A multi-frame quest scripts. Same as 2, except is runs for multiple frames.
  7. A client quest. Runs continuously but is signalled to do certain things by other quests and/or objects (e.g. the client side of Cobl's death handling).
  8. A server quest. flip side of number 4. E.g. the server (Cobl) side of Cobl's death handling.)
So, here's there's a range of behavior some of which (e.g the repository for function stages) that's fairly function like (or maybe fairly library like). Anyway, it's hard to see where to draw the line. And there's a risk that a quest that starts off being used for one purpose may end up including other functions. (E.g. something that's initially a script stage repository may later have an active quest script that does stuff.)
In contrast, objects that act as functions are fairly distinct from their original intended usage. Their "objectness" is pretty much irrelevant. Rather, they're created specifically to act specifically as functions for other scripts.
I think you have a good point, I'm just not sure where to draw the line yet. Probably best thing is to evolve your terminology as you find useful and then post it here. (E.g. pre-obse, someone put up a quest that could be used as a math library. If I had something like that in cobl, I'd be tempted to call it cobMathLib.) --Wrye 23:59, 8 April 2008 (EDT)
So far I only use quests for SI references, so I haven't felt the need to use a specific key (i.e., for the SI Alchemy Equipment I called the quest cobStaticAppSI and the script ...QS). To be honest, it's rare that a quest would be better, so it's not really an issue.--Haama 19:08, 9 April 2008 (EDT)

Looping[edit]

I don't believe there should or can be specific instructions for looping. The given instructions can have their own problems:

  1. When conditionally removing items from a container you'll need to increase the iXxx variable if you don't remove the item, but leave it the same if you remove all of the item. It's much easier to start from numXxx - 1 and go to 0.
  2. It's unnecessarily slow for inventory walking - GetNumItems can be almost as bad as calling GetInventoryObject for each object. The iXxx < numXxx test would be redundant as you always want to make sure your variable isn't NULL. Also, Oblivion processes simple if pInvObj lines nearly 33% faster than if iXxx < numXxx.
    • This is quite a bit of personal taste - but "Xxx" is a meaningless term to me. I see it's just another name for variable, but it doesn't pop at me. Instead I propose "Index". --Haama 17:59, 3 April 2008 (EDT)
That might be useful to clarify in best practices somewhere (and I did see something to that effect for inventory walking at CS Wiki). However, I also have had to loop over spells, factions and through limited length arrays. I didn't quite follow the lat bit about "Xxx". To be more concrete. I had to loop over player factions. In which case, I used iFaction, numFactions and rFaction. By Xxx, I mean "Faction" or "Spell" or whatever. If you mean, use "indexFaction" instead of "iFaction", that seemed to be too wordy to me. If coders typically follow the same patter of naming loop related variables, then it will be pretty clear, I think. --Wrye

Ref vs. Base[edit]

This information seems redundant in most cases. Are they only supposed to be used in cases when you would have both the reference and the base object records? There is some need when using blackbox functions (i.e., MagicItemsHaveSameEffect takes base object records), however I don't think it's an issue now and would much prefer making all functions take both the reference and base object. The OBSE team already has functions to determine which is which, and it may be time to threaten a small riot if they don't have a release soon (j/k). --Haama 17:59, 3 April 2008 (EDT)

Use them when you need to distinguish between the two. For Wrye Morph I did need to do that quite a bit. E.g. clone a form to get the base, set some stuff on the base, then place a ref of the base and do further ref specific operations on it. If you don't need to distinguish between ref and base, then don't use the suffixes. --Wrye 22:40, 6 April 2008 (EDT)

Ref Variables[edit]

Very minor, but I prefer "p". For most fonts, "r" is invisible (like the one used by UESP). I know most scripts are already using this, so I wonder if both might be acceptable.--Haama 17:59, 3 April 2008 (EDT)

Problem with 'p' is that it's too vague. Okay, a pointer. But a pointer to what? Does p point to a ref, an array or a string? But an 'a' points to an array, an 'r' to a ref and an 's' to a string. That seems quite a bit clearer.
However, it's not a big deal. If your code consistently uses 'p' that's fine.
PS. I do almost all my editing in an outside editor. I do a lot of select all and paste. :) I hate to imagine using TESCS script editor for anything complex. --Wrye 22:40, 6 April 2008 (EDT)
Yeah, but there were a lot of variables (and a year of using 'p') to change :P and so a lot of chances for errors. OTOH, it's done and I used the 'r's anyway.--Haama 18:49, 9 April 2008 (EDT)

Proposal for Pluggy Registration[edit]

(writing as it would appear in the article; will wait for discussion, Inventory Tracking and a more advanced RUE before moving over) Some aspects of COBL require Pluggy, and so can use an advanced Registration system. The Pluggy system will allow multiple mods to have ownership and allow mods to interact in more complex ways.

For example, for the Alchemy Upgrade system in RUE there are several upgrade fields - Price, Weight, Effects, Model, etc. Let's say Mod A wants to handle Price and Weight, Mod B wants to handle Effects, and Mod C wants to handle Weight and Model, so there is a conflict over Weight between Mod A and C. This can be resolved in a number of ways: the player could have complete control and can switch which mod has control, it could be first come first serve (until the first mod is removed), last in first served, etc. For the other fields, each mod will have it's own control until removed. (To make this work, RUE will need to be included as one of the competing mods and will need to be the ultimate default.)

(For Inventory Tracking, multiple mods will be stored in an array and won't turn off until all of the registered mods have been removed).

This system will also require a reference, however it uses this reference to get the EspID and name of the mod. Then an array is created with the same EspID as the mod. When the mod is removed this array will be destroyed, and the mod can be de-registered. On the modder's side, they will to provide a reference (anything but globals will do) to a functional activator (instead of an external variable?) which will handle the array set up and mod tracking.--Haama 14:29, 8 April 2008 (EDT)

I skimmed :), but... seems fine. --Wrye 00:02, 9 April 2008 (EDT)
Alright, you'll see something like it in the Inventory Tracking stuff and an upcoming version of RUE.--Haama 18:48, 9 April 2008 (EDT)

Requirements[edit]

Wrye, upon further reflection, and as far as I know, the only time you would need to worry about Player Requirements would be the functional activators. So, I put all compile requirements where you had it, and the player requirements in the FAS script type block.
--Haama 00:55, 16 March 2009 (EDT)

Okay, that works for me. --Wrye 02:35, 16 March 2009 (EDT)

Script Types[edit]

I'm trying to define the script types. I've added some. I'm suggesting "Private" instead of "Internal". However, another scheme might be Overridable or External or Internal. Still, Public, Private, have history in computer science which is useful.

I'm also thinking of types of quest scripts. "Monitor" and "Service" are more specific/accurate than "Quest" for most of our scripts. --Wrye 16:16, 16 March 2009 (EDT)

Hmm... Maybe "Background" instead of "Monitor". --Wrye 16:22, 16 March 2009 (EDT)
Depends on the circumstances? Background would "do stuff" (i.e., Clock) while a monitor would only wait for a key press and then activate another script (i.e., how I should have done Denock, Poison-Con). I've been thinking about this more recently because I've been thinking about a Universal Hotkey System for COBL. (... in another sense, I need to stop thinking about it because I keep trying to create functions that will handle walking through all 4 types of lists - containers, leveled lists, pluggy arrays and OBSE arrays, instead of waiting for OBSE arrays and converting everything, which I can't do and keep backwards compatibility and... yeah, this has been in my head off and on for 2 weeks now...). I'd also like to make more use of Montior+Activate because Waruddar keeps teasing me with context menus...
Private/Public - I'd avoid them because of the history. The variables aren't actually Private, we just wish that they were. We could just label them "DON'T CHANGE THESE VARIBLES!!!" :) I take it that input/output still work, though? I was wondering if input should be parameter?
--Haama 17:25, 16 March 2009 (EDT)
Wait a minute, I think I missed the points.
On public/private - I was thinking about variables, but you mean script types? Yeah, public/private/override sounds better than internal for script types. I'm looking at cobMortQ and I like it - just use one of the 3 for the header, then the description, then usage information?
...
And then I scrolled down, you do mean variables for public/private.
For quest scripts - most of the ones I've created are private scripts, and I plan to stop using them altogether. If you had more time I'd try to convince you to do the same. (Mostly because of the above hotkey/context menu stuff, also to avoid painful rewrites like the Alchemy Sorter.)
Services - these are much like functional activators, so maybe functional quests?
My minds been heading off to tangents all day, making the relatively simple MQI amazingly complex. I'm going to ignore as many tangents as I can, write up a quick bug-fix version (that should have been released 2 weeks ago) and send it to you. Then I'll try this again.
--Haama 17:56, 16 March 2009 (EDT)
One thing I brought up earlier, but I'm not sure if you saw it - we could use the scriptname line as a divider line. Everything above the line is for modders using the script/object as a resource. Everything below the line could be for script editors updating the script.
--Haama 18:54, 16 March 2009 (EDT)
For public/private/override, I just meant for script types, not for variables (we already settled on not using public/private for variables). And input as part of the parameter is too messy. I'll go ahead and start using Public/Private/Overrideable now.
Below the line... Hmm... I'll think about it... --Wrye 23:10, 16 March 2009 (EDT)
Having tried it in practice, I like "Monitor Quest Script" and "Service Quest Script". "Functional Quest Script" might seems symmetric with "functional activator", but "service" is more accurate, since such scripts don't return immediately, and in fact, often run for a number of frames.
Below the line... I don't think that works. There are several scripts where input/output variables are heavily documented for the benefit of the modder that will be working with it. E.g. cobMortQS, cobPcXS. --Wrye 23:28, 16 March 2009 (EDT)
One more... Variables Quest Script -- for a quest script that has no active code, but instead only serves to hold variables. E.g. cobPcX. --Wrye 23:34, 16 March 2009 (EDT)
Last bit of consciousness for the night:
Below the fold: Aye, but you could comment out the variable names above the scn and use the real ones below. It would help keep the variables together for editors, as well. I was really thinking of the split for Private scripts, but it's not necessary.
How much information should we mention about Private scripts? For instance, Move Quest Items will have a Version Control private script that is a functional activator. For modders, they shouldn't touch it at all. For editors, I guess they should know what the hell I'm doing, why it's an activator and how to use it, etc.
Variable quest script - sounds good. We'll add more as it comes up. One that I can already think of - Init quest scripts (i.e., Denock). However, I'm going to start putting these in the General quest (i.e., the second run for the CharGen Fix), so I don't plan to add any more to COBL.
Looks: Earlier you had
;--PRIVATE----------------
Personally, the extra dashes do attract your attention to the line, but then they drown out the PRIVATE. (Not so bad with Wiki's font, but quite distracting in TES4Edit.) A space or two can prevent the distraction effect
;--PRIVATE -----------------------
Should COBL version be a float or should we start using integers (like BASH)?
I noticed in a few scritps that you had some different spacing, i.e.,
;--VERSION HISTORY
; v1.66  Stuff
I preferred the double space in the front, but only when I stop to think about it :P Either way, but I guess we should standardize on it.
--Haama 02:17, 17 March 2009 (EDT)
Duplicate variable names above the fold: Neah, that's too much of a pain. Info on variables should be close to the variables themselves.
Space after PRIVATE. No problem.
Spacing. I use two spaces after the first colon. I also use two spaces afer v1.66 -- makes the comment stand out more.
Version number. Let's keep it as major.minor. Besides there was actually a jump to 1.00 at once point.
And I scooted the REQUIRES lines over just to be consistent. --Wrye 16:15, 17 March 2009 (EDT)