mirror of
https://github.com/JezuzLizard/Recompilable-gscs-for-BO2-zombies-and-multiplayer.git
synced 2025-06-08 18:07:54 -05:00
547 lines
15 KiB
Plaintext
547 lines
15 KiB
Plaintext
#include maps/mp/gametypes/_rank;
|
|
#include maps/mp/bots/_bot;
|
|
#include maps/mp/_utility;
|
|
#include common_scripts/utility;
|
|
|
|
init() //checked changed to match cerberus output
|
|
{
|
|
level endon( "game_ended" );
|
|
level.bot_banned_killstreaks = array( "KILLSTREAK_RCBOMB", "KILLSTREAK_QRDRONE", "KILLSTREAK_REMOTE_MISSILE", "KILLSTREAK_REMOTE_MORTAR", "KILLSTREAK_HELICOPTER_GUNNER" );
|
|
for ( ;; )
|
|
{
|
|
level waittill( "connected", player );
|
|
if ( !player istestclient() )
|
|
{
|
|
continue;
|
|
}
|
|
player thread on_bot_connect();
|
|
}
|
|
}
|
|
|
|
on_bot_connect() //checked changed to match cerberus output
|
|
{
|
|
self endon( "disconnect" );
|
|
if ( isDefined( self.pers[ "bot_loadout" ] ) )
|
|
{
|
|
return;
|
|
}
|
|
wait 0.1;
|
|
if ( ( self getentitynumber() % 2 ) == 0 )
|
|
{
|
|
wait 0.05;
|
|
}
|
|
self maps/mp/bots/_bot::bot_set_rank();
|
|
if ( level.onlinegame && !sessionmodeisprivate() )
|
|
{
|
|
self botsetdefaultclass( 5, "class_assault" );
|
|
self botsetdefaultclass( 6, "class_smg" );
|
|
self botsetdefaultclass( 7, "class_lmg" );
|
|
self botsetdefaultclass( 8, "class_cqb" );
|
|
self botsetdefaultclass( 9, "class_sniper" );
|
|
}
|
|
else
|
|
{
|
|
self botsetdefaultclass( 5, "class_assault" );
|
|
self botsetdefaultclass( 6, "class_smg" );
|
|
self botsetdefaultclass( 7, "class_lmg" );
|
|
self botsetdefaultclass( 8, "class_cqb" );
|
|
self botsetdefaultclass( 9, "class_sniper" );
|
|
}
|
|
max_allocation = 10;
|
|
for ( i = 1; i <= 3; i++ )
|
|
{
|
|
if ( self isitemlocked( maps/mp/gametypes/_rank::getitemindex( "feature_allocation_slot_" + i ) ) )
|
|
{
|
|
max_allocation--;
|
|
}
|
|
}
|
|
self bot_construct_loadout( max_allocation );
|
|
self.pers[ "bot_loadout" ] = 1;
|
|
}
|
|
|
|
bot_construct_loadout( allocation_max ) //checked matches cerberus output
|
|
{
|
|
if ( self isitemlocked( maps/mp/gametypes/_rank::getitemindex( "feature_cac" ) ) )
|
|
{
|
|
return;
|
|
}
|
|
pixbeginevent( "bot_construct_loadout" );
|
|
item_list = bot_build_item_list();
|
|
bot_construct_class( 0, item_list, allocation_max );
|
|
bot_construct_class( 1, item_list, allocation_max );
|
|
bot_construct_class( 2, item_list, allocation_max );
|
|
bot_construct_class( 3, item_list, allocation_max );
|
|
bot_construct_class( 4, item_list, allocation_max );
|
|
killstreaks = item_list[ "killstreak1" ];
|
|
if ( isDefined( item_list[ "killstreak2" ] ) )
|
|
{
|
|
killstreaks = arraycombine( killstreaks, item_list[ "killstreak2" ], 1, 0 );
|
|
}
|
|
if ( isDefined( item_list[ "killstreak3" ] ) )
|
|
{
|
|
killstreaks = arraycombine( killstreaks, item_list[ "killstreak3" ], 1, 0 );
|
|
}
|
|
if ( isDefined( killstreaks ) && killstreaks.size )
|
|
{
|
|
bot_choose_weapon( 0, killstreaks );
|
|
bot_choose_weapon( 0, killstreaks );
|
|
bot_choose_weapon( 0, killstreaks );
|
|
}
|
|
self.claimed_items = undefined;
|
|
pixendevent();
|
|
}
|
|
|
|
bot_construct_class( class, items, allocation_max ) //checked partially changed to match cerberus output did not change while loop to for loop see github for more info
|
|
{
|
|
allocation = 0;
|
|
claimed_count = bot_build_claimed_list( items );
|
|
self.claimed_items = [];
|
|
while ( allocation < allocation_max )
|
|
{
|
|
secondary_chance = 40;
|
|
remaining = allocation_max - allocation;
|
|
if ( remaining >= 1 && bot_make_choice( 95, claimed_count[ "primary" ], 1 ) )
|
|
{
|
|
weapon = bot_choose_weapon( class, items[ "primary" ] );
|
|
claimed_count[ "primary" ]++;
|
|
allocation++;
|
|
bot_choose_weapon_option( class, "camo", 0 );
|
|
bot_choose_weapon_option( class, "reticle", 0 );
|
|
allocation += bot_choose_primary_attachments( class, weapon, allocation, allocation_max );
|
|
}
|
|
else if ( !claimed_count[ "primary" ] )
|
|
{
|
|
secondary_chance = 100;
|
|
}
|
|
remaining = allocation_max - allocation;
|
|
if ( remaining >= 1 && bot_make_choice( secondary_chance, claimed_count[ "secondary" ], 1 ) )
|
|
{
|
|
if ( remaining >= 2 && randomint( 100 ) < 10 )
|
|
{
|
|
self botclassadditem( class, "BONUSCARD_OVERKILL" );
|
|
weapon = bot_choose_weapon( class, items[ "primary" ] );
|
|
allocation++;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
weapon = bot_choose_weapon( class, items[ "secondary" ] );
|
|
bot_choose_weapon_option( class, "camo", 1 );
|
|
}
|
|
allocation++;
|
|
claimed_count[ "secondary" ]++;
|
|
allocation += bot_choose_secondary_attachments( class, weapon, allocation, allocation_max );
|
|
}
|
|
perks_chance = 50;
|
|
lethal_chance = 30;
|
|
tactical_chance = 20;
|
|
if ( claimed_count[ "specialty1" ] && claimed_count[ "specialty2" ] && claimed_count[ "specialty3" ] )
|
|
{
|
|
perks_chance = 0;
|
|
}
|
|
if ( claimed_count[ "primarygrenade" ] )
|
|
{
|
|
lethal_chance = 0;
|
|
}
|
|
if ( claimed_count[ "specialgrenade" ] )
|
|
{
|
|
tactical_chance = 0;
|
|
}
|
|
if ( ( perks_chance + lethal_chance + tactical_chance ) <= 0 )
|
|
{
|
|
return;
|
|
}
|
|
next_action = bot_chose_action( "perks", perks_chance, "lethal", lethal_chance, "tactical", tactical_chance, "none", 0 );
|
|
if ( next_action == "perks" )
|
|
{
|
|
remaining = allocation_max - allocation;
|
|
if ( remaining >= 3 && !claimed_count[ "specialty1" ] && randomint( 100 ) < 25 )
|
|
{
|
|
self botclassadditem( class, "BONUSCARD_PERK_1_GREED" );
|
|
bot_choose_weapon( class, items[ "specialty1" ] );
|
|
bot_choose_weapon( class, items[ "specialty1" ] );
|
|
claimed_count[ "specialty1" ] = 2;
|
|
allocation += 3;
|
|
}
|
|
remaining = allocation_max - allocation;
|
|
if ( remaining >= 3 && !claimed_count[ "specialty2" ] && randomint( 100 ) < 25 )
|
|
{
|
|
self botclassadditem( class, "BONUSCARD_PERK_2_GREED" );
|
|
bot_choose_weapon( class, items[ "specialty2" ] );
|
|
bot_choose_weapon( class, items[ "specialty2" ] );
|
|
claimed_count[ "specialty2" ] = 2;
|
|
allocation += 3;
|
|
}
|
|
remaining = allocation_max - allocation;
|
|
if ( remaining >= 3 && !claimed_count[ "specialty3" ] && randomint( 100 ) < 25 )
|
|
{
|
|
self botclassadditem( class, "BONUSCARD_PERK_3_GREED" );
|
|
bot_choose_weapon( class, items[ "specialty3" ] );
|
|
bot_choose_weapon( class, items[ "specialty3" ] );
|
|
claimed_count[ "specialty3" ] = 2;
|
|
allocation += 3;
|
|
}
|
|
remaining = allocation_max - allocation;
|
|
i = 0;
|
|
while ( i < 3 )
|
|
{
|
|
perks = [];
|
|
remaining = allocation_max - allocation;
|
|
if ( remaining > 0 )
|
|
{
|
|
if ( !claimed_count[ "specialty1" ] )
|
|
{
|
|
perks[ perks.size ] = "specialty1";
|
|
}
|
|
if ( !claimed_count[ "specialty2" ] )
|
|
{
|
|
perks[ perks.size ] = "specialty2";
|
|
}
|
|
if ( !claimed_count[ "specialty3" ] )
|
|
{
|
|
perks[ perks.size ] = "specialty3";
|
|
}
|
|
if ( perks.size )
|
|
{
|
|
perk = random( perks );
|
|
bot_choose_weapon( class, items[ perk ] );
|
|
claimed_count[ perk ]++;
|
|
allocation++;
|
|
i++;
|
|
continue;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
else if ( next_action == "lethal" )
|
|
{
|
|
remaining = allocation_max - allocation;
|
|
if ( remaining >= 2 && randomint( 100 ) < 50 )
|
|
{
|
|
if ( !claimed_count[ "primarygrenade" ] )
|
|
{
|
|
bot_choose_weapon( class, items[ "primarygrenade" ] );
|
|
claimed_count[ "primarygrenade" ]++;
|
|
allocation++;
|
|
}
|
|
self botclassadditem( class, "BONUSCARD_DANGER_CLOSE" );
|
|
allocation++;
|
|
}
|
|
else if ( remaining >= 1 && !claimed_count[ "primarygrenade" ] )
|
|
{
|
|
bot_choose_weapon( class, items[ "primarygrenade" ] );
|
|
claimed_count[ "primarygrenade" ]++;
|
|
allocation++;
|
|
}
|
|
}
|
|
else if ( next_action == "tactical" )
|
|
{
|
|
remaining = allocation_max - allocation;
|
|
if ( remaining >= 2 && !claimed_count[ "specialgrenade" ] && randomint( 100 ) < 50 )
|
|
{
|
|
weapon = bot_choose_weapon( class, items[ "specialgrenade" ] );
|
|
if ( weapon == "WEAPON_TACTICAL_INSERTION" || weapon == "WEAPON_WILLY_PETE" )
|
|
{
|
|
claimed_count[ "specialgrenade" ] = 1;
|
|
allocation += 1;
|
|
}
|
|
else
|
|
{
|
|
self botclassadditem( class, weapon );
|
|
claimed_count[ "specialgrenade" ] = 2;
|
|
allocation += 2;
|
|
}
|
|
}
|
|
else if ( remaining >= 1 && !claimed_count[ "specialgrenade" ] )
|
|
{
|
|
bot_choose_weapon( class, items[ "specialgrenade" ] );
|
|
claimed_count[ "specialgrenade" ]++;
|
|
allocation++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bot_make_choice( chance, claimed, max_claim ) //checked changed at own discretion
|
|
{
|
|
if ( claimed < max_claim && randomint( 100 ) < chance )
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bot_chose_action( action1, chance1, action2, chance2, action3, chance3, action4, chance4 ) //checked changed to match cerberus output
|
|
{
|
|
chance1 = int( chance1 / 10 );
|
|
chance2 = int( chance2 / 10 );
|
|
chance3 = int( chance3 / 10 );
|
|
chance4 = int( chance4 / 10 );
|
|
actions = [];
|
|
for ( i = 0; i < chance1; i++ )
|
|
{
|
|
actions[ actions.size ] = action1;
|
|
}
|
|
for ( i = 0; i < chance2; i++ )
|
|
{
|
|
actions[ actions.size ] = action2;
|
|
}
|
|
for ( i = 0; i < chance3; i++ )
|
|
{
|
|
actions[ actions.size ] = action3;
|
|
}
|
|
for ( i = 0; i < chance4; i++ )
|
|
{
|
|
actions[ actions.size ] = action4;
|
|
}
|
|
return random( actions );
|
|
}
|
|
|
|
bot_item_is_claimed( item ) //checked changed to match cerberus output
|
|
{
|
|
foreach ( claim in self.claimed_items )
|
|
{
|
|
if ( claim == item )
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bot_choose_weapon( class, items ) //checked changed to match cerberus output
|
|
{
|
|
if ( !isDefined( items ) || !items.size )
|
|
{
|
|
return undefined;
|
|
}
|
|
start = randomint( items.size );
|
|
for ( i = 0; i < items.size; i++ )
|
|
{
|
|
weapon = items[ start ];
|
|
if ( !bot_item_is_claimed( weapon ) )
|
|
{
|
|
break;
|
|
}
|
|
start = ( start + 1 ) % items.size;
|
|
}
|
|
self.claimed_items[ self.claimed_items.size ] = weapon;
|
|
self botclassadditem( class, weapon );
|
|
return weapon;
|
|
}
|
|
|
|
bot_build_weapon_options_list( optiontype ) //checked changed to match cerberus output
|
|
{
|
|
level.botweaponoptionsid[ optiontype ] = [];
|
|
level.botweaponoptionsprob[ optiontype ] = [];
|
|
prob = 0;
|
|
for ( row = 0; row < 255; row++ )
|
|
{
|
|
if ( tablelookupcolumnforrow( "mp/attachmentTable.csv", row, 1 ) == optiontype )
|
|
{
|
|
index = level.botweaponoptionsid[ optiontype ].size;
|
|
level.botweaponoptionsid[ optiontype ][ index ] = int( tablelookupcolumnforrow( "mp/attachmentTable.csv", row, 0 ) );
|
|
prob += int( tablelookupcolumnforrow( "mp/attachmentTable.csv", row, 15 ) );
|
|
level.botweaponoptionsprob[ optiontype ][ index ] = prob;
|
|
}
|
|
}
|
|
}
|
|
|
|
bot_choose_weapon_option( class, optiontype, primary ) //checked changed to match cerberus output may need to review order of operations
|
|
{
|
|
if ( !isDefined( level.botweaponoptionsid ) )
|
|
{
|
|
level.botweaponoptionsid = [];
|
|
level.botweaponoptionsprob = [];
|
|
bot_build_weapon_options_list( "camo" );
|
|
bot_build_weapon_options_list( "reticle" );
|
|
}
|
|
if ( !level.onlinegame && !level.systemlink )
|
|
{
|
|
return;
|
|
}
|
|
numoptions = level.botweaponoptionsprob[ optiontype ].size;
|
|
maxprob = level.botweaponoptionsprob[ optiontype ][ numoptions - 1 ];
|
|
if ( !level.systemlink && self.pers[ "rank" ] < 20 )
|
|
{
|
|
maxprob += ( 4 * maxprob ) * ( ( 20 - self.pers[ "rank" ] ) / 20 );
|
|
}
|
|
rnd = randomint( int( maxprob ) );
|
|
for ( i = 0; i < numoptions; i++ )
|
|
{
|
|
if ( level.botweaponoptionsprob[ optiontype ][ i ] > rnd )
|
|
{
|
|
self botclasssetweaponoption( class, primary, optiontype, level.botweaponoptionsid[ optiontype ][ i ] );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
bot_choose_primary_attachments( class, weapon, allocation, allocation_max ) //checked changed to match cerberus output
|
|
{
|
|
attachments = getweaponattachments( weapon );
|
|
remaining = allocation_max - allocation;
|
|
if ( !attachments.size || !remaining )
|
|
{
|
|
return 0;
|
|
}
|
|
attachment_action = bot_chose_action( "3_attachments", 25, "2_attachments", 35, "1_attachments", 35, "none", 5 );
|
|
if ( remaining >= 4 && attachment_action == "3_attachments" )
|
|
{
|
|
a1 = random( attachments );
|
|
self botclassaddattachment( class, weapon, a1, "primaryattachment1" );
|
|
count = 1;
|
|
attachments = getweaponattachments( weapon, a1 );
|
|
if ( attachments.size )
|
|
{
|
|
a2 = random( attachments );
|
|
self botclassaddattachment( class, weapon, a2, "primaryattachment2" );
|
|
count++;
|
|
attachments = getweaponattachments( weapon, a1, a2 );
|
|
if ( attachments.size )
|
|
{
|
|
a3 = random( attachments );
|
|
self botclassadditem( class, "BONUSCARD_PRIMARY_GUNFIGHTER" );
|
|
self botclassaddattachment( class, weapon, a3, "primaryattachment3" );
|
|
return 4;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
else if ( remaining >= 2 && attachment_action == "2_attachments" )
|
|
{
|
|
a1 = random( attachments );
|
|
self botclassaddattachment( class, weapon, a1, "primaryattachment1" );
|
|
attachments = getweaponattachments( weapon, a1 );
|
|
if ( attachments.size )
|
|
{
|
|
a2 = random( attachments );
|
|
self botclassaddattachment( class, weapon, a2, "primaryattachment2" );
|
|
return 2;
|
|
}
|
|
return 1;
|
|
}
|
|
else if ( remaining >= 1 && attachment_action == "1_attachments" )
|
|
{
|
|
a = random( attachments );
|
|
self botclassaddattachment( class, weapon, a, "primaryattachment1" );
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bot_choose_secondary_attachments( class, weapon, allocation, allocation_max ) //checked changed to match cerberus output
|
|
{
|
|
attachments = getweaponattachments( weapon );
|
|
remaining = allocation_max - allocation;
|
|
if ( !attachments.size || !remaining )
|
|
{
|
|
return 0;
|
|
}
|
|
attachment_action = bot_chose_action( "2_attachments", 10, "1_attachments", 40, "none", 50, "none", 0 );
|
|
if ( remaining >= 3 && attachment_action == "2_attachments" )
|
|
{
|
|
a1 = random( attachments );
|
|
self botclassaddattachment( class, weapon, a1, "secondaryattachment1" );
|
|
attachments = getweaponattachments( weapon, a1 );
|
|
if ( attachments.size )
|
|
{
|
|
a2 = random( attachments );
|
|
self botclassadditem( class, "BONUSCARD_SECONDARY_GUNFIGHTER" );
|
|
self botclassaddattachment( class, weapon, a2, "secondaryattachment2" );
|
|
return 3;
|
|
}
|
|
return 1;
|
|
}
|
|
else if ( remaining >= 1 && attachment_action == "1_attachments" )
|
|
{
|
|
a = random( attachments );
|
|
self botclassaddattachment( class, weapon, a, "secondaryattachment1" );
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bot_build_item_list() //checked partially changed to match cerberus output did not change while loop to for loop see github for more info
|
|
{
|
|
pixbeginevent( "bot_build_item_list" );
|
|
items = [];
|
|
i = 0;
|
|
while ( i < 256 )
|
|
{
|
|
row = tablelookuprownum( level.statstableid, 0, i );
|
|
if ( row > -1 )
|
|
{
|
|
slot = tablelookupcolumnforrow( level.statstableid, row, 13 );
|
|
if ( slot == "" )
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
number = int( tablelookupcolumnforrow( level.statstableid, row, 0 ) );
|
|
if ( self isitemlocked( number ) )
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
allocation = int( tablelookupcolumnforrow( level.statstableid, row, 12 ) );
|
|
if ( allocation < 0 )
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
name = tablelookupcolumnforrow( level.statstableid, row, 3 );
|
|
if ( bot_item_is_banned( slot, name ) )
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
if ( !isDefined( items[ slot ] ) )
|
|
{
|
|
items[ slot ] = [];
|
|
}
|
|
items[ slot ][ items[ slot ].size ] = name;
|
|
}
|
|
i++;
|
|
}
|
|
pixendevent();
|
|
return items;
|
|
}
|
|
|
|
bot_item_is_banned( slot, item ) //checked changed to match cerberus output
|
|
{
|
|
if ( item == "WEAPON_KNIFE_BALLISTIC" )
|
|
{
|
|
return 1;
|
|
}
|
|
if ( /* getDvarInt( #"97A055DA" ) == 0 && */ item == "WEAPON_PEACEKEEPER" )
|
|
{
|
|
return 1;
|
|
}
|
|
if ( slot != "killstreak1" && slot != "killstreak2" && slot != "killstreak3" )
|
|
{
|
|
return 0;
|
|
}
|
|
foreach ( banned in level.bot_banned_killstreaks )
|
|
{
|
|
if ( item == banned )
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bot_build_claimed_list( items ) //checked changed to match cerberus output
|
|
{
|
|
claimed = [];
|
|
keys = getarraykeys( items );
|
|
foreach ( key in keys )
|
|
{
|
|
claimed[ key ] = 0;
|
|
}
|
|
return claimed;
|
|
}
|
|
|