1 #using scripts\shared\array_shared;
2 #using scripts\shared\rank_shared;
4 #insert scripts\shared\shared.gsh;
5 #insert scripts\shared\statstable_shared.gsh;
7 #using scripts\mp\killstreaks\_killstreaks;
9 #using scripts\mp\bots\_bot;
11 #define BOT_ALLOCATION_MAX 10
12 #define BOT_ALLOCATION_UNLOCK_MAX 3
13 #define BOT_RANK_ALL_OPTIONS_AVAILABLE 20
14 #define BOT_RANK_OPTIONS_MULTIPLIER 4
16 #namespace bot_loadout;
23 if ( !isdefined( itemName ) )
29 case "WEAPON_KNIFE_LOADOUT":
31 case "WEAPON_PISTOL_STANDARD":
32 case "WEAPON_PISTOL_BURST":
33 case "WEAPON_PISTOL_FULLAUTO":
35 case "WEAPON_LAUNCHER_STANDARD":
36 case "WEAPON_LAUNCHER_LOCKONLY":
38 case "WEAPON_SMG_STANDARD":
39 case "WEAPON_SMG_BURST":
40 case "WEAPON_SMG_FASTFIRE":
41 case "WEAPON_SMG_LONGRANGE":
42 case "WEAPON_SMG_VERSATILE":
43 case "WEAPON_SMG_CAPACITY":
46 case "WEAPON_AR_STANDARD":
47 case "WEAPON_AR_ACCURATE":
49 case "WEAPON_AR_DAMAGE":
50 case "WEAPON_AR_FASTBURST":
51 case "WEAPON_AR_LONGBURST":
52 case "WEAPON_AR_MARKSMAN":
54 case "WEAPON_LMG_CQB":
55 case "WEAPON_LMG_HEAVY":
56 case "WEAPON_LMG_LIGHT":
57 case "WEAPON_LMG_SLOWFIRE":
59 case "WEAPON_SNIPER_FASTBOLT":
60 case "WEAPON_SNIPER_FASTSEMI":
61 case "WEAPON_SNIPER_POWERBOLT":
62 case "WEAPON_SNIPER_CHARGESHOT":
64 case "WEAPON_SHOTGUN_FULLAUTO":
65 case "WEAPON_SHOTGUN_PRECISION":
66 case "WEAPON_SHOTGUN_PUMP":
67 case "WEAPON_SHOTGUN_SEMIAUTO":
70 case "WEAPON_FRAGGRENADE":
71 case "WEAPON_HATCHET":
72 case "WEAPON_STICKY_GRENADE":
74 case "WEAPON_BOUNCINGBETTY":
75 case "WEAPON_INCENDIARY_GRENADE":
78 case "WEAPON_WILLY_PETE":
79 case "WEAPON_STUN_GRENADE":
80 case "WEAPON_EMPGRENADE":
81 case "WEAPON_FLASHBANG":
82 case "WEAPON_PROXIMITY_GRENADE":
88 case "KILLSTREAK_RECON":
89 case "KILLSTREAK_COUNTER_UAV":
97 case "KILLSTREAK_SATELLITE":
100 case "KILLSTREAK_RAPS":
103 case "KILLSTREAK_SENTINEL":
131 if (
IS_TRUE( level.perksEnabled ) )
138 foreach( className, classValue
in level.classMap )
140 if ( !isSubstr( className,
"custom" ) )
145 classIndex = int( className[className.size-1] );
151 if ( RandomInt( 100 ) < 95 )
157 otherItems = Array ( lethals, tacticals, specialties1, specialties2, specialties3 );
158 otherItems = array::randomize( otherItems );
160 for ( i = 0; i < otherItems.size; i ++ )
166 for ( i = 0; i <
pickedItems.size && i < level.maxAllocation; i++ )
194 if ( !isdefined( items ) || items.size <= 0 )
204 self.loadoutClasses = [];
205 self.launcherClassCount = 0;
207 foreach( className, classValue
in level.classMap )
209 if ( isSubstr( className,
"custom" ) )
211 if ( level.disableCAC )
216 classIndex = int( className[className.size-1] );
222 classIndex = level.classToClassNum[ classValue ];
225 primary =
self GetLoadoutWeapon( classIndex,
"primary" );
226 secondary =
self GetLoadoutWeapon( classIndex,
"secondary" );
228 botClass = SpawnStruct();
229 botClass.name = className;
230 botClass.index = classIndex;
231 botClass.value = classValue;
232 botClass.primary = primary;
233 botClass.secondary = secondary;
235 if ( botClass.secondary.isRocketLauncher )
237 self.launcherClassCount++;
240 self.loadoutClasses[
self.loadoutClasses.size ] = botClass;
246 currValue =
self.pers[
"class"];
247 if ( !isdefined( currValue ) )
252 foreach( botClass
in self.loadoutClasses )
254 if ( botClass.value == currValue )
276 heroWeaponRef =
self GetHeroWeaponName();
278 if ( IsItemRestricted( heroWeaponRef ) )
284 self BotClassAddItem( 0, heroWeaponName );
291 heroAbilityRef =
self GetHeroAbilityName();
293 if ( IsItemRestricted( heroAbilityRef ) )
299 self BotClassAddItem( 0, heroAbilityName );
311 for( i = 0; i < 3 && i < killstreaks.size; i++ )
313 self BotClassAddItem( 0, killstreaks[i] );
344 if ( allocation < 0 )
351 if ( IsItemRestricted( ref ) )
358 if ( !SessionModeIsPrivate() &&
self IsItemLocked( number ) )
363 if ( isdefined( filterGroup ) )
367 if ( group != filterGroup )
373 if ( isdefined( filterSlot ) )
377 if ( slot != filterSlot )
383 items[items.size] =
name;
402 if ( reference != itemReference )
419 level endon(
"game_ended" );
421 level.bot_banned_killstreaks = Array (
"KILLSTREAK_RCBOMB",
422 "KILLSTREAK_QRDRONE",
423 "KILLSTREAK_REMOTE_MISSILE",
424 "KILLSTREAK_REMOTE_MORTAR",
425 "KILLSTREAK_HELICOPTER_GUNNER" );
428 level waittill(
"connected", player );
430 if ( !player IsTestClient() )
441 self endon(
"disconnect" );
443 if ( isdefined(
self.pers[
"bot_loadout" ] ) )
450 if (
self GetEntityNumber() % 2 == 0 )
457 self BotSetRandomCharacterCustomization();
459 if ( level.onlineGame && !SessionModeIsPrivate() )
461 self BotSetDefaultClass( 5,
"class_assault" );
462 self BotSetDefaultClass( 6,
"class_smg" );
463 self BotSetDefaultClass( 7,
"class_lmg" );
464 self BotSetDefaultClass( 8,
"class_cqb" );
465 self BotSetDefaultClass( 9,
"class_sniper" );
469 self BotSetDefaultClass( 5,
"class_assault" );
470 self BotSetDefaultClass( 6,
"class_smg" );
471 self BotSetDefaultClass( 7,
"class_lmg" );
472 self BotSetDefaultClass( 8,
"class_cqb" );
473 self BotSetDefaultClass( 9,
"class_sniper" );
478 if ( !SessionModeIsPrivate() )
482 if (
self IsItemLocked( rank::GetItemIndex(
"feature_allocation_slot_" + i ) ) )
490 self.pers[
"bot_loadout" ] =
true;
495 if ( !SessionModeIsPrivate() &&
self IsItemLocked( rank::GetItemIndex(
"feature_cac" ) ) )
501 pixbeginevent(
"bot_construct_loadout" );
514 killstreaks = item_list[
"killstreak1"];
516 if ( isdefined( item_list[
"killstreak2"] ) )
518 killstreaks = ArrayCombine( killstreaks, item_list[
"killstreak2"],
true,
false );
521 if ( isdefined( item_list[
"killstreak3"] ) )
523 killstreaks = ArrayCombine( killstreaks, item_list[
"killstreak3"],
true,
false );
526 if ( isdefined( killstreaks ) && killstreaks.size )
533 self.claimed_items = undefined;
542 self.claimed_items = [];
546 claimed_count[
"primary"]++;
556 return ( claimed < max_claim && RandomInt( 100 ) < chance );
559 function chose_action( action1, chance1, action2, chance2, action3, chance3, action4, chance4 )
561 chance1 = Int( chance1 / 10 );
562 chance2 = Int( chance2 / 10 );
563 chance3 = Int( chance3 / 10 );
564 chance4 = Int( chance4 / 10 );
568 for( i = 0; i < chance1; i++ )
570 actions[ actions.size ] = action1;
573 for( i = 0; i < chance2; i++ )
575 actions[ actions.size ] = action2;
578 for( i = 0; i < chance3; i++ )
580 actions[ actions.size ] = action3;
583 for( i = 0; i < chance4; i++ )
585 actions[ actions.size ] = action4;
588 return array::random( actions );
593 foreach( claim
in self.claimed_items )
606 if ( !isdefined( items ) || !items.size )
611 start = RandomInt( items.size );
613 for( i = 0; i < items.size; i++ )
615 weapon = items[ start ];
622 start = ( start + 1 ) % items.size;
625 self.claimed_items[
self.claimed_items.size ] = weapon;
627 self BotClassAddItem( weaponclass, weapon );
633 level.botWeaponOptionsId[optionType] = [];
634 level.botWeaponOptionsProb[optionType] = [];
636 csv_filename =
"gamedata/weapons/common/attachmentTable.csv";
638 for ( row = 0 ; row < 255 ; row++ )
642 index = level.botWeaponOptionsId[optionType].size;
645 level.botWeaponOptionsProb[optionType][index] = prob;
652 if ( !isdefined( level.botWeaponOptionsId ) )
654 level.botWeaponOptionsId = [];
655 level.botWeaponOptionsProb = [];
662 if ( !level.onlineGame && !level.systemLink )
667 numOptions = level.botWeaponOptionsProb[optionType].size;
668 maxProb = level.botWeaponOptionsProb[optionType][numOptions-1];
672 rnd = RandomInt( Int( maxProb ) );
673 for (i=0 ; i<numOptions ; i++)
675 if ( level.botWeaponOptionsProb[optionType][i] > rnd )
677 self BotClassSetWeaponOption( weaponclass, primary, optionType, level.botWeaponOptionsId[optionType][i] );
685 attachments = weapon.supportedAttachments;
686 remaining = allocation_max - allocation;
688 if ( !attachments.size || !remaining )
693 attachment_action =
chose_action(
"3_attachments", 25,
"2_attachments", 35,
"1_attachments", 35,
"none", 5 );
695 if ( remaining >= 4 && attachment_action ==
"3_attachments" )
697 a1 = array::random( attachments );
698 self BotClassAddAttachment( weaponclass, weapon, a1,
"primaryattachment1" );
701 attachments = GetWeaponAttachments( weapon, a1 );
703 if ( attachments.size )
705 a2 = array::random( attachments );
706 self BotClassAddAttachment( weaponclass, weapon, a2,
"primaryattachment2" );
709 attachments = GetWeaponAttachments( weapon, a1, a2 );
711 if ( attachments.size )
713 a3 = array::random( attachments );
714 self BotClassAddItem( weaponclass,
"BONUSCARD_PRIMARY_GUNFIGHTER" );
715 self BotClassAddAttachment( weaponclass, weapon, a3,
"primaryattachment3" );
722 else if ( remaining >= 2 && attachment_action ==
"2_attachments" )
724 a1 = array::random( attachments );
725 self BotClassAddAttachment( weaponclass, weapon, a1,
"primaryattachment1" );
727 attachments = GetWeaponAttachments( weapon, a1 );
729 if ( attachments.size )
731 a2 = array::random( attachments );
732 self BotClassAddAttachment( weaponclass, weapon, a2,
"primaryattachment2" );
738 else if ( remaining >= 1 && attachment_action ==
"1_attachments" )
740 a = array::random( attachments );
741 self BotClassAddAttachment( weaponclass, weapon,
a,
"primaryattachment1" );
750 attachments = weapon.supportedAttachments ;
751 remaining = allocation_max - allocation;
753 if ( !attachments.size || !remaining )
758 attachment_action =
chose_action(
"2_attachments", 10,
"1_attachments", 40,
"none", 50,
"none", 0 );
760 if ( remaining >= 3 && attachment_action ==
"2_attachments" )
762 a1 = array::random( attachments );
763 self BotClassAddAttachment( weaponclass, weapon, a1,
"secondaryattachment1" );
765 attachments = GetWeaponAttachments( weapon, a1 );
767 if ( attachments.size )
769 a2 = array::random( attachments );
770 self BotClassAddItem( weaponclass,
"BONUSCARD_SECONDARY_GUNFIGHTER" );
771 self BotClassAddAttachment( weaponclass, weapon, a2,
"secondaryattachment2" );
777 else if ( remaining >= 1 && attachment_action ==
"1_attachments" )
779 a = array::random( attachments );
780 self BotClassAddAttachment( weaponclass, weapon,
a,
"secondaryattachment1" );
806 if ( !SessionModeIsPrivate() &&
self IsItemLocked( number ) )
813 if ( allocation < 0 )
825 if ( !isdefined( items[slot] ) )
830 items[ slot ][ items[slot].size ] =
name;
839 if ( item ==
"WEAPON_KNIFE_BALLISTIC" )
844 if ( GetDvarInt(
"tu6_enableDLCWeapons") == 0 && item ==
"WEAPON_PEACEKEEPER" )
849 if ( slot !=
"killstreak1" && slot !=
"killstreak2" && slot !=
"killstreak3" )
854 foreach( banned
in level.bot_banned_killstreaks )
856 if ( item == banned )
868 keys = GetArrayKeys( items );
870 foreach( key
in keys )