Skip to content
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

Trip mine laser beam duplicates after going back and forth through level changes #3245

Open
SamVanheer opened this issue Feb 10, 2022 · 1 comment

Comments

@SamVanheer
Copy link

SamVanheer commented Feb 10, 2022

An active trip mine will duplicate its laser beam after going back and forth through level changes.

This video shows the problem:
https://www.youtube.com/watch?v=PizJX3pc0xk

This happens because effects entities like beams don't transition to other maps:

return (CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | flags;

When the trip mine transitions to another map it recreates the beam. When you go back to the previous map it will also recreate the beam, but the original beam entity will still exist since the beam is saved and restored by default:

halflife/dlls/effects.h

Lines 110 to 111 in c7240b9

if ( pev->spawnflags & SF_BEAM_TEMPORARY )
flags = FCAP_DONT_SAVE;

Effects entities encode which entity they attach to in a way that makes transitioning them rather complicated so that's not an option.

To fix this the beam needs to be made temporary so that the trip mine code can recreate it on demand.

Change this:

DEFINE_FIELD( CTripmineGrenade, m_pBeam, FIELD_CLASSPTR ),

To this:

//Don't save, recreate.
//DEFINE_FIELD(CTripmineGrenade, m_pBeam, FIELD_CLASSPTR),

After this line:

m_pBeam = CBeam::BeamCreate( g_pModelNameLaser, 10 );

Add this:

//Mark as temporary so the beam will be recreated on save game load and level transitions.
m_pBeam->pev->spawnflags |= SF_BEAM_TEMPORARY;

The trip mine will now recreate the beam. The logic for this already exists:

halflife/dlls/tripmine.cpp

Lines 277 to 283 in c7240b9

// respawn detect.
if ( !m_pBeam )
{
MakeBeam( );
if ( tr.pHit )
m_hOwner = CBaseEntity::Instance( tr.pHit ); // reset owner too
}

But is incorrect, and will cause some tripmines to explode when loading save games (e.g. on c1a3d).

This is the corrected code:

if (!m_pBeam)
{
	// Use the same trace parameters as the original trace above so the right entity is hit.
	TraceResult tr2;
	UTIL_TraceLine(pev->origin + m_vecDir * 8, pev->origin - m_vecDir * 32, dont_ignore_monsters, ENT(pev), &tr2);
	MakeBeam();
	if (tr2.pHit)
	{
		// reset owner too
		pev->owner = tr2.pHit;
		m_hOwner = CBaseEntity::Instance(tr2.pHit);
	}
}

Also of note: the reason why the beams seem to attach to random entities (the light and battery in the video) is because the beam uses PointEntInit, and the entity endpoint stores the index of the entity. The tripmine entity index is not consistent between the two maps, so it will attach to whichever entity is in that slot, if any. If there is no entity it will still attach to that slot, but the origin value won't be valid and will likely be 0, 0, 0, or whatever the last value was that the client received from the server for that slot.

Issue #1670 covers a bug fix that changes the beam to use PointsInit so that particular aspect of this bug won't happen. Instead the beams will overlap, creating a seemingly brighter beam.

This bug was originally found by vasiavasiavasia95.

@SamVanheer
Copy link
Author

Updated with a fix for tripmines exploding when loading save games.

@SamVanheer SamVanheer reopened this Sep 26, 2022
hammermaps added a commit to sohl-modders/Updated-SOHL-1.2 that referenced this issue Apr 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants