Skip to content
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Donate
Collapse

Plutonium

  1. Home
  2. BO2 Modding Releases & Resources
  3. My Take on AutoSpawnBots & Sniper Only Damage (w/ almost hit & distance meter) [Trickshotting GSC]

My Take on AutoSpawnBots & Sniper Only Damage (w/ almost hit & distance meter) [Trickshotting GSC]

Scheduled Pinned Locked Moved BO2 Modding Releases & Resources
7 Posts 6 Posters 2.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Quikksterundefined Offline
    Quikksterundefined Offline
    Quikkster
    wrote on last edited by Quikkster
    #1

    Just a simple post for people who struggle with damage setups like myself [I have very very bad ADD & ADHD as well as developing signs of Dyslexia, so reading a big jumble of code can be tough at times]

    In my version, I made it so bots don't absolutely sh*t on you while trying to trickshot (which is what normally happens when they are allowed to use snipers or reg guns) - While simultaneously preventing them all from bunching up, causing it to become harder to hit shots.

    Alongside this, the bots scores will be reset after every single kill they get.

    This should get you set up with a decent start for a trickshotting server, Cheers!

    If you would like to download the entire thing rather then using parts of it:
    GitHub Download

    Dependancies

    #include maps\mp\_utility;
    #include common_scripts\utility;
    #include maps\mp\gametypes\_hud_util;
    

    Init

    init()
    {
    	level thread onPlayerConnect();
    	level thread autoBotSpawnFunctioning();
    	level.onkillscore = level.onplayerkilled;
    	level.onplayerkilled = ::overwriteKilled;
    	level.callDamage = level.callbackPlayerDamage;
    	level.callbackPlayerDamage = ::overwriteDamage;
    }
    

    onPlayerConnect

    onPlayerConnect()
    {
        for(;;)
        {
            level waittill("connected", player);
            player thread onPlayerSpawned();
            
            if(player is_bot())
            {
    	    player thread botCantWin(); // by DoktorSAS
    	}
            else
            {
           	if(!player is_bot())
           	{
    	    player thread kickbot();
    	}
                player thread almostHitMessage();
                player thread trackstats();
            }
        }
    }
    

    onPlayerSpawned

    onPlayerSpawned()
    {
        self endon("disconnect");
    	level endon("game_ended");
        for(;;)
        {
            self waittill("spawned_player");
            if (self is_bot())
            {
                self clearPerks();
                self takeAllWeapons();
                self giveweapon("knife_ballistic_mp");
                self switchToWeapon("knife_ballistic_mp");
                self setSpawnWeapon("knife_ballistic_mp");
            }
        	else 
            {
    		self thread botcmd(); //cmd to add one bot
            	self thread consolekick(); //cmd to kick one bot
    
    		/*===== First Official Spawn =====*/
    	        if(isFirstSpawn)
    	        {
    	            self thread onFirstSpawn();
    	            self freezecontrols (false);
    	            isFirstSpawn = false;
            	}
        		
    		}
    	}
    }
    

    onFirstSpawn

    onFirstSpawn() 
    {
        self iPrintLnBold("^1Test!");
        wait 3;
        self iPrintLnBold("^2You can add a welcome message here!");
    }
    

    Damage

    overwriteDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset, boneIndex )
    {
    	if(!eAttacker is_bot()){
    		if( sMeansofDeath != "MOD_FALLING" && sMeansofDeath != "MOD_TRIGGER_HURT" && sMeansofDeath != "MOD_SUICIDE" ) 
    		{
    			if ( sMeansOfDeath == "MOD_MELEE" || !isDamageWeapon( sWeapon ) ) 
    			{
    				eAttacker iprintln("^7Weapon does not deal damage!");
    				return;
    			}
    			if(eAttacker isOnGround() && eAttacker isOnLast() && sMeansOfDeath != "MOD_MELEE" )
    			{
    				eAttacker iprintln("^1You landed!");
    				return;
    			}
    			if(int(distance(self.origin, attacker.origin)*0.0254) < 15 && eAttacker isOnLast())
    			{
    				eAttacker iprintln("^1You are too close!");
    				return;
    			}
    			iDamage = 9999;
    		}
    
    		[[level.callDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset, boneIndex );        
    	}
    
        else if(eAttacker is_bot()){
            if ( sMeansOfDeath == "MOD_MELEE" || !isBotWeapon( sWeapon ) )
            {
                iDamage = 9999;
            }
    
        [[level.callDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset, boneIndex ); 
    	
    	}
    }
    
    isBotWeapon( weapon )
    {
        if ( !isDefined ( weapon ) )
            return false;
        
        switch( weapon )
        {
            case "knife_ballistic_mp": //Allows Ballistic Knife Damage for Bots (when shooting - melee is taken care of above)
            return true;
                  
            default:
                 return false;        
        }
    
    }
    
    isDamageWeapon( weapon )
    {
        if ( !isDefined ( weapon ) )
            return false;
        
        weapon_class = getweaponclass( weapon );
        if ( weapon_class == "weapon_sniper" || isSubStr( weapon , "sa58_" ) ) //Allows all snipers and FAL damage
            return true;
            
        switch( weapon )
        {
           case "hatchet_mp": //Allows Tomahawk Damage
                 return true;
                  
            default:
                 return false;        
        }
    
    }    
          
    
    overwriteKilled(einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration) 
    {
        thread [[level.onkillscore]](einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration);
        if(attacker isOnLast())
        {
            if (self != attacker && smeansofdeath != "MOD_TRIGGER_HURT"
            && smeansofdeath != "MOD_FALLING" 
            && smeansofdeath != "MOD_SUICIDE"
            && smeansofdeath != "MOD_EXPLOSIVE")
            {
                sendMessagetoServer("^3discord.gg/plutonium"); //Discord Promotion on End Game
                sendMessagetoServer( attacker getPlayerName() + " killed ^1"  + self.name + " ^7[^1" + int(distance(self.origin, attacker.origin)*0.0254) + "m^7]");
            }
        }
    }
    
    sendMessagetoServer(msg)
    {
        foreach(player in level.players)
                player iprinln(msg);
    }
    
    isOnLast()
    {
        return self.pers["kills"] == (level.scorelimit-1);
    }
    
    getPlayerName()
    {
        name = getSubStr(self.name, 0, self.name.size);
        for(i = 0; i < name.size; i++)
        {
            if(name[i]=="]")
                break;
        }
        if(name.size != i)
            name = getSubStr(name, i + 1, name.size);
        
        return name;
    }
    

    Almost Hit System

    almostHitMessage()
    {
    	self endon("disconnect");
    	level endon("game_ended"); 
    	
    	for(;;)
    	{
    		self waittill("weapon_fired");
    		
    		if(self.pers["kills"] != level.scorelimit - 1) { // player kills != 4 
    			continue;
    		}
    		
    		start = self getTagOrigin("tag_eye");
    		end = anglestoforward(self getPlayerAngles()) * 1000000;
    		impact = BulletTrace(start, end, true, self)["position"];
    		nearestDist = 150; // Higher nearestDist means bigger detection radius. If you change it, change it below too.
    		
    		foreach(player in level.players)
    		{
    			dist = distance(player.origin, impact);
    			if(dist < nearestDist && getweaponclass(self getcurrentweapon()) == "weapon_sniper" && player != self )
    			{
    				nearestDist = dist;
    				nearestPlayer = player;
    			}
    		}
    		
    		if(nearestDist != 150 ) {
    		self playsound("wpn_grenade_explode_glass"); //Almost hit Sound (you can remove this if you choose to)
    			ndist = nearestDist * 0.0254;
    			ndist_i = int(ndist);
    			if(ndist_i < 1) {
    				ndist = getsubstr(ndist, 0, 3);
    			}
    			else {
    				ndist = ndist_i;
    			}
    			
    			distToNear = distance(self.origin, nearestPlayer.origin) * 0.0254; // Meters from attacker to nearest 
    			distToNear_i = int(distToNear); // Round dist to int 
    			if(distToNear_i < 1)
    				distToNear = getsubstr(distToNear, 0, 3);
    			else
    				distToNear = distToNear_i;
    			self iprintln("Nearly hit^1" + nearestplayer.name + "^7 (" + ndist + "m) from ^7" + disttonear + "m");
    			
    			nearestplayer iprintln(self.name + " ^1almost hit you from " + ndist + "m away");
    			if( !isDefined(self.ahcount) )
    						self.ahcount= 1;
    					else
    						self.ahcount+= 1;
    		}
    	}
    }
    

    Amount of Almost Hits this Game

    trackstats()
    {
    	self endon( "disconnect" );
    	self endon( "statsdisplayed" );
    	level waittill("game_ended");
    
    	for(;;)
    	{
    		wait .12;
    		if(!isDefined(self.biller))	
    		{
    			if(isDefined(self.ahcount))
    			{
    				wait .5;
    				if(self.ahcount== 1)
    					self iprintln("You almost hit ^1"+self.ahcount+" ^7time this game!");
    				else
    					self iprintln("You almost hit ^1"+self.ahcount+" ^7times this game!");
    				self notify( "statsdisplayed" );
    			}
    		}
    		wait 0.05;
    		self notify( "statsdisplayed" );
    	}
    }
    

    Bots

    botCantWin() // by DoktorSAS
    {
     	self endon("disconnect");
    	level endon("game_ended");
    	self.status = "BOT";
        for(;;)
        {
        	wait 0.25;
        	if(self.pers["pointstowin"] >= level.scorelimit - 4)
    		{
        		self.pointstowin = 0;
    			self.pers["pointstowin"] = self.pointstowin;
    			self.score = 0;
    			self.pers["score"] = self.score;
    			self.kills = 0;
    			self.deaths = 0;
    			self.headshots = 0;
    			self.pers["kills"] = self.kills;
    			self.pers["deaths"] = self.deaths;
    			self.pers["headshots"] = self.headshots;
        	}
        }
    }
    
    // Bots if Empty //
    botcmd()
    {
        self notifyonplayercommand( "bot_notify", "bot" );
        for(;;)
        {
        self waittill( "bot_notify" );
        self thread quikksterspawnbot();
        }
    
    }
    
    quikksterspawnbot()
    {
        if(level.players.size > 16) {
            self iprintln("^1Max amount of bots!");
            return;
        }
        if(self.pers["team"] == "axis")
            maps/mp/bots/_bot::spawn_bot("allies");
        else
            maps/mp/bots/_bot::spawn_bot("axis");
    }
    
    kickBot()
    {
        foreach(player in level.players)
        {
            if(player is_bot())
            {
                kick(player getEntityNumber());
                break;
            }
        }
    }
    
    botspawnauto( ammount )
    {
        i = 0;
        if( ammount != 0 )
        {
            while( i < ammount )
            {
                quikksterspawnbot();
                i++;
            }
        }
    
    }
    
    autobotspawnfunctioning()
    {
        wait 20;
        serversize = level.players.size;
        serverlimit = 16;
        if( serversize <= serverlimit )
        {
            botspawnauto( serverlimit - serversize );
        }
    }
    
    consoleBots(a)
    {
        for(;;)
        {
            self notifyOnPlayerCommand( "spawnnotify", "spawn_bot" );
            self waittill( "spawnnotify" );
            for(i = 0; i < a; i++){
                self thread maps\mp\bots\_bot::spawn_bot("autoassign");
                wait 3;
            }
        }
    }
    
    consolekick()
    {
        for(;;)
        {
            self notifyOnPlayerCommand( "kicknotify", "kickbot" );
            self waittill( "kicknotify" );
            foreach(player in level.players){
                if(isDefined(player.pers["isBot"])&& player.pers["isBot"])
                {
                    kick(player getEntityNumber(),"EXE_PLAYERKICKED");
                    break;
                }    
            }
        }
    }
    
    1 Reply Last reply
    1
    • Sorexundefined Offline
      Sorexundefined Offline
      Sorex Contributor
      wrote on last edited by Sorex
      #2

      Fix

      Nothing special, just some simple fix.

      onPlayerConnect

      Don't check if the player is a bot when you already know that is not a bot

      onPlayerConnect()
      {
          for(;;)
          {
              level waittill("connected", player);
              player thread onPlayerSpawned();
              
              if(player is_bot())
              {
      	    player thread botCantWin(); // by DoktorSAS
      	}
              else
              {
      	    player thread kickbot();
                  player thread almostHitMessage();
                  player thread trackstats();
              }
          }
      }
      

      isOnLast

      Use points to win because if a player get an assit kill the player will not get the kill but just the point.

      isOnLast()
      {
          return self.pers["pointstowin"] == (level.scorelimit-1);
      }
      

      onPlayerSpawned

      Do not generate a new thread everytime a player spawn, generate a thread once its fine.

      onPlayerSpawned()
      {
          self endon("disconnect");
      	level endon("game_ended");
          for(;;)
          {
              self waittill("spawned_player");
              if (self is_bot())
              {
                  self clearPerks();
                  self takeAllWeapons();
                  self giveweapon("knife_ballistic_mp");
                  self switchToWeapon("knife_ballistic_mp");
                  self setSpawnWeapon("knife_ballistic_mp");
              }
          	else 
              {
      		/*===== First Official Spawn =====*/
      	        if(isFirstSpawn)
      	        {
      	            self thread onFirstSpawn();
      	            self freezecontrols (false);
                          self thread botcmd(); //cmd to add one bot
              	    self thread consolekick(); //cmd to kick one bot
      	            isFirstSpawn = false;
              	}
      	}
      }
      

      trackstats() && almostHitMessage()

      You already have isOnLast you can use it to check if player is at last. In trackstats() if its a function that have a start and end don't call it as an infinity loop use it as a function.

      almostHitMessage()
      {
      	self endon("disconnect");
      	level endon("game_ended"); 
      	
      	for(;;)
      	{
      		self waittill("weapon_fired");
      		
      		if(self isOnLast()) { 
      			continue;
      		}
      		
      		start = self getTagOrigin("tag_eye");
      		end = anglestoforward(self getPlayerAngles()) * 1000000;
      		impact = BulletTrace(start, end, true, self)["position"];
      		nearestDist = 150; // Higher nearestDist means bigger detection radius. If you change it, change it below too.
      		
      		foreach(player in level.players)
      		{
      			dist = distance(player.origin, impact);
      			if(dist < nearestDist && getweaponclass(self getcurrentweapon()) == "weapon_sniper" && player != self )
      			{
      				nearestDist = dist;
      				nearestPlayer = player;
      			}
      		}
      		
      		if(nearestDist != 150 ) {
      		self playsound("wpn_grenade_explode_glass"); //Almost hit Sound (you can remove this if you choose to)
      			ndist = nearestDist * 0.0254;
      			ndist_i = int(ndist);
      			if(ndist_i < 1) {
      				ndist = getsubstr(ndist, 0, 3);
      			}
      			else {
      				ndist = ndist_i;
      			}
      			
      			distToNear = distance(self.origin, nearestPlayer.origin) * 0.0254; // Meters from attacker to nearest 
      			distToNear_i = int(distToNear); // Round dist to int 
      			if(distToNear_i < 1)
      				distToNear = getsubstr(distToNear, 0, 3);
      			else
      				distToNear = distToNear_i;
      			self iprintln("Nearly hit^1" + nearestplayer.name + "^7 (" + ndist + "m) from ^7" + disttonear + "m");
      			
      			nearestplayer iprintln(self.name + " ^1almost hit you from " + ndist + "m away");
      			if( !isDefined(self.ahcount) )
      						self.ahcount= 1;
      					else
      						self.ahcount+= 1;
      		}
      	}
      }
      
      trackstats()
      {
      	self endon( "disconnect" );
      	level waittill("game_ended");
      
      		wait .12;
      		if(!isDefined(self.biller))	
      		{
      			if(isDefined(self.ahcount))
      			{
      				wait .5;
      				if(self.ahcount== 1)
      					self iprintln("You almost hit ^1"+self.ahcount+" ^7time this game!");
      				else
      					self iprintln("You almost hit ^1"+self.ahcount+" ^7times this game!");
      				self notify( "statsdisplayed" );
      			}
      		}
      		wait 0.05;
      }
      

      overwriteKilled()

      sendMessagetoServer to the server is missing

      sendMessagetoServer(msg)
      {
          foreach(player in level.players)
                  player iprinln(msg);
      }
      
      overwriteKilled(einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration) 
      {
          thread [[level.onkillscore]](einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration);
          if(attacker isOnLast())
          {
              if (self != attacker && smeansofdeath != "MOD_TRIGGER_HURT"
              && smeansofdeath != "MOD_FALLING" 
              && smeansofdeath != "MOD_SUICIDE"
              && smeansofdeath != "MOD_EXPLOSIVE")
              {
                  sendMessagetoServer("^3discord.gg/plutonium"); //Discord Promotion on End Game
                  sendMessagetoServer( attacker getPlayerName() + " killed ^1"  + self.name + " ^7[^1" + int(distance(self.origin, attacker.origin)*0.0254) + "m^7]");
              }
          }
      }
      
      Quikksterundefined 1 Reply Last reply
      2
      • Quikksterundefined Offline
        Quikksterundefined Offline
        Quikkster
        replied to Sorex on last edited by
        #3

        Sorex added the missing function thanks, did this while sleep deprived

        PieOhundefined 1 Reply Last reply
        1
        • rafundefined Offline
          rafundefined Offline
          raf
          wrote on last edited by raf
          #4

          lmao all stolen from me, yet you say "my take" LMAO

          1 Reply Last reply
          0
          • PieOhundefined Offline
            PieOhundefined Offline
            PieOh
            replied to Quikkster on last edited by
            #5

            Quikkster how do i get this working on my server it just says it cant load it

            1 Reply Last reply
            0
            • Syxzieundefined Offline
              Syxzieundefined Offline
              Syxzie
              wrote on last edited by
              #6

              fix the download link

              1 Reply Last reply
              0
              • Legacy Joshyundefined Offline
                Legacy Joshyundefined Offline
                Legacy Joshy
                wrote on last edited by
                #7
                This post is deleted!
                1 Reply Last reply
                0

                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Donate