User:JRoush

From the Oblivion ConstructionSet Wiki
Revision as of 12:08, 25 August 2010 by imported>JRoush (→‎Detection)
Jump to navigation Jump to search

Notes on Scripting

General Scripting

Adding or removing (possibly any modifying of) effects in an enchantment (or, presumably, a spell) that is currently affecting an actor results in CTD. Instead, we must cloneform the enchantment and use that instead. Previous testing gives me hope that the game might garbage collect unused formids.

Modifications to non-cloned forms (e.g. changes to name, etc) do not appear to stick upon reloading the game. Dynamically generated spells must be cloned, or else the base forms modified in script every time the game is reloaded.

Cloned forms are not removed when the mod is deactivated. Since there is no way for the average player to remove cloned spells from spell merchants, a "cleanup" script must be provided to do so. - makes the whole use of cloned spells unattractive -

GetOwner appears to work only on references (not items in a container). There is a stolen flag, I believe, but not sure how to set it.

Moveto and PositionCell don't transfer meshes. the 'usual' workarounds assume transfer to the current cell, and don't work for destination cells that aren't loaded.

Using GetIconPath on an object with no icon causes a CTD.

Menu Scripting

Traits of the form <user#> are parameters set by the game enigne. The visible manifestations (text, slider position, etc.) are usually set to derive from these inputs. As of OBSE v0017 modifying most traits from scripts will destroy derivative relationships; it appears that some values (e.g. quantity slider traits) are safe to modify. Modifying the <user#> traits directly one can "fake" user input; in particular spell/potion names and slider bar positions. Derivative relationships are reloaded when the menu is. Note that the HUD (and possibly the inventory) reloads only after exiting to the main menu; changes to the HUD will persist until then.

The Arrow + Enter keys can normally be used to navigate menus. I haven't found (or seriously looked for) a way to determine which tile is the focus of a keyboard event. It looks like the focus is *either* keyboard or mouse based, and transitions from one to the other are inconsistent or bugged. At any rate, OBSE v0017 GetActiveUIComponent* functions work only for tiles focused on by the mouse. Also, arrow+enter menu navigation is NOT based on mapped controls and cannot be disabled using Disablekey. It CAN be disabled by removing all traits of the form <xbutton>, <xleft>, <xright>, etc. from the menu in question, but not by simply setting them to zero in scripts. This is a problem because an errant keystrokes can apparently derail a ClickMenuButton call, which makes setting up long chains of automated click events unfeasible.

The GetCursorPos function is a bit dodgy. Returned positions are not consistent, and seem to depend on integrated movement history. This, combined with the lack of a function to get screen resolution, makes it impractical for use in menus (specifically, I couldn't use it to script in a custom slider bar).

Detection

Detection is Oblivion's stealth mechanic. The concept isn't complicated: every actor has a degree of awareness of every other nearby actor, called a detection level. If this detection level is above a certain threshold then the searching actor (the "detector") is fully aware of the hiding actor (the "target"). The detector can then attack, offer a greeting, report the target's crimes, etc. If the detection level falls below the threshold again, the detector "loses" the target and can no longer interact with it.

Quite a few factors go into calculating detection levels. They fall into three basic categories: Sight, Sound, and Sneak Skill. Sight factors basically describe how well the detector can see the target, and only matter if the detector actually has a direct line-of-sight. Sound factors measure how much noise the target is making, from movement and from being in combat. Skill factors measure the relative sneak skill of the two actors. In all three cases, the distance from the detector to target plays a very important role. Whether or not the target has attacked the detector can make an enormous difference as well.

The complete list of factors and their values is listed below. Note that each factor is given a 'shorthand' name for reference other formulas. Also note that many of the factors are conditional - they take a "default" value some times and a more complicated value at others. Some formulas even have conditional parts - an extra multiplier or additive bonus that is used only under certain circumstances. These conditions are given as clearly as possible in the formulas; just be sure to read them carefully.

Distance
Shorthand
Value
Max Detection Distance
maxDist
fSneakMaxDistance * (fSneakExteriorDistanceMult, for exterior cells)
Distance Factor
distMult
1 - (distance between detector and target) / maxDist
Sound
Shorthand
Value
Line-of-Sight Sound Factor
losSound
fSneakSoundLosMult if detector has line of sight to target

1.0 otherwise

Swimming Sound Factor
swimSound
0.0 if target is under water

1.0 otherwise

Running Factor
running
fSneakRunningMult if target is running

1.0 otherwise

Movement Bonus
moving

fSneakBootWeightBase + fSneakBootWeightMult * (target boot weight) if target is moving

0.0 if target is stationary

In-Combat Bonus
combat
fSneakTargetInCombatBonus if target is in combat

0.0 otherwise

Overall Sound Bonus
fSneakSoundsMult * distMult * losSound * swimSound * (running * moving + combat)
Sight
Shorthand
Value
Line-of-Sight Factor
losSight
1.0 if detector has line of sight to target

0.0 otherwise

Swimming Sight Factor
swimSight
fSneakSwimmingLightMult if target is under water

1.0 otherwise

Light Factor
light
fDetectionSneakLightMod + (light level on target) * (fDetectionNightEyeBonus, if detector has Night Eye)

Light Factor is capped at 100

Invisiblity Factor
invis
0.0 if target has Invisibility

1.0 - (target's Chameleon level, max 100) / 100.0, otherwise

Blindness Factor
blind
1.0 - (detector's Blindness level, from "Blindness" stat) / 100.0
Overall Sight Bonus
fSneakSleepBonus if detector is sleeping

fSneakLightMult * distMult * losSight * swimSight * light * invis * blind, otherwise

Skill
Shorthand
Value
Overall Skill Bonus
fSneakSkillMult * [(detector's Sneak skill) * distMult - (target's Sneak skill, if target is sneaking)]
Detection Level
Shorthand
Value
Overall Detection Level

-100.0 if invis >= 100.0 (i.e. target has Invisibility or 100% Chameleon)

0.0 if target didn't attack detector -AND- (distance between target and detector) > maxDist

fSneakBaseValue + (fSneakTargetAttackBonus, if target attacked detector) + Overall Sound Bonus + Overall Sight Bonus + Overall Skill Bonus, otherwise

If the Overall Detection Level is greater than a certain threshold, the detector can becomes aware of the target. The thresholds are:

Threshold
Used By
fSneakUnseenMin all actors that are unaware of target

all non-hostile actors

fSneakLostMin hostile actors that are searching for target
iAICombatMinDetection hostile actors that are in combat with target

A final note: The target-is-in-combat bonus is fairly significant. Combined with the much lower combat threshold, this can make it very difficult for an actor to return to hiding once a hostile actor has seen them.