boiii-scripts/mp/bots/_bot_hq.gsc
2023-04-13 17:30:38 +02:00

436 lines
14 KiB
Plaintext

#using scripts\shared\array_shared;
#using scripts\shared\util_shared;
#using scripts\mp\bots\_bot;
#using scripts\mp\bots\_bot_combat;
#namespace bot_hq;
function hq_think()
{
time = GetTime();
if ( time < self.bot.update_objective )
{
return;
}
self.bot.update_objective = time + RandomIntRange( 500, 1500 );
if ( should_patrol_hq() )
{
self patrol_hq();
}
else if ( !has_hq_goal() )
{
self move_to_hq();
}
if ( self is_capturing_hq() )
{
self capture_hq();
}
hq_tactical_insertion();
hq_grenade();
if ( !is_capturing_hq() && !self AtGoal( "hq_patrol" ) )
{
mine = GetNearestNode( self.origin );
point = hq_nearest_point();
if ( IsDefined( mine ) && bot::navmesh_points_visible( mine.origin, point ) )
{
self LookAt( level.radio.baseorigin + ( 0, 0, 30 ) );
}
}
}
function has_hq_goal()
{
origin = self GetGoal( "hq_radio" );
if ( isdefined( origin ) )
{
foreach( point in level.radio.points )
{
if ( DistanceSquared( origin, point ) < 64 * 64 )
{
return true;
}
}
}
return false;
}
function is_capturing_hq()
{
return ( self AtGoal( "hq_radio" ) );
}
function should_patrol_hq()
{
if ( level.radio.gameobject.ownerTeam == "neutral" )
{
return false;
}
if ( level.radio.gameobject.ownerTeam != self.team )
{
return false;
}
if ( hq_is_contested() )
{
return false;
}
return true;
}
function patrol_hq()
{
self CancelGoal( "hq_radio" );
if ( self AtGoal( "hq_patrol" ) )
{
node = GetNearestNode( self.origin );
if ( isdefined( node ) && node.type == "Path" )
{
self SetStance( "crouch" );
}
else
{
self SetStance( "stand" );
}
if ( GetTime() > self.bot.update_lookat )
{
origin = self get_look_at();
z = 20;
if ( DistanceSquared( origin, self.origin ) > 512 * 512 )
{
z = RandomIntRange( 16, 60 );
}
self LookAt( origin + ( 0, 0, z ) );
if ( DistanceSquared( origin, self.origin ) > 256 * 256 )
{
dir = VectorNormalize( self.origin - origin );
dir = VectorScale( dir, 256 );
origin = origin + dir;
}
self bot_combat::combat_throw_proximity( origin );
self.bot.update_lookat = GetTime() + RandomIntRange( 1500, 3000 );
}
goal = self GetGoal( "hq_patrol" );
nearest = hq_nearest_point();
mine = GetNearestNode( goal );
if ( isdefined( mine ) && !bot::navmesh_points_visible( mine.origin, nearest ) )
{
self ClearLookAt();
self CancelGoal( "hq_patrol" );
}
if ( GetTime() > self.bot.update_objective_patrol )
{
self ClearLookAt();
self CancelGoal( "hq_patrol" );
}
return;
}
nearest = hq_nearest_point();
if ( self HasGoal( "hq_patrol" ) )
{
goal = self GetGoal( "hq_patrol" );
if ( DistanceSquared( self.origin, goal ) < 256 * 256 )
{
origin = self get_look_at();
self LookAt( origin );
}
if ( DistanceSquared( self.origin, goal ) < 128 * 128 )
{
self.bot.update_objective_patrol = GetTime() + RandomIntRange( 3000, 6000 );
}
mine = GetNearestNode( goal );
if ( isdefined( mine ) && !bot::navmesh_points_visible( mine.origin, nearest ) )
{
self ClearLookAt();
self CancelGoal( "hq_patrol" );
}
return;
}
points = util::PositionQuery_PointArray( nearest, 0, 512, 70, 64 );
points = NavPointSightFilter( points, nearest );
assert( points.size );
i = RandomInt( points.size );
for ( ; i < points.size; i++ )
{
if ( self bot::friend_goal_in_radius( "hq_radio", points[i], 128 ) == 0 )
{
if ( self bot::friend_goal_in_radius( "hq_patrol", points[i], 256 ) == 0 )
{
self AddGoal( points[i], 24, 3, "hq_patrol" );
return;
}
}
}
}
function move_to_hq()
{
self ClearLookAt();
self CancelGoal( "hq_radio" );
self CancelGoal( "hq_patrol" );
if ( self GetStance() == "prone" )
{
self SetStance( "crouch" );
wait( 0.25 );
}
if ( self GetStance() == "crouch" )
{
self SetStance( "stand" );
wait( 0.25 );
}
points = array::randomize( level.radio.points );
foreach( point in points )
{
if ( self bot::friend_goal_in_radius( "hq_radio", point, 64 ) == 0 )
{
self AddGoal( point, 24, 3, "hq_radio" );
return;
}
}
self AddGoal( array::random( points ), 24, 3, "hq_radio" );
}
function get_look_at()
{
enemy = self bot::get_closest_enemy( self.origin, true );
if ( isdefined( enemy ) )
{
node = GetVisibleNode( self.origin, enemy.origin );
if ( isdefined( node ) && DistanceSquared( self.origin, node.origin ) > 128 * 128 )
{
return node.origin;
}
}
enemies = self bot::get_enemies( false );
if ( enemies.size )
{
enemy = array::random( enemies );
}
if ( isdefined( enemy ) )
{
node = GetVisibleNode( self.origin, enemy.origin );
if ( isdefined( node ) && DistanceSquared( self.origin, node.origin ) > 128 * 128 )
{
return node.origin;
}
}
spawn = array::random( level.spawnpoints );
node = GetVisibleNode( self.origin, spawn.origin );
if ( isdefined( node ) && DistanceSquared( self.origin, node.origin ) > 128 * 128 )
{
return node.origin;
}
return level.radio.baseorigin;
}
function capture_hq()
{
self AddGoal( self.origin, 24, 3, "hq_radio" );
self SetStance( "crouch" );
if ( GetTime() > self.bot.update_lookat )
{
origin = self get_look_at();
z = 20;
if ( DistanceSquared( origin, self.origin ) > 512 * 512 )
{
z = RandomIntRange( 16, 60 );
}
self LookAt( origin + ( 0, 0, z ) );
if ( DistanceSquared( origin, self.origin ) > 256 * 256 )
{
dir = VectorNormalize( self.origin - origin );
dir = VectorScale( dir, 256 );
origin = origin + dir;
}
self bot_combat::combat_throw_proximity( origin );
self.bot.update_lookat = GetTime() + RandomIntRange( 1500, 3000 );
}
}
function any_other_team_touching( skip_team )
{
foreach( team in level.teams )
{
if ( team == skip_team )
continue;
if ( level.radio.gameobject.numtouching[ team ] )
return true;
}
return false;
}
function is_hq_contested( skip_team )
{
if ( any_other_team_touching( skip_team ) )
{
return true;
}
enemy = self bot::get_closest_enemy( level.radio.baseorigin, true );
if ( isdefined( enemy ) && DistanceSquared( enemy.origin, level.radio.baseorigin ) < 512 * 512 )
{
return true;
}
return false;
}
function hq_grenade()
{
enemies = bot::get_enemies();
if ( !enemies.size )
{
return;
}
if ( self AtGoal( "hq_patrol" ) || self AtGoal( "hq_radio" ) )
{
if ( self GetWeaponAmmoStock( GetWeapon( "proximity_grenade" ) ) > 0 )
{
origin = get_look_at();
if ( self bot_combat::combat_throw_proximity( origin ) )
{
return;
}
}
}
if ( !is_hq_contested( self.team ) )
{
self bot_combat::combat_throw_smoke( level.radio.baseorigin );
return;
}
enemy = self bot::get_closest_enemy( level.radio.baseorigin, false );
if ( isdefined( enemy ) )
{
origin = enemy.origin;
}
else
{
origin = level.radio.baseorigin;
}
dir = VectorNormalize( self.origin - origin );
dir = ( 0, dir[1], 0 );
origin = origin + VectorScale( dir, 128 );
if ( !self bot_combat::combat_throw_lethal( origin ) )
{
self bot_combat::combat_throw_tactical( origin );
}
}
function hq_tactical_insertion()
{
if ( !self HasWeapon( GetWeapon( "tactical_insertion" ) ) )
{
return;
}
dist = self GetLookAheadDist();
dir = self GetLookaheadDir();
if ( !isdefined( dist ) || !isdefined( dir ) )
{
return;
}
point = hq_nearest_point();
mine = GetNearestNode( self.origin );
if ( isdefined( mine ) && !bot::navmesh_points_visible( mine.origin, point ) )
{
origin = self.origin + VectorScale( dir, dist );
next = GetNearestNode( origin );
if ( isdefined( next ) && bot::navmesh_points_visible( next.origin, point ) )
{
bot_combat::combat_tactical_insertion( self.origin );
}
}
}
function hq_nearest_point()
{
return array::random( level.radio.points );
}
function hq_is_contested()
{
enemy = self bot::get_closest_enemy( level.radio.baseorigin, false );
return ( IsDefined( enemy ) && DistanceSquared( enemy.origin, level.radio.baseorigin ) < level.radio.node_radius * level.radio.node_radius );
}