Skip to content

OverlayInterface: Add free uid back to m_freeIndices. - #8

Open
ZenoArrows wants to merge 1 commit into
expired6978:masterfrom
ZenoArrows:free-indices
Open

ZenoArrows wants to merge 1 commit into
expired6978:masterfrom
ZenoArrows:free-indices

Conversation

@ZenoArrows

@ZenoArrows ZenoArrows commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

This PR implements a fix for a bug brought up in a fork: https://github.com/nopse0/f4ee-patched

The basic issue is that while OverlayInterface::RemoveAll adds each UID back to m_freeIndices this step is skipped when removing a single overlay using OverlayInterface::RemoveOverlay.

Bug description in the fork

There is a nasty bug in the OverlayInterface::RemoveOverlay function. The UID of the removed overlay is not added to the list "m_freeIndices". This has the effect that if the list of free indices is empty and you add two overlays to an actor, and then remove the first one, that after that, all overlays you add will get the UID of the second one and overwrite it. It' s impossible after that to increase the number of overlays a npc has. This bug makes it practically impossible to use overlays with a limited duration with AAF (or NAF+NAFBridge). If there are other known bugs in the LooksMenu overlay f4ee.dll, feel free to send merge requests.

Example:

Int uid1 = Overlays.AddOverlay( <params for overlay 1> )
Int uid2 = Overlays.AddOverlay( <params for overlay 2> )
Overlays.RemoveOverlay(uid1)

After this, all overlays you add will have the value of uid2 and overwrite the second:

Int uid3 = Overlays.AddOverlay( <params for overlay 3> )
Int uid4 = Overlays.AddOverlay( <params for overlay 4> )
...
Int uidn = Overlays.AddOverlay( <params for overlay n> )

=> uid3 = uid4 = ... = uidn = uid2

This is because the GetNextUID() function looks like this:

OverlayInterface::UniqueID OverlayInterface::GetNextUID()
{
    SimpleLocker locker(&m_overlayLock);

    OverlayInterface::UniqueID nextUID = 0;
    if(!m_freeIndices.empty()) {
        nextUID = m_freeIndices.back();
        m_freeIndices.pop_back();
    } else {
        nextUID = m_dataMap.size() + 1; // This only happens when free indices is empty, meaning we've filled gaps in m_dataMap
    }

    return nextUID;
}

So in RemoveOverlay() the removed UID must be added to the list of free indices (otherwise you get the error described above) !!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant