-
Notifications
You must be signed in to change notification settings - Fork 249
bugfix(tunnel): Restore retail compatibility after changes to TunnelTracker::onTunnelDestroyed() and TunnelContain::onCapture() #3242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,7 +50,9 @@ | |
| // ------------------------------------------------------------------------ | ||
| TunnelTracker::TunnelTracker() | ||
| { | ||
| #if RETAIL_COMPATIBLE_CRC | ||
| m_tunnelCount = 0; | ||
| #endif | ||
| m_containListSize = 0; | ||
| m_heroUnitsContained = 0; | ||
| m_curNemesisID = INVALID_ID; | ||
|
|
@@ -224,28 +226,73 @@ Bool TunnelTracker::isInContainer( Object *obj ) | |
| // ------------------------------------------------------------------------ | ||
| void TunnelTracker::onTunnelCreated( const Object *newTunnel ) | ||
| { | ||
| DEBUG_ASSERTCRASH(std::find(m_tunnelIDs.begin(), m_tunnelIDs.end(), newTunnel->getID()) == m_tunnelIDs.end(), | ||
| ("TunnelTracker::onTunnelCreated - New tunnel was already added; this shouldn't happen")); | ||
|
|
||
| #if RETAIL_COMPATIBLE_CRC | ||
| m_tunnelCount++; | ||
| #endif | ||
| m_tunnelIDs.push_back( newTunnel->getID() ); | ||
| m_needsFullHealTimeUpdate = true; | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------------ | ||
| void TunnelTracker::onTunnelDestroyed( const Object *deadTunnel ) | ||
| { | ||
| #if RETAIL_COMPATIBLE_CRC | ||
|
|
||
| DEBUG_ASSERTCRASH(static_cast<Int>(m_tunnelCount) > 0 && m_tunnelCount == m_tunnelIDs.size(), | ||
|
xezon marked this conversation as resolved.
|
||
| ("TunnelTracker::onTunnelDestroyed - Tunnel count is unexpected")); | ||
|
|
||
| const size_t oldSize = m_tunnelIDs.size(); | ||
|
Caball009 marked this conversation as resolved.
|
||
| m_tunnelIDs.remove(deadTunnel->getID()); | ||
|
|
||
| (void)oldSize; | ||
| DEBUG_ASSERTCRASH(oldSize != m_tunnelIDs.size(), | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In reality this assert is hit right and we cannot fix it? Maybe it should be a debug log instead then? Asserts are meant to be used to validate conditions and need to be fixed if violated. |
||
| ("TunnelTracker::onTunnelDestroyed - Attempting to remove object '%s' that has never been tracked as a tunnel", deadTunnel->getName().str())); | ||
|
|
||
| m_tunnelCount--; | ||
| m_needsFullHealTimeUpdate = true; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| if( m_tunnelCount == 0 ) | ||
| { | ||
| std::list<ObjectID>::iterator it = std::find(m_tunnelIDs.begin(), m_tunnelIDs.end(), deadTunnel->getID()); | ||
| if (it == m_tunnelIDs.end()) | ||
| // Kill everyone in our contain list. Cave in! | ||
| iterateContained( destroyObject, nullptr, FALSE ); | ||
| m_containList.clear(); | ||
| m_containListSize = 0; | ||
| } | ||
| else | ||
| { | ||
| // TheSuperHackers @bugfix Caball009 01/09/2026 Check if container is empty before accessing it. | ||
| // The tunnel count may diverge from the container size, because of bugs that cannot be fixed with | ||
| // retail compatibility enabled. Expected retail behavior: empty container access results in a nullptr. | ||
| Object *tunnel = m_tunnelIDs.empty() ? nullptr : TheGameLogic->findObjectByID( m_tunnelIDs.front() ); | ||
|
|
||
| // Otherwise, make sure nobody inside remembers the dead tunnel as the one they entered | ||
| // (scripts need to use so there must be something valid here) | ||
| for(ContainedItemsList::iterator it = m_containList.begin(); it != m_containList.end(); ) | ||
| { | ||
| DEBUG_CRASH(("TunnelTracker::onTunnelDestroyed - Attempting to remove object '%s' that has never been tracked as a tunnel", deadTunnel->getName().str())); | ||
| return; | ||
| Object* obj = *it; | ||
| ++it; | ||
| if( obj->getContainedBy() == deadTunnel ) | ||
| obj->onContainedBy( tunnel ); | ||
| } | ||
| } | ||
|
|
||
| m_tunnelCount--; | ||
| #else | ||
|
|
||
| const std::list<ObjectID>::iterator it = std::find(m_tunnelIDs.begin(), m_tunnelIDs.end(), deadTunnel->getID()); | ||
| if (it != m_tunnelIDs.end()) | ||
| { | ||
| m_tunnelIDs.erase(it); | ||
| m_needsFullHealTimeUpdate = true; | ||
| } | ||
| else | ||
| { | ||
| DEBUG_CRASH(("TunnelTracker::onTunnelDestroyed - Attempting to remove object '%s' that has never been tracked as a tunnel", | ||
| deadTunnel->getName().str())); | ||
| } | ||
|
|
||
| if( m_tunnelCount == 0 ) | ||
| if( m_tunnelIDs.empty() ) | ||
| { | ||
| // Kill everyone in our contain list. Cave in! | ||
| iterateContained( destroyObject, nullptr, FALSE ); | ||
|
|
@@ -254,7 +301,10 @@ void TunnelTracker::onTunnelDestroyed( const Object *deadTunnel ) | |
| } | ||
| else | ||
| { | ||
| m_needsFullHealTimeUpdate = true; | ||
|
|
||
| Object *validTunnel = TheGameLogic->findObjectByID( m_tunnelIDs.front() ); | ||
|
|
||
| // Otherwise, make sure nobody inside remembers the dead tunnel as the one they entered | ||
| // (scripts need to use so there must be something valid here) | ||
| for(ContainedItemsList::iterator it = m_containList.begin(); it != m_containList.end(); ) | ||
|
|
@@ -265,6 +315,8 @@ void TunnelTracker::onTunnelDestroyed( const Object *deadTunnel ) | |
| obj->onContainedBy( validTunnel ); | ||
| } | ||
| } | ||
|
|
||
| #endif // RETAIL_COMPATIBLE_CRC | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------------ | ||
|
|
@@ -379,13 +431,19 @@ void TunnelTracker::crc( Xfer *xfer ) | |
| // ------------------------------------------------------------------------------------------------ | ||
| /** Xfer method | ||
| * Version Info: | ||
| * 1: Initial version */ | ||
| * 1: Initial version | ||
| * 2: TheSuperHackers @tweak Removed m_tunnelCount (should always be equal to m_tunnelIDs.size()) | ||
| */ | ||
| // ------------------------------------------------------------------------------------------------ | ||
| void TunnelTracker::xfer( Xfer *xfer ) | ||
| { | ||
|
|
||
| // version | ||
| #if RETAIL_COMPATIBLE_XFER_SAVE | ||
| XferVersion currentVersion = 1; | ||
| #else | ||
| XferVersion currentVersion = 2; | ||
| #endif | ||
| XferVersion version = currentVersion; | ||
| xfer->xferVersion( &version, currentVersion ); | ||
|
|
||
|
|
@@ -424,8 +482,25 @@ void TunnelTracker::xfer( Xfer *xfer ) | |
| m_needsFullHealTimeUpdate = true; | ||
| } | ||
|
|
||
| // tunnel count | ||
| xfer->xferUnsignedInt( &m_tunnelCount ); | ||
| #if RETAIL_COMPATIBLE_CRC | ||
| if (version <= 1) | ||
| { | ||
| xfer->xferUnsignedInt(&m_tunnelCount); | ||
| } | ||
| else | ||
| { | ||
| if (xfer->getXferMode() == XFER_LOAD) | ||
| { | ||
| m_tunnelCount = m_tunnelIDs.size(); | ||
| } | ||
| } | ||
| #else | ||
| if (version <= 1) | ||
| { | ||
| UnsignedInt tunnelCount = m_tunnelIDs.size(); | ||
| xfer->xferUnsignedInt(&tunnelCount); | ||
| } | ||
| #endif | ||
|
|
||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.