Created
January 11, 2024 12:57
-
-
Save Pinsplash/27a72c6271e850cec6e2cf479c3f81cd to your computer and use it in GitHub Desktop.
Source gauss debug mod
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This is a debug mod which was used in the making of and briefly featured in this video: https://www.youtube.com/watch?v=xmv_4XxzeFs | |
This mod recreates the HL1/HLS tau cannon beam behavior in HL2. | |
Pro: This mod can visualize a beam's path. Very easy to understand. | |
Con: This is not necessarily 1:1 with beam behavior in either game because the player entity acts differently in all 3 games and line traces work differently in HL1 than in Source. | |
If you see a result that doesn't match expectations, the result should be confirmed in HL1/HLS. Debug lines can be placed in HLS with drawline. | |
If you want to test something from an HL1 map, you can copy maps and textures from HLS without needing to recompile. | |
To build, add into an existing 2013 SP SDK mod. https://www.youtube.com/watch?v=BtiAvNkEpC0 | |
To use, type gauss in the console to fire a primary beam. To fire a secondary beam, specify an amount of damage with the command (e.g. gauss 200). To use HLS behavior, use gauss_hls instead. | |
Beams are white until they penetrate, where they become yellow. Orange is the line that finds space on the other side of the wall when penetrating. Blue is the line that traces back to the point of impact. Green represents thickness. | |
Lines are offset in 1 unit increments to prevent overlap, which makes it hard to understand what's happening. This can be mostly disabled with gauss_offset. | |
Text debug messages have been formatted to still be decently readable if lines print out of order. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//in CBaseEntity::OnTakeDamage | |
Msg("%s took %0.01f damage\n", GetClassname(), info.GetDamage()); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CON_COMMAND(gauss, "")//hl1 | |
{ | |
CBasePlayer* pPlayer = UTIL_GetLocalPlayer(); | |
CHL2_Player *pHL2Player = static_cast<CHL2_Player*>(pPlayer); | |
bool bPrimaryFire = !(args.ArgC() > 1);//argument is damage amount. if no argument, then we're primary fire. | |
float flDamage = bPrimaryFire ? 20 : atoi(args[1]);//we always know the damage for primary fire. | |
pHL2Player->Gauss(bPrimaryFire, flDamage, false); | |
} | |
CON_COMMAND(gauss_hls, "")//half life source | |
{ | |
CBasePlayer* pPlayer = UTIL_GetLocalPlayer(); | |
CHL2_Player *pHL2Player = static_cast<CHL2_Player*>(pPlayer); | |
bool bPrimaryFire = !(args.ArgC() > 1);//argument is damage amount. if no argument, then we're primary fire. | |
float flDamage = bPrimaryFire ? 20 : atoi(args[1]);//we always know the damage for primary fire. | |
pHL2Player->Gauss(bPrimaryFire, flDamage, true); | |
} | |
ConVar gauss_offset("gauss_offset", "1"); | |
void CHL2_Player::Gauss(bool bPrimaryFire, float flDamage, bool bHalfLifeSource) | |
{ | |
CBasePlayer *pPlayer = this; | |
Vector vecDir = pPlayer->GetAutoaimVector(0); | |
Vector vecSrc = pPlayer->Weapon_ShootPosition(); | |
Msg("Starting %s fire with damage %f\n", bPrimaryFire ? "primary" : "secondary", flDamage); | |
if (flDamage < 25 && !bPrimaryFire) Msg("Note: Damage of %f is impossibly low.\n", flDamage); | |
if (!(flDamage > 10)) Msg("Note: Beam will do nothing if damage <= 10.\n"); | |
if (flDamage > 200) Msg("Note: Damage of %f is impossibly high.\n", flDamage); | |
Vector vecDest = vecSrc + vecDir * 8192; | |
CBaseEntity *pentIgnore = pPlayer; | |
trace_t traceBeam, tracePunch, traceBack; | |
bool bHasPunched = false; | |
int nMaxHits = 10; | |
float flExpDmg = 0;//total amount of damage from explosions | |
while (flDamage > 10 && nMaxHits > 0) | |
{ | |
nMaxHits--; | |
UTIL_TraceLine(vecSrc, vecDest, MASK_SHOT, pentIgnore, COLLISION_GROUP_NONE, &traceBeam); | |
//NDebugOverlay::Line(vecSrc, traceBeam.endpos, 255, 255, bPrimaryFire ? 0 : 255, false, 30); | |
if (bHasPunched) | |
UTIL_AddDebugLineColor(vecSrc - Vector(0, 0, (gauss_offset.GetBool() ? 9 - nMaxHits : 0)), traceBeam.endpos - Vector(0, 0, (gauss_offset.GetBool() ? 9 - nMaxHits : 0)), 255, 255, 0); | |
else | |
UTIL_AddDebugLineColor(vecSrc, traceBeam.endpos, 255, 255, 255); | |
//if a beam segment went nowhere, represent it with a downward line, otherwise the line is invisible | |
if (vecSrc == traceBeam.endpos) | |
UTIL_AddDebugLineColor(vecSrc - Vector(0, 0, (gauss_offset.GetBool() ? 9 - nMaxHits : 0) + 1), traceBeam.endpos - Vector(0, 0, (gauss_offset.GetBool() ? 9 - nMaxHits : 0) - 1), 255, 255, 0); | |
Msg("Hit %i, s1, %f damage. Beam went from %0.1f %0.1f %0.1f to %0.1f %0.1f %0.1f. vecDest %0.1f %0.1f %0.1f.\n", 10 - nMaxHits, flDamage, vecSrc.x, vecSrc.y, vecSrc.z, traceBeam.endpos.x, traceBeam.endpos.y, traceBeam.endpos.z, vecDest.x, vecDest.y, vecDest.z); | |
if (traceBeam.allsolid) | |
{ | |
Msg("Hit %i, s1.1, Beam stuck in solid, ending.\n", 10 - nMaxHits); | |
break; | |
} | |
CBaseEntity *pEntity = traceBeam.m_pEnt; | |
if (pEntity == NULL) | |
{ | |
Msg("Hit %i, s1.2, Beam hit nothing, ending.\n", 10 - nMaxHits); | |
break; | |
} | |
bool bShouldDamageEntity = (pEntity->m_takedamage != DAMAGE_NO); | |
if (bShouldDamageEntity) | |
{ | |
Msg("Hit %i, s1.3, Hurting %s named %s for %f damage.\n", 10 - nMaxHits, pEntity->GetClassname(), STRING(pEntity->GetEntityName()), flDamage); | |
ClearMultiDamage(); | |
CTakeDamageInfo info(pPlayer, pPlayer, flDamage, bHalfLifeSource ? DMG_ENERGYBEAM : DMG_BULLET);//inflictor was originally [this] (the gun). this is an okay concession. | |
CalculateMeleeDamageForce(&info, vecDir, traceBeam.endpos); | |
pEntity->DispatchTraceAttack(info, vecDir, &traceBeam); | |
ApplyMultiDamage(); | |
} | |
else | |
Msg("Hit %i, s1.4, Entity %s named %s cannot be hurt.\n", 10 - nMaxHits, pEntity->GetClassname(), STRING(pEntity->GetEntityName())); | |
if (pEntity->IsBSPModel() && !bShouldDamageEntity) | |
{ | |
Msg("Hit %i, s2.1, Entity is an undamageable brush.\n", 10 - nMaxHits); | |
pentIgnore = NULL; | |
float n = -DotProduct(traceBeam.plane.normal, vecDir); | |
if (n < 0.5)//60 degrees | |
{ | |
Msg("Hit %i, s3.1, n is %f. Reflecting. Reducing damage by %f percent.\n", 10 - nMaxHits, n, 100 * n); | |
Vector r = 2.0 * traceBeam.plane.normal * n + vecDir; | |
vecDir = r; | |
if (bHalfLifeSource) | |
vecSrc = traceBeam.endpos; | |
else | |
vecSrc = traceBeam.endpos + vecDir * 8; | |
vecDest = vecSrc + vecDir * 8192; | |
//added a print statement in CBaseEntity::OnTakeDamage to see how much damage the explosion does to each entity, cannot be seen from here. | |
RadiusDamage(CTakeDamageInfo(pPlayer, pPlayer, flDamage * n, DMG_BLAST), traceBeam.endpos, flDamage * n * 2.5, CLASS_NONE, NULL); | |
flExpDmg += flDamage * n; | |
if (n == 0) | |
{ | |
Warning("Hit %i, s3.1.1, Sanity Check: n was 0, set to 0.1.\n", 10 - nMaxHits);//implies beam is coplanar to surface. | |
n = 0.1; | |
} | |
flDamage = flDamage * (1 - n); | |
} | |
else | |
{ | |
Msg("Hit %i, s3.2, n = %f, penetrating.\n", 10 - nMaxHits, n); | |
if (bHasPunched) | |
{ | |
Msg("Hit %i, s3.2.1, Beam already penetrated once, ending.\n", 10 - nMaxHits); | |
break; | |
} | |
bHasPunched = true; | |
if (!bPrimaryFire) | |
{ | |
UTIL_TraceLine(traceBeam.endpos + vecDir * 8, vecDest, MASK_SHOT, pentIgnore, COLLISION_GROUP_NONE, &tracePunch); | |
//NDebugOverlay::Line(traceBeam.endpos + vecDir * 8, tracePunch.endpos, 255, 128, 0, false, 30); | |
UTIL_AddDebugLineColor(traceBeam.endpos + vecDir * 8 + Vector(0, 0, 1), tracePunch.endpos + Vector(0, 0, 1), 255, 128, 0);//to avoid occupying the same space, making the lines difficult to understand, these 2 lines have a small vertical offset. | |
//if line went nowhere, represent it with a downward line, otherwise the line is invisible | |
if (tracePunch.startpos == tracePunch.endpos) | |
UTIL_AddDebugLineColor(tracePunch.endpos + Vector(0, 0, 1), tracePunch.endpos - Vector(0, 0, 1), 255, 128, 0); | |
Msg("Hit %i, s4.1, Using secondary fire. TracePunch landed at %0.1f %0.1f %0.1f.\n", 10 - nMaxHits, tracePunch.endpos.x, tracePunch.endpos.y, tracePunch.endpos.z); | |
if (!tracePunch.allsolid) | |
{ | |
UTIL_TraceLine(tracePunch.endpos, traceBeam.endpos, MASK_SHOT, pentIgnore, COLLISION_GROUP_NONE, &traceBack); | |
//NDebugOverlay::Line(tracePunch.endpos, traceBack.endpos, 0, 0, 255, false, 30); | |
UTIL_AddDebugLineColor(tracePunch.endpos + Vector(0, 0, 2), traceBack.endpos + Vector(0, 0, 2), 0, 0, 255); | |
float m = (traceBack.endpos - traceBeam.endpos).Length(); | |
UTIL_AddDebugLineColor(traceBack.endpos + Vector(0, 0, 3), traceBeam.endpos + Vector(0, 0, 3), 0, 255, 0); | |
//if line went nowhere, represent it with a downward line, otherwise the line is invisible | |
if (m == 0) | |
UTIL_AddDebugLineColor(traceBack.endpos + Vector(0, 0, 1), traceBack.endpos - Vector(0, 0, 1), 0, 255, 0); | |
Msg("Hit %i, s5.1, Wall has other side. TraceBack lands at %0.1f %0.1f %0.1f. Wall is %f thick while damage is %f, %s.\n", 10 - nMaxHits, traceBack.endpos.x, traceBack.endpos.y, traceBack.endpos.z, m, flDamage, (m < flDamage) ? "penetrating" : "cannot penetrate"); | |
if (m < flDamage) | |
{ | |
if (m == 0) | |
{ | |
Warning("Hit %i, s6.1, Sanity Check: m was 0, set to 1.\n", 10 - nMaxHits);//implies wall is infinitely thin. | |
m = 1; | |
} | |
Msg("Hit %i, s6.2, Damage (%f) reduced by m (%f) to %f\n", 10 - nMaxHits, flDamage, m, flDamage - m); | |
flDamage -= m; | |
float damage_radius = flDamage * 2.5; | |
RadiusDamage(CTakeDamageInfo(pPlayer, pPlayer, flDamage, DMG_BLAST), traceBack.endpos + vecDir * 8, damage_radius, CLASS_NONE, NULL); | |
flExpDmg += flDamage; | |
vecSrc = traceBack.endpos + vecDir; | |
} | |
} | |
else | |
{ | |
Msg("Hit %i, s5.2, Nothing on other side of wall, ending.\n", 10 - nMaxHits); | |
flDamage = 0; | |
} | |
} | |
else | |
{ | |
Msg("Hit %i, s4.2, Cannot penetrate with primary fire, ending.\n", 10 - nMaxHits); | |
flDamage = 0; | |
} | |
} | |
} | |
else | |
{ | |
if (pEntity->IsBSPModel() && bShouldDamageEntity) Msg("Hit %i, s2.2, Entity is damageable, piercing.\n", 10 - nMaxHits); | |
if (!pEntity->IsBSPModel() && !bShouldDamageEntity) Msg("Hit %i, s2.2, Entity is not a brush, piercing.\n", 10 - nMaxHits); | |
if (!pEntity->IsBSPModel() && bShouldDamageEntity) Msg("Hit %i, s2.2, Entity is damageable AND not a brush, piercing.\n", 10 - nMaxHits); | |
vecSrc = traceBeam.endpos + vecDir; | |
pentIgnore = pEntity; | |
} | |
} | |
if (!(flDamage > 10)) | |
Msg("End: Damage (%0.01f) fell below 10, ending beam.\n", flDamage); | |
else if (!(nMaxHits > 0)) | |
Msg("End: Reached max interations.\n"); | |
Msg("Explosion Damage Total: %f\n", flExpDmg); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//in CHL2_Player definition | |
void Gauss(bool bPrimaryFire, float flDamage, bool bHalfLifeSource); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//For unclear reasons the original debug line function was not working well, so I made this. | |
//----------------------------------------------------------------------------- | |
// Purpose: Adds a debug line to be drawn on the screen | |
// Input : If testLOS is true, color is based on line of sight test | |
// Output : | |
//----------------------------------------------------------------------------- | |
void UTIL_AddDebugLineColor(const Vector &startPos, const Vector &endPos, int r, int g, int b) | |
{ | |
OverlayLine_t* debugLine = GetDebugOverlayLine(); | |
debugLine->origin = startPos; | |
debugLine->dest = endPos; | |
//debugLine->noDepthTest = noDepthTest; | |
debugLine->draw = true; | |
debugLine->r = r; | |
debugLine->g = g; | |
debugLine->b = b; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern void UTIL_AddDebugLineColor(const Vector &startPos, const Vector &endPos, int r, int g, int b); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//in CEngineSprite::GetMaterial line 420 (nice) add this to prevent a crash in c3a1a | |
if (!pMaterial)//randomly encountered in c3a1a HLS | |
return NULL; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment