smilz0 / Left4Bots

Improvements for the L4D2 survivor bots
https://steamcommunity.com/sharedfiles/filedetails/?id=3022416274
34 stars 4 forks source link

Fix pick up melee loop #85

Closed 4512369781 closed 5 months ago

4512369781 commented 6 months ago

The tonfa dropped by riot does not have the "m_strMapSetScriptName" parameter and function "Left4Utils.GetMeleeIdByModel" has a bug, this two reason caused can't get the correct melee id.

Only matching "w_*" is not enough.
// Model to show in firstperson
"viewmodel"     "models/weapons/melee/v_tonfa.mdl"

// Model to show in thirdperson
"playermodel"   "models/weapons/melee/w_tonfa.mdl"

fix pickup melee loop.zip

smilz0 commented 6 months ago

Thank you. Btw, is this related to the bots swapping weapon over and over or they just not pick the item up?

4512369781 commented 6 months ago

Thank you. Btw, is this related to the bots swapping weapon over and over or they just not pick the item up?

Yes, this fixes "bots swapping weapon over and over".

about not pick up item, I think one reason is custom skins, my smg skins let "center pos" under ground, so bot not pick up it in c1m1, use "origin pos" can fix this. and other reason is about "TraceLine", i guess it hit something transparent, adjust "tracemask_pickups" should be some help.

//delete some thing, need test more.
//tracemask_pickups = 16395; //CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_WINDOW | CONTENTS_GRATE
::Left4Bots.CanTraceToPickup <- function (bot, item)
{
    //local mask = 0x1 | 0x8 | 0x40 | 0x2000 | 0x4000  | 0x8000000; // CONTENTS_SOLID | CONTENTS_GRATE | CONTENTS_BLOCKLOS | CONTENTS_IGNORE_NODRAW_OPAQUE | CONTENTS_MOVEABLE | CONTENTS_DETAIL
    local traceTable = { start = bot.EyePosition(), end = item.GetOrigin(), ignore = bot, mask = Settings.tracemask_pickups };

    TraceLine(traceTable);

    //printl("fraction: " + traceTable.fraction);
    //DebugDrawCircle(traceTable.pos, Vector(0, 0, 255), 255, 10, true, 0.1);

    return (traceTable.fraction > 0.98 || !traceTable.hit || !traceTable.enthit || traceTable.enthit == item || traceTable.enthit.GetClassname() == "prop_health_cabinet");
}
smilz0 commented 6 months ago

Hey mate, i think i simplified your fix a little bit: https://github.com/smilz0/Left4Lib/commit/dbf18b4c7679ce5dc2f81e98fa726eed21db645a Let me know if i messed up something.

About the CanTraceToPickup i don't think that using GetOrigin will fix it. Look at the comment on the ::Left4Utils.CanTraceTo function. Depending on the angle of the bot looking at the item, GetOrigin was making the trace to fall outside of the item's hitbox and so not hit it. GetCenter solved it. It shouldn't matter if the center of the item is actually under the ground because the trace is supposed to hit the part above and make this condition true: traceTable.enthit == item. Also, yes the default tracemask_pickups, in some maps, can make the trace hit some invisible wall and make the bots not "see" the item. It happens in c1m3 in the room with the stop alarm button with the medkit on the table next to the door. A different value of tracemask_pickups can solve but i don't know if there is a value that works every time, this is why i turned it into a setting, so people can make a settings_mapname.txt file and set a different value for these maps.

4512369781 commented 6 months ago

Hey mate, i think i simplified your fix a little bit: smilz0/Left4Lib@dbf18b4 Let me know if i messed up something.

I tested it and works great.

About the CanTraceToPickup

bots ignore smg green circle is center point these screenshot shows why use "GetCenter" can not hit smg in c1m1 with this custom skins

and fix another bug about bots not pick up the last item in "cfg/weapons/*.txt".

StringToFile() : Due to a bug, string is saved with zero byte at the end.

::Left4Bots.LoadWeaponPreferences <- function (survivor, scope)
{
    // WeapPref array has one sub-array for each inventory slot
    // Each sub-array contains the weapons from the highest to the lowest priority one for that inventory slot
    scope.WeapPref <- [[], [], [], [], []];

    // WeapNoPref array contains a flag for each inventory slot
    // The flag indicates whether the priority of the weapons in WeapPref for that slot must be ignored
    scope.WeapNoPref <- [false, false, false, false, false];

    if (!survivor || !survivor.IsValid() || !scope)
        return;

    //Logger.Debug("LoadWeaponPreferences - survivor: " + survivor.GetPlayerName());

    // TODO: do this with the character id instead
    local filename = GetCharacterDisplayName(survivor);
    if (filename == null || filename == "")
        filename = survivor.GetPlayerName(); // Apparently the L4D1 survivors in The Passing 3 don't have a CharacterDisplayName
    filename = Settings.file_weapons_prefix + filename.tolower() + ".txt";
    local lines = Left4Utils.FileToStringList(filename);
    if (!lines)
        return;

    local c = 0;
    for (local i = 0; i < lines.len(); i++)
    {
        local line = Left4Utils.StripComments(lines[i]);
        if (line != "")
        {
            local weaps = split(line, ",");
            for (local x = 0; x < weaps.len(); x++)
            {
                //delete space characters which cause bug
                local wp = strip(weaps[x]);

                if (x == 0 && wp == "*")
                    scope.WeapNoPref[i] = true;
                else
                {
                    local id = Left4Utils.GetWeaponIdByName(wp);

                    //Logger.Debug("LoadWeaponPreferences - i: " + i + " - w: " + wp + " - id: " + id);

                    if (id > Left4Utils.WeaponId.none && id != Left4Utils.MeleeWeaponId.none && id != Left4Utils.UpgradeWeaponId.none)
                    {
                        scope.WeapPref[i].append(id); // valid weapon
                        c++;
                    }
                }
            }
        }
    }

    Logger.Debug("LoadWeaponPreferences - Loaded " + c + " preferences for survivor: " + survivor.GetPlayerName() + " from file: " + filename);
}
smilz0 commented 6 months ago

Thanks! I Added the fix to the LoadWeaponPreferences function but i still don't think that GetOrigin is the solution for CanTraceToPickup. I tried that smg skin and indeed there is a problem with it. It seems that the trace never hits the item, it always hits the ground. Same with GetOrigin, but the difference with GetOrigin is that fraction is enough to make this condition true: traceTable.fraction > 0.98. You can also solve by using a different value for the trace mask. Infact if you use tracemask_others instead of tracemask_pickups, it works even with GetCenter and the bots pick that smg up no problem.