mirror of
https://github.com/JezuzLizard/t4sp_bot_warfare.git
synced 2025-04-20 05:25:44 +00:00
cleanup
This commit is contained in:
parent
65ad154eb6
commit
81e65a3adb
@ -1,7 +1,5 @@
|
|||||||
# T4ZM-Zombie-Bots
|
# T4SP-Bots
|
||||||
Bots for T4ZM.
|
Bots for T4SP.
|
||||||
|
|
||||||
Coby basted code from https://github.com/ineedbots/t4m_bot_warfare
|
Coby basted code from https://github.com/ineedbots/t4m_bot_warfare
|
||||||
Credit to ineedbots for his bot warfare mods for various games.
|
Credit to ineedbots for his bot warfare mods for various games.
|
||||||
|
|
||||||
Requires https://github.com/JezuzLizard/T4ZM-Script-Overhaul
|
|
@ -155,6 +155,11 @@ handleBots()
|
|||||||
*/
|
*/
|
||||||
onPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime )
|
onPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime )
|
||||||
{
|
{
|
||||||
|
if ( self isBot() && getDvarInt( "bots_t8_mode" ) )
|
||||||
|
{
|
||||||
|
iDamage = int( iDamage * 0.1 );
|
||||||
|
}
|
||||||
|
|
||||||
if ( self is_bot() )
|
if ( self is_bot() )
|
||||||
{
|
{
|
||||||
self maps\bots\_bot_internal::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime );
|
self maps\bots\_bot_internal::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime );
|
||||||
@ -164,6 +169,16 @@ onPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon,
|
|||||||
self [[level.prevCallbackPlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime );
|
self [[level.prevCallbackPlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onActorDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, iTimeOffset )
|
||||||
|
{
|
||||||
|
if ( isDefined( eAttacker ) && isPlayer( eAttacker ) && eAttacker isBot() && getDvarInt( "bots_t8_mode" ) )
|
||||||
|
{
|
||||||
|
iDamage += int( self.maxhealth * randomFloatRange( 0.25, 1.25 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
self [[level.prevCallbackActorDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, iTimeOffset );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Starts the callbacks.
|
Starts the callbacks.
|
||||||
*/
|
*/
|
||||||
@ -172,6 +187,9 @@ hook_callbacks()
|
|||||||
wait 0.05;
|
wait 0.05;
|
||||||
level.prevCallbackPlayerDamage = level.callbackPlayerDamage;
|
level.prevCallbackPlayerDamage = level.callbackPlayerDamage;
|
||||||
level.callbackPlayerDamage = ::onPlayerDamage;
|
level.callbackPlayerDamage = ::onPlayerDamage;
|
||||||
|
|
||||||
|
level.prevCallbackActorDamage = level.callbackActorDamage;
|
||||||
|
level.callbackActorDamage = ::onActorDamage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -764,6 +764,7 @@ load_waypoints()
|
|||||||
level.waypoints = GetAllNodes();
|
level.waypoints = GetAllNodes();
|
||||||
level.waypointCount = level.waypoints.size;
|
level.waypointCount = level.waypoints.size;
|
||||||
|
|
||||||
|
level.waypointsInPlayableArea = [];
|
||||||
level.waypointsInPlayableArea = get_nodes_in_playable_area();
|
level.waypointsInPlayableArea = get_nodes_in_playable_area();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1040,7 +1041,16 @@ random_normal_distribution( mean, std_deviation, lower_bound, upper_bound )
|
|||||||
*/
|
*/
|
||||||
inLastStand()
|
inLastStand()
|
||||||
{
|
{
|
||||||
return self maps\_laststand::player_is_in_laststand();
|
func = GetFunction( "maps/_laststand", "player_is_in_laststand" );
|
||||||
|
|
||||||
|
return self [[func]]();
|
||||||
|
}
|
||||||
|
|
||||||
|
isReviving( revivee )
|
||||||
|
{
|
||||||
|
func = GetFunction( "maps/_laststand", "is_reviving" );
|
||||||
|
|
||||||
|
return self [[func]]( revivee );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1048,6 +1058,11 @@ inLastStand()
|
|||||||
*/
|
*/
|
||||||
getRandomGoal()
|
getRandomGoal()
|
||||||
{
|
{
|
||||||
|
if ( !level.waypointsInPlayableArea.size )
|
||||||
|
{
|
||||||
|
return self.origin;
|
||||||
|
}
|
||||||
|
|
||||||
return PickRandom( level.waypointsInPlayableArea ).origin;
|
return PickRandom( level.waypointsInPlayableArea ).origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ init()
|
|||||||
level.bot_objectives = [];
|
level.bot_objectives = [];
|
||||||
level.bot_objectives[level.bot_objectives.size] = CreateObjectiveForManger( "revive", maps\bots\objectives\_revive::Finder, maps\bots\objectives\_revive::Executer, 1000 );
|
level.bot_objectives[level.bot_objectives.size] = CreateObjectiveForManger( "revive", maps\bots\objectives\_revive::Finder, maps\bots\objectives\_revive::Executer, 1000 );
|
||||||
level.bot_objectives[level.bot_objectives.size] = CreateObjectiveForManger( "powerup", maps\bots\objectives\_powerup::Finder, maps\bots\objectives\_powerup::Executer, 2500 );
|
level.bot_objectives[level.bot_objectives.size] = CreateObjectiveForManger( "powerup", maps\bots\objectives\_powerup::Finder, maps\bots\objectives\_powerup::Executer, 2500 );
|
||||||
|
level.bot_objectives[level.bot_objectives.size] = CreateObjectiveForManger( "wallweapon", maps\bots\objectives\_wallweapon::Finder, maps\bots\objectives\_wallweapon::Executer, 7500 );
|
||||||
}
|
}
|
||||||
|
|
||||||
connected()
|
connected()
|
||||||
|
@ -10,7 +10,7 @@ Finder( eObj )
|
|||||||
|
|
||||||
if ( self inLastStand() )
|
if ( self inLastStand() )
|
||||||
{
|
{
|
||||||
return Answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( i = 0; i < ents.size; i++ )
|
for ( i = 0; i < ents.size; i++ )
|
||||||
@ -40,7 +40,7 @@ Priority( eObj, eEnt )
|
|||||||
{
|
{
|
||||||
// TODO: check powerup type
|
// TODO: check powerup type
|
||||||
base_priority = 0;
|
base_priority = 0;
|
||||||
base_priority += ClampLerp( Distance( self.origin, eEnt.origin ), 300, 700, 2, -2 );
|
base_priority += ClampLerp( get_path_dist( self.origin, eEnt.origin ), 300, 700, 2, -2 );
|
||||||
|
|
||||||
if ( self HasBotObjective() )
|
if ( self HasBotObjective() )
|
||||||
{
|
{
|
||||||
|
@ -56,7 +56,7 @@ Finder( eObj )
|
|||||||
Priority( eObj, eEnt )
|
Priority( eObj, eEnt )
|
||||||
{
|
{
|
||||||
base_priority = 3;
|
base_priority = 3;
|
||||||
base_priority += ClampLerp( Distance( self.origin, eEnt.origin ), 500, 1200, 2, -2 );
|
base_priority += ClampLerp( get_path_dist( self.origin, eEnt.origin ), 500, 1200, 2, -2 );
|
||||||
|
|
||||||
if ( self HasBotObjective() )
|
if ( self HasBotObjective() )
|
||||||
{
|
{
|
||||||
@ -114,9 +114,9 @@ WatchForCancelRevive( revivee )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( revivee.revivetrigger.beingrevived && !self maps\_laststand::is_reviving( revivee ) )
|
if ( revivee.revivetrigger.beingrevived && !self isReviving( revivee ) )
|
||||||
{
|
{
|
||||||
self CancelObjective( "revivee.revivetrigger.beingrevived && !self maps\_laststand::is_reviving( revivee )" );
|
self CancelObjective( "revivee.revivetrigger.beingrevived && !self isReviving( revivee )" );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ ClampLerp( dist, min_dist, max_dist, max_bonus, min_bonus )
|
|||||||
{
|
{
|
||||||
answer += max_bonus;
|
answer += max_bonus;
|
||||||
}
|
}
|
||||||
else if ( dist <= max_dist )
|
else if ( dist >= max_dist )
|
||||||
{
|
{
|
||||||
answer += min_bonus;
|
answer += min_bonus;
|
||||||
}
|
}
|
||||||
@ -172,9 +172,23 @@ get_angle_offset_node( forward_size, angle_offset, offset )
|
|||||||
angles += angle_offset;
|
angles += angle_offset;
|
||||||
node = self.origin + ( AnglesToForward( angles ) * forward_size ) + offset;
|
node = self.origin + ( AnglesToForward( angles ) * forward_size ) + offset;
|
||||||
node = clamp_to_ground( node );
|
node = clamp_to_ground( node );
|
||||||
|
|
||||||
|
self thread debug_offset_line( node );
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug_offset_line( node )
|
||||||
|
{
|
||||||
|
self notify( "debug_offset_line" );
|
||||||
|
self endon( "debug_offset_line" );
|
||||||
|
|
||||||
|
for ( ;; )
|
||||||
|
{
|
||||||
|
line( self.origin, node );
|
||||||
|
wait 0.05;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clamp_to_ground( org )
|
clamp_to_ground( org )
|
||||||
{
|
{
|
||||||
trace = playerPhysicsTrace( org + ( 0, 0, 20 ), org - ( 0, 0, 2000 ) );
|
trace = playerPhysicsTrace( org + ( 0, 0, 20 ), org - ( 0, 0, 2000 ) );
|
||||||
|
214
maps/bots/objectives/_wallweapon.gsc
Normal file
214
maps/bots/objectives/_wallweapon.gsc
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
#include common_scripts\utility;
|
||||||
|
#include maps\_utility;
|
||||||
|
#include maps\bots\_bot_utility;
|
||||||
|
#include maps\bots\objectives\_utility;
|
||||||
|
|
||||||
|
Finder( eObj )
|
||||||
|
{
|
||||||
|
answer = [];
|
||||||
|
|
||||||
|
if ( self inLastStand() )
|
||||||
|
{
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
weapon_spawns = GetEntArray( "weapon_upgrade", "targetname" );
|
||||||
|
|
||||||
|
if ( !isDefined( weapon_spawns ) || weapon_spawns.size <= 0 )
|
||||||
|
{
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
weapons = self GetWeaponsList();
|
||||||
|
|
||||||
|
// TODO check if need a new weapon, rate weapons too is better then current etc
|
||||||
|
|
||||||
|
for ( i = 0; i < weapon_spawns.size; i++ )
|
||||||
|
{
|
||||||
|
player_has_weapon = false;
|
||||||
|
|
||||||
|
if ( !isDefined( weapon_spawns[i].zombie_weapon_upgrade ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( h = 0; h < weapons.size; h++ )
|
||||||
|
{
|
||||||
|
if ( weapons[h] == weapon_spawns[i].zombie_weapon_upgrade )
|
||||||
|
{
|
||||||
|
player_has_weapon = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is_grenade = ( WeaponType( weapon_spawns[i].zombie_weapon_upgrade ) == "grenade" );
|
||||||
|
|
||||||
|
if ( !player_has_weapon || is_grenade )
|
||||||
|
{
|
||||||
|
func = GetFunction( "maps/_zombiemode_weapons", "get_weapon_cost" );
|
||||||
|
|
||||||
|
if ( self.score < [[func]]( weapon_spawns[i].zombie_weapon_upgrade ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
func = GetFunction( "maps/_zombiemode_weapons", "get_ammo_cost" );
|
||||||
|
|
||||||
|
if ( self.score < [[func]]( weapon_spawns[i].zombie_weapon_upgrade ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model = getEnt( weapon_spawns[ i ].target, "targetname" );
|
||||||
|
|
||||||
|
if ( !isDefined( model ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
org = self getOffset( model );
|
||||||
|
|
||||||
|
if ( GetPathIsInaccessible( self.origin, org ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
answer[answer.size] = self CreateFinderObjective( eObj, eObj.sName + "_" + weapon_spawns[i] GetEntityNumber(), weapon_spawns[i], self Priority( eObj, weapon_spawns[i] ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
getOffset( model )
|
||||||
|
{
|
||||||
|
// some weapons have 90 offset... how to handle this??
|
||||||
|
angle_off = -90;
|
||||||
|
|
||||||
|
org = model get_angle_offset_node( 40, ( 0, angle_off, 0 ), ( 0, 0, 1 ) );
|
||||||
|
|
||||||
|
return org;
|
||||||
|
}
|
||||||
|
|
||||||
|
Priority( eObj, eEnt )
|
||||||
|
{
|
||||||
|
// TODO: check weallweapon type
|
||||||
|
|
||||||
|
base_priority = 0;
|
||||||
|
base_priority += ClampLerp( get_path_dist( self.origin, eEnt.origin ), 0, 800, 2, -2 );
|
||||||
|
|
||||||
|
if ( self HasBotObjective() )
|
||||||
|
{
|
||||||
|
base_priority -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( eEnt.zombie_weapon_upgrade == "zombie_kar98k" )
|
||||||
|
{
|
||||||
|
base_priority -= 99;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base_priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
Executer( eObj )
|
||||||
|
{
|
||||||
|
self endon( "disconnect" );
|
||||||
|
self endon( "zombified" );
|
||||||
|
|
||||||
|
weapon = eObj.eEnt;
|
||||||
|
|
||||||
|
self thread WatchForCancel( weapon );
|
||||||
|
|
||||||
|
self GoDoWallweapon( eObj );
|
||||||
|
|
||||||
|
self WatchForCancelCleanup();
|
||||||
|
self ClearScriptAimPos();
|
||||||
|
self ClearScriptGoal();
|
||||||
|
self CompletedObjective( eObj.bWasSuccessful, eObj.sReason );
|
||||||
|
}
|
||||||
|
|
||||||
|
WatchForCancelCleanup()
|
||||||
|
{
|
||||||
|
self notify( "WatchForCancelWallweapon" );
|
||||||
|
}
|
||||||
|
|
||||||
|
WatchForCancel( weapon )
|
||||||
|
{
|
||||||
|
self endon( "disconnect" );
|
||||||
|
self endon( "zombified" );
|
||||||
|
self endon( "WatchForCancelWallweapon" );
|
||||||
|
|
||||||
|
for ( ;; )
|
||||||
|
{
|
||||||
|
wait 0.05;
|
||||||
|
|
||||||
|
if ( self inLastStand() )
|
||||||
|
{
|
||||||
|
self CancelObjective( "self inLastStand()" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WatchToGoToWeapon( weapon )
|
||||||
|
{
|
||||||
|
self endon( "cancel_bot_objective" );
|
||||||
|
self endon( "disconnect" );
|
||||||
|
self endon( "zombified" );
|
||||||
|
self endon( "goal" );
|
||||||
|
self endon( "bad_path" );
|
||||||
|
self endon( "new_goal" );
|
||||||
|
|
||||||
|
for ( ;; )
|
||||||
|
{
|
||||||
|
wait 0.05;
|
||||||
|
|
||||||
|
if ( self IsTouching( weapon ) )
|
||||||
|
{
|
||||||
|
self notify( "goal" );
|
||||||
|
break; // is this needed?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GoDoWallweapon( eObj )
|
||||||
|
{
|
||||||
|
self endon( "cancel_bot_objective" );
|
||||||
|
|
||||||
|
weapon = eObj.eEnt;
|
||||||
|
model = getEnt( weapon.target, "targetname" );
|
||||||
|
org = self getOffset( model );
|
||||||
|
|
||||||
|
// go to weapon
|
||||||
|
self thread WatchToGoToWeapon( weapon );
|
||||||
|
self SetScriptGoal( org, 32 );
|
||||||
|
|
||||||
|
result = self waittill_any_return( "goal", "bad_path", "new_goal" );
|
||||||
|
|
||||||
|
if ( result != "goal" )
|
||||||
|
{
|
||||||
|
eObj.sReason = "didn't go to weapon";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// istouching use triggers doesnt work well
|
||||||
|
if ( !self IsTouching( weapon ) && false )
|
||||||
|
{
|
||||||
|
eObj.sReason = "not touching weapon";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ok we are touching weapon, lets look at it
|
||||||
|
self SetScriptAimPos( weapon.origin );
|
||||||
|
|
||||||
|
// wait to look at it
|
||||||
|
wait 1;
|
||||||
|
|
||||||
|
// press use
|
||||||
|
self thread BotPressUse( 0.15 );
|
||||||
|
wait 0.1;
|
||||||
|
|
||||||
|
eObj.sReason = "completed";
|
||||||
|
eObj.bWasSuccessful = true;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -1,635 +0,0 @@
|
|||||||
#include common_scripts\utility;
|
|
||||||
#include maps\_utility;
|
|
||||||
#include maps\bots\_bot_utility;
|
|
||||||
#include maps\bots\script_objectives\_obj_utility;
|
|
||||||
|
|
||||||
register_bot_objective( objective_group )
|
|
||||||
{
|
|
||||||
if ( !isDefined( level.zbot_objective_glob ) )
|
|
||||||
{
|
|
||||||
level.zbot_objective_glob = [];
|
|
||||||
}
|
|
||||||
if ( !isDefined( level.zbot_objective_glob[ objective_group ] ) )
|
|
||||||
{
|
|
||||||
level.zbot_objective_glob[ objective_group ] = spawnStruct();
|
|
||||||
level.zbot_objective_glob[ objective_group ].active_objectives = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
add_possible_bot_objective( objective_group, target_ent, is_global_shared )
|
|
||||||
{
|
|
||||||
if ( !isDefined( target_ent ) )
|
|
||||||
{
|
|
||||||
objective_assert( objective_group, undefined, "add_possible_bot_objective", "[ent was undefined]" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
id = target_ent getEntityNumber();
|
|
||||||
|
|
||||||
if ( !isDefined( level.zbot_objective_glob ) )
|
|
||||||
{
|
|
||||||
objective_assert( objective_group, id, "add_possible_bot_objective", "Trying to add objective before calling register_bot_objective for objective group " + objective_group );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !isDefined( level.zbot_objective_glob[ objective_group ] ) )
|
|
||||||
{
|
|
||||||
objective_assert( objective_group, id, "add_possible_bot_objective", "Trying to add objective to group " + objective_group + " before calling register_bot_objective" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
objective_struct = spawnStruct();
|
|
||||||
objective_struct.group = objective_group;
|
|
||||||
objective_struct.is_global_shared = is_global_shared;
|
|
||||||
objective_struct.target_ent = target_ent;
|
|
||||||
objective_struct.owner = undefined;
|
|
||||||
objective_struct.is_objective = true;
|
|
||||||
objective_struct.bad = false;
|
|
||||||
objective_struct.id = id;
|
|
||||||
|
|
||||||
level.zbot_objective_glob[ objective_group ].active_objectives[ "obj_id_" + id ] = objective_struct;
|
|
||||||
|
|
||||||
return level.zbot_objective_glob[ objective_group ].active_objectives[ "obj_id_" + id ];
|
|
||||||
}
|
|
||||||
|
|
||||||
get_objective( objective_group, ent, id )
|
|
||||||
{
|
|
||||||
return get_objective_safe( objective_group, ent, id, "get_objective_by_entity_ref" );
|
|
||||||
}
|
|
||||||
|
|
||||||
get_all_objectives_for_group( objective_group )
|
|
||||||
{
|
|
||||||
return level.zbot_objective_glob[ objective_group ].active_objectives;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_get_objective()
|
|
||||||
{
|
|
||||||
return self.zbot_current_objective;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_has_objective()
|
|
||||||
{
|
|
||||||
return isDefined( self.zbot_current_objective );
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_set_objective( objective_group, ent, id )
|
|
||||||
{
|
|
||||||
objective = get_objective_safe( objective_group, ent, id, "bot_set_objective" );
|
|
||||||
if ( !isDefined( objective ) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_obj_history = spawnStruct();
|
|
||||||
new_obj_history.id = ent getEntityNumber();
|
|
||||||
new_obj_history.group = objective_group;
|
|
||||||
new_obj_history.ent_start_pos = ent.origin;
|
|
||||||
new_obj_history.ent_end_pos = ent.origin;
|
|
||||||
new_obj_history.bot_start_pos = self.origin;
|
|
||||||
new_obj_history.bot_end_pos = self.origin;
|
|
||||||
new_obj_history.start_time = getTime();
|
|
||||||
new_obj_history.end_time = getTime();
|
|
||||||
new_obj_history.time_spent = 0;
|
|
||||||
|
|
||||||
self.bot_obj_history_prev_index = self.bot_obj_history_index;
|
|
||||||
if ( self.bot_obj_history_index >= self.bot_obj_history_max_entries )
|
|
||||||
{
|
|
||||||
self.bot_obj_history_index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.obj_history[ self.bot_obj_history_index ] = new_obj_history;
|
|
||||||
self.zbot_current_objective = objective;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_clear_objective()
|
|
||||||
{
|
|
||||||
objective = self.zbot_current_objective;
|
|
||||||
if ( !isDefined( objective ) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self bot_clear_objective_owner( objective.group, objective.target_ent );
|
|
||||||
self.zbot_current_objective = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
objective_has_owner( objective_group, ent, id )
|
|
||||||
{
|
|
||||||
objective = get_objective_safe( objective_group, ent, id, "objective_has_owner" );
|
|
||||||
if ( !isDefined( objective ) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !isDefined( id ) )
|
|
||||||
{
|
|
||||||
id = ent getEntityNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !objective.is_global_shared )
|
|
||||||
{
|
|
||||||
objective_assert( objective_group, id, "objective_has_owner", "Objective with " + id + " id number cannot be set to have an owner because is_global_shared field is false in group " + objective_group );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isDefined( objective.owner );
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_is_objective_owner( objective_group, ent, id )
|
|
||||||
{
|
|
||||||
objective = get_objective_safe( objective_group, ent, id, "bot_is_objective_owner" );
|
|
||||||
if ( !isDefined( objective ) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !isDefined( id ) )
|
|
||||||
{
|
|
||||||
id = ent getEntityNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !objective.is_global_shared )
|
|
||||||
{
|
|
||||||
objective_assert( objective_group, id, "bot_is_objective_owner", "Objective with " + id + " id number cannot be set to have an owner because is_global_shared field is false in group " + objective_group );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isDefined( objective.owner ) && objective.owner == self;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_set_objective_owner( objective_group, ent, id )
|
|
||||||
{
|
|
||||||
objective = get_objective_safe( objective_group, ent, id, "bot_set_objective_owner" );
|
|
||||||
if ( !isDefined( objective ) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !isDefined( id ) )
|
|
||||||
{
|
|
||||||
id = ent getEntityNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !objective.is_global_shared )
|
|
||||||
{
|
|
||||||
objective_assert( objective_group, id, "bot_set_objective_owner", "Objective with " + id + " id number cannot be set to have an owner because is_global_shared field is false in group " + objective_group );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
objective.owner = self;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_clear_objective_owner( objective_group, ent, id )
|
|
||||||
{
|
|
||||||
objective = get_objective_safe( objective_group, ent, id, "clear_objective_owner" );
|
|
||||||
if ( !isDefined( objective ) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !isDefined( objective.owner ) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( objective.owner != self )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
objective.owner = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
mark_objective_bad( objective_group, ent, id )
|
|
||||||
{
|
|
||||||
objective = get_objective_safe( objective_group, ent, id, "mark_objective_bad" );
|
|
||||||
if ( !isDefined( objective ) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
objective.bad = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
free_bot_objective( objective_group, ent, id )
|
|
||||||
{
|
|
||||||
objective = get_objective_safe( objective_group, ent, id, "free_bot_objective" );
|
|
||||||
if ( !isDefined( objective ) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( isDefined( ent ) )
|
|
||||||
{
|
|
||||||
id = ent getEntityNumber();
|
|
||||||
}
|
|
||||||
players = getPlayers();
|
|
||||||
for ( i = 0; i < players.size; i++ )
|
|
||||||
{
|
|
||||||
if ( players[ i ] is_bot() )
|
|
||||||
{
|
|
||||||
if ( isDefined( players[ i ].zbot_current_objective ) && players[ i ].zbot_current_objective == objective )
|
|
||||||
{
|
|
||||||
players[ i ].zbot_current_objective = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
level.zbot_objective_glob[ objective_group ].active_objectives[ "obj_id_" + id ] = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
get_objective_safe( objective_group, ent, id, function_name )
|
|
||||||
{
|
|
||||||
if ( !isDefined( ent ) && !isDefined( id ) )
|
|
||||||
{
|
|
||||||
objective_assert( objective_group, id, function_name, "[ent and id were undefined]" );
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( isDefined( ent ) )
|
|
||||||
{
|
|
||||||
id = ent getEntityNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !isDefined( level.zbot_objective_glob[ objective_group ] ) )
|
|
||||||
{
|
|
||||||
objective_assert( objective_group, id, function_name, "[obj group is invalid]" );
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
active_objectives = level.zbot_objective_glob[ objective_group ].active_objectives;
|
|
||||||
|
|
||||||
objective = active_objectives[ "obj_id_" + id ];
|
|
||||||
|
|
||||||
objective_exists = isDefined( objective );
|
|
||||||
if ( !objective_exists )
|
|
||||||
{
|
|
||||||
objective_assert( objective_group, id, function_name, "[obj was undefined]" );
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return objective;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_objective_print( objective_group, id, message, function_name )
|
|
||||||
{
|
|
||||||
if ( getDvarInt( "bot_obj_debug_all" ) != 0 || getDvarInt( "bot_obj_debug_" + objective_group ) != 0 )
|
|
||||||
{
|
|
||||||
self objective_info_print( objective_group, id, function_name, message );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
objective_assert( objective_group, id, function_name, message )
|
|
||||||
{
|
|
||||||
assertMsg( message );
|
|
||||||
if ( getDvarInt( "bot_obj_debug_all" ) != 0 || getDvarInt( "bot_obj_debug_" + objective_group ) != 0 )
|
|
||||||
{
|
|
||||||
if ( !isDefined( id ) )
|
|
||||||
{
|
|
||||||
error_message = "BOT_OBJ_ERROR: Time <" + getTime() + "> " + function_name + "() Obj <" + objective_group + "> " + message;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error_message = "BOT_OBJ_ERROR: Time <" + getTime() + "> " + function_name + "() Obj <" + objective_group + "> Ent <" + id + "> " + message;
|
|
||||||
}
|
|
||||||
logprint( error_message + "\n" );
|
|
||||||
printConsole( error_message );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
objective_info_print( objective_group, id, function_name, message )
|
|
||||||
{
|
|
||||||
message = "BOT_OBJ_INFO: Time <" + getTime() + "> " + function_name + "() Obj <" + objective_group + "> ent <" + id + "> " + message;
|
|
||||||
logprint( message + "\n" );
|
|
||||||
printConsole( message );
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_objective_history_get_oldest()
|
|
||||||
{
|
|
||||||
oldest = self.obj_history[ 0 ];
|
|
||||||
for ( i = 1; i < self.obj_history.size; i++ )
|
|
||||||
{
|
|
||||||
if ( oldest.end_time < self.obj_history[ i ] )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
oldest = self.obj_history[ i ];
|
|
||||||
}
|
|
||||||
return oldest;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_objective_history_get_current()
|
|
||||||
{
|
|
||||||
return self.obj_history[ self.bot_obj_history_index ];
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_objective_history_get_previous()
|
|
||||||
{
|
|
||||||
return self.obj_history[ self.bot_obj_history_prev_index ];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********Action Section**********/
|
|
||||||
|
|
||||||
register_bot_action( action_name, action_func, init_func, post_think_func, should_do_func, check_if_complete_func, should_cancel_func, priority_func )
|
|
||||||
{
|
|
||||||
if ( !isDefined( level.zbots_actions ) )
|
|
||||||
{
|
|
||||||
level.zbots_actions = [];
|
|
||||||
}
|
|
||||||
if ( !isDefined( level.zbots_actions[ action_name ] ) )
|
|
||||||
{
|
|
||||||
level.zbots_actions[ action_name ] = spawnStruct();
|
|
||||||
}
|
|
||||||
level.zbots_actions[ action_name ].action = action_func;
|
|
||||||
level.zbots_actions[ action_name ].init_func = init_func;
|
|
||||||
level.zbots_actions[ action_name ].post_think_func = post_think_func;
|
|
||||||
level.zbots_actions[ action_name ].should_do_func = should_do_func;
|
|
||||||
level.zbots_actions[ action_name ].check_if_complete_func = check_if_complete_func;
|
|
||||||
level.zbots_actions[ action_name ].should_cancel_func = should_cancel_func;
|
|
||||||
level.zbots_actions[ action_name ].priority_func = priority_func;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_process_action()
|
|
||||||
{
|
|
||||||
self endon( "stop_action_think" );
|
|
||||||
|
|
||||||
action_name = self.bot_action.action_name;
|
|
||||||
|
|
||||||
self [[ level.zbots_actions[ action_name ].init_func ]]();
|
|
||||||
|
|
||||||
self thread [[ level.zbots_actions[ action_name ].action ]]( self.bot_action.obj );
|
|
||||||
|
|
||||||
self.running_action = true;
|
|
||||||
self wait_for_action_completion( action_name );
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_for_action_completion( action_name )
|
|
||||||
{
|
|
||||||
action_complete_name = action_name + "_complete";
|
|
||||||
action_cancel_name = action_name + "_cancel";
|
|
||||||
|
|
||||||
result = self waittill_any_return( action_complete_name, action_cancel_name );
|
|
||||||
|
|
||||||
end_state = undefined;
|
|
||||||
|
|
||||||
if ( ( result == action_complete_name ) )
|
|
||||||
{
|
|
||||||
end_state = "completed";
|
|
||||||
}
|
|
||||||
else if ( result == action_cancel_name )
|
|
||||||
{
|
|
||||||
end_state = "canceled";
|
|
||||||
}
|
|
||||||
|
|
||||||
self notify( action_name + "_end_think" );
|
|
||||||
|
|
||||||
self [[ level.zbots_actions[ action_name ].post_think_func ]]( end_state );
|
|
||||||
|
|
||||||
self.bot_action = undefined;
|
|
||||||
|
|
||||||
self.obj_history[ self.bot_obj_history_index ].end_time = getTime();
|
|
||||||
end_time = self.obj_history[ self.bot_obj_history_index ].end_time;
|
|
||||||
start_time = self.obj_history[ self.bot_obj_history_index ].start_time;
|
|
||||||
self.obj_history[ self.bot_obj_history_index ].time_spent = end_time - start_time;
|
|
||||||
self.obj_history[ self.bot_obj_history_index ].bot_end_pos = self.origin;
|
|
||||||
self.bot_obj_history_index++;
|
|
||||||
self.running_action = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_pick_action()
|
|
||||||
{
|
|
||||||
action_keys = getArrayKeys( level.zbots_actions );
|
|
||||||
|
|
||||||
possible_actions = NewHeap( ::HeapPriority );
|
|
||||||
for ( i = 0; i < action_keys.size; i++ )
|
|
||||||
{
|
|
||||||
struct = spawnStruct();
|
|
||||||
struct.possible_objs = [];
|
|
||||||
if ( self [[ level.zbots_actions[ action_keys[ i ] ].should_do_func ]]( struct ) )
|
|
||||||
{
|
|
||||||
available_objs = struct.possible_objs;
|
|
||||||
for ( j = 0; j < available_objs.size; j++ )
|
|
||||||
{
|
|
||||||
possible_action = spawnStruct();
|
|
||||||
possible_action.action_name = action_keys[ i ];
|
|
||||||
possible_action.priority = self [[ level.zbots_actions[ action_keys[ i ] ].priority_func ]]( available_objs[ j ] );
|
|
||||||
possible_action.obj = available_objs[ j ];
|
|
||||||
possible_actions HeapInsert( possible_action );
|
|
||||||
printConsole( self.playername + " Adding obj " + action_keys[ i ] + " id " + available_objs[ j ].id + " to queue of size: " + possible_actions.data.size );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
forced_action = getDvar( "bots_debug_forced_action" );
|
|
||||||
|
|
||||||
if ( ( !isDefined( possible_actions.data ) || possible_actions.data.size <= 0 ) && forced_action == "" )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( forced_action != "" )
|
|
||||||
{
|
|
||||||
entnum_and_forced_action = strTok( forced_action, " " );
|
|
||||||
if ( entnum_and_forced_action.size != 2 )
|
|
||||||
{
|
|
||||||
setDvar( "bots_debug_forced_action", "" );
|
|
||||||
}
|
|
||||||
else if ( int( entnum_and_forced_action[ 0 ] ) == self getEntityNumber() && isDefined( level.zbots_actions[ entnum_and_forced_action[ 1 ] ] ) )
|
|
||||||
{
|
|
||||||
possible_action = spawnStruct();
|
|
||||||
possible_action.action_name = entnum_and_forced_action[ 1 ];
|
|
||||||
possible_action.priority = 999;
|
|
||||||
self.bot_action = possible_action;
|
|
||||||
setDvar( "bots_debug_forced_action", "" );
|
|
||||||
printConsole( self.playername + " Picking forced action " + self.bot_action.action_name + " Priority " + self.bot_action.priority );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
self.bot_action = possible_actions.data[ 0 ];
|
|
||||||
printConsole( self.playername + " Picking action " + self.bot_action.action_name + " Priority " + self.bot_action.priority );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_check_action_complete( action_name )
|
|
||||||
{
|
|
||||||
assert( isDefined( level.zbots_actions[ action_name ].check_if_complete_func ) );
|
|
||||||
|
|
||||||
is_complete = self [[ level.zbots_actions[ action_name ].check_if_complete_func ]]();
|
|
||||||
|
|
||||||
if ( is_complete )
|
|
||||||
{
|
|
||||||
self notify( action_name + "_complete" );
|
|
||||||
self notify( "goal" );
|
|
||||||
}
|
|
||||||
return is_complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_check_if_action_should_be_canceled_in_group( action_name )
|
|
||||||
{
|
|
||||||
should_cancel = self [[ level.zbots_actions[ action_name ].should_cancel_func ]]();
|
|
||||||
if ( should_cancel )
|
|
||||||
{
|
|
||||||
self notify( action_name + "_cancel" );
|
|
||||||
self notify( "goal" );
|
|
||||||
}
|
|
||||||
|
|
||||||
return should_cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_check_if_action_should_be_canceled_globally( action_name )
|
|
||||||
{
|
|
||||||
should_cancel = self action_should_be_canceled_global( action_name );
|
|
||||||
if ( should_cancel )
|
|
||||||
{
|
|
||||||
self notify( action_name + "_cancel" );
|
|
||||||
self notify( "goal" );
|
|
||||||
}
|
|
||||||
return should_cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_action_think()
|
|
||||||
{
|
|
||||||
self endon( "disconnect" );
|
|
||||||
self endon( "zombified" );
|
|
||||||
level endon( "end_game" );
|
|
||||||
|
|
||||||
self thread bot_action_pump();
|
|
||||||
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
if ( getDvarInt( "bot_obj_debug_all" ) != 0 )
|
|
||||||
{
|
|
||||||
wait 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wait 1;
|
|
||||||
}
|
|
||||||
//Wait until the end of the frame so any variables set by _bot_internal in the current frame will have up to date values
|
|
||||||
waittillframeend;
|
|
||||||
|
|
||||||
self.bot_action = undefined;
|
|
||||||
if ( !self bot_pick_action() )
|
|
||||||
{
|
|
||||||
if ( getDvarInt( "bot_obj_debug_all" ) != 0 )
|
|
||||||
{
|
|
||||||
printConsole( "BOT_ACTION_THINK: " + self.playername + " does not have an action selected" );
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
self bot_process_action();
|
|
||||||
|
|
||||||
while ( !maps\so\zm_common\_zm_utility::is_player_valid( self ) )
|
|
||||||
{
|
|
||||||
if ( getDvarInt( "bot_obj_debug_all" ) != 0 )
|
|
||||||
{
|
|
||||||
printConsole( "BOT_ACTION_THINK: " + self.playername + " is not in a valid state" );
|
|
||||||
}
|
|
||||||
wait 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_action_pump()
|
|
||||||
{
|
|
||||||
self endon( "disconnect" );
|
|
||||||
self endon( "zombified" );
|
|
||||||
level endon( "end_game" );
|
|
||||||
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
wait 0.05;
|
|
||||||
if ( !isDefined( self.bot_action ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
action_name = self.bot_action.action_name;
|
|
||||||
if ( self bot_check_action_complete( action_name ) )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if ( self bot_check_if_action_should_be_canceled_globally( action_name ) )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if ( self bot_check_if_action_should_be_canceled_in_group( action_name ) )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
while ( !maps\so\zm_common\_zm_utility::is_player_valid( self ) )
|
|
||||||
{
|
|
||||||
wait 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
action_should_be_postponed_global( action_name )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
action_should_be_canceled_global( action_name )
|
|
||||||
{
|
|
||||||
obj = self bot_get_objective();
|
|
||||||
|
|
||||||
goal_canceled = false;
|
|
||||||
if ( !isDefined( obj ) )
|
|
||||||
{
|
|
||||||
self.obj_cancel_reason = "Obj didn't exist";
|
|
||||||
goal_canceled = true;
|
|
||||||
}
|
|
||||||
else if ( !isDefined( obj.target_ent ) )
|
|
||||||
{
|
|
||||||
self.obj_cancel_reason = "Obj entity doesn't exist";
|
|
||||||
canceled_goal = true;
|
|
||||||
}
|
|
||||||
else if ( isDefined( obj.target_ent.player_visibility ) && !obj.target_ent.player_visibility[ self getEntityNumber() + "" ] )
|
|
||||||
{
|
|
||||||
self.obj_cancel_reason = "Trigger wasn't visible";
|
|
||||||
goal_canceled = true;
|
|
||||||
}
|
|
||||||
else if ( !isDefined( obj.target_ent.bot_use_node ) && self GetPathIsInaccessible( obj.target_ent.origin ) )
|
|
||||||
{
|
|
||||||
self.obj_cancel_reason = "Path to ent was inaccessible";
|
|
||||||
goal_canceled = true;
|
|
||||||
}
|
|
||||||
else if ( isDefined( obj.target_ent.bot_use_node ) && self GetPathIsInaccessible( obj.target_ent.bot_use_node ) )
|
|
||||||
{
|
|
||||||
self.obj_cancel_reason = "Path to use node was inaccessible";
|
|
||||||
goal_canceled = true;
|
|
||||||
}
|
|
||||||
else if ( obj.bad )
|
|
||||||
{
|
|
||||||
self.obj_cancel_reason = "Obj was bad";
|
|
||||||
goal_canceled = true;
|
|
||||||
}
|
|
||||||
else if ( !maps\so\zm_common\_zm_utility::is_player_valid( self ) )
|
|
||||||
{
|
|
||||||
self.obj_cancel_reason = "In invalid state";
|
|
||||||
goal_canceled = true;
|
|
||||||
}
|
|
||||||
return goal_canceled;
|
|
||||||
}
|
|
||||||
|
|
||||||
get_angle_offset_node( forward_size, angle_offset, offset )
|
|
||||||
{
|
|
||||||
if ( !isDefined( forward_size ) )
|
|
||||||
{
|
|
||||||
forward_size = 40;
|
|
||||||
}
|
|
||||||
if ( !isDefined( angle_offset ) )
|
|
||||||
{
|
|
||||||
angle_offset = ( 0, 0, 0 );
|
|
||||||
}
|
|
||||||
if ( !isDefined( offset ) )
|
|
||||||
{
|
|
||||||
offset = ( 0, 0, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
angles = ( 0, self.angles[ 1 ], 0 );
|
|
||||||
angles += angle_offset;
|
|
||||||
node = self.origin + ( AnglesToForward( angles ) * forward_size ) + offset;
|
|
||||||
node = clamp_to_ground( node );
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
clamp_to_ground( org )
|
|
||||||
{
|
|
||||||
trace = playerPhysicsTrace( org + ( 0, 0, 20 ), org - ( 0, 0, 2000 ) );
|
|
||||||
return trace;
|
|
||||||
}
|
|
@ -1,167 +0,0 @@
|
|||||||
#include common_scripts\utility;
|
|
||||||
#include maps\_utility;
|
|
||||||
#include maps\bots\_bot_utility;
|
|
||||||
#include maps\bots\script_objectives\_obj_utility;
|
|
||||||
#include maps\bots\script_objectives\_obj_common;
|
|
||||||
#include maps\bots\script_objectives\_obj_actions;
|
|
||||||
#include maps\bots\script_objectives\_obj_trackers;
|
|
||||||
|
|
||||||
init()
|
|
||||||
{
|
|
||||||
register_bot_action( "powerup",
|
|
||||||
::bot_grab_powerup,
|
|
||||||
::bot_powerup_init,
|
|
||||||
::bot_powerup_post_think,
|
|
||||||
::bot_should_grab_powerup,
|
|
||||||
::bot_check_complete_grab_powerup,
|
|
||||||
::bot_powerup_should_cancel,
|
|
||||||
::bot_powerup_priority );
|
|
||||||
|
|
||||||
register_bot_action( "revive",
|
|
||||||
::bot_revive_player,
|
|
||||||
::bot_revive_player_init,
|
|
||||||
::bot_revive_player_post_think,
|
|
||||||
::bot_should_revive_player,
|
|
||||||
::bot_check_complete_revive_player,
|
|
||||||
::bot_revive_player_should_cancel,
|
|
||||||
::bot_revive_player_priority );
|
|
||||||
|
|
||||||
register_bot_action( "magicbox",
|
|
||||||
::bot_magicbox_purchase,
|
|
||||||
::bot_magicbox_purchase_init,
|
|
||||||
::bot_magicbox_purchase_post_think,
|
|
||||||
::bot_should_purchase_magicbox,
|
|
||||||
::bot_check_complete_purchase_magicbox,
|
|
||||||
::bot_magicbox_purchase_should_cancel,
|
|
||||||
::bot_magicbox_purchase_priority );
|
|
||||||
|
|
||||||
register_bot_action( "perk",
|
|
||||||
::bot_perk_purchase,
|
|
||||||
::bot_perk_purchase_init,
|
|
||||||
::bot_perk_purchase_post_think,
|
|
||||||
::bot_should_purchase_perk,
|
|
||||||
::bot_check_complete_perk_purchase,
|
|
||||||
::bot_perk_purchase_should_cancel,
|
|
||||||
::bot_perk_purchase_priority );
|
|
||||||
|
|
||||||
register_bot_action( "door",
|
|
||||||
::bot_door_purchase,
|
|
||||||
::bot_door_purchase_init,
|
|
||||||
::bot_door_purchase_post_think,
|
|
||||||
::bot_should_purchase_door,
|
|
||||||
::bot_check_complete_door_purchase,
|
|
||||||
::bot_door_purchase_should_cancel,
|
|
||||||
::bot_door_purchase_priority );
|
|
||||||
|
|
||||||
register_bot_action( "debris",
|
|
||||||
::bot_debris_purchase,
|
|
||||||
::bot_debris_purchase_init,
|
|
||||||
::bot_debris_purchase_post_think,
|
|
||||||
::bot_should_purchase_debris,
|
|
||||||
::bot_check_complete_debris_purchase,
|
|
||||||
::bot_debris_purchase_should_cancel,
|
|
||||||
::bot_debris_purchase_priority );
|
|
||||||
|
|
||||||
register_bot_action( "wallbuy",
|
|
||||||
::bot_wallbuy_purchase,
|
|
||||||
::bot_wallbuy_purchase_init,
|
|
||||||
::bot_wallbuy_purchase_post_think,
|
|
||||||
::bot_should_purchase_wallbuy,
|
|
||||||
::bot_check_complete_wallbuy_purchase,
|
|
||||||
::bot_wallbuy_purchase_should_cancel,
|
|
||||||
::bot_wallbuy_purchase_priority );
|
|
||||||
|
|
||||||
register_bot_action( "wallbuyammo",
|
|
||||||
::bot_wallbuy_ammo_purchase,
|
|
||||||
::bot_wallbuy_ammo_purchase_init,
|
|
||||||
::bot_wallbuy_ammo_purchase_post_think,
|
|
||||||
::bot_should_purchase_wallbuy_ammo,
|
|
||||||
::bot_check_complete_wallbuy_ammo_purchase,
|
|
||||||
::bot_wallbuy_ammo_purchase_should_cancel,
|
|
||||||
::bot_wallbuy_ammo_purchase_priority );
|
|
||||||
|
|
||||||
register_bot_action( "packapunch",
|
|
||||||
::bot_packapunch_purchase,
|
|
||||||
::bot_packapunch_purchase_init,
|
|
||||||
::bot_packapunch_purchase_post_think,
|
|
||||||
::bot_should_purchase_packapunch,
|
|
||||||
::bot_check_complete_packapunch_purchase,
|
|
||||||
::bot_packapunch_purchase_should_cancel,
|
|
||||||
::bot_packapunch_purchase_priority );
|
|
||||||
|
|
||||||
register_bot_action( "power",
|
|
||||||
::bot_power_activate,
|
|
||||||
::bot_power_activate_init,
|
|
||||||
::bot_power_activate_post_think,
|
|
||||||
::bot_should_activate_power,
|
|
||||||
::bot_check_complete_power_activate,
|
|
||||||
::bot_power_activate_should_cancel,
|
|
||||||
::bot_power_activate_priority );
|
|
||||||
|
|
||||||
register_bot_objective( "magicbox" );
|
|
||||||
register_bot_objective( "wallbuy" );
|
|
||||||
register_bot_objective( "wallbuyammo" );
|
|
||||||
register_bot_objective( "perk" );
|
|
||||||
register_bot_objective( "door" );
|
|
||||||
register_bot_objective( "debris" );
|
|
||||||
register_bot_objective( "trap" );
|
|
||||||
register_bot_objective( "packapunch" );
|
|
||||||
register_bot_objective( "power" );
|
|
||||||
register_bot_objective( "revive" );
|
|
||||||
//register_bot_objective( "grabbuildable" );
|
|
||||||
//register_bot_objective( "buildbuildable" );
|
|
||||||
//register_bot_objective( "part" );
|
|
||||||
register_bot_objective( "powerup" );
|
|
||||||
|
|
||||||
if ( getDvar( "bots_obj_buy_blockers" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "bots_obj_buy_blockers", true );
|
|
||||||
}
|
|
||||||
|
|
||||||
create_static_objectives();
|
|
||||||
}
|
|
||||||
|
|
||||||
connected()
|
|
||||||
{
|
|
||||||
self endon( "disconnect" );
|
|
||||||
|
|
||||||
self.on_powerup_grab_func = ::bot_on_powerup_grab;
|
|
||||||
self.on_revive_success_func = ::bot_on_revive_success;
|
|
||||||
self.on_magicbox_weapon_grab_func = ::bot_on_magicbox_weapon_grab;
|
|
||||||
self.on_perk_purchase_func = ::bot_on_perk_purchase;
|
|
||||||
self.on_door_purchase_func = ::bot_on_door_purchase_func;
|
|
||||||
self.on_debris_purchase_func = ::bot_on_debris_purchase_func;
|
|
||||||
self.on_wallbuy_purchase_func = ::bot_on_wallbuy_purchase_func;
|
|
||||||
self.on_wallbuy_ammo_purchase_func = ::bot_on_wallbuy_ammo_purchase_func;
|
|
||||||
|
|
||||||
self.obj_cancel_reason = "";
|
|
||||||
|
|
||||||
self.obj_history = [];
|
|
||||||
self.bot_obj_history_max_entries = 20;
|
|
||||||
self.bot_obj_history_index = 0;
|
|
||||||
self.bot_obj_history_prev_index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
spawned()
|
|
||||||
{
|
|
||||||
self endon( "disconnect" );
|
|
||||||
level endon( "intermission" );
|
|
||||||
self endon( "zombified" );
|
|
||||||
|
|
||||||
self thread bot_action_think();
|
|
||||||
//self thread cleanup_on_disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
start_bot_threads()
|
|
||||||
{
|
|
||||||
self endon( "disconnect" );
|
|
||||||
level endon( "intermission" );
|
|
||||||
self endon( "zombified" );
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Add ability to pause an action so the bot won't be doing it while its paused but when its unpaused they can resume the action with the same settings
|
|
||||||
//Similar to postpone except instead of selecting a new action the current action is preserved
|
|
||||||
action_should_be_paused_global( primary_group_name, action_name )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
@ -1,397 +0,0 @@
|
|||||||
#include common_scripts\utility;
|
|
||||||
#include maps\_utility;
|
|
||||||
#include maps\bots\_bot_utility;
|
|
||||||
#include maps\bots\script_objectives\_obj_common;
|
|
||||||
#include maps\bots\script_objectives\_obj_utility;
|
|
||||||
|
|
||||||
create_static_objectives()
|
|
||||||
{
|
|
||||||
if ( getDvar( "magicbox_node_forward_size" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "magicbox_node_forward_size", 55 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "magicbox_node_vertical_offset" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "magicbox_node_vertical_offset", 10 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "magicbox_node_angle" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "magicbox_node_angle", 90 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "perk_node_forward_size" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "perk_node_forward_size", 55 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "perk_node_vertical_offset" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "perk_node_vertical_offset", 1 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "perk_node_angle" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "perk_node_angle", -90 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "wallbuy_node_forward_size" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "wallbuy_node_forward_size", 40 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "wallbuy_node_vertical_offset" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "wallbuy_node_vertical_offset", 1 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "wallbuy_node_angle" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "wallbuy_node_angle", -90 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "packapunch_node_forward_size" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "packapunch_node_forward_size", 55 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "packapunch_node_vertical_offset" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "packapunch_node_vertical_offset", 1 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "packapunch_node_angle" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "packapunch_node_angle", -90 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "power_node_forward_size" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "power_node_forward_size", 55 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "power_node_vertical_offset" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "power_node_vertical_offset", 1 );
|
|
||||||
}
|
|
||||||
if ( getDvar( "power_node_angle" ) == "" )
|
|
||||||
{
|
|
||||||
setDvar( "power_node_angle", -90 );
|
|
||||||
}
|
|
||||||
weapon_spawns = GetEntArray( "weapon_upgrade", "targetname" );
|
|
||||||
|
|
||||||
if ( isDefined( weapon_spawns ) && weapon_spawns.size > 0 )
|
|
||||||
{
|
|
||||||
for( i = 0; i < weapon_spawns.size; i++ )
|
|
||||||
{
|
|
||||||
obj = add_possible_bot_objective( "wallbuy", weapon_spawns[ i ], false );
|
|
||||||
obj = add_possible_bot_objective( "wallbuyammo", weapon_spawns[ i ], false );
|
|
||||||
model = getEnt( weapon_spawns[ i ].target, "targetname" );
|
|
||||||
weapon_spawns[ i ].bot_use_node = model get_angle_offset_node( getDvarInt( "wallbuy_node_forward_size" ), ( 0, getDvarInt( "wallbuy_node_angle" ), 0 ), ( 0, 0, getDvarInt( "wallbuy_node_vertical_offset" ) ) );
|
|
||||||
model thread wallbuy_debug();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vending_triggers = GetEntArray( "zombie_vending", "targetname" );
|
|
||||||
|
|
||||||
if ( isDefined( vending_triggers ) && vending_triggers.size > 0 )
|
|
||||||
{
|
|
||||||
for ( i = 0; i < vending_triggers.size; i++ )
|
|
||||||
{
|
|
||||||
obj = add_possible_bot_objective( "perk", vending_triggers[ i ], false );
|
|
||||||
model = getEnt( vending_triggers[ i ].target, "targetname" );
|
|
||||||
vending_triggers[ i ].bot_use_node = model get_angle_offset_node( getDvarInt( "perk_node_forward_size" ), ( 0, getDvarInt( "perk_node_angle" ), 0 ), ( 0, 0, getDvarInt( "perk_node_vertical_offset" ) ) );
|
|
||||||
model thread perk_debug();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: See if its possible to automatically detect if a door is blocking an objective
|
|
||||||
zombie_doors = GetEntArray( "zombie_door", "targetname" );
|
|
||||||
|
|
||||||
if ( isDefined( zombie_doors ) && zombie_doors.size > 0 )
|
|
||||||
{
|
|
||||||
for ( i = 0; i < zombie_doors.size; i++ )
|
|
||||||
{
|
|
||||||
if ( isDefined( zombie_doors[ i ].script_noteworthy ) && zombie_doors[ i ].script_noteworthy == "electric_door" )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
obj = add_possible_bot_objective( "door", zombie_doors[ i ], true );
|
|
||||||
}
|
|
||||||
level thread watch_door_objectives( zombie_doors );
|
|
||||||
}
|
|
||||||
|
|
||||||
zombie_debris = GetEntArray( "zombie_debris", "targetname" );
|
|
||||||
|
|
||||||
if ( isDefined( zombie_debris ) && zombie_debris.size > 0 )
|
|
||||||
{
|
|
||||||
for ( i = 0; i < zombie_debris.size; i++ )
|
|
||||||
{
|
|
||||||
obj = add_possible_bot_objective( "debris", zombie_debris[ i ], true );
|
|
||||||
}
|
|
||||||
level thread watch_debris_objectives( zombie_debris );
|
|
||||||
}
|
|
||||||
|
|
||||||
vending_upgrade_trigger = GetEntArray("zombie_vending_upgrade", "targetname");
|
|
||||||
|
|
||||||
if ( isDefined( vending_upgrade_trigger ) && vending_upgrade_trigger.size > 0 )
|
|
||||||
{
|
|
||||||
for ( i = 0; i < vending_upgrade_trigger.size; i++ )
|
|
||||||
{
|
|
||||||
obj = add_possible_bot_objective( "packapunch", vending_upgrade_trigger[ i ], false );
|
|
||||||
model = getEnt( vending_triggers[ i ].target, "targetname" );
|
|
||||||
vending_upgrade_trigger[ i ].bot_use_node = model get_angle_offset_node( getDvarInt( "packapunch_node_forward_size" ), ( 0, getDvarInt( "packapunch_node_angle" ), 0 ), ( 0, 0, getDvarInt( "packapunch_node_vertical_offset" ) ) );
|
|
||||||
model thread packapunch_debug();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
master_switch = getent("power_switch","targetname");
|
|
||||||
if ( !isDefined( master_switch ) )
|
|
||||||
{
|
|
||||||
master_switch = getent("master_switch","targetname");
|
|
||||||
}
|
|
||||||
if ( isDefined( master_switch ) )
|
|
||||||
{
|
|
||||||
obj = add_possible_bot_objective( "power", master_switch, false );
|
|
||||||
master_switch.bot_use_node = master_switch get_angle_offset_node( getDvarInt( "power_node_forward_size" ), ( 0, getDvarInt( "power_node_angle" ), 0 ), ( 0, 0, getDvarInt( "power_node_vertical_offset" ) ) );
|
|
||||||
//model thread power_debug();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( isDefined( level.chests ) && level.chests.size > 0 )
|
|
||||||
{
|
|
||||||
level thread watch_magicbox_objectives();
|
|
||||||
}
|
|
||||||
|
|
||||||
//maps\bots\script_objectives\_obj_trackers;
|
|
||||||
level thread store_powerups_dropped();
|
|
||||||
level thread watch_for_downed_players();
|
|
||||||
}
|
|
||||||
|
|
||||||
watch_power_objective( power_switch )
|
|
||||||
{
|
|
||||||
while ( !isDefined( level.flag ) && !isDefined( level.flag[ "power_on" ] ) )
|
|
||||||
{
|
|
||||||
wait 0.05;
|
|
||||||
}
|
|
||||||
players = getPlayers();
|
|
||||||
for ( i = 0; i < players.size; i++ )
|
|
||||||
{
|
|
||||||
player = players[ i ];
|
|
||||||
if ( player bot_get_objective() == "power" )
|
|
||||||
{
|
|
||||||
player.sucessfully_activated_power = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
waittillframeend;
|
|
||||||
free_bot_objective( "power", power_switch );
|
|
||||||
}
|
|
||||||
|
|
||||||
watch_door_objectives( zombie_doors )
|
|
||||||
{
|
|
||||||
level endon( "end_game" );
|
|
||||||
|
|
||||||
for ( doors_opened_count = 0; doors_opened_count < zombie_doors.size; doors_opened_count++ )
|
|
||||||
{
|
|
||||||
level waittill( "door_opened", door, player );
|
|
||||||
free_bot_objective( "door", door );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watch_debris_objectives( zombie_debris )
|
|
||||||
{
|
|
||||||
level endon( "end_game" );
|
|
||||||
|
|
||||||
for ( debris_opened_count = 0; debris_opened_count < zombie_debris.size; debris_opened_count++ )
|
|
||||||
{
|
|
||||||
level waittill( "debris_opened", debris, player );
|
|
||||||
free_bot_objective( "debris", debris );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
store_powerups_dropped()
|
|
||||||
{
|
|
||||||
level endon( "end_game" );
|
|
||||||
|
|
||||||
level thread free_powerups_dropped();
|
|
||||||
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
level waittill( "powerup_dropped", powerup );
|
|
||||||
waittillframeend;
|
|
||||||
if ( !isDefined( powerup ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
obj = add_possible_bot_objective( "powerup", powerup, true );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free_powerups_dropped()
|
|
||||||
{
|
|
||||||
level endon( "end_game" );
|
|
||||||
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
level waittill( "powerup_freed", powerup );
|
|
||||||
id = powerup getEntityNumber();
|
|
||||||
waittillframeend;
|
|
||||||
free_bot_objective( "powerup", powerup, id );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watch_for_downed_players()
|
|
||||||
{
|
|
||||||
level endon( "end_game" );
|
|
||||||
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
level waittill( "player_entered_laststand", player );
|
|
||||||
if ( !isDefined( player ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
obj = add_possible_bot_objective( "revive", player, true );
|
|
||||||
obj.accessible = true;
|
|
||||||
player thread free_revive_objective_when_needed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free_revive_objective_when_needed()
|
|
||||||
{
|
|
||||||
level endon( "end_game" );
|
|
||||||
|
|
||||||
id = self getEntityNumber();
|
|
||||||
self waittill_any( "disconnect", "zombified", "player_revived" );
|
|
||||||
|
|
||||||
waittillframeend;
|
|
||||||
|
|
||||||
free_bot_objective( "revive", self, id );
|
|
||||||
}
|
|
||||||
|
|
||||||
watch_magicbox_objectives()
|
|
||||||
{
|
|
||||||
level endon( "end_game" );
|
|
||||||
|
|
||||||
level waittill( "connected", player );
|
|
||||||
|
|
||||||
cur_magicbox = maps\so\zm_common\_zm_magicbox::get_active_magicbox();
|
|
||||||
add_possible_bot_objective( "magicbox", cur_magicbox, true );
|
|
||||||
lid = cur_magicbox maps\so\zm_common\_zm_magicbox::get_chest_pieces()[ 1 ];
|
|
||||||
cur_magicbox.bot_use_node = lid get_angle_offset_node( getDvarInt( "magicbox_node_forward_size" ), ( 0, getDvarInt( "magicbox_node_angle" ), 0 ), ( 0, 0, getDvarInt( "magicbox_node_vertical_offset" ) ) );
|
|
||||||
|
|
||||||
cur_magicbox thread magicbox_debug();
|
|
||||||
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
level waittill( "magicbox_teddy_bear", old_magicbox );
|
|
||||||
waittillframeend;
|
|
||||||
free_bot_objective( "magicbox", old_magicbox );
|
|
||||||
level waittill( "new_magicbox", new_magicbox );
|
|
||||||
add_possible_bot_objective( "magicbox", new_magicbox, true );
|
|
||||||
lid = new_magicbox maps\so\zm_common\_zm_magicbox::get_chest_pieces()[ 1 ];
|
|
||||||
new_magicbox.bot_use_node = lid get_angle_offset_node( getDvarInt( "magicbox_node_forward_size" ), ( 0, getDvarInt( "magicbox_node_angle" ), 0 ), ( 0, 0, getDvarInt( "magicbox_node_vertical_offset" ) ) );
|
|
||||||
new_magicbox thread magicbox_debug();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
magicbox_debug()
|
|
||||||
{
|
|
||||||
self notify( "magicbox_debug" );
|
|
||||||
self endon( "magicbox_debug");
|
|
||||||
level endon( "magicbox_teddy_bear" );
|
|
||||||
if ( getDvarInt( "bot_obj_debug_all" ) == 0 && getDvarInt( "bot_obj_debug_perk" ) == 0 )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
lid = self maps\so\zm_common\_zm_magicbox::get_chest_pieces()[ 1 ];
|
|
||||||
node = lid get_angle_offset_node( getDvarInt( "magicbox_node_forward_size" ), ( 0, getDvarInt( "magicbox_node_angle" ), 0 ), ( 0, 0, getDvarInt( "magicbox_node_vertical_offset" ) ) );
|
|
||||||
self.bot_use_node = node;
|
|
||||||
line( self.origin, node, ( 1.0, 1.0, 1.0 ) );
|
|
||||||
wait 0.05;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
perk_debug()
|
|
||||||
{
|
|
||||||
if ( getDvarInt( "bot_obj_debug_all" ) == 0 && getDvarInt( "bot_obj_debug_perk" ) == 0 )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
node = self get_angle_offset_node( getDvarInt( "perk_node_forward_size" ), ( 0, getDvarInt( "perk_node_angle" ), 0 ), ( 0, 0, getDvarInt( "perk_node_vertical_offset" ) ) );
|
|
||||||
self.bot_use_node = node;
|
|
||||||
line( self.origin, node, ( 1.0, 1.0, 1.0 ) );
|
|
||||||
wait 0.05;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wallbuy_debug()
|
|
||||||
{
|
|
||||||
if ( getDvarInt( "bot_obj_debug_all" ) == 0 && getDvarInt( "bot_obj_debug_wallbuy" ) == 0 )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
node = self get_angle_offset_node( getDvarInt( "wallbuy_node_forward_size" ), ( 0, getDvarInt( "wallbuy_node_angle" ), 0 ), ( 0, 0, getDvarInt( "wallbuy_node_vertical_offset" ) ) );
|
|
||||||
self.bot_use_node = node;
|
|
||||||
line( self.origin, node, ( 1.0, 1.0, 1.0 ) );
|
|
||||||
wait 0.05;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
packapunch_debug()
|
|
||||||
{
|
|
||||||
if ( getDvarInt( "bot_obj_debug_all" ) == 0 && getDvarInt( "bot_obj_debug_packapunch" ) == 0 )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
node = self get_angle_offset_node( getDvarInt( "packapunch_node_forward_size" ), ( 0, getDvarInt( "packapunch_node_angle" ), 0 ), ( 0, 0, getDvarInt( "packapunch_node_vertical_offset" ) ) );
|
|
||||||
self.bot_use_node = node;
|
|
||||||
line( self.origin, node, ( 1.0, 1.0, 1.0 ) );
|
|
||||||
wait 0.05;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_on_powerup_grab( powerup )
|
|
||||||
{
|
|
||||||
self bot_objective_print( "powerup", powerup getEntityNumber(), "bot_on_powerup_grab", "Bot <" + self.playername + "> grabbed powerup" );
|
|
||||||
self.successfully_grabbed_powerup = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_on_revive_success( revivee )
|
|
||||||
{
|
|
||||||
self bot_objective_print( "revive", revivee getEntityNumber(), "bot_on_revive_success", "Bot <" + self.playername + "> revived <" + revivee.playername + ">" );
|
|
||||||
self.successfully_revived_player = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_on_magicbox_weapon_grab( magicbox, weapon )
|
|
||||||
{
|
|
||||||
self bot_objective_print( "magicbox", magicbox getEntityNumber(), "bot_on_magicbox_weapon_grab", "Bot <" + self.playername + "> grabbed <" + weapon + "> from the box" );
|
|
||||||
self.successfully_grabbed_magicbox_weapon = true;
|
|
||||||
self.last_magicbox_purchase_time = getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_on_perk_purchase( trigger, perk )
|
|
||||||
{
|
|
||||||
self bot_objective_print( "perk", trigger getEntityNumber(), "bot_on_perk_purchase", "Bot <" + self.playername + "> purchased <" + perk + ">" );
|
|
||||||
self.successfully_bought_perk = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_on_door_purchase_func( door )
|
|
||||||
{
|
|
||||||
self bot_objective_print( "door", door getEntityNumber(), "bot_on_door_purchase_func", "Bot <" + self.playername + "> purchased door" );
|
|
||||||
self.successfully_bought_door = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_on_debris_purchase_func( debris )
|
|
||||||
{
|
|
||||||
self bot_objective_print( "debris", debris getEntityNumber(), "bot_on_debris_purchase_func", "Bot <" + self.playername + "> purchased debris" );
|
|
||||||
self.successfully_bought_debris = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_on_wallbuy_purchase_func( trigger, weapon )
|
|
||||||
{
|
|
||||||
self bot_objective_print( "wallbuy", trigger getEntityNumber(), "bot_on_wallbuy_purchase_func", "Bot <" + self.playername + "> purchased wallbuy <" + weapon + ">" );
|
|
||||||
self.successfully_bought_wallbuy = true;
|
|
||||||
self.last_wallbuy_purchase_time = getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
bot_on_wallbuy_ammo_purchase_func( trigger, weapon )
|
|
||||||
{
|
|
||||||
self bot_objective_print( "wallbuyammo", trigger getEntityNumber(), "bot_on_wallbuy_ammo_purchase_func", "Bot <" + self.playername + "> purchased wallbuy ammo <" + weapon + ">" );
|
|
||||||
self.successfully_bought_wallbuy_ammo = true;
|
|
||||||
}
|
|
@ -1,234 +0,0 @@
|
|||||||
#include common_scripts\utility;
|
|
||||||
#include maps\_utility;
|
|
||||||
#include maps\bots\_bot_utility;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Checks whether the path generated by the ASTAR path finding is inaccessible
|
|
||||||
*/
|
|
||||||
GetPathIsInaccessible( to, best_effort )
|
|
||||||
{
|
|
||||||
if ( isDefined( best_effort ) )
|
|
||||||
{
|
|
||||||
path = generatePath( self.origin, to, self.team, level.bot_allowed_negotiation_links, best_effort );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
path = generatePath( self.origin, to, self.team, level.bot_allowed_negotiation_links );
|
|
||||||
}
|
|
||||||
return !isDefined( path ) || ( path.size <= 0) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
swap_array_index( array, index1, index2 )
|
|
||||||
{
|
|
||||||
temp = array[ index1 ];
|
|
||||||
array[ index1 ] = array[ index2 ];
|
|
||||||
array[ index2 ] = temp;
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
quickSort(array, compare_func, compare_func_arg1)
|
|
||||||
{
|
|
||||||
return quickSortMid( array, 0, array.size - 1, compare_func, compare_func_arg1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Quicksort algorithm copied from T7 modified for T4
|
|
||||||
*/
|
|
||||||
quickSortMid( array, start, end, compare_func, compare_func_arg1 )
|
|
||||||
{
|
|
||||||
i = start;
|
|
||||||
k = end;
|
|
||||||
|
|
||||||
if(!IsDefined(compare_func))
|
|
||||||
compare_func = ::quicksort_compare;
|
|
||||||
|
|
||||||
if (end - start >= 1)
|
|
||||||
{
|
|
||||||
pivot = array[start];
|
|
||||||
|
|
||||||
while (k > i)
|
|
||||||
{
|
|
||||||
while ( [[ compare_func ]](array[i], pivot, compare_func_arg1) && i <= end && k > i)
|
|
||||||
i++;
|
|
||||||
while ( ![[ compare_func ]](array[k], pivot, compare_func_arg1) && k >= start && k >= i)
|
|
||||||
k--;
|
|
||||||
if (k > i)
|
|
||||||
array = swap_array_index(array, i, k);
|
|
||||||
}
|
|
||||||
array = swap_array_index(array, start, k);
|
|
||||||
array = quickSortMid(array, start, k - 1, compare_func);
|
|
||||||
array = quickSortMid(array, k + 1, end, compare_func);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return array;
|
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
quicksort_compare(left, right, compare_func_arg1)
|
|
||||||
{
|
|
||||||
return left <= right;
|
|
||||||
}
|
|
||||||
|
|
||||||
quicksort_compare_priority_field(left, right, compare_func_arg1)
|
|
||||||
{
|
|
||||||
return left.priority <= right.priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
quicksort_compare_pers_value_highest_to_lowest( left, right, compare_func_arg1 )
|
|
||||||
{
|
|
||||||
return left.pers[ compare_func_arg1 ] <= right.pers[ compare_func_arg1 ];
|
|
||||||
}
|
|
||||||
|
|
||||||
quicksort_compare_pers_value_lowest_to_highest( left, right, compare_func_arg1 )
|
|
||||||
{
|
|
||||||
return left.pers[ compare_func_arg1 ] >= right.pers[ compare_func_arg1 ];
|
|
||||||
}
|
|
||||||
|
|
||||||
assign_priority_to_powerup( powerup )
|
|
||||||
{
|
|
||||||
if ( !isDefined( powerup ) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
priority = 0;
|
|
||||||
powerup_is_max_ammo = false;
|
|
||||||
switch ( powerup.powerup_name )
|
|
||||||
{
|
|
||||||
case "zombie_blood":
|
|
||||||
case "insta_kill":
|
|
||||||
case "nuke":
|
|
||||||
priority += 2;
|
|
||||||
break;
|
|
||||||
case "full_ammo":
|
|
||||||
powerup_is_max_ammo = true;
|
|
||||||
priority += 1;
|
|
||||||
break;
|
|
||||||
case "double_points":
|
|
||||||
case "fire_sale":
|
|
||||||
case "carpenter":
|
|
||||||
case "free_perk":
|
|
||||||
priority += 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
priority += 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ( powerup_is_max_ammo )
|
|
||||||
{
|
|
||||||
LOW_AMMO_THRESHOLD = 0.3;
|
|
||||||
|
|
||||||
players = getPlayers();
|
|
||||||
|
|
||||||
for ( i = 0; i < players.size; i++ )
|
|
||||||
{
|
|
||||||
weapons = players[ i ] getWeaponsListPrimaries();
|
|
||||||
for ( j = 0; j < weapons.size; j++ )
|
|
||||||
{
|
|
||||||
if ( players[ i ] getWeaponAmmoStock( weapons[ j ] ) <= int( weaponmaxammo( weapons[ j ] ) * LOW_AMMO_THRESHOLD ) )
|
|
||||||
{
|
|
||||||
priority += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( priority > 3 )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( maps\_laststand::player_any_player_in_laststand() )
|
|
||||||
{
|
|
||||||
switch ( powerup.powerup_name )
|
|
||||||
{
|
|
||||||
case "zombie_blood":
|
|
||||||
case "insta_kill":
|
|
||||||
case "nuke":
|
|
||||||
priority += 1;
|
|
||||||
break;
|
|
||||||
case "full_ammo":
|
|
||||||
priority += 0;
|
|
||||||
break;
|
|
||||||
case "double_points":
|
|
||||||
case "fire_sale":
|
|
||||||
case "carpenter":
|
|
||||||
case "free_perk":
|
|
||||||
priority -= 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
priority += 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( powerup.time_left_until_timeout < 10.0 )
|
|
||||||
{
|
|
||||||
priority += 1;
|
|
||||||
}
|
|
||||||
if ( priority < 0 )
|
|
||||||
{
|
|
||||||
priority = 0;
|
|
||||||
}
|
|
||||||
powerup.priority = priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
sort_array_by_priority_field( array, item )
|
|
||||||
{
|
|
||||||
if ( isDefined( item ) )
|
|
||||||
{
|
|
||||||
array[ array.size ] = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
array = quickSort( array, ::quicksort_compare_priority_field, undefined );
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
get_players_sorted_by_highest_pers_value( pers_name )
|
|
||||||
{
|
|
||||||
players = getPlayers();
|
|
||||||
|
|
||||||
if ( !isDefined( players[ 0 ].pers[ pers_name ] ) )
|
|
||||||
{
|
|
||||||
assertMsg( "Uninitialized pers value: " + pers_name );
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return quickSort( players, ::quicksort_compare_pers_value_highest_to_lowest, pers_name );
|
|
||||||
}
|
|
||||||
|
|
||||||
get_players_sorted_by_lowest_pers_value( pers_name )
|
|
||||||
{
|
|
||||||
players = getPlayers();
|
|
||||||
|
|
||||||
if ( !isDefined( players[ 0 ].pers[ pers_name ] ) )
|
|
||||||
{
|
|
||||||
assertMsg( "Uninitialized pers value: " + pers_name );
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return quickSort( players, ::quicksort_compare_pers_value_lowest_to_highest, pers_name );
|
|
||||||
}
|
|
||||||
|
|
||||||
get_path_dist( start, end )
|
|
||||||
{
|
|
||||||
path = generatePath( start, end, self.team, level.bot_allowed_negotiation_links, 192.0 );
|
|
||||||
if ( !isDefined( path ) || path.size <= 0 )
|
|
||||||
{
|
|
||||||
return 9999999;
|
|
||||||
}
|
|
||||||
dist = 0;
|
|
||||||
prev_node = undefined;
|
|
||||||
for ( i = 0; i < path.size; i++ )
|
|
||||||
{
|
|
||||||
if ( i == 0 )
|
|
||||||
{
|
|
||||||
prev_node = path[ i ];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
dist += distance( prev_node.origin, path[ i ].origin );
|
|
||||||
prev_node = path[ i ];
|
|
||||||
}
|
|
||||||
|
|
||||||
return dist;
|
|
||||||
}
|
|
@ -5,57 +5,4 @@
|
|||||||
init()
|
init()
|
||||||
{
|
{
|
||||||
level thread maps\bots\_bot::init();
|
level thread maps\bots\_bot::init();
|
||||||
|
|
||||||
if ( getDvar( "player_debug_bots" ) == "" )
|
|
||||||
setDvar( "player_debug_bots", 1 );
|
|
||||||
|
|
||||||
thread test_bot_pathing();
|
|
||||||
}
|
|
||||||
|
|
||||||
test_bot_pathing()
|
|
||||||
{
|
|
||||||
if ( !getDvarInt( "player_debug_bots" ) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
player = undefined;
|
|
||||||
|
|
||||||
while ( !isDefined( player ) || player is_bot() )
|
|
||||||
level waittill( "connected", player );
|
|
||||||
|
|
||||||
PrintConsole( "player has CMDS! " + player.playername );
|
|
||||||
player endon( "disconnect" );
|
|
||||||
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
wait 0.05;
|
|
||||||
|
|
||||||
if ( !player UseButtonPressed() )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
bots = getBotArray();
|
|
||||||
|
|
||||||
if ( player AttackButtonPressed() )
|
|
||||||
{
|
|
||||||
player iprintln( "Telling bots to go to you" );
|
|
||||||
|
|
||||||
for ( i = 0; i < bots.size; i++ )
|
|
||||||
{
|
|
||||||
bots[i] SetScriptGoal( player.origin );
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( player AdsButtonPressed() )
|
|
||||||
{
|
|
||||||
player iprintln( "Telling bots to ROAM" );
|
|
||||||
|
|
||||||
for ( i = 0; i < bots.size; i++ )
|
|
||||||
{
|
|
||||||
bots[i] ClearScriptGoal();
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,395 +0,0 @@
|
|||||||
#include maps\_utility;
|
|
||||||
#include common_scripts\utility;
|
|
||||||
|
|
||||||
main()
|
|
||||||
{
|
|
||||||
replaceFunc( GetFunction( "maps/_utility", "wait_network_frame" ), ::wait_network_frame_func );
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_network_frame_func()
|
|
||||||
{
|
|
||||||
wait 0.05;
|
|
||||||
}
|
|
||||||
|
|
||||||
init()
|
|
||||||
{
|
|
||||||
level thread print_new_rounds();
|
|
||||||
level thread onPlayerConnect();
|
|
||||||
level thread spitOutTime();
|
|
||||||
|
|
||||||
if ( getDvar( "killtest_bot_debug" ) == "" )
|
|
||||||
setDvar( "killtest_bot_debug", 0 );
|
|
||||||
|
|
||||||
level thread addBot();
|
|
||||||
|
|
||||||
level thread setupcallbacks();
|
|
||||||
}
|
|
||||||
|
|
||||||
setupcallbacks()
|
|
||||||
{
|
|
||||||
wait 1;
|
|
||||||
|
|
||||||
level.killtestoldoverrideplayerdamage = level.callbackPlayerDamage;
|
|
||||||
level.callbackPlayerDamage = ::killtestoverrideplayerdamage;
|
|
||||||
|
|
||||||
level.killtestoldoverrideactordamage = level.callbackActorDamage;
|
|
||||||
level.callbackActorDamage = ::killtestoverrideactordamage;
|
|
||||||
}
|
|
||||||
|
|
||||||
killtestoverrideactordamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, iTimeOffset )
|
|
||||||
{
|
|
||||||
setDvar( "aa_player_damage_dealt", 0 );
|
|
||||||
|
|
||||||
if ( isPlayer( eAttacker ) && eAttacker isBot() && getDvarInt( "bots_t8_mode" ) )
|
|
||||||
{
|
|
||||||
iDamage += int( self.maxhealth * randomFloatRange( 0.25, 1.25 ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
self [[level.killtestoldoverrideactordamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, iTimeOffset );
|
|
||||||
}
|
|
||||||
|
|
||||||
killtestoverrideplayerdamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime )
|
|
||||||
{
|
|
||||||
if ( self isBot() && getDvarInt( "bots_t8_mode" ) )
|
|
||||||
{
|
|
||||||
iDamage = int( iDamage * 0.1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
//PrintConsole( self GetPlayerName() + " took " + iDamage );
|
|
||||||
|
|
||||||
self [[level.killtestoldoverrideplayerdamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime );
|
|
||||||
}
|
|
||||||
|
|
||||||
print_new_rounds()
|
|
||||||
{
|
|
||||||
while ( 1 )
|
|
||||||
{
|
|
||||||
level waittill( "new_zombie_round", round_num );
|
|
||||||
|
|
||||||
PrintConsole( "New zombie round!: " + round_num );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spitOutTime()
|
|
||||||
{
|
|
||||||
startTime = GetTime();
|
|
||||||
|
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
wait 60;
|
|
||||||
PrintConsole( "TIME: " + ( GetTime() - startTime ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
botMoveTo( to )
|
|
||||||
{
|
|
||||||
self.moveTo = to;
|
|
||||||
}
|
|
||||||
|
|
||||||
walk_to_player()
|
|
||||||
{
|
|
||||||
self endon( "disconnect" );
|
|
||||||
self endon( "zombified" );
|
|
||||||
|
|
||||||
bot_allowed_negotiation_links = [];
|
|
||||||
bot_allowed_negotiation_links[ bot_allowed_negotiation_links.size ] = "zombie_jump_down_72";
|
|
||||||
bot_allowed_negotiation_links[ bot_allowed_negotiation_links.size ] = "zombie_jump_down_96";
|
|
||||||
bot_allowed_negotiation_links[ bot_allowed_negotiation_links.size ] = "zombie_jump_down_120";
|
|
||||||
bot_allowed_negotiation_links[ bot_allowed_negotiation_links.size ] = "zombie_jump_down_127";
|
|
||||||
bot_allowed_negotiation_links[ bot_allowed_negotiation_links.size ] = "zombie_jump_down_184";
|
|
||||||
bot_allowed_negotiation_links[ bot_allowed_negotiation_links.size ] = "zombie_jump_down_190";
|
|
||||||
|
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
wait 0.05;
|
|
||||||
|
|
||||||
// stop bot moving
|
|
||||||
self botMoveTo( self.origin );
|
|
||||||
|
|
||||||
// get a player
|
|
||||||
non_bot_player = undefined;
|
|
||||||
players = getPlayers();
|
|
||||||
|
|
||||||
for ( i = 0; i < players.size; i++ )
|
|
||||||
{
|
|
||||||
player = players[i];
|
|
||||||
|
|
||||||
if ( player isBot() )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
non_bot_player = player;
|
|
||||||
}
|
|
||||||
|
|
||||||
goal = ( 0, 0, 50 );
|
|
||||||
|
|
||||||
if ( isdefined( non_bot_player ) )
|
|
||||||
{
|
|
||||||
goal = non_bot_player.origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate a path to the player
|
|
||||||
path = generatePath( self.origin, goal, self.team, bot_allowed_negotiation_links );
|
|
||||||
|
|
||||||
if ( !isdefined( path ) || !path.size )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// traverse each node in the path
|
|
||||||
for ( i = 0; i < path.size; i++ )
|
|
||||||
{
|
|
||||||
path_node = path[i];
|
|
||||||
|
|
||||||
while ( distance2d( self.origin, path_node.origin ) >= 7 )
|
|
||||||
{
|
|
||||||
wait 0.05;
|
|
||||||
|
|
||||||
self botMoveTo( path_node.origin );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// blindly go to player after traversing each path node
|
|
||||||
while ( distance2d( self.origin, goal ) >= 10 )
|
|
||||||
{
|
|
||||||
wait 0.05;
|
|
||||||
|
|
||||||
self botMoveTo( goal );
|
|
||||||
}
|
|
||||||
|
|
||||||
// done
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
do_move()
|
|
||||||
{
|
|
||||||
self endon( "disconnect" );
|
|
||||||
self endon( "zombified" );
|
|
||||||
|
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
wait 0.05;
|
|
||||||
waittillframeend;
|
|
||||||
|
|
||||||
move_To = self.moveTo;
|
|
||||||
angles = self GetPlayerAngles();
|
|
||||||
dir = ( 0, 0, 0 );
|
|
||||||
|
|
||||||
if ( DistanceSquared( self.origin, move_To ) >= 49 )
|
|
||||||
{
|
|
||||||
cosa = cos( 0 - angles[1] );
|
|
||||||
sina = sin( 0 - angles[1] );
|
|
||||||
|
|
||||||
// get the direction
|
|
||||||
dir = move_To - self.origin;
|
|
||||||
|
|
||||||
// rotate our direction according to our angles
|
|
||||||
dir = ( dir[0] * cosa - dir[1] * sina,
|
|
||||||
dir[0] * sina + dir[1] * cosa,
|
|
||||||
0 );
|
|
||||||
|
|
||||||
// make the length 127
|
|
||||||
dir = VectorNormalize( dir ) * 127;
|
|
||||||
|
|
||||||
// invert the second component as the engine requires this
|
|
||||||
dir = ( dir[0], 0 - dir[1], 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
self botMovement( int( dir[0] ), int( dir[1] ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addBot()
|
|
||||||
{
|
|
||||||
if ( !getDvarInt( "killtest_bot_debug" ) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// level waittill("connected", player);
|
|
||||||
wait 5;
|
|
||||||
|
|
||||||
guy = addTestClient();
|
|
||||||
|
|
||||||
if ( !isDefined( guy ) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
guy endon( "disconnect" );
|
|
||||||
|
|
||||||
guy botStop();
|
|
||||||
|
|
||||||
wait 5;
|
|
||||||
|
|
||||||
if ( !isDefined( guy ) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
guy.killingAll = true;
|
|
||||||
weapon = "ray_gun";
|
|
||||||
guy giveWeapon( weapon ); // ptrs41_zombie zombie_doublebarrel
|
|
||||||
guy switchToWeapon( weapon ); // colt_dirty_harry
|
|
||||||
|
|
||||||
guy thread walk_to_player();
|
|
||||||
guy thread do_move();
|
|
||||||
|
|
||||||
while ( isDefined( guy ) )
|
|
||||||
{
|
|
||||||
if ( isDefined( level.isPlayerDead ) && [[level.isPlayerDead]]( guy ) )
|
|
||||||
{
|
|
||||||
wait 2.5;
|
|
||||||
guy removeTestClient();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
guy giveMaxAmmo( weapon );
|
|
||||||
|
|
||||||
wait 0.05;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onPlayerConnect()
|
|
||||||
{
|
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
level waittill( "connected", player );
|
|
||||||
|
|
||||||
player thread onSpawned();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onSpawned()
|
|
||||||
{
|
|
||||||
self endon( "disconnect" );
|
|
||||||
|
|
||||||
self.killingAll = false;
|
|
||||||
|
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
self waittill( "spawned_player" );
|
|
||||||
|
|
||||||
self thread killAllZombsWithBullets();
|
|
||||||
self thread watchKillAllButton();
|
|
||||||
|
|
||||||
if ( !self isBot() )
|
|
||||||
self thread moveBot();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EyeTraceForward()
|
|
||||||
{
|
|
||||||
origin = self getTagOrigin( "tag_eye" );
|
|
||||||
angles = self GetPlayerAngles();
|
|
||||||
forward = AnglesToForward( angles );
|
|
||||||
endpoint = origin + forward * 15000;
|
|
||||||
|
|
||||||
res = BulletTrace( origin, endpoint, false, undefined );
|
|
||||||
|
|
||||||
return res["position"];
|
|
||||||
}
|
|
||||||
|
|
||||||
moveBot()
|
|
||||||
{
|
|
||||||
self endon( "disconnect" );
|
|
||||||
self endon( "zombified" );
|
|
||||||
|
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
wait 0.05;
|
|
||||||
|
|
||||||
if ( self MeleeButtonPressed() && self AdsButtonPressed() )
|
|
||||||
{
|
|
||||||
players = get_players();
|
|
||||||
|
|
||||||
for ( i = 0; i < players.size; i++ )
|
|
||||||
{
|
|
||||||
player = players[i];
|
|
||||||
|
|
||||||
if ( !player isBot() )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( self AttackButtonPressed() && isDefined( player.bot.moveTo ) )
|
|
||||||
player SetOrigin( player.bot.moveTo );
|
|
||||||
else
|
|
||||||
player SetOrigin( self EyeTraceForward() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watchKillAllButton()
|
|
||||||
{
|
|
||||||
self endon( "disconnect" );
|
|
||||||
self endon( "zombified" );
|
|
||||||
|
|
||||||
wait 5;
|
|
||||||
|
|
||||||
self notifyOnPlayerCommand( "+smoke", "toggle_killall" );
|
|
||||||
|
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
self waittill( "toggle_killall" );
|
|
||||||
|
|
||||||
self.killingAll = !self.killingAll;
|
|
||||||
self iPrintLn( "Killing all: " + self.killingAll );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
do_magic_bullets()
|
|
||||||
{
|
|
||||||
self endon( "disconnect" );
|
|
||||||
self endon( "zombified" );
|
|
||||||
|
|
||||||
myeye = self getTagOrigin( "tag_eye" );
|
|
||||||
|
|
||||||
if ( !isDefined( myeye ) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
zombies = GetAiSpeciesArray( "axis", "all" );
|
|
||||||
weap = self GetCurrentWeapon();
|
|
||||||
|
|
||||||
for ( i = 0; i < zombies.size; i++ )
|
|
||||||
{
|
|
||||||
zombie = zombies[i];
|
|
||||||
|
|
||||||
if ( isDefined( zombie ) )
|
|
||||||
{
|
|
||||||
if ( getDvarInt( "killtest_overflow_health_test" ) )
|
|
||||||
{
|
|
||||||
if ( zombie.maxhealth != 2147483647 )
|
|
||||||
{
|
|
||||||
zombie.maxhealth = 2147483647;
|
|
||||||
zombie.health = zombie.maxhealth;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
zombie DoDamage( zombie.health + 666, zombie.origin, self, 0, "headshot" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hit_loc = undefined;
|
|
||||||
|
|
||||||
if ( randomint( 2 ) )
|
|
||||||
hit_loc = zombie getTagOrigin( "j_head" );
|
|
||||||
else
|
|
||||||
hit_loc = zombie getTagOrigin( "j_spine4" );
|
|
||||||
|
|
||||||
if ( isDefined( hit_loc ) )
|
|
||||||
{
|
|
||||||
if ( sighttracepassed( myeye, hit_loc, false, self ) )
|
|
||||||
{
|
|
||||||
magicbullet( weap, myeye, hit_loc, self );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
killAllZombsWithBullets()
|
|
||||||
{
|
|
||||||
self endon( "disconnect" );
|
|
||||||
self endon( "zombified" );
|
|
||||||
|
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
wait 0.05;
|
|
||||||
|
|
||||||
if ( !self.killingAll )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
self thread do_magic_bullets();
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user