.:: Bots United ::.

.:: Bots United ::. (http://forums.bots-united.com/index.php)
-   General Bot Coding (http://forums.bots-united.com/forumdisplay.php?f=24)
-   -   Another IsShootableThruObstacle() function!!!!!!!! (http://forums.bots-united.com/showthread.php?t=7235)

Immortal_BLG 26-08-2009 10:36

Another IsShootableThruObstacle() function!!!!!!!!
 
I wrote the function, placed below, that's 99,99% more accuracy than functions from PoDBot, YaPB or another bot!!!!!!!! - It based on cheat's CanPenetrate() function.

Code:

const bool Bot::IsShootableThruObstacle (const Math::Vector3D &destination)
{
        // This function returns true if enemy can be shoot through some obstacle, false otherwise.

        if (m_profile->skill <= 70u)
                return false;

        unsigned char currentWeaponPenetrationPower = g_weaponProperties[m_currentWeapon->GetID ()].penetrationPower;

        if (currentWeaponPenetrationPower == 0u)
                return false;

        // set conditions....
        Math::Vector3D source (m_edict->GetEyePosition ());
        const Math::Vector3D &direction ((destination - source).Normalize () * 8.0f);        // 8 units long

        do
        {
                // trace from the bot's eyes to destination...
                HalfLifeEngine::Globals::g_halfLifeEngine->TraceLine (source, destination, HalfLifeEngine::SDK::Constants::TraceIgnore_Monsters, m_edict, m_traceResult);

                if (m_traceResult.isStartSolid)
                {
                        if (m_traceResult.isAllSolid)
                                return false;

                        // move 8 units closer to the destination....
                        source += direction;
                }
                else
                {
                        // check if line hit anything
                        if (m_traceResult.fraction == 1.0f)
                                return true;

                        --currentWeaponPenetrationPower;

                        // move 8 units closer to the destination....
                        source = m_traceResult.endPosition + direction;
                }
        } while (currentWeaponPenetrationPower > 0u);

        return false;
}

There 'm_traceResult' it's a HL engine TraceResult structure, placed in main bot class for memory economy :P.
'currentWeaponPenetrationPower' it's a number, that's can be calculated with below function (from cheat, too)
Code:

int CorrectGun(int weaponID)
{
        if (weaponID == WEAPONLIST_SG550 || weaponID == WEAPONLIST_G3SG1 || weaponID == WEAPONLIST_SCOUT || weaponID == WEAPONLIST_AWP)
                return 3;
        if (weaponID == WEAPONLIST_AUG || weaponID == WEAPONLIST_M249 || weaponID == WEAPONLIST_M4A1 || weaponID == WEAPONLIST_DEAGLE || weaponID == WEAPONLIST_SG552 || weaponID == WEAPONLIST_AK47|| weaponID == WEAPONLIST_FAMAS || weaponID == WEAPONLIST_GALIL)
                return 2;

        return 0;
}

- but for me it's too slow, and I placed the numbers above into the WeaponProperties_t structure.

Immortal_BLG 20-12-2009 05:54

Re: Another IsShootableThruObstacle() function!!!!!!!!
 
Another function to determine penetration damage.

Code:

enum WeaponBulletType_t
{
        WeaponBulletType_0,
        WeaponBulletType_1,
        WeaponBulletType_2,
        WeaponBulletType_3,
        WeaponBulletType_4,
        WeaponBulletType_5,
        WeaponBulletType_6,
        WeaponBulletType_7,
        WeaponBulletType_8,
        WeaponBulletType_9,
        WeaponBulletType_10,
        WeaponBulletType_11,
        WeaponBulletType_12,
        WeaponBulletType_13,
        WeaponBulletType_14,
        WeaponBulletType_15
};

enum WeaponObstaclePenetrationPower_t
{
        WeaponObstaclePenetrationPower_0,
        WeaponObstaclePenetrationPower_1,
        WeaponObstaclePenetrationPower_2
};

enum Constants_t
{
        HalfMapSize = 4096u,
        MapSize    = 8192u
};

enum TextureType_t
{
        TextureType_None,

        TextureType_Concrete    = 'C',
        TextureType_Metal        = 'M',
        TextureType_Dirt        = 'D',
        TextureType_Ventillation = 'V',
        TextureType_Grate        = 'G',
        TextureType_Tile        = 'T',
        TextureType_SloshLiquid  = 'S',
        TextureType_Wood        = 'W',
        TextureType_Computer    = 'P',
        TextureType_Grass        = 'X',
        TextureType_Glass        = 'Y',
        TextureType_Flesh        = 'F',
        TextureType_Snow        = 'N'
};

struct WeaponPenetrationInformation_t
{
        WeaponBulletType_t bulletType;                        // weapon bullet type
        unsigned char      penetrationPower;                // can shoot thru walls
        unsigned short    maximumShootDistance;        // maximum shoot distance

        // Information: damage/obstacle pierce for usp/m4a1 - unsilenced/silenced.
        unsigned char      damage1;                        // damage 1
        unsigned char      damage2;                        // damage 2

        float              obstaclePierce1;                        // obstacle pierce 1
        float              obstaclePierce2;                        // obstacle pierce 2
} g_weaponPenetrationInformation[] =
{
        // Terminator, since weapon id's are starting from 1 in Half-Life engine. :-(
        {WeaponBulletType_0,  WeaponObstaclePenetrationPower_0,          0u,  0u,  0u,  0.0f,  0.0f},                // WeaponID_None

        {WeaponBulletType_15, WeaponObstaclePenetrationPower_0, HalfMapSize,  32u,  0u,  0.8f,  0.0f},                // WeaponID_P228
        {WeaponBulletType_0,  WeaponObstaclePenetrationPower_0,          0u,  0u,  0u,  0.0f,  0.0f},                // WeaponID_Shield
        {WeaponBulletType_11, WeaponObstaclePenetrationPower_2, MapSize,      75u,  0u,  0.98f,  0.0f},                // WeaponID_Scout
        {WeaponBulletType_0,  WeaponObstaclePenetrationPower_0,          0u,  97u,  0u,  0.0f,  0.0f},                // WeaponID_Esplosive
        {WeaponBulletType_0,  WeaponObstaclePenetrationPower_0,          0u, 115u,  0u,  0.0f,  0.0f},                // WeaponID_XM1014
        {WeaponBulletType_0,  WeaponObstaclePenetrationPower_0,          0u,  0u,  0u,  0.0f,  0.0f},                // WeaponID_C4
        {WeaponBulletType_9,  WeaponObstaclePenetrationPower_0, MapSize,      29u,  0u,  0.82f,  0.0f},                // WeaponID_MAC10
        {WeaponBulletType_12, WeaponObstaclePenetrationPower_1, MapSize,      32u,  0u,  0.96f,  0.0f},                // WeaponID_Aug
        {WeaponBulletType_0,  WeaponObstaclePenetrationPower_0,          0u,  0u,  0u,  0.0f,  0.0f},                // WeaponID_Smoke
        {WeaponBulletType_1,  WeaponObstaclePenetrationPower_0, MapSize,      36u,  0u,  0.75f,  0.0f},                // WeaponID_Elite
        {WeaponBulletType_15, WeaponObstaclePenetrationPower_0, HalfMapSize,  20u,  0u,  0.885f, 0.0f},                // WeaponID_FiveSeven
        {WeaponBulletType_9,  WeaponObstaclePenetrationPower_0, MapSize,      30u,  0u,  0.82f,  0.0f},                // WeaponID_UMP45
        {WeaponBulletType_12, WeaponObstaclePenetrationPower_1, MapSize,      70u,  0u,  0.98f,  0.0f},                // WeaponID_SG550
        {WeaponBulletType_12, WeaponObstaclePenetrationPower_1, MapSize,      30u,  0u,  0.96f,  0.0f},                // WeaponID_Galil
        {WeaponBulletType_12, WeaponObstaclePenetrationPower_1, MapSize,      30u,  0u,  0.96f,  0.0f},                // WeaponID_Famas
        {WeaponBulletType_9,  WeaponObstaclePenetrationPower_0, HalfMapSize,  34u, 30u,  0.79f,  0.79f},        // WeaponID_USP
        {WeaponBulletType_1,  WeaponObstaclePenetrationPower_0, MapSize,      25u,  0u,  0.75f,  0.0f},                // WeaponID_Glock18
        {WeaponBulletType_10, WeaponObstaclePenetrationPower_2, MapSize,    115u,  0u,  0.99f,  0.0f},                // WeaponID_AWP
        {WeaponBulletType_1,  WeaponObstaclePenetrationPower_0, MapSize,      26u,  0u,  0.84f,  0.0f},                // WeaponID_MP5
        {WeaponBulletType_12, WeaponObstaclePenetrationPower_1, MapSize,      32u,  0u,  0.97f,  0.0f},                // WeaponID_M249
        {WeaponBulletType_0,  WeaponObstaclePenetrationPower_0, HalfMapSize, 172u,  0u,  0.0f,  0.0f},                // WeaponID_M3
        {WeaponBulletType_12, WeaponObstaclePenetrationPower_1, MapSize,      32u, 33u,  0.97f,  0.95f},        // WeaponID_M4A1
        {WeaponBulletType_1,  WeaponObstaclePenetrationPower_0, MapSize,      20u,  0u,  0.85f,  0.0f},                // WeaponID_TMP
        {WeaponBulletType_11, WeaponObstaclePenetrationPower_1, MapSize,      80u,  0u,  0.98f,  0.0f},                // WeaponID_G3SG1
        {WeaponBulletType_0,  WeaponObstaclePenetrationPower_0,          0u,  0u,  0u,  0.0f,  0.0f},                // WeaponID_Flashbang
        {WeaponBulletType_13, WeaponObstaclePenetrationPower_1, MapSize,      54u,  0u,  0.81f,  0.0f},                // WeaponID_Deagle
        {WeaponBulletType_12, WeaponObstaclePenetrationPower_1, MapSize,      33u,  0u,  0.955f, 0.0f},                // WeaponID_SG552
        {WeaponBulletType_11, WeaponObstaclePenetrationPower_1, MapSize,      36u,  0u,  0.98f,  0.0f},                // WeaponID_AK47
        {WeaponBulletType_0,  WeaponObstaclePenetrationPower_0,          0u,  16u, 66u,  0.0f,  0.0f},                // WeaponID_Knife
        {WeaponBulletType_14, WeaponObstaclePenetrationPower_0, HalfMapSize,  21u,  0u,  0.885f, 0.0f}                // WeaponID_P90
};

template <typename elementType> inline void Swap (elementType &left, elementType &right)
{
        // This template function exchanges values stored at 'left' and 'right'.

        // different, worth swapping
        assert (&left != &right);

        elementType temp (left);

        // swap....
        left = right;
        right = temp;
}

inline const bool GetLineFromFileBuffer (const char *const fileBuffer, unsigned int fileSize, unsigned int &filePosition, char *const buffer, const unsigned short bufferSize)
{
        // Bullet-proofing
        assert (filePosition < fileSize);

        unsigned int index (filePosition);

        // fgets always NULL terminates, so only read bufferSize - 1 characters
        if (fileSize - filePosition > bufferSize - 1u)
                fileSize = filePosition + bufferSize - 1u;

        // Stop at the next newline (inclusive) or end of buffer
        while (index < fileSize)
                if (fileBuffer[index++] == '\n')
                        break;

        // If we actually advanced the pointer, copy it over
        if (index > filePosition)
        {
                // We read in size bytes
                const unsigned short size (static_cast <unsigned short> (index - filePosition));

                // copy it out
                memcpy (buffer, fileBuffer + filePosition, size);

                buffer[size] = 0;

                // Update file pointer
                filePosition = index;

                return true;
        }

        // No data read, bail
        return false;
}

class TexturesManager
{
        private:
                enum
                {
                        MaximumTextureNameLength = 13u,        // only load first n chars of name
                        MaximumTexturesNumber    = 512u        // max number of textures loaded
                };

                struct Texture_t
                {
                        char type;                                                                // texture type (from 'TextureType_t' enumeration)
                        char name[MaximumTextureNameLength];        // texture name
                };

                Texture_t      m_textures[MaximumTexturesNumber];
                unsigned short m_texturesNumber;

        public:
                TexturesManager (void) : m_texturesNumber (0u)
                {
                        int fileSize;
                        unsigned char *const file (LOAD_FILE_FOR_ME ("sound/materials.txt", &fileSize));

                        if (file == NULL)
                                return;

                        char *buffer;
                        unsigned int filePosition (0u);
                        unsigned short startIndex, endIndex;

                        // for each line in the file...
                        while (GetLineFromFileBuffer (static_cast <const char *const> (static_cast <const void *const> (file)), fileSize, filePosition, buffer, 511u))
                        {
                                startIndex = 0u;

                                // skip whitespaces
                                while (buffer[startIndex] != 0 && isspace (buffer[startIndex]))
                                        ++startIndex;

                                if (buffer[startIndex] == 0)
                                        continue;

                                // skip comment lines
                                if (buffer[startIndex] == '/' || !isalpha (buffer[startIndex]))
                                        continue;

                                // get texture type
                                m_textures[m_texturesNumber].type = static_cast <char> (toupper (buffer[startIndex++]));

                                // skip whitespace
                                while (buffer[startIndex] != 0 && isspace (buffer[startIndex]))
                                        ++startIndex;

                                if (buffer[startIndex] == 0)
                                        continue;

                                // get sentence name
                                endIndex = startIndex;

                                while (buffer[endIndex] != 0 && !isspace (buffer[endIndex]))
                                        ++endIndex;

                                if (buffer[endIndex] == 0)
                                        continue;

                                // null-terminate name and save in sentences array
                                buffer[min (endIndex, MaximumTextureNameLength - 1u + startIndex)] = 0;

                                strcpy (m_textures[m_texturesNumber].name, buffer + startIndex);

                                if (++m_texturesNumber == MaximumTexturesNumber)
                                        break;
                        }

                        // Must use engine to free since we are in a .dll
                        FREE_FILE (file);

                        SortTextures ();
                }

        private:
                inline void SwapTextures (const unsigned short i, const unsigned short j)
                {
                        Swap (m_textures[i].type, m_textures[j].type);
                        Swap (m_textures[i].name, m_textures[j].name);
                }

                inline void SortTextures (void)
                {
                        // Bubble sort, yuck, but this only occurs at startup and it's only 512 elements...

                        for (unsigned short i (0u), j; i < m_texturesNumber; ++i)
                                for (j = i + 1u; j < m_texturesNumber; ++j)
                                        if (stricmp (m_textures[i].name, m_textures[j].name) > 0)
                                        {
                                                // Swap
                                                SwapTextures (i, j);
                                        }
                }

                inline const char FindTextureType (const char *const name) const
                {
                        // given texture name, find texture type
                        // if not found, return type 'concrete'

                        unsigned short pivot, left (0u);
                        int right (m_texturesNumber), value;

                        do
                        {
                                // To start, find the subscript of the middle position.
                                if ((value = strnicmp (m_textures[pivot = static_cast <unsigned short> ((left + right) / 2u)].name, name)) == 0)
                                        return m_textures[pivot].type;

                                if (value > 0)        // If the number is > key, increase position by one.
                                        left = pivot + 1u;
                                else        // Else (value < 0), decrease position by one.
                                        right = pivot - 1;
                        } while (left <= right);

                        return TextureType_Concrete;
                }

        public:
                inline const char GetTextureType (Edict_t *const entity, const Math::Vector3D &source, const Math::Vector3D &destination) const
                {
                        const unsigned short entityIndex (ENTINDEX (entity));

                        if (entityIndex == 0u)
                        {
                                // get texture from entity or world (world is ent(0))
                                const char *textureName (TRACE_TEXTURE (entity, source, destination));

                                if (textureName != NULL)
                                {
                                        // strip leading '-0' or '+0~' or '{' or '!'
                                        if (*textureName == '-' || *textureName == '+')
                                                textureName += 2u;

                                        if (*textureName == '{' || *textureName == '!' || *textureName == '~' || *textureName == ' ')
                                                ++textureName;

                                        // '}}'
                                        // get texture type
                                        return FindTextureType (textureName);
                                }
                        }
                        else if (entityIndex >= 1u && entityIndex <= g_pGlobals->maxClients)        // Player
                                return TextureType_Flesh;        // hit body

                        return TextureType_None;
                }
};

TexturesManager *g_texturesManager;        // NOTE: Initialize this after getting the engine functions!

const unsigned char Bot::GetPenetrationDamage (const Math::Vector3D &source, const Math::Vector3D &destination)
{
        if (m_profile->skill <= 70u)
                return 0u;

        unsigned char currentWeaponPenetrationPower (static_cast <unsigned char> (g_weaponProperties[m_currentWeapon->GetID ()].penetrationPower));

        if (currentWeaponPenetrationPower == WeaponObstaclePenetrationPower_0)
                return false;

        Math::Vector3D start (source), end (destination), direction (end - start);
        float distanceFraction, damageMult (0.5f), distanceMaximum (0.0f);
        const float length (direction.GetLength ());
        unsigned char bulletVelocity (0u);
        float distance (g_weaponPenetrationInformation[m_currentWeapon->GetID ()].maximumShootDistance);
        unsigned char currentWeaponPenetrationPower (g_weaponPenetrationInformation[m_currentWeapon->GetID ()].currentWeaponPenetrationPower + 1u);

        // What damage/obstaclePierce (first(silenced) or second(unsilenced)) can easily identify with CS offsets (for windows=74, for linux=don't know :), flags=USP_SILENCED = (1u << 0u), M4A1_SILENCED = (1u << 2u)) - ONLY FOR USP OR M4A1!!!!!!!!!!!!
        unsigned char damage (g_weaponPenetrationInformation[m_currentWeapon->GetID ()].damage1);
        const float obstaclePierce (g_weaponPenetrationInformation[m_currentWeapon->GetID ()].obstaclePierce1);

        direction /= length;

        end = direction * distance + start;

        ++currentWeaponPenetrationPower;

        // damage gets a randomlong added to it in first switch
        switch (g_weaponPenetrationInformation[m_currentWeapon->GetID ()].bulletType)
        {
                case WeaponBulletType_1:
                        bulletVelocity = 21u;
                        distanceMaximum = 800.0f;

                        break;

                case WeaponBulletType_9:
                        switch (yb_wall_sensitivity.GetInt ())
                        {
                                case 0u:
                                        damage -= 2u;

                                        break;

                                case 2u:
                                        damage += 2u;

                                        break;
                        }

                        bulletVelocity = 15u;
                        distanceMaximum = 500.0f;

                        break;

                case WeaponBulletType_13:
                        bulletVelocity = 30u;
                        distanceMaximum = 1000.0f;

                        break;

                case WeaponBulletType_11:
                        switch (yb_wall_sensitivity.GetInt ())
                        {
                                case 0u:
                                        damage -= 2u;

                                        break;

                                case 2u:
                                        damage += 2u;

                                        break;
                        }

                        bulletVelocity = 39u;
                        distanceMaximum = 5000.0f;

                        break;

                case WeaponBulletType_12:
                        switch (yb_wall_sensitivity.GetInt ())
                        {
                                case 0u:
                                        damage -= 3u;

                                        break;

                                case 2u:
                                        damage += 3u;

                                        break;
                        }

                        bulletVelocity = 35u;
                        distanceMaximum = 4000.0f;

                        break;

                case WeaponBulletType_10:
                        switch (yb_wall_sensitivity.GetInt ())
                        {
                                case 0u:
                                        damage -= 4u;

                                        break;

                                case 2u:
                                        damage += 4u;

                                        break;
                        }

                        bulletVelocity = 45u;
                        distanceMaximum = 8000.0f;

                        break;

                case WeaponBulletType_14:
                        switch (yb_wall_sensitivity.GetInt ())
                        {
                                case 0u:
                                        damage -= 4u;

                                        break;

                                case 2u:
                                        damage += 6u;

                                        break;

                                default:
                                        ++damage;

                                        break;
                        }

                        bulletVelocity = 30u;
                        distanceMaximum = 2000.0f;

                        break;

                case WeaponBulletType_15:
                        switch (yb_wall_sensitivity.GetInt ())
                        {
                                case 0u:
                                        damage -= 4u;

                                        break;

                                case 2u:
                                        damage += 6u;

                                        break;

                                default:
                                        ++damage;

                                        break;
                        }

                        bulletVelocity = 25u;
                        distanceMaximum = 800.0f;

                        break;

                default:
                        break;
        }

        for (/*Empty*/; /*Empty*/; /*Empty*/)
        {
                TRACE_LINE (start, end, TraceIgnore_Monsters, m_edict, m_traceResult);

                if (m_traceResult.fraction == 1.0f)
                        return 0u;

                switch (g_texturesManager->GetTextureType (m_traceResult.hitEntity, start, end))
                {
                        case TextureType_Concrete:
                                bulletVelocity *= 0.25f;

                                break;

                        case TextureType_Grate:
                                bulletVelocity *= 0.5f;
                                damageMult = 0.4f;

                                break;

                        case TextureType_Metal:
                                bulletVelocity *= 0.15f;
                                damageMult = 0.2f;

                                break;

                        case TextureType_Computer:
                                bulletVelocity *= 0.4f;

                                break;

                        case TextureType_Tile:
                                bulletVelocity *= 0.65f;
                                damageMult = 0.2f;

                                break;

                        case TextureType_Ventillation:
                                bulletVelocity *= 0.5f;
                                damageMult = 0.45f;

                                break;

                        case TextureType_Wood:
                                damageMult = 0.6f;

                        default:
                                break;
                }

                if ((m_traceResult.endPosition - source).GetLength () >= length)
                {
                        m_traceResult.fraction = (destination - start).GetLength () / (end - start).GetLength ();

                        distanceFraction = distance * m_traceResult.fraction;

                        damage *= pow (obstaclePierce, distanceFraction * 0.002f);

                        return damage;
                }

                if (--currentWeaponPenetrationPower == 0u || (distanceFraction = distance * m_traceResult.fraction) > distanceMaximum)
                        return 0u;

                damage *= pow (obstaclePierce, distanceFraction * 0.002f);

                start = bulletVelocity * direction + m_traceResult.endPosition;
                distance = (distance - distanceFraction) * 0.5f;
                end = direction * distance + start;
                distanceFraction = damage;
                damage = static_cast <unsigned char> (distanceFraction * damageMult);
        }
}

Sorry, that without explanations - in the first place: badly with English, secondly: I badly explain :)
In general, anyone interested - will understand :)

Whistler 20-12-2009 06:03

Re: Another IsShootableThruObstacle() function!!!!!!!!
 
well this looks much more detailed than the original PB function :) don't know how you figured this out but good job anyway :)


All times are GMT +2. The time now is 08:21.

Powered by vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.