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

Topic created · 4 Posts · 521 Views
  • 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;
                }    
            }
        }
    }
    
  • 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]");
            }
        }
    }
    
  • @Sorex added the missing function thanks, did this while sleep deprived

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

Log in to reply