Open Gvbavx opened 1 month ago
This might not be too hard to fix, I think there is a flag in the engine that marks a prop as explosive. If I could find that flag or variable. I can stop the bot from marking them as breakable objects.
I have been looking for a way to make this dynamic and it's not looking real good right now.... I have been looking into the 2013 Source SDK and I have yet to find a way on how to check if a prop is explosive or not based on the model alone. I did figure out that the data is stored on the model itself, I just need to see if I can grab that data is its even accessible in Lua.
Found some code in the 2013 Source SDK that might help: https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/game/shared/props_shared.cpp#L263-L419
//-----------------------------------------------------------------------------
// Purpose: Parse a keyvalues section into the prop
//
// pInteractionSection is a bit of jiggery-pokery to get around the unfortunate
// fact that the interaction KV sections ("physgun_interactions", "fire_interactions", etc)
// are OUTSIDE the "prop_data" KV section in the model, but may be contained WITHIN the
// specified Base's "prop_data" section (i.e. in propdata.txt)
//-----------------------------------------------------------------------------
int CPropData::ParsePropFromKV( CBaseEntity *pProp, KeyValues *pSection, KeyValues *pInteractionSection )
{
IBreakableWithPropData *pBreakableInterface = dynamic_cast<IBreakableWithPropData*>(pProp);
if ( !pBreakableInterface )
return PARSE_FAILED_BAD_DATA;
if ( !pBreakableInterface )
return PARSE_FAILED_BAD_DATA;
int iBaseResult = PARSE_SUCCEEDED;
// Do we have a base?
char const *pszBase = pSection->GetString( "base" );
if ( pszBase && pszBase[0] )
{
iBaseResult = ParsePropFromBase( pProp, pszBase );
if ( (iBaseResult != PARSE_SUCCEEDED) && (iBaseResult != PARSE_SUCCEEDED_ALLOWED_STATIC) )
return iBaseResult;
}
// Allow overriding of Block LOS
int iBlockLOS = pSection->GetFloat( "blockLOS", -1 );
if ( iBlockLOS != -1 )
{
pBreakableInterface->SetPropDataBlocksLOS( iBlockLOS != 0 );
}
// Set whether AI can walk on this prop
int iIsWalkable = pSection->GetFloat( "AIWalkable", -1 );
if ( iIsWalkable != -1 )
{
pBreakableInterface->SetPropDataIsAIWalkable( iIsWalkable != 0 );
}
// Set custom damage table
const char *pszTableName;
if ( pBreakableInterface->GetPhysicsDamageTable() == NULL_STRING )
{
pszTableName = pSection->GetString( "damage_table", NULL );
}
else
{
pszTableName = pSection->GetString( "damage_table", STRING(pBreakableInterface->GetPhysicsDamageTable()) );
}
if ( pszTableName && pszTableName[0] )
{
pBreakableInterface->SetPhysicsDamageTable( AllocPooledString( pszTableName ) );
}
else
{
pBreakableInterface->SetPhysicsDamageTable( NULL_STRING );
}
// Get multiplayer physics mode if not set by map
pBreakableInterface->SetPhysicsMode( pSection->GetInt( "physicsmode",
pBreakableInterface->GetPhysicsMode() ) );
const char *multiplayer_break = pSection->GetString( "multiplayer_break", NULL );
if ( multiplayer_break )
{
mp_break_t mode = MULTIPLAYER_BREAK_DEFAULT;
if ( FStrEq( multiplayer_break, "server" ) )
{
mode = MULTIPLAYER_BREAK_SERVERSIDE;
}
else if ( FStrEq( multiplayer_break, "client" ) )
{
mode = MULTIPLAYER_BREAK_CLIENTSIDE;
}
else if ( FStrEq( multiplayer_break, "both" ) )
{
mode = MULTIPLAYER_BREAK_BOTH;
}
pBreakableInterface->SetMultiplayerBreakMode( mode );
}
// Get damage modifiers, but only if they're specified, because our base may have already overridden them.
pBreakableInterface->SetDmgModBullet( pSection->GetFloat( "dmg.bullets", pBreakableInterface->GetDmgModBullet() ) );
pBreakableInterface->SetDmgModClub( pSection->GetFloat( "dmg.club", pBreakableInterface->GetDmgModClub() ) );
pBreakableInterface->SetDmgModExplosive( pSection->GetFloat( "dmg.explosive", pBreakableInterface->GetDmgModExplosive() ) );
// Get the health (unless this is an override prop)
if ( !FClassnameIs( pProp, "prop_physics_override" ) && !FClassnameIs( pProp, "prop_dynamic_override" ) )
{
pProp->SetHealth( pSection->GetInt( "health", pProp->GetHealth() ) );
// Explosive?
pBreakableInterface->SetExplosiveDamage( pSection->GetFloat( "explosive_damage", pBreakableInterface->GetExplosiveDamage() ) );
pBreakableInterface->SetExplosiveRadius( pSection->GetFloat( "explosive_radius", pBreakableInterface->GetExplosiveRadius() ) );
#ifdef GAME_DLL
// If we now have health, we're not allowed to ignore physics damage
if ( pProp->GetHealth() )
{
pProp->RemoveSpawnFlags( SF_PHYSPROP_DONT_TAKE_PHYSICS_DAMAGE );
}
#endif
}
const char *pszBreakableModel;
if ( pBreakableInterface->GetBreakableModel() == NULL_STRING )
{
pszBreakableModel = pSection->GetString( "breakable_model", NULL );
}
else
{
pszBreakableModel = pSection->GetString( "breakable_model", STRING(pBreakableInterface->GetBreakableModel()) );
}
if ( pszBreakableModel && pszBreakableModel[0] )
{
pBreakableInterface->SetBreakableModel( AllocPooledString( pszBreakableModel ) );
}
else
{
pBreakableInterface->SetBreakableModel( NULL_STRING );
}
pBreakableInterface->SetBreakableSkin( pSection->GetInt( "breakable_skin", pBreakableInterface->GetBreakableSkin() ) );
pBreakableInterface->SetBreakableCount( pSection->GetInt( "breakable_count", pBreakableInterface->GetBreakableCount() ) );
// Calculate the maximum size of the breakables this breakable will produce
Vector vecSize = pProp->CollisionProp()->OBBSize();
// Throw away the smallest coord
int iSmallest = SmallestAxis(vecSize);
vecSize[iSmallest] = 1;
float flVolume = vecSize.x * vecSize.y * vecSize.z;
int iMaxSize = floor( flVolume / (32.0*32.0) );
pBreakableInterface->SetMaxBreakableSize( iMaxSize );
// Now parse our interactions
for ( int i = 0; i < PROPINTER_NUM_INTERACTIONS; i++ )
{
// If we hit this assert, we have too many interactions for our current storage solution to handle
Assert( i < 32 );
propdata_interaction_s *pInteraction = &sPropdataInteractionSections[i];
KeyValues *pkvCurrentInter = pInteractionSection->FindKey( pInteraction->pszSectionName );
if ( pkvCurrentInter )
{
char const *pszInterBase = pkvCurrentInter->GetString( pInteraction->pszKeyName );
if ( pszInterBase && pszInterBase[0] && !stricmp( pszInterBase, pInteraction->pszValue ) )
{
pBreakableInterface->SetInteraction( (propdata_interactions_t)i );
}
}
}
// If the base said we're allowed to be static, return that
if ( iBaseResult == PARSE_SUCCEEDED_ALLOWED_STATIC )
return PARSE_SUCCEEDED_ALLOWED_STATIC;
// Otherwise, see if our propdata says we are allowed to be static
if ( pSection->GetInt( "allowstatic", 0 ) )
return PARSE_SUCCEEDED_ALLOWED_STATIC;
return PARSE_SUCCEEDED;
}
I also found this which might help as well. I wonder if the internal variables are still on the entity. If that's true, then I could easily fix this issue. I need to do more testing first. https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/game/server/props.h#L123-L126
// IBreakableWithPropData
void SetDmgModBullet( float flDmgMod ) { m_flDmgModBullet = flDmgMod; }
void SetDmgModClub( float flDmgMod ) { m_flDmgModClub = flDmgMod; }
void SetDmgModExplosive( float flDmgMod ) { m_flDmgModExplosive = flDmgMod; }
float GetDmgModBullet( void ) { return m_flDmgModBullet; }
float GetDmgModClub( void ) { return m_flDmgModClub; }
float GetDmgModExplosive( void ) { return m_flDmgModExplosive; }
void SetExplosiveRadius( float flRadius ) { m_explodeRadius = flRadius; }
void SetExplosiveDamage( float flDamage ) { m_explodeDamage = flDamage; }
float GetExplosiveRadius( void ) { return m_explodeRadius; }
float GetExplosiveDamage( void ) { return m_explodeDamage; }
A bot will shoot a explosive prop if it was Bumping into the explosive prop, that could kill itself