Since I was looking for an answer too and I found one (think I took example from
https://github.com/Derpduck/L4D2-Comp-Stripper-Rework/), I thought I post it here.
You can create a vector and then attach it to a func_nav_blocker. I found it easier to create all func_nav_blocker in stripper and only remove the ones I want by an extra script.
This example is for dead air 1 map vs (custom nav_mesh needed to use the right window to go down)
But you will see how the bots will stop at the block windows to the roof, that will show you that the nav is cut, just noclip to roof, they wont follow.
PHP Code:
modify:
{
match:
{
"classname" "logic_auto"
}
insert:
{
"OnMapSpawn" "window_event_nav_block_a,AddOutput,mins -20 -200 -300,0,-1"
"OnMapSpawn" "window_event_nav_block_a,AddOutput,maxs 20 200 300,0,-1"
"OnMapSpawn" "window_event_nav_block_a,AddOutput,solid 2,0,-1"
"OnMapSpawn" "window_event_nav_block_a,BlockNav,,1,-1"
"OnMapSpawn" "window_event_nav_block_b,AddOutput,mins -200 -20 -300,0,-1"
"OnMapSpawn" "window_event_nav_block_b,AddOutput,maxs 200 20 300,0,-1"
"OnMapSpawn" "window_event_nav_block_b,AddOutput,solid 2,0,-1"
"OnMapSpawn" "window_event_nav_block_b,BlockNav,,1,-1"
}
}
add:
{
"classname" "func_nav_blocker"
"origin" "3332 192 614"
"targetname" "window_event_nav_block_a"
"teamToBlock" "-1"
}
{
"classname" "func_nav_blocker"
"origin" "3632 761 614"
"targetname" "window_event_nav_block_b"
"teamToBlock" "-1"
}
add:
{
"classname" "prop_dynamic"
"solid" "6"
"targetname" "leftwindow1"
"origin" "3332 100 550"
"angles" "0 90 90"
"model" "models/props_highway/plywood_01.mdl"
"disableshadows" "1"
}
add:
{
"classname" "prop_dynamic"
"solid" "6"
"targetname" "leftwindow2"
"origin" "3332 230 550"
"angles" "0 90 90"
"model" "models/props_highway/plywood_01.mdl"
"disableshadows" "1"
}
add:
{
"classname" "prop_dynamic"
"solid" "6"
"targetname" "leftwindow3"
"origin" "3332 360 550"
"angles" "0 90 90"
"model" "models/props_highway/plywood_01.mdl"
"disableshadows" "1"
}
add:
{
"classname" "prop_dynamic"
"solid" "6"
"targetname" "leftwindow4"
"origin" "3332 100 598"
"angles" "0 90 90"
"model" "models/props_highway/plywood_01.mdl"
"disableshadows" "1"
}
add:
{
"classname" "prop_dynamic"
"solid" "6"
"targetname" "leftwindow5"
"origin" "3332 230 598"
"angles" "0 90 90"
"model" "models/props_highway/plywood_01.mdl"
"disableshadows" "1"
}
add:
{
"classname" "prop_dynamic"
"solid" "6"
"targetname" "leftwindow6"
"origin" "3332 360 598"
"angles" "0 90 90"
"model" "models/props_highway/plywood_01.mdl"
"disableshadows" "1"
}
add:
{
"classname" "prop_dynamic"
"solid" "0"
"targetname" "rightexit"
"origin" "3630 745 657"
"angles" "0 90 0"
"model" "models/props/cs_office/exit_ceiling.mdl"
"disableshadows" "1"
}
add:
{
"classname" "prop_dynamic"
"solid" "0"
"targetname" "leftexit"
"origin" "3354 190 657"
"angles" "0 0 0"
"model" "models/props/cs_office/exit_ceiling.mdl"
"disableshadows" "1"
}
add:
{
"classname" "prop_dynamic"
"solid" "6"
"targetname" "rightwindow1"
"origin" "3665 760 550"
"angles" "0 0 90"
"model" "models/props_highway/plywood_01.mdl"
"disableshadows" "1"
}
add:
{
"classname" "prop_dynamic"
"solid" "6"
"targetname" "rightwindow2"
"origin" "3665 760 598"
"angles" "0 0 90"
"model" "models/props_highway/plywood_01.mdl"
"disableshadows" "1"
}
add:
{
"classname" "prop_dynamic"
"solid" "6"
"targetname" "rightwindow3"
"origin" "3465 760 550"
"angles" "0 0 90"
"model" "models/props_highway/plywood_01.mdl"
"disableshadows" "1"
}
add:
{
"classname" "prop_dynamic"
"solid" "6"
"targetname" "rightwindow4"
"origin" "3465 760 598"
"angles" "0 0 90"
"model" "models/props_highway/plywood_01.mdl"
"disableshadows" "1"
}
This is old sintax mixed only to show how I open or block based on tankflow.
PHP Code:
#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <l4d_direct>
//#pragma newdecls required
new iTankPercent = 0;
public void OnPluginStart()
{
HookEvent("round_freeze_end", event_round_freeze_end, EventHookMode_PostNoCopy);
}
public void event_round_freeze_end(Event event, const char[] name, bool dontBroadcast)
{
char sMap[64];
char targetname[128];
GetCurrentMap(sMap, sizeof(sMap));
if (StrEqual(sMap, "l4d_vs_airport01_greenhouse", false))
{
if (L4DDirect_GetVSTankToSpawnThisRound(0))
{
iTankPercent = RoundToNearest(GetTankFlow(0)*100.0);
}
if(iTankPercent<66)
{
int target = -1;
while((target = FindEntityByClassname(target, "func_nav_blocker")) > -1)
{
if(IsValidEntity(target))
{
GetEntPropString(target, Prop_Data, "m_iName", targetname, sizeof(targetname));
if(StrEqual(targetname,"window_event_nav_block_a"))
{
AcceptEntityInput(target, "Kill");
}
}
}
target = -1;
while((target = FindEntityByClassname(target, "prop_dynamic")) > -1)
{
if(IsValidEntity(target))
{
GetEntPropString(target, Prop_Data, "m_iName", targetname, sizeof(targetname));
if(StrEqual(targetname,"leftwindow1"))
{
AcceptEntityInput(target, "Kill");
}
if(StrEqual(targetname,"leftwindow2"))
{
AcceptEntityInput(target, "Kill");
}
if(StrEqual(targetname,"leftwindow3"))
{
AcceptEntityInput(target, "Kill");
}
if(StrEqual(targetname,"leftwindow4"))
{
AcceptEntityInput(target, "Kill");
}
if(StrEqual(targetname,"leftwindow5"))
{
AcceptEntityInput(target, "Kill");
}
if(StrEqual(targetname,"leftwindow6"))
{
AcceptEntityInput(target, "Kill");
}
if(StrEqual(targetname,"rightexit"))
{
AcceptEntityInput(target, "Kill");
}
}
}
}
else
{
int target = -1;
while((target = FindEntityByClassname(target, "func_nav_blocker")) > -1)
{
if(IsValidEntity(target))
{
GetEntPropString(target, Prop_Data, "m_iName", targetname, sizeof(targetname));
if(StrEqual(targetname,"window_event_nav_block_b"))
{
AcceptEntityInput(target, "Kill");
}
}
}
target = -1;
while((target = FindEntityByClassname(target, "prop_dynamic")) > -1)
{
if(IsValidEntity(target))
{
GetEntPropString(target, Prop_Data, "m_iName", targetname, sizeof(targetname));
if(StrEqual(targetname,"rightwindow1"))
{
AcceptEntityInput(target, "Kill");
}
if(StrEqual(targetname,"rightwindow2"))
{
AcceptEntityInput(target, "Kill");
}
if(StrEqual(targetname,"rightwindow3"))
{
AcceptEntityInput(target, "Kill");
}
if(StrEqual(targetname,"rightwindow4"))
{
AcceptEntityInput(target, "Kill");
}
if(StrEqual(targetname,"leftexit"))
{
AcceptEntityInput(target, "Kill");
}
}
}
}
}
}
stock Float:GetTankFlow(round)
{
new Float:tankflow = L4DDirect_GetVSTankFlowPercent(round);
return tankflow;
}
The vector will be on the spawned func_nav_blocker. the vector should touch the nav_mesh, then it will cut it. Make sure to always cut ALL connections. If the path has for example two windows, then cut both by making the vector longer. You need to fully cut it.
Works best on windows and door, because it is easier to set up.
Stand in middle of window or door, then get pos by console "cl_showpos 1".
try to set vector acordingly must start bottom front left and top back right corner.
just add additional space -100 +100 and depth -20 +20
This will be always "on" as made above. you could use a trigger to turn it off.
I use a sepereate script that depends on the tank flow.
if tank flow is <66 it will kill the entity and =>66 the other. ( I allowed rotoblin to use lower and higher flows, to 66 seemed ok)
With this kind of approach you can accomplish dynamic path based on tank flow.
If you make a custom nav_mesh with 2 ways, you could cut the nav on one side and open on other side, by killing one func_nav_block entitiy. then simply kill the entities you used as prop_dynamic to block the way as well.
Then the bots will only go the open way and ignore the other.
Since I bound the removal to tankflow which is equal in rotoblin versus, the block will be always same for both teams. Great.
__________________