File information

Last updated

Original upload

Created by

Tiawar

Uploaded by

Tiawar

Virus scan

Some manually verified files

Documentation

Readme

View as plain text

Name: EngineBugFixes
Version: 2.1
Date: 2018/12/27
Category: Utilities
Requirements: Oblivion Patch 1.2.0.416, Oblivion Script Extender (OBSE) v20 or later
Author: Tiawar



[General]

EngineBugFixes is an OBSE plugin containing bug fixes for the Oblivion game engine.
It distinguishes two types of engine modifications:

1) Fix Fixes something that probably everyone would consider a bug.
2) Patch Changes something that may or may not be considered a bug but which I felt could be improved.

See below for a current list of fixes/patches.
All fixes and patches can be enabled/disabled separately to ensure maximum compatibility with other OBSE plugins.


[Install]

1) Extract the files to a temporary location.
2) Copy the files in the Data folder to (install folder)\Oblivion\Data\


[Uninstall]

1) Delete the files/folders associated with the mod.


[Usage]

To enable a particular fix or patch set its value to 1 in the INI file. To disable, set the value to 0.


[Source Code]

The included source code (separate download) gives you an overview of the locations in the engine that will be patched
as well as a general insight into the patches themselves.
However, it is currently NOT possible to compile the plugin from the code as it is missing the project that recreates
the game engine classes and maps functions to memory addresses.
This project is HUGE and currently not for share (not in a sharable state anyway...).


[Settings]

Since v1.4, EBF has a general settings section in the ini file.

1.) iDebugLevel (v1.4)
Enables debug output to the log file. Check the individual fix/patch definitions to see which patch supports debug info.
The value is a number indicating how much debug info should be printed. Higher levels include output for lower levels.

0: None
1: Normal (recommended)
2: Verbose

2) sUserLogPath (v1.5)
This setting allows you to redirect EngineBugFixes's log output to a different location.
The default log is created in the game folder. The specified path should include the file name and extension.


[Script Commands]

Since v1.5, EBF defines its own set of commands which can be called from a script or the console.

1.) EBFGetVersion

Returns the current version of EngineBugFixes multiplied by 100. (i.e. v1.5 reports as 150)

2.) EBFGetEnableState (patchName:string)

Returns the enable state of a particular patch. The patch name argument must not include the patch/fix suffix.
E.g. To query the enable state of the "SpeedTreeLoadFix" pass "SpeedTreeLoad" as the patch name.
The return value is 0 (NotFound), 1 (Disabled) or 2 (Enabled).


[Patch Descriptions]

Fixes:
======

InitRendererFix (v1.0)
----------------------
Problem: When launching the game with an unsupported screen resolution it crashes to desktop immediately without any
hint about the actual problem.
Cause: The renderer initialization code was supposed to show a message box reporting the invalid resolution but
since the function does not return immediately the error code is lost when the function finally returns.
Solution: The fix makes the initialization function return immediately when an invalid screen resolution is detected so
the message box is shown instead of just crashing.


SpeedTreeLoadFix (v1.0)
-----------------------
Problem: Random crashes while moving around in the wilderness.
Cause: Trees are loaded in the background but the code is not thread-safe.
Solution: This fix modifies the code to make it thread-safe.
Remarks: This fixes ONE major cause for random crashes in the wilderness but that does not necessarily mean that all
possible causes for random CTDs are fixed... :(


ShadowCameraFix (v1.0)
----------------------
Problem: Dropping chameleon effect or switching from first person to third person view sometimes leaves you with no
shadow until you turn the camera around. NPCs entering the screen from behind the player often have the same
problem.
Cause: The shadow update code uses outdated camera FOV when determining whether an actor's shadow is in the visible screen
area or not. Ironically, the code to update the shadow camera position and rotation is in a function which only runs
when the shadow is in the visible area. That's why it takes almost a full swing with the main camera until the shadow
enters the visible screen area again and the shadow camera gets updated again.
Solution: The fix updates the shadow camera position and rotation before checking whether the shadow is in the visible area or not.
Remarks: The patches made should not conflict with the shadeMe plugin but since the shadeMe plugin uses its own shadow engine it is
unknown whether this fix will have an effect or not if both are enabled.


CreatureLightingFix (v1.0)
--------------------------
Problem: Some creatures like horses and trolls always report light level 0 which affects detection handling in game.
Cause: The game needs a lighting object from one of the meshes in an actor's 3D to determine the light level.
To increase performance the code avoids a full recursive lookup for an appropriate node in the actor's 3D but rather
grabs the first node under the actor's 3D root who's name doesn't start with "BIP". The developers expected this to be
one of the equipped objects (character) or something from the NIF list (creature).
However, some creature skeletons have extra nodes directly under 3D root (e.g. "EntryPoint" for horses"). These nodes
produce false positives as they don't have a mesh attached from which the code could extract the lighting object.
Solution: The fix makes sure that a node with a mesh attached (and subsequently a valid lighting object) is returned.


WeaponCollisionFix (v1.0)
-------------------------
Problem: Weapons do not fall to the ground but stay "frozen" in the air after an actor is killed.
Cause: When an actor dies in combat there is a chance that he/she will drop the weapon he/she is currently holding.
When detaching the weapon's 3D from the actor the engine needs to copy some havok collision data from
the actor's 3D. This information is taken from the actor's right hand node (Bip01 R Hand). The code expects
the right hand node to be the direct parent of the weapon node. Some custom skeletons insert a scale node between
the right hand node and the weapon node so the lookup fails leaving the dropped weapon without collision.
Solution: The fix recursively searches the actor's 3D for the right hand node if it is not the direct parent of the weapon node
so the right hand node is found even in non-standard skeleton NIFs.


SexChangeFix (v1.0)
-------------------
Problem: Using script command "SexChange" on an actor with 3D causes immediate CTD.
Cause: The script command releases the FaceGen nodes in the actor's 3D but does not remove them from the cached object list.
Subsequent access to these dangling pointers lead to memory access violation (i.e. CTD).
Solution: The fix clears and rebuilds the cached object list after releasing the FaceGen nodes.
Additionally, a new head for the actor is created since the game does not bother to create one.


GetAlarmedFix (v1.0)
--------------------
Problem: Script command "GetAlarmed" ocassionally causes CTD.
Cause: A call to this function leads to CTD if the actor currently has no AI package. An actor is considered to be
"alarmed" if the current package is of type "AlarmPackage" but strangely enough, instead of just checking the
package type the command compares the string representation of the package type returned by a conversion function
to the fixed string "Alarm". The conversion function returns a NULL-pointer if the actor has no AI package.
The result is then passed to the standard string comparison function which does not like NULL-pointers at all.
Solution: The fix ensures that a valid string is passed to string comparison function.


CellDistanceFix (v1.0)
----------------------
Problem: Potential oddities in low-level path finding and cell scan for actor's attempting to find furniture or objects.
Cause: The purpose of the function is to determine the 2D distance of a given point to the boundaries of a cell.
One of the four cases in the calculation has a bug so the returned distance is sometimes wrong.
Solution: A simple patch so the distance is calculated correctly.
Remarks: Judging the impact of this bug is difficult since it affects stuff running in background like pathing.
Supposedly, low level pathing (cell hopping) should work better with this fix. The function is also called when
scanning cells for furniture or objects to acquire.


FollowerDoubleFaceFix (v1.0)
----------------------------
Problem: Using fast travel will leave followers with two heads and/or helmets.
Cause: Unlike interior/exterior switches, fast traveling does not temporarily force followers into low level processing.
They stay in high level processing and thus keep their 3D when added to the new cell.
The new cell, when loading, queues all refs in its list for 3D loading leading to double faces and helmets.
(Due to some differences in the loading process other slots are not affected.)
Solution: The fix hooks the cell loading function and skips 3D loading for actors that already have 3D.
Debug (L2): Adds a line to the log file whenever 3D loading of an actor is skipped because he/she already has 3D.


ShutdownCTDFix (v1.0)(v1.7)
---------------------------
Problem: CTD when quitting the game. There are several individual causes for this problem.
Cause1: Undeleted ref problem: Refs that are defined as initially deleted in a master or plugin file and then undeleted in an
overriding plugin are not removed from the internal list of unused objects. They are also not added to their supposed
parent cell's object list which in turn skipps the call to the InitItem() function that converts form IDs specified in
mod files to pointers to actual objects. This is usually not a problem except when the ref as an enable-state parent.
When the ref is about to get deleted on shutdown it tries to unregister itself from it's enable-state parent but since
the link to the parent is still a form ID (that is now interpreted as a memory address) the game crashes.
Solution1: Remove undeleted refs from the list of unused objects and register them to their parent cells.
Cause2: Cell reset problem: When quitting the game and returning to the main menu all objects in game are reset to their initial
state. Problems occur when a persistent ref is initially paced in an exterior cell but is now in an interior cell when
the game resets it. Because of the way parent cells are handled the game tries to remove the ref from the initial
parent cell and not the current parent cell so it remains in the cell's object list during the rest of the game.
When quitting the game the ref is destroyed twice causing CTD.
Solution2: Remove the ref from it's current parent cell on reset.
Cause3: Reset object problem: When loading a save game from the in-game menu or after returning to the main menu any cell-changed,
non-persistent refs get deleted once the ResetObject phase is completed. Since the refs are not yet initialized at this
point the same problem as described in Cause1 occurs.
Solution3: Call InitItem() on refs that are about to be deleted to ensure pointers to enable-state parents are valid.
Cause4: World persistent ref map problem: World spaces keep lists of all persistent objects belonging to a particular exterior cell
in a map. This map uses the cell's grid coordinates as a key for the object lists. When an object is added to a cell the game
checks the object's current pos to find the grid coordinates of the appropriate cell and adds the object to list. The same
procedure is used when unregistering an object that is to be removed from the cell. The problem comes from the fact that
when an object is moved to another cell its position is updated before unregistering it from the current cell and registering
it to the new cell. So while the registering process has the correct (new) coordinates for the object the unregistering
process fails because it would need the old coordinates for the object it used when the object was registered. The object
stays in the object list for the old cell which leads to similar problems as with the cell reset problem mentioned above.
Additionally, the world space's map keeps growing as objects are added and removed and when an exterior cell that was loaded
before is loaded again objects may be added to the cell's object list which don't belong there (anymore) which may have
unpredictable side effects.
Solution4: Since cause end effect are far appart in the code the chosen solution is to add an additional map to the world spaces
and store the grid coordinates of the objects at the time the objects were registered. This makes the unregistering
independent of the object's current pos. To archive this some unused padding bytes in TESWorldSpace class are used to
store a pointer to the new map.
Remarks: This fix was originally called 'UndeletedRefLoadFix'. It is now a collection of individual fixes for problems that
contribute to CTD on shutdown. Unless you have a bugged mod that itself causes CTDs you should be able to quit
the game without getting CTD most of the time with this but there are still some occasional crashes left that are
hard to diagnose. New fixes might be added to the collection if a problem is found and a fix is possible.
Some of the problems addressed by these patches may cause CTD during the game as well (e.g. when returning to main menu)
so it is strongly recommended to leave them all enabled even if you use plugins that bypass the shutdown process
like FastExit. Only disable a patch if it conflicts with another OBSE plugin.
Setting: bInstallUndeletedRefPatch
Enables (1) or disables (0) the patch for the undeleted ref problem.
Setting: bInstallCellResetPatch
Enables (1) or disables (0) the patch for the cell reset problem.
Setting: bInstallResetObjectPatch
Enables (1) or disables (0) the patch for the reset object problem.
Setting: bInstallWorldPersistentRefMapPatch
Enables (1) or disables (0) the patch for the world persistent ref map problem.

DeathItemFix (v1.0)
-------------------
Problem: When a leveled list produces more than one death item the item count for the first item is used for all subsequent items.
Additionally, multiple scripted death items will cause memory leaks.
Cause: See poblem description. Two simple bugs in the function that resolved death items for actors.
Solution: The fix replaces the loop that handles the leveled list generated death items to avoid these bugs.
Remarks: Since most leveled lists for death items produce only one item this fix is rarely needed.


DropItemFix (v1.0)
------------------
Problem: CTD when an NPC drops items. The exact circumstances under which this happens are unclear.
The behavior was observed with the AI package "MirisaDeliverMeat" (0003154D) in Oblivion.esm.
Cause: The game sets the player as the owner for the dropped items if no other owner is specified.
It even tries to do so when the item to drop has no ExtraDataList (each ExtraDataList represents an item "stack").
Since ownership information is stored in the ExtraDataList the game crashes on a NULL-pointer exception.
Solution: Skip ownership assignment when the item has no ExtraDataList.


LoadCreatedBaseObjectsFix (v1.0)
--------------------------------
Problem: CTD with created/cloned NPCs after load order changes.
Cause: This is a bug in OBSE, not the game engine. To fix problems with scripts trying to access created base obects which are
not loaded yet OBSE delays the object initialization until all objects are loaded. However, adjusting form IDs
to the current load order during the initialization process is slightly different for created base objects that it is for
forms loaded from a mod file. To distinguish between the two cases, a flag is set in th class that handles save game load.
The OBSE devs overlooked the setting/unsetting of this flag so references inside created base object definitions are not
resolved properly if the load order changed. In case of NPC's race, hair and eyes this leads to CTD when the NPC is loaded.
Solution: The fix keeps the required flag set until OBSE has initialized all created base objects. This is a temporary solution.
Hopefully, newer versions of OBSE will have this bug fixed.
Remarks: Applying this fix does not repair affected base objects with a wrong form ID caused by this bug. It can only prevent the
bug from corrupting the form IDs while activated.
Debug (L2): Adds two lines to the log. One when the crucial flag is set and one when it is unset.


PlayerDeathCameraFix (v1.1)(v1.3)(v2.0)
---------------------------------------
Problem1: Camera is stuck at ground level when trying to resurrect the player after death.
Cause1: Resurrecting the player not really supported by the game so no code was added to reset the changes made to the camera.
Solution1: The fix resets the camera to the initial height when resurrecting the player. The timer to show the load game menu is
also reset so the menu doesn't pop up immediately the second time the player dies.
Remarks1: The implementation was changed in v1.3. The fix now properly resets the camera height when the player is marked as Essential.
Problem2: Player controls are stuck if the player dies while in first person mode and the 'Essential' flag is set on the player.
Cause2: The game waits forever for the knocked state to get updated but the knocked state system does not support first person mode at all
so this event never happens. The devs forgot to force a switch to third person mode whenever the essential PC dies.
Solution2: The problem is fixed by adding a switch to third person mode when the essential player dies.
Setting: bFixEssentialPlayer1PCamera (v2.0)
Enables (1) or disables (0) the additional fix for the first person camera as described in Problem2.


UseItemAtPackageFix (v1.2)(v1.3)
--------------------------------
Problem: UseItemAt AI packages not working properly with certain objects types or only working the first time.
Cause: Items used by an AI package (food, etc.) is never cleared. When the game gets to the UseItemAt AI procedure it
first verifies that the item to use is of the spefified object type (of set in the editor). If not, the Acquire procedure
is called. But when the object type is a type which does not really represent an item (e.g. Weapons: H2H or spells)
the Acquire procedure returns command to the UseItemAt procedure immediately, without updating the item to use, thus
closing the circle. Additionally, a bug in the selection of an actual spell for spell type objects types causes the spell
to be use only once before it is lost and never used again while the package is running.
Solution: The fix clears the leftover 'item to use' in the Acquire procedure before going back to the UseItemAt procedure.
Remarks: Implementation was changed in v1.3. The spell item selection is now fixed as well.


Cell3x3LocalMapIconsFix (v1.2)
------------------------------
Problem: Making modifications to the exterior cell at grid coordinates 3/3 makes all map markers on the local map disappear.
Cause: A strange piece of code (leftover from a debugging session?) replaces the grid x/y coordinates from the current cell
with the formula ((uGridsToLoad - 1) / 2) + 1 whenever the cell with these coordinates is found in the world space's
cell list. Exterior cells are usually created dynamically when the cell is loaded. Only when a mod adds or modifies
something in the cell does it get added to the cell list at startup. While the cell is not in the list the problem does
not occur. The problem DOES occur while the cell is in the range of loaded cell even if no mod modifies it.
Solution: The fix simply removes the code that replaces the grid coordinates of the current cell when loading map markers for the
local map.
Remarks: The 3/3 coordinates in the name refer to the coordinates of the problematic cell when using the initial uGridToLoad value
of 5. If this value is changed the coordinates for the affected cell also change.


CellChangeCollidedArows3DFix (v1.3)
-----------------------------------
Problem: When moving to a cell that is currently not loaded (and not in the loaded cell cache) then all arrows stuck in the
player's body end up as a clump somewhere near the 0/0/0 point of the cell.
Cause: The 3D of arrows stuck in an object is attached to the collided node in the 3D of the object.
When the actor changes cell, the arrow's parent cell must be updated as well. The arrows are also added to the object
list of the cell. When the cell gets loaded it loads (if necessary) and attaches the 3D of all its objects to it's own
node in the scene graph. For arrows, this means that they loose their parent node and get attached to the cell's 3D instead.
Since the offset from the collided node is usually small they reapear near the 0/0/0 pos within the cell.
Solution: The fix makes sure that arrows that collided with actors are not attached to the cell's 3D when the cell loads.


ScriptPackageFix: (v1.3)
------------------------
Problem: The script command "RemoveScriptPackage" can lead to memory leaks as well as heading targets and followers not getting
removed properly in some cases.
Cause: The usual pattern for removing a script package is to first use "GetIsCurrentPackage" to verify that the actor's
current package is the script package one wants to remove before actually removing the package with "RemoveScriptPackage".
A huge problem whith this approach is that "GetIsCurrentPackage" will return true even if the actor's current package is
NOT the package in question because it was temporarily interrupted by a dynamic package (Dialogue, Flee, Combat, etc.).
In this case the function checks the SAVED package (the package that will be restored once the dynamic package finishes).
"RemoveScriptPackage", on the other hand, unconditionally removes the current main package, which may or may not be the
script package for which "GetIsCurrentPackage" just returned true. Furthermore, "RemoveScriptPackage" simply sets the
current main package to NULL, followed by a call to EvaluatePackage, so no cleanup action is performed.
Solution: This fix changes the "RemoveScriptPackage" command so it checks for a dynamic package first. Dynamic packages won't be
removed. If the current saved package is not a dynamic package the saved package will be removed instead. This ensures
that the "GetIsCurrentPackage" + "RemoveScriptPackage" pattern will work as expected.
Additionally, cleanup action for the package target's follower list is performed.
Remarks: This fix was originally called "RemoveScriptPackageFix". Implementation was changed completely in v1.4. The fix no longer
prevents the removal of packages that are not marked as script packages since the script package flag is lost when the user
saves and reloads. The check for the script package flag being set prevented the combination of GetIsCurrentPackage +
RemoveScriptPackage from working after reloading.
Debug (L1): Logs failure to remove actor from target's follower list because of unexpected package target (should not happen).
Debug (L2): Logs the performed action for "RemoveScriptPackage" in case the current main package is a dynamic package.


HUDInfoQualityIconFix (v1.3)
----------------------------
Problem: The quality icon for apparatus type objects is not shown in the HUD info when the mouse cursor is hovering over such objects.
Cause: A bug in the ref's base object lookup code prevents refs of apparatus type objects to be recognized as such.
Solution: The fix ensures that apparatus type object refs are properly recognized so the HUD icon shows up.


CreatureBipedObjectEquipFix (v1.4)(v1.7)
----------------------------------------
Problem: When using the EquipItem script command on creatures with an unsupported clothing or armor object the creature's
entire 3D gets duplicated (two bodies, two heads, etc.)
Cause: Creatures cannot equip clothing or armor (except shields). The EquipItem command will not equip these items, but
an update of the actor's 3D is still triggered if the item uses the upper body, lower body, hand or foot slot.
For creatures this means that the entire NIF file list (as specified in the editor) will be loaded but the already
loaded 3D is not released.
Solution: Determining which 3D part from the NIF list is attached to which node in the existing 3D proved to be quite difficult
so releasing the existing parts was not an option. The current solution simply aborts the EquipItem method for creatures
if the item to equip is of type Clothing or Armor unless it is a shield, amulet or ring.
Remarks: Creatures cannot equip amulets or rings either but these are handled differently and don't trigger a full update of the
actor's 3D so it's save to call EquipItem with those.
A second patch was added in v1.7 to the RemoveWornItems AI procedure which is called when an actor starts combat while
on an AI package with the RemoveWeapons or RemoveArmor flag set. Again, reloading of the actor's 3D has to be skipped
if the actor is a creature to avoid body model duplication (and in some cases CTD).

DialogueWaitFix (v1.4)
----------------------
Problem: Sometimes dialogue between two NPCs does not start. The NPCs keep staring at each other.
Cause: When a Dialogue AI package interrupts a package that was currently executing the Acquire procedure then the
AcquireObject info in the process causes the TravelTarget procedure to take the wrong code path. This moves the
aproaching actor's procedure index to the Wait procedure instead of activating the other actor. With both actors
in the Wait procedure the dialogue cannot start.
Solution: Check whether the current package is a Dialogue package when the actor has an AcquireObject while executing the
TravelTarget procedure.


ExteriorCellTempObjectsLoadFix (v1.4)
-------------------------------------
Problem: When moving to a new world space created by mod there is no ground and no static objects.
Only doors, actors and trees are loaded.
Cause: This problem happens if a new world space is defined in a master file that is not loaded in the same slot
as it was in CS. All cells with visible-when-distant objects are affected.
In a mod file, the visible-when-distant sub-group appears before the temporary objects sub-group.
Both groups (if present) are loaded in one loop. When the loading function encounters the temporary objects sub-group
header it verifies that the parent cell form ID specified in the header matches the form ID of the current cell that is
getting loaded. Since the current cell's form ID is adjusted to the running game's load order the comparison to the form
ID in the header (which is still in CS load order) will fail unless the running game's load order matches the load order
at creation time. When the form ID comparison fails the entire temp objects sub-group is ignored.
Solution: The fix adjusts the parent cell form ID from the group header to the running game's load order before comparing it to the
current cell's form ID. This ensures that the temp objects sub-group always loads correctly.
Remarks: This fix cannot help if a mod author makes the mistake of altering a world space defined in a master file when the mod
itself is also a master file.


BuyItemFromContainerFix (v1.5)(v2.1)
------------------------------------
Problem: NPCs fail to buy items (food) from containers owned by a merchant. The bug can sometimes lead to CTD.
Cause: The engine wrongly handles buyable items in containers as items that can be activated.
Solution: Handle these items like items found in a merchant's inventory: Transfer the item to the buyer's inventory
and the required gold to the merchant's inventory.
Update: Code was rewritten in v2.1 to address an additional problem. Since the actor has to walk up to the container owner
to actually buy the item there is a chance that another actor has already bought the same item. In that case the actor
is paying for an item he/she doesn't get. Additionally, the game may crash if the NPC chose a specific item stack
that is no longer valid. This is likely the case if the selected item is scripted.


DialogMenuEmptyTopicsFix (v1.5)
-------------------------------
Problem: Dialog menu topic list is empty (invisible) if dialogue was started while menus were hidden.
Cause: This problem occurs because the topic list's 3D cannot be attached to it's supposed parent node
when it is created if menus are hidden. It gets attached to the menu root node instead where it
does not get proper update notifications.
Solution: Postpone topic list's 3D creation until menus are re-enabled.


LoadCellTempDataFix (v1.5)
--------------------------
Problem: Cell temp data (including landscape) fails to load if an object moved into an unloaded cell.
Cause: The bug only occurs if the cell is modified by a mod. The engine distinguishes between objects
added by a mod (loaded when game starts) and stuff defined in the master file (loaded when the
cell itself needs to be loaded). Modified exterior cells usually don't have master file information
because they were created when reading the modified cell record whereas the master file record was skipped
during initial mod loading. This is not a problem because master file information is usually taken from
the parent world space when an exterior cell needs to be loaded. However, when an object is moved into
such a cell while it is not loaded, the game needs to load the temp data (landscape) to properly place the
new object. This process uses the master file information from the cell itself so it may fail if the
cell has no master file in it's source file list. It still sets the "Temp Data Loaded" flag on the cell
preventing subsequent cell loads from loading the missing temp data.
Solution: The solution calls the same method that is used when the cell is actually loaded. This will use the master file
information from the parent world instead of the cell itself.


RunScriptLineFix (v1.5)
-----------------------
Problem: There is a small chance that you will get CTD on startup if a mod uses OBSE script command 'RunScriptLine' or
'RunBatchScript'.
Cause: A bug in the OBSE code gives a 1:255 chance that the game's console instance is not yet created when one of
the above mentioned commands is called for the first time.
Solution: This patch simply ensures that the console instance is created before any sripts run.
Remarks: CTD only occurs in OBSE v0020 or lower. In v0021 CTD is prevented but the bug is still not fixed so the script
commands may still fail.


SpellPurchaseCrashFix (v1.6)
----------------------------
Problem: Game crashes when buying the last remaining spell from a vendor's list by using the arrow keys on the keyboard.
Cause: Insufficient NULL-pointer checks in game code.
Solution: Added the necessary checks to avoid CTD.
Debug (L2): Prints a message to the log file when CTD was prevented.


GlobalAnimTimerFix (v1.6)
-------------------------
Problem: Non-actor animations (doors, traps, flames, etc.) may freeze when the total playing time exceeds a certain limit.
Cause: The global animation timer which all non-actor animations use to update their states is a 32-bit floating point
value which gets higher and higher as the frame time is added each frame. The value is never reset and is also
stored in the save game. Due to the limited precision of 32-bit floating point values, when the value becomes very
high and a small value like the frame time is added to it, the small number may lose some bits in the mantissa which
effectively truncates it to zero. Thus the global animation timer will not increase anymore and the animations that
use the timer for calculating the current frame are stuck.
The problem occurs when the value reaches 4A000000h, which represents 2097152.0. If the timer represents real time
seconds then this would correspond to 583.54 hours of playing time. However, it has been observed that the limit is
reached much faster with higher frame rates.
Solution: The patch resets the timer on save game load whenever it reaches 48000000h (131072.0) which is quite below the limit.
Remarks: Like all other solutions for this bug it is theoretically possible that an animation which ran while the game was saved
may glitch on load after the timer got reset. However, in all the years these patches were in use no one has ever
reported anything noticeable. In any case, these potential glitches, should they occur, would most likely resolve
themselves after a few seconds.
A message will be written to the log file whenever the timer is reset.
Debug (L2): The current value of the global animation timer is written to the log file whenever a save game is loaded.


AIPackageScheduleEvaluationFix (v1.6)(v1.8)
-------------------------------------------
Problem: AI package schedules evaluation does not work correctly when the schedule crosses midnight.
Cause: The combination of month/day/week-day/hour + duration with all of these supporting the special value 'Any'
creates a complexity in the AI package schedule evaluation that is far greater than what the devs anticipated.
The default schedule evaluation function does not work correctly when the schedule crosses midnight and it only
checks the previous and the current day for possible matches.
It also assumes that every in-game month has exactly 30 days which is not true.
Solution: This patch rewrites the schedule evaluation function to properly support schedules that cross midnight.
It also supports schedule durations exceeding 24 hours up to a full year.
Remarks: Due to rising complexity in the evaluation function support for schedule durations > 24 hours is limited to fixed day
and single week-day schedules. The month can be set to 'Any' in both cases.
Multiple week-days (i.e. Loredas + Sundas) are not supported. (There are no such AI packages in vanilla Oblivion.)
If such a schedule is encountered the duration will be limited to 24 hours and a warning message is written to the log file.
Keep in mind that if a schedule sets the start hour to 'Any' the schedule will evaluate to 'true' on the specified day from
start to finish but not beyond. In other words the duration for these schedules will be ignored. This is consistent with
the behavior of the original function for schedule durations <= 24 hours.
Setting: bSurpressRepeatedWarnings
Enables (1) or disables (0) the option that limits warning log messages to one per AI package in a single game session.
This is to prevent the log file from printing the same message every time such a package is evaluated.
Update: Since v1.8 evaluating AI packages with a duration > 24 hours will no longer produce warnings if the schedule is set to
run at any time. Such packages will not use their duration value anyway, so the warning about truncated duration is
meaningless.


AcquireWeaponNoAmmoFix (v1.7)
-----------------------------
Problem: Actor in combat is just standing around doing nothing even when attacked.
Cause: If the combat AI for an actor chooses the ranged melee strategy but the actor currently does not have ammo equipped
the code will not check the inventory for existing ammo but try to acquire (search ground, etc.) some.
If ammo can be found this is not a problem, but if no ammo can be found the actor will just stand around and do nothing.
Solution: Add code to check actor's inventory for ammo first before switching to the Acquire maneuver.
Remarks: This bug is quite rare. Usually an actor equips bow and ammo simultaeously. It is not known under what circumstances
an actor in combat ends up with a bow equipped but no ammo but it has been observed.

PickupItemOwnershipFix (v1.7)
-----------------------------
Problem: When picking up dropped ingredient items using the quantity menu and selecting less then the full count the remaining
items will loose ownership while the picked up items will count as stolen.
Cause: The remaining (dropped) item stack loosing ownership is caused by a wrong flag when copying data from the existing
stack to the newly created stack that is to go into the player's inventory. The flag causes all data from the source
stack to be removed after copying.
The picked up stack getting marked as stolen is caused by a wrong comparison between the player ref and item's owner.
Since the later is a base object (not a reference) the comparison is never true so the stack ends up in the player's
inventory with the 'Player' ownership remaining which the inventory menu treats as a stolen item.
Solution: The remaining stack loosing ownership and other data is solved by setting the correct copy flag so existing data is
not removed if the player does not pick up the whole stack.
The picked up stack getting marked as stolen is solved by comparing the player's base object to the item owner so
the 'Player' ownership data is properly removed.
Remarks: This bug only happens when picking up ingredient items since only ingredient items will trigger the quantity menu
which lets the player pick up less than the whole stack.
In all other cases the whole stack is moved to the player's inventory so the problem doesn't arise.

BloodDecalMemLeakFix (v1.7)
---------------------------
Problem: Memory leak depending on your settings in Oblivion.ini.
Cause: The blood decal generation code creates decal data objects before checking the bDecalsOnSkinnedGeometry ini setting.
If the setting is 0 (false) and the target mesh is skinned then the decal will not be created but the decal data is
not destroyed. Since the decal data references objects which themselves reference potentially large textures these
textures will never be purged and remain in memory for the entire game session.
Solution: Change code so the decal data is only created if the decal itself is created.
Remarks: This bug only occurs if bDecalsOnSkinnedGeometry is set to 0 but it doesn't hurt to have the fix enabled even if you
have decals on skinned geometry enabled. Performance is not affected by this patch.

BowAndTorch3DFix (v1.7)
-----------------------
Problem: CTD on exit, when going through a load door or when updating an actor's 3D.
Cause: When an NPC equips a bow while already holding a torch the torch's 3D may accidently get attached to the back weapon
node in the skeleton (where the bow's 3D is supposed to go). When such an actor's 3D gets unloaded the game crashes
because the torch's 3D is destroyed twice.
Solution: Add an additional check in the code to prevent the torch's 3D getting reassigned to the back weapon node.

VerboseMessgesFix (v1.8)
------------------------
Problem: CTD or broken console messages when verbose messages are enabled.
Cause1: Insufficient NULL-pointer checks in the DisintegrateWeaponEffect active effect code causes CTD when the effect is applied
to an actor who currently has no weapon equipped.
Solution1: Skip the message if the actor has no weapon equipped.
Cause2: Broken messages (and possibly CTD in some cases) about reflected damage when hitting an actor who has ReflectDamage > 0
are caused by an incorrect call to the PrintToConsole function. The call omitts the reflected damage points in the argument
list so the points are never printed and the target name is interpreted as a number (which can occasionally cause CTD).
Solution2: Call PrintToConsole with all the necessary arguments.
Remarks: This is a collection fix for bugs that only occur when verbose messages are enabled via the 'Verbose' console command.
If verbose messages are enabled, the game prints various messages (mostly combat related) to the console. These messages
can be very helpful for understanding or debugging the game mechanics. They have no meaning for normal gameplay.
Setting: bInstallDisintegrateWeaponEffectFix
Enables (1) or disables (0) the patch for the bug described above in Cause1.
Setting: bInstallReflectDamageFix
Enables (1) or disables (0) the patch for the bug described above in Cause2.


SummonAILocationTargetFix (v1.8)
--------------------------------
Problem: When setting the SummonCreateDefend AI package for summoned, commanded or reanimated creatures the code sets the
package's location target reference before setting the location info's type to 'Reference'. The location info
rejects the target reference because it (still) has the wrong type.
Solution: Set the correct location info type before setting the target.
Remarks: It is currently unknown what consequences the failure to set the location target actually has in game. The patch
only fixes some lines of code that are in the wrong order.

UIMessageFix (v1.8)
-------------------
Problem: No more notice messages are shown until the game is restarted. Notices refer to the messages shown in the upper left corner
of the screen.
Cause: Queueing an empty string causes the menu to not find the active notice anymore so the message queue will never get updated
again.
Solution: Treat NULL-pointers, empty strings and single spaces as an 'empty' message. This way the string comparison always works
and the menu can find the active notice.
Remarks: It is usually not possible to send an empty string to the notice queue when using the common script functions like 'Message'
or 'MessageEx'. The only way to send an empty string to the queue is by modifying game settings like 'sNoCharge' to nothing
in TES4Edit or similar tools. The bug can be avoided by making sure no game setting is set to an empty string.
Setting: bInstallEmptyNoticeBugFix
Enables (1) or disables (0) the main patch for the problem mentioned above.
Setting: bInstallNoticeSubtitlesBugFix
Enables (1) or disables (0) the patch for an additional bug fix where queueing a notice message wrongly resets the subtitles
state timer and state.

CrimeGoldRemovalFix (v1.8)
--------------------------
Problem: NPC bounty is never removed except when essential actors are knocked down.
Cause: Code only removes the required gold from the actor's inventory when paying but not the bounty.
Solution: Add necessary code to the resurrect and crime gold pay functions.
Setting: bRemoveOnPay
Enables (1) or disables (0) the patch that removes bounty after the NPC has properly payed the gold to a guard.
Setting: bRemoveOnResurrect
Enables (1) or disables (0) the patch that removes bounty when an NPC is resurrected.

ActivateDoorWhileInvisibleFix (v1.8)
------------------------------------
Problem: Unable to move after going through a load door.
Cause: The update function for the 'teleport fade state' explicitly checks the Invisibility actor value. While this value
is not zero the state cannot advance to the 'FadeIn' state when the actor has passed through the door. Since active
effects are not updated before the fade state is 'Normal' again an invisibility spell cast at the same time the
player activated the door (thus evading the hard-coded dispel for invisibility) will never terminate and the teleport
fade process can never complete. The player's controls will remain disabled.
Solution: Remove the explicit check for the Invisibility actor value.
Remarks: Tests have shown that the check for the actor value is completely unnecessary. Even with a permanent modification of
the Invisibility value the fade-in process works as expected.

ActorWithoutProcessCTDFix (v1.9)
--------------------------------
Problem: CTD when using certain script commands on an actor who currently has no AI process assigned.
Cause: Insufficient tests for NULL-pointers before accessing an actor's AI process.
Solution: Add missing tests for NULL-pointers.
Remarks: This is a collection fix for a couple of script commands that may cause CTD for the same reason mentioned above.
Setting: bInstallGetAttackedFix
Enables (1) or disables (0) the patch that fixes the GetAttacked script command.
Setting: bInstallGetFurnitureMarkerIDFix
Enables (1) or disables (0) the patch that fixes the GetFurnitureMarkerID script command.
Setting: bInstallGetLineOfSightFix
Enables (1) or disables (0) the patch that fixes the GetLineOfSight script command.
Setting: bInstallGetWalkSpeedFix
Enables (1) or disables (0) the patch that fixes the GetWalkSpeed script command.
Setting: bInstallIsActorUsingATorchFix
Enables (1) or disables (0) the patch that fixes the IsActorUsingATorch script command.
Setting: bInstallIsCurrentFurnitureObjFix
Enables (1) or disables (0) the patch that fixes the IsCurrentFurnitureObj script command.
Setting: bInstallIsCurrentFurnitureRefFix
Enables (1) or disables (0) the patch that fixes the IsCurrentFurnitureRef script command.
Setting: bInstallIsRunningFix
Enables (1) or disables (0) the patch that fixes the IsRunning script command.
Setting: bInstallIsTalkingFix
Enables (1) or disables (0) the patch that fixes the IsTalking script command.

BoundItemEvaluationFix (v1.9)
-----------------------------
Problem: Actor with bound weapon fails to start combat + potentially other issues.
Cause: This problem is specific to bound weapons and weapons equipped via script with the 'Cannot Wear' flag (also known as the
'No Unequip' flag) set. Shields may also be affected. The cause of the problem lies in the equipment evaluation function for
NPCs which starts by unequipping all items followed by unsetting the cached equipped inventory entries for the weapon, ammo,
shield, and torch slot. The cached entries are unset unconditionally but if one of these slots had an item with the
'Cannot Wear' flag set then the preceeding call to UnequipAllItems() did not really unequip the item. The missing cached
entries may then cause further problems in the AI code. E.g. the CombatController AI package fails to determine a suitable
combat strategy when combat starts causing the actor to just stand around and do nothing.
Solution: Keep the cached inventory entries in the equipment evaluation function if the items are still equipped after the call to
UnequipAllItems().

CanHaveFlamesFix (v1.9)
-----------------------
Problem: CTD when using script command CanHaveFlames.
Cause: The command needs to access the reference's 3D object but does not check for a NULL-pointer. If the reference's 3D is NULL
the game crashes.
Solution: Add the missing NULL-pointer check.

HighProcessTeleportFix (v1.9)
-----------------------------
Problem: When an NPC in a loaded cell uses a load door where the destination is also in a loaded cell the NPC may fade out in front
of the activated door only to fade in again at the same spot, thus unable to go to the teleport destination.
Cause: The normal teleport for doors works as intended and the NPC's coordinates are updated properly but since the NPC is still
in high processing the character controller (which handles collision, etc.) may still have the old coordinates. In the next
frame the NPC's coordinates are updated to the char controller's coordinates as part of the movement/physics update so he/she
will be back at the original position in front of the load door he/she just passed through.
Solution: Update the char controller's coordinates after passing through a door if the destination cell is loaded.
(If the destination cell is not loaded the NPC will fall to low processing and the char controller is removed so everything
works as expected.)

MagicCastFailureSoundFix (v1.9)
-------------------------------
Problem: Player's magic cast failure sounds suddenly stop playing.
Cause: The handles to the cast failure sounds for the different magic schools are cached in the player character instance
after they have been successfully loaded. Purging cell buffers and other cleanup actions may unload the actual sound
from memory but the cached handles in the player character instance are not released when that happens. When trying to
play a cast failure sound the code sees the handle and expects the sound to be loaded but since it is not loaded anymore
calling Play() on the handle does nothing.
Solution: Check that the sound is still loaded before calling Play() on the handle and reload the sound if necessary.

PackageStartEquipmentFix (v1.9)
-------------------------------
Problem: NPCs may not unequip or re-equip armor/weapons according to the AI package flags when a new package starts.
Cause: When an NPCs starts a new AI package an equipment evaluation only occurs if the REPLACED package was either a sleep
package or had either the Armor Unequipped or the Weapons Unequipped flag set. The same flags on the new package do NOT
cause an equipment reevaluation. Furthermore, if the NPC was in conversation while the editor package was supposed to
switch to a new package then the NPC will reevaluate his/her equipment after the conversation but the 3D model is not
updated. He/she may appear to be still wearing full armor even if the armor was unequipped.
Solution: Force an equipment evaluation and 3D model update whenever an NPC in a loaded cell switches to a new (editor) package
if either the old or the new package have any 'unequip' flags set.

SoundEffectsFix (v1.9)
----------------------
Problem: 3D sounds appear to stop working after closing a menu. This does not happen in the cell the player is right after
loading a save game.
Cause: Unknown. The sounds are still playing but for some reason they are not audible even though the volume has not changed.
Solution: Setting the volume of the sound to the minimum (muted) value right before setting the actual volume when all sounds are
resumed after closing the menu appears to fix the problem. It is currently unknown WHY this fixes it but apparently it does...

StaffEnchantmentCastTypeFix (v1.9)
----------------------------------
Problem: Using a staff at an enchantment altar will result in an enchantment where all effects work on Touch instead of Target
which is the correct effect range for staffs. The available effects are also filtered for the Touch range and not for the
Target range.
Cause: Enchanting staffs is not really supported in the game. There are no 'empty' staffs in the vanilla game but they can be
added by mods. Since the enchantment menu does not expect Staffs as source items no code was written to properly update
the cast type and effect range for staffs.
Solution: The fix adds the necessary code so that enchantments for staffs get the correct Target effect range. It also ensures that
available effects are filtered for the Target range and not the Touch range.

UnloadedObjectReferencesFix (v1.9)
----------------------------------
Problem: Potential CTD due to access to unoaded objects + save game bloat.
Cause: When an object reference in game gets unloaded it must be unregistered from all other actors and objects that may
hold a reference to said object ref. However, the function responsible for the unregistering fails to unregister the
ref from two places in the player class instance: disposition modifiers and the 'greeter' ref (i.e. actor that is about
say a greeting to the player). This leads to pointers to non-existing objects which would cause CTD when accessed.
Additionally, when saving the game, whatever data is at the location in memory where the object originally was is stored
in the save game's form ID table which holds all form IDs referenced in the save game. These entries to non-existing
form IDs unneccessarily increase the size of the lookup table which affects save time. (Load time is not affected.)
Solution: Add code to unregister the unloaded object ref from the above mentioned places in the player class instance.

WeaponSwitchFix (v1.9)(v2.0)
----------------------------
Problem: Creatures with bow and melee weapon switch from ranged to melee when the player gets too close but the melee weapon gets
unequipped immediately and the creature continues to fight with hand-to-hand only.
Cause: A timing problem in the code causes the newly equipped melee weapon to get unequipped when evaluating the current
animation action. Once the creature fights with hand-to-hand it never returns to weapons since its h2h damage is usually
higher than the weapon damage.
Solution: Prevent melee weapon from getting unequipped after a ranged to melee weapon switch.
Remarks: This fix was unavailable in v1.9 due to an internal bug. The bug was fixed in v2.0.

CellChangedRefMemLeakFix (v2.0)
-------------------------------
Problem: Memory leak and possible CTD at shutdown.
Cause: When a saved game is loaded and an object ref is marked as having moved from its original cell then the game code
must go through the original cell's full list of plugin files that modify the cell and try to find a plugin that
actually has the ref in its list of temporary objects. The ref is than created and its definition loaded from the plugin
file before the save game changes are applied. This all works ok if the ref is only defined in one plugin file but if
another plugin overrides the ref's form record then the ref is created more than once and the pevious instances leak.
Since the leaked instances are not yet initialized (i.e. contain form IDs instead of pointers to forms) it can cause
CTD at shutdown when a ref's destructor is called.
Solution: Make sure the object ref is only created once when loading its definition from the original parent cell's source plugins.

ObjectPaletteFix: (v2.0)
------------------------
Problem: CTD (especially when INI setting 'bFixFaceNormals' is enabled)
Cause: The gamebryo engine defines a 'object palette' class which maps names of nodes and meshes in a ref's 3D to the
actual objects for quick lookup. The object palette is usually initialized when a ref's animation object is created and
after certain events in the animation system. Bethesda's code, however, does not update the palette after an actor unequips items.
This leads to the palette containing pointers to deleted objects which, when accessed, cause instant CTD. Since the game usually
only uses the palette to look up special nodes with unique names the invalid pointers are harmless most of the time. One case
where the problem becomes apparent, however, is the INI setting 'bFixFaceNormals', as the code tries to look up an object with
the name 'UpperBody' in an actor's 3D. Since even the vanilla armors sometimes contain multiple meshes named 'UpperBody' the
chance that the object palette returns a pointer to a deleted object is quite high.
Solution: Unregister all meshes and nodes from equipped items when they get unequipped.

SavedHavokDataFix: (v2.0)
-------------------------
Problem1: T-pose for dead actors + memory leak
Cause1: Because of the peculiarities of the threaded background loading system for cell objects it can sometimes happen that an
actor's 3D gets unloaded and reloaded before the saved rag-doll data of a dead actor is applied. In this case the current
pose is saved as the new rag-doll data, replacing the original data (which leaks). When the actor's 3D is finally loaded
the actor appears in the 'T-pose', which is simply the original pose from the skeleton NIF file.
Solution1: Prevent code from overriding existing rag-doll data and properly release the unwanted dummy data.
Problem2: Stretched objects and uncontrolled movement for partially havok-enabled objects (hanging lights, havok'ed roots), etc.
Cause2: The game engine is supposed to remove all havok data for cell objects when the cell resets. When the game is saved, the
engine removes the data from all loaded objects in expired cells to keep the save game size as small as possible. If the object
is not loaded at the time the game is saved, a special flag is set so the data is removed the next time the object is loaded.
However, the code only removes havok data taken directly from the collision objects in the ref's 3D but not data that has already
been moved to the object's extra data list. The result is partially reset havok data which leads to all sorts of problems as
the ones mentioned above.
Solution2: Make sure expired saved havok data in the extra data list is properly removed from all refs.
Setting: bPreventSavedHavokDataOverwrite
Enables (1) or disables (0) the fix for 'Problem1'.
Setting: bPreventExpiredHavokDataLoad
Enables (1) or disables (0) the fix for 'Problem2'.
Setting: bSkipAllStaticHavokDataLoad
Enables (1) or disables (0) an optional patch that skips loading of ALL havok data for static objects and non-carryable lights.
This means that all havok moved objects will reset to their original position when a cell is loaded.
It is basically a much less refined version of Solution2 solving the havok related problems for objects by simply resetting
everything in the cell and is therefore not recommended unless resetting everything is exactly what you want.
The functionality of the patch is identical to the old 'HavokMovedDataLoadPatch', which was removed in v2.0 and replaced by the new fix.
This setting is initially disabled and must be enabled in the INI file by the user.
Remarks: Both solutions can only prevent the related problems from occuring. They can NOT fix these problems if the damage is already done
and persisted in the save game file. Such objects or actors would have to be put into havok mode again (push/hit/grab etc.).
Then the fix can prevent the problems from occuring again.

CombatBuffSpellSelectionFix (v2.1)
----------------------------------
Problem: NPCs never use spells Spell Absorption and Reflect Damage in combat even if they are in their spell list.
Cause: When combat starts the game selects spells based on their category (restore, buff, melee, etc.).
The buff spell category has a fixed list of supported magical effects. Reflect Damage (REDG) is not in the list.
Spell Absorption (SABS) is also not in the list, but Absorb Magicka (ABSP) is, even though ABSP never actually goes
into the buff spell list since it is a hostile spell and therefore counts as a melee spell. It seems likely that
the devs meant SABS and not ABSP when compiling the list of supported buff spell effects.
Solution: Exchange the useless ABSP effect with SABS in the list of supported buff spell effects.
Since it is debatable whether the omission of REDG is intentional or a bug adding this effect to the buff spell list
is implemented as an optional patch.
Setting: bAllowReflectDamageEffect
Enables (1) or disables (0) the optional patch for adding Reflect Damage (REDG) to the list of buff spells an NPC can use
during combat.

HaggleDispositionFix (v2.1)
---------------------------
Problem: Merchant's disposition towards the player is not used in the equation to calculate item prices when the player wants to sell something.
Cause: The code wrongly calculates the merchant's disposition towards him/herself (which is always 100) instead of the disposition towards
the player.
Solution: Fix code so it correctly uses the merchant's disposition towards the player.

RemoveExcessDeadFix (v2.1)
--------------------------
Problem: Respawning actors fail to respawn because they were previously disabled by the game.
Cause: The game tries to preserve performance in a scene with many actors by selectively disabling corpses.
This can be a problem if a disabled actor is supposed to respawn. The actors respawn normally but since they
are still disabled they won't appear in the game anymore.
Solution: Is is not possible to distinguish actors disabled by the 'Remove Excess Dead' routine from actors disabled by
scripts or the console by the time the actors are supposed to respawn. This patch works by excluding respawning
actors from the removal routine so they don't get disabled.

SleepCastLoopFix (v2.1)
-----------------------
Problem: NPCs stuck in a restore spell casting loop while trying to use a bed or bedroll.
Cause: NPCs in high processing usually try to restore their health to max after combat if they can. If they happen to be on a sleep AI
package at that time then they might get stuck in a casting animation loop when they use a bed or bedroll. The code for entering a
bed and for casting a spell are fighting each other, replacing the other's animation while waiting for their own animation to finish.
Solution: Check the casting state before trying to use a bed or bedroll and also check the actor's Sit/Sleep state before attempting
to cast a restore spell.

SneakPowerAttackFix (v2.1)
--------------------------
Problem: When the player becomes a journeyman in Acrobatics, normal attacks while sneaking use the same animation as for power attacks.
Cause: Explicit code in the player character's input handler to use the power attack animation in sneak mode if the Acrobatics skill
level is Journeyman or higher.
Solution: Skip the code that changes the animation.
Remarks: Since there is explicit code for changing the animation it remains unclear whether this is a bug or intentional. Apparently the
change was introduced by one of the official patches. Using the power attack animation for normal attacks has no real benefit but
rather acts as a penalty (longer animation draining more fatigue). There is also no connection between the Dodge skill perk obtained
when becomming a Journeyman in Acrobatics and the change for the sneak attack animation so I decided to treat it as a bug.
It is possible that the piece of code is either the remainder of a debugging session by a dev or a stub for a supposed larger
code change which never got finished.


Patches:
========

SmallBushBillboardPatch (v1.0)
------------------------------
Problem: Smaller bushes don't show up as distant LOD objects.
Cause: The game is hard coded to not to show distant LOD for trees where the billboard dimensions are smaller than 200x350.
This affects about half the bushes defined in Oblivion.esm.
Solution: The patch lowers the threshold size to 10x10 so smaller bushes appear as distant LOD as well.
Remarks: Since distant LOD land is less detailed than the actual landscape small bushes on top of distant hills and mountains
may float in the air a bit.


EvaluateEquipmentPatch (v1.0)(v1.8)
-----------------------------------
Problem: NPC's selection of upper and lower body slot items is overridden by the selection of hand or foot items if thy also
use the upper or lower body slot.
Cause: The hierarchy for body equipment is upper -> lower -> hand -> foot. If an object selected for a higher slot also uses
a lower slot then the selection for the lower slot is skipped. But if the selection for a lower slot happens to
choose an object which also uses a higher slot then the selection for the higher slot is discarded.
Example: Object (a) uses the upper body slot, object (b) uses upper/lower/hand/foot slot (i.e. full body), object (c) uses
the hand slot. The equipment evaluation may choose object (a) for the upper body slot because it has better stats than (b).
But if object (b) has better stats than (c) then object (b) will be selected when evaluating the hand slot. And since
object (b) also uses the upper and lower body slots any objects previously selected for these slots will be discarded
as object (b) replaces them, even if the previously selected items for these slots would have had better stats then
object (b) alone.
Solution: The patch makes sure that objects using multiple slots are only selected during the evaluation of the slot that is highest
in the hierarchy.
Remarks: It has to be noted that this patch affects the equipment choice of some vanilla NPCs which may or may not be a wanted side
effect. One particular example is NPC Lucien Lachance who will wear his clothing instead of the Black Hand Robe. This is
because the black hand robe has a value of 0 so the game considers his normal clothing to be better than the robe. The only
reason why he is wearing the robe in the game is because it uses the hand slot, so when the robe is selected as the
best item for the hand slot it replaces the previously selected clothing items for the upper and lower body slot.
This would be a case where the effect of this patch is probably unwanted. A solution to this problem would be to assign a
proper value to the Black Hand Robe so it has precedence over the clothing items during equipment evaluation.
Update: Since v1.8 actors for whom the modified equipment evaluation is unwanted like Lucien Lachance can be explicitly
excluded by adding an exclusion entry to the ini file under the [EvaluateEquipmentPatch] section. Actors can be excluded
via their object reference or their base object. An exclusion entry must have the following format:
Exclude#= |
The <> parts are placeholders for:
any number that is not already used by another entry
the name of plugin or master file (e.g. Oblivion.esm) containing the actor to exclude
the form ID (hexadecimal) of the actor to exclude inside the plugin or master file
Example: Exclude#1=Oblivion.esm | 000224ED
The example line will exclude Lucien Lachance (defined in Oblivion.esm with object ID 00224ED) from the patch.


CombatBlockPatch (v1.3)
-----------------------
Problem: NPCs in combat go into blocking mode even though nobody is attacking them.
Cause: An NPC's blocking behavior is based entirely on his/her current target's attack action (attack anim playing or not).
What the code fails to check is whether the current target is actually attacking the NPC and not somebody else.
Solution: This patch modifies the blocking behavior so that the NPC will only consider blocking if he/she is within a
45 degree (to each side) view angle of his/her current target (i.e. the current target is looking in the NPC's direction
while attacking).


FloraOwnershipPatch (v1.4)
--------------------------
Problem: Moving the crosshair over owned flora refs shows the "Steal" icon but harvesting these objects does not count as a crime.
Cause: There is simply no code for crime handling when activating a flora ref.
Solution: This patch adds crime handling code to the Activate method of flora objects. Harvesting owned flora will count as stealing.
Remarks: Flora objects don't have a value defined. The implicit value for all flora is therefore 1.


HavokMovedDataLoadPatch (v1.4)(v2.0)
------------------------------------
Removed: This patch was removed in v2.0 and replaced with the more refined SavedHavokDataFix.
The functionality of this patch is still available as an optional patch in the new fix.
See the documentation for the SavedHavokDataFix for details.


TerrainLODLoadPatch (v1.4)
--------------------------
Problem: LOD files for world spaces require users/modders to either adjust the file names to the current load order or to use
tools which "inject" the world space's form ID into the 00 mod index.
Cause: The LOD file names contain the full form ID of the world space which is load order dependent. If the names don't match
the current load order LOD meshes and textures will not be loaded.
Solution: This patch allows LOD files to be loaded using an alternative naming scheme that is load order independent. The game will
first try to load the files using the original, load order dependent names. If the files cannot be loaded then it tries
the alternative names.
Remarks: The alternative naming scheme expectes the files to be placed in a subfolder named after the mod file that defines the
world space (including file extension). The actual file name is the same as the original name, only the form ID part is
replaced with the editor ID of the world space.
Example: A LOD mesh file for a world space with editor ID "MyWorld" may be named "4781446.-32.-32.32.nif" by the CS.
This file would be located in "Data\Meshes\Landscape\LOD\4781446.-32.-32.32.nif". The alternative file name would be
"MyWorld.-32.-32.32.nif". If the mod that defines this new world space is called "MyMod.esm" then the path to the
alternatively named file would be "Data\Meshes\Landscape\LOD\MyMod.esm\MyWorld.-32.-32.32.nif".
Again, the engine will first try to load the file from the original location. If it cannot find the file (e.g. because the
load order changed) then it will try to load the file from the alternative location. The alternative file location does
not depend on the load order.
Debug (L1): Prints a line to the log file if an alternative LOD file name cannot be created because the world space has no
editor ID (shouldn't really happen).


DialogConditionsEvalPatch (v1.7)
--------------------------------
Problem: Unexpected behavior in the internal selection of dialog lines.
Cause: When a condition item in a dialog line has the OR flag set then the evaluation changes from
"this and the next condition must be true" to "either this or the next condition must be true".
Unlike AI package conditions the evaluation of dialog topic lines must satisfy two condition lists -
one from the parent quest and one from the dialog line itself.
Problems may arise when the last condition in the quest's condition list has the OR flag set.
Since the evaluation code just evaluates all conditions consecutively the last condition from the quest
will get OR'ed with the first condition in the dialog line's condition list, which is most likely not
what the mod author wanted.
Solution: Close the condition list evaluation for the parent quest before evaluating the dialog line's conditions.
Remarks: The described behavior is not necessarily a bug in the technical sense. It is still logical.
However, OR'ing a condition with an unknown second condition will give unpredictable results and is therefore
unlikely to be expected behavior.
Of course, the logical solution is to not set the OR flag in a quest's condition list's last condition item and
that is what mod authors should do, but since it can happen accidently (there are quests in Oblivion.esm which
have this problem, but they are harmless) this patch avoids the problem until the mod author fixes it properly.


PluginLoadErrorMessageBoxPatch (v1.7)
-------------------------------------
Problem: Game CTDs on startup before the title screen appears.
Cause: If a plugin file depends on another file (master) that cannot be found in the data folder when loading, the game
cannot proceed and terminates the process. An error message would be added to a 'Warnings' file but since messaging
is disabled in the release version of the game the user gets no information about what caused the crash.
Solution: This patch will show a message box in case of a CTD caused by a missing master file. The message shows information
about which plugin caused the crash and which master file is missing.

SleepWearPatch (v1.9)
---------------------
Problem: Inconsistent behavior in the equipment evaluation when NPCs enter a bed.
Cause: The code for evaluating equipment when a cell loads and sleeping NPCs are moved to their beds is different from the code
that runs when the NPC has walked up to the bed in a loaded cell. In the first case no armor is equipped, in the latter case
clothing is prefered but the NPC will equip armor if no clothing is available for a particular equipment slot.
In the latter case the selection of clothes is also limited to the upper and lower body slot for some reason so an NPC will
sleep in boots and gauntlets even so he/she has shoes in the inventory.
Solution: This patch tries to unify the equipment choices for the implicit evaulation that happens when an NPCs enters a bed.
Since there is no perfect solution the patch offers three different modes to choose from:
1) Force Unequip Armor: NPCs will always unequip all armor when going to bed. If no clothing is available for a slot then
nothing will be equipped.
2) Use Package Flags: NPCs will wear armor or chothing according to the 'Unequip Armor' flag of the Sleep AI packages they use.
Since many sleep packages (i.e. Bandits, City Guards, etc.) don't have the flag set the NPCs will sleep in full armor unless
their packages are modified.
3) Prefer Clothing: This mode is closest to the vanilla behavior. NPCs will try to equip clothes for each slot if available.
They will use armor if no clothing is available for that slot. If no armor and clothing is available nothing is equipped.
The clothing evaluation is extended to all slots so boots are properly unequipped if shoes are available.
Setting: iSleepWearMode
Specifies the desired mode to use. Valid values are 0 (Force Unequip Armor), 1 (Use Package Flags) and 2 (Prefer Clothing).
Setting: bUnequipGlovesIfClothingPreferred
Enables (1) or disables (0) an option for the 'Prefer Clothing' sleep wear mode which forces unequipping gloves while sleeping.
This option is only used if the selected sleep wear mode is 'Prefer Clothing'. This mode prefers clothing over armor but
since there is no clothing item for the hands slot in the vanilla game NPCs will still sleep with their gloves equipped.
By enabling this option the problem can be avoided.


[History]

2.1 2018/12/27 New: CombatBuffSpellSelectionFix
HaggleDispositionFix
RemoveExcessDeadFix
SleepCastLoopFix
SneakPowerAttackFix
Update: BuyItemFromContainerFix
2.0 2018/07/29 New: CellChangedRefMemLeakFix
ObjectPaletteFix
SavedHavokDataFix
Update: PlayerDeathCameraFix
WeaponSwitchFix
Remove: HavokMovedDataLoadPatch
1.9 2018/02/20 New: ActorWithoutProcessCTDFix
BoundItemEvaluationFix
CanHaveFlamesFix
HighProcessTeleportFix
MagicCastFailureSoundFix
PackageStartEquipmentFix
StaffEnchantmentCastTypeFix
SoundEffectsFix
UnloadedObjectReferencesFix
WeaponSwitchFix
SleepWearPatch
1.8 2017/12/13 New: ActivateDoorWhileInvisibleFix
CrimeGoldRemovalFix
SummonAILocationTargetFix
UIMessageFix
VerboseMessagesFix
Update: AIPackageScheduleEvaluationFix
EvaluateEquipmentPatch
1.7 2017/10/10 New: AcquireWeaponNoAmmoFix
BowAndTorch3DFix
BloodDecalMemLeakFix
PickupItemOwnershipFix
DialogConditionsEvalPatch
PluginLoadErrorMessageBoxPatch
Update: ShutdownCTDFix
CreatureBipedObjectEquipFix
Other: Some code changes to allow individual settings for each patch/fix.
1.6 2017/05/17 New: SpellPurchaseCrashFix
GlobalAnimTimerFix
AIPackageScheduleEvaluationFix
1.5 2017/03/20 New: BuyItemFromContainerFix
DialogMenuEmptyTopicsFix
LoadCellTempDataFix
RunScriptLineFix
Other: Code rewrite for better scalability.
1.4 2016/10/24 New: CreatureBipedObjectEquipFix
DialogueWaitFix
ExteriorCellTempObjectsLoadFix
FloraOwnershipPatch
HavokMovedDataLoadPatch
TerrainLODLoadPatch
Update: ScriptPackageFix
Other: Added debug level setting.
1.3 2016/09/07 New: CellChangeCollidedArrows3DFix
RemoveScriptPackageFix
HUDInfoQualityIconFix
CombatBlockPatch
Update: PlayerDeathCameraFix
UseItemPackageFix
1.2 2016/08/01 New: UseItemPackageHandToHandFix
Cell3x3LocalMapIconsFix
1.1 2016/07/21 New: PlayerResurrectCameraFix
1.0 2016/07/18 Initial release.


[Credits]

Thanks to the OBSE team for the Oblivion Script Extender.
Thanks to Bethesda for creating Oblivion.
Thanks to TESNexus.com for the a one-stop-shop resource for authors and players.
Thanks to Gruftikus for adding support for the TerrainLODLoadPatch in tes4ll.
Thanks to everyone who helped with debugging and testing.


[Legal]

This mod is provided as "is".
The author is not responsible for any damage done to your save game, game installation
or even your computer (though such an event happening is highly unlikely).
Use at your own risk.

Top