T-Rizzle12 / Custom-Gmod-Bot

Originally a personal gmod bot that I decided to make public.
Apache License 2.0
6 stars 2 forks source link

Bot can't tell if a prop is explosive #65

Open Gvbavx opened 1 month ago

Gvbavx commented 1 month ago

20241004155208_1 20241004155315_1 A bot will shoot a explosive prop if it was Bumping into the explosive prop, that could kill itself

T-Rizzle12 commented 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.

T-Rizzle12 commented 1 month ago

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.

T-Rizzle12 commented 3 weeks ago

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;
}
T-Rizzle12 commented 3 weeks ago

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; }