// This script contains functionality to allow covert op to steal uniforms from corpses. // Usage: // TODO: // The null check is just in case the script is executed multiple times if(ScriptGoals.disguise_goal == null) { // For cleanliness, we're going to store all our functions and variables inside a table, // within the ScriptGoals global table. // The ScriptGoals is a global table created by the bot by default, as a standardized storage location // for goals implemented in script. Script goals should make their own table under the ScriptGoals global table. ScriptGoals.disguise_goal = table(); // The name for this goal ScriptGoals.disguise_goal.Name = "steal_uniform"; // A debug flag for enabling/disabling printed messages. Useful for debugging this goal. ScriptGoals.disguise_goal.Debug = false; // We'll store the goal check delay for the thread function here, just to put most of the // configuration options neatly at the top of the script for readability. ScriptGoals.disguise_goal.ThreadCheckDelay = 2; // This function just holds the functionality to search a corpse table for the closest one. // It returns a gameentity ScriptGoals.disguise_goal.LookForClosestCorpse = function( _bot ) { // Get a table containing all players and corpses. corpseList = table(); //_bot.GetAllType( CAT.PLAYER, CLASS.ANYPLAYER, corpseList ); _bot.GetAllType( CAT.MISC, CLASS.CORPSE, corpseList ); // Some debug messages if( ScriptGoals.disguise_goal.Debug ) { //print("tableCount(corpseList) before health check", tableCount(corpseList)); } botPos = _bot.GetPosition(); nearestCorpse = null; nearestCorpseDist = 10000; // Filter out all players that are alive, or on the other team. foreach ( index and entity in corpseList ) { if( ScriptGoals.disguise_goal.Debug ) { DrawEntityAABB ( entity, COLOR.RED ); } // What's my current health/armor. healthArmorTable = GetEntHealthAndArmor( entity ); // Skip invalid corpses. if( ( healthArmorTable.Health <= 0 ) && !GetEntFlags( entity, ENTFLAG.DISABLED ) && !_bot.IsAllied( entity ) ) { entPos = GetEntPosition( entity ); distSq = (entPos - botPos).LengthSq(); if( nearestCorpse == null || distSq < nearestCorpseDist ) { nearestCorpse = entity; nearestCorpseDist = distSq; } } } // Some debug messages if( ScriptGoals.disguise_goal.Debug ) { print("tableCount(corpseList) after health check", tableCount(corpseList)); } return nearestCorpse; }; // This function should be called when the goal is finished so that it can do cleanup. ScriptGoals.disguise_goal.LookForDisguiseGoalThread = function() { // Check if the bot already has this goal. if(this.WatchForDisguiseThread) { threadKill(this.WatchForDisguiseThread); } this.WatchForDisguiseThread = threadId(); // The loop condition can check the class, so if the bot changes class this script goal will end cleanly. while( this.GetClass() == CLASS.COVERTOPS ) { // Some debug messages if( ScriptGoals.disguise_goal.Debug ) { print("ScriptGoals.disguise_goal"); } // Check if this bot is already disguised. If so, we can skip a big section of this code. botEnt = this.GetGameEntity(); if( !GetEntFlags( botEnt, ENTFLAG.DISGUISED ) && !GetEntFlags( botEnt, ENTFLAG.CARRYINGGOAL ) && !this.HasTarget() ) { // Look for a corpse we can steal a uniform from. nearestCorpse = ScriptGoals.disguise_goal.LookForClosestCorpse( this ); if( nearestCorpse ) { // Some debug messages if( ScriptGoals.disguise_goal.Debug ) { print("Heading to a corpse.", nearestCorpse); } // Set a script goal for this function, so other script goals can not attempt to // take control. this.scriptgoal = ScriptGoals.disguise_goal.Name; // Go to the goal. corpsePosition = GetEntPosition( nearestCorpse ); this.SetScriptControlled( true ); this.GoTo( corpsePosition, Vector3(0,0,0) ); if( block(EVENT.GOAL_SUCCESS, EVENT.GOAL_FAILED) == EVENT.GOAL_SUCCESS ) { // Some debug messages if( ScriptGoals.disguise_goal.Debug ) { print("Attempting to steal uniform.", nearestCorpse); } // Take control of the weapons now. this.SetScriptControlledWeapons( true ); // Keep doing this until we're disguised while ( !GetEntFlags( botEnt, ENTFLAG.DISGUISED ) && !GetEntFlags( botEnt, ENTFLAG.CARRYINGGOAL ) && !this.HasTarget() ) { if( ScriptGoals.disguise_goal.Debug ) { DrawEntityAABB ( nearestCorpse, COLOR.RED ); } this.MoveTowards( corpsePosition ); this.TurnToPosition( corpsePosition ); this.PressButton( BTN.USE ); yield(); } if( GetEntFlags( botEnt, ENTFLAG.DISGUISED) ) { // Some debug messages if( ScriptGoals.disguise_goal.Debug ) { print("Stole uniform."); } } } // Null the script goal, so other script goals can possibly use this bot. this.scriptgoal = null; this.SetScriptControlledWeapons( false ); this.SetScriptControlled( false ); } } else { // We are disguised, so do whatever. } sleep( ScriptGoals.disguise_goal.ThreadCheckDelay ); } // Clear the goal on the way out. if( this.scriptgoal == ScriptGoals.disguise_goal.Name ) { this.scriptgoal = null; } }; }