smilz0 / Left4Bots

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

When one bot is incapacitated, the others always try to heal it and die #87

Open Wokgui opened 8 months ago

Wokgui commented 8 months ago

Hello,

Very nice addon, but something really annoying : when a bot is incapacitated by the tank, all the others try to heal it and run right into the tank, so I am always alone in front of tanks.

And another thing : is there a way to make bots give me their throwables right away when they get one ? There is sometimes a very long delay and sometimes they never do so. (when we are fighting)

Thanks !

smilz0 commented 8 months ago

Yes i know but unfortunately this is a vanilla behavior and i was unable to find a way to prevent it. I leave this issue here in case someone else finds it.

For the items you can use the 'give' command (default vocalizer line: 'i'm here') in any moment.

NewbieZz commented 8 months ago

True, the bot will always try to revive incapacitated players, even when tank is beside.

Maybe someone can try to look into avoiddanger from advance bot ai, it works, but i don't know how to apply to left4bots2

Wokgui commented 8 months ago

Exactly what I was going to say : advanced bots ai does not have this problem. I would prefer to use left4bots instead as it is much more customizable, but this incapacited thing makes it unusable. I dont know anything about add ons so I cant do it myself.

NewbieZz commented 8 months ago

I think advance bot ai used navigator pause

oblivcheck commented 1 month ago

I believe that advance bot ai prevents bots from rescuing incapacitated survivors by blocking the navigation mesh in the area where the survivor is down. For example, by obtaining the position of the incapacitated survivor, it’s possible to identify the corresponding NavMesh ID, Then use NAVMESHID to block the NAV AREA. (NavMesh vscript functions should be enough to achieve this) DEMO

However, I’m not very familiar with L4D2 vscript. If you're still interested, could you consider updating this mod?

See Also

scripts/vscripts/aiupdatehandler.nut

~Line 1846


????
{
....
Other code
....

::NavigatorPause.fall <- function(player) {
    if(!BotAI.IsEntityValid(player)) return true;
    if(player.IsDominatedBySpecialInfected() || player.IsGettingUp() || player.IsStaggering() || player.IsIncapacitated() || player.IsHangingFromLedge()) {
        return true;
    }

    return false;
}

::NavigatorPause.useAidItem <- function(player) {
    if(!BotAI.IsEntityValid(player)) return true;
    if(player.GetActiveWeapon()) {
        local name = player.GetActiveWeapon().GetClassname();
        if(name == "weapon_first_aid_kit" || name == "weapon_defibrillator" || name == "weapon_upgradepack_explosive" || name == "weapon_upgradepack_incendiary")
            return true;
    }

    return false;
}

::NavigatorPause.avoidDanger <- function(player) {
    if(!BotAI.IsEntityValid(player)) return true;
    local target = BotAI.GetTarget(player);
    if(BotAI.IsEntitySI(target) && BotAI.GetTarget(target) == player) {
        if(target.GetZombieType() != 8) {
            return true;
        } else if(BotAI.nextTickDistance(player, target) <= 200) {
            return true;
        }
    }
    local dangerous = BotAI.getBotAvoid(player);
    foreach(danger in dangerous) {
        if(BotAI.IsEntitySI(danger) && BotAI.GetTarget(danger) == player) {
            if(BotAI.BotFullPower && !BotAI.HasTank)
                player.OverrideFriction(1, 0.7);
            if(danger.GetZombieType() != 8) {
                return true;
            } else if(BotAI.nextTickDistance(player, danger) <= 200) {
                return true;
            }
        }
    }

    return false;
}

https://developer.valvesoftware.com/wiki/Nav_Mesh/Console_commands

https://developer.valvesoftware.com/wiki/Left_4_Dead_2/Scripting/Script_Functions#CNavMesh

::CNavMesh
::TerrorNavArea

https://developer.valvesoftware.com/wiki/List_of_L4D_Series_Nav_Mesh_Attributes

BLOCKED_SURVIVOR

> $ grep -R NavMesh *

scripts/vscripts/rayman1103_vslib/utils.nut:        NavMesh.UnblockRescueVehicleNav();
scripts/vscripts/ai_taskes/ai-avoiddanger.nut:                          NavMesh.GetNavAreasInRadius(player.GetOrigin(), 400, areas);
scripts/vscripts/ai_lib/ai_utils.nut:       local area = NavMesh.GetNavArea(m_trace.enthit.GetOrigin(), 100);
scripts/vscripts/ai_lib/ai_navigator.nut:            goalArea = NavMesh.GetNavArea(goalPos, 150);
scripts/vscripts/ai_lib/ai_navigator.nut:                    goalArea = NavMesh.GetNavArea(targetPos, 150);
scripts/vscripts/ai_lib/ai_navigator.nut:                build = NavMesh.GetNavAreasFromBuildPath(player.GetLastKnownArea(), null, goalPos, 9999, 2, false, paths);
scripts/vscripts/ai_lib/ai_navigator.nut:                    goalArea = NavMesh.GetNavArea(goalPos, 150);
scripts/vscripts/ai_lib/ai_navigator.nut:                            goalArea = NavMesh.GetNavArea(targetPos, 150);
scripts/vscripts/ai_lib/ai_navigator.nut:            endArea = NavMesh.GetNavArea(pos + Vector(0, 0, 50), 200);
scripts/vscripts/ai_lib/ai_navigator.nut:            endArea = NavMesh.GetNearestNavArea(pos + Vector(0, 0, 50), 200, true, true);
scripts/vscripts/ai_lib/ai_events.nut:                  local area = NavMesh.GetNearestNavArea(victim.GetOrigin(), 500, true, true);
scripts/vscripts/aiupdatehandler.nut:   NavMesh.GetObstructingEntities(obstacles);
scripts/vscripts/aiupdatehandler.nut:   NavMesh.GetAllLadders(ladders);
oblivcheck commented 1 month ago

Sourcemod Plugin: https://forums.alliedmods.net/showthread.php?p=2829159#post2829159

Mystik-Spiral commented 1 month ago

Thinking about the method above, it seems like rather than blocking the nav area around the incapped survivor, it would be better to block the nav area around the tank. The nav area to block around the tank should probably use a variable, and would need to be updated at some frequency, probably also using a variable. I am not sure how often the update would be needed, but maybe once per second or two as I doubt there is a need to update it every frame. By blocking the nav area around the tank, you allow non-incapped survivors to pick up incapped survivors even when the tank is alive, but out of range. This may be particularly helpful when there are multiple tanks spawned. For example, if playing Tank Challenge or Tanks Playground, an incapped survivor might never be picked up since there is nearly always one or more tanks spawned.

smilz0 commented 1 month ago

Hey guys, thanks for the input. The nav area blocking method wouldn't be too difficult to implement, i already do that with the spitter's spit. However i've lost the count of how many times, in my games, the team was saved by a bot who decided to revive a downed teammate right next to a tank. I don't know if there is a fix to this that would work in every situation.

oblivcheck commented 1 month ago

I think you could try tracking the tank's target changes and check if the tank is visible to a certain bot.