local Game = game;
-- Services
local RunService = Game : GetService( "RunService" );
local Workspace = Game : GetService( "Workspace" );
local Players = Game : GetService( "Players" );
-- Cache
local GetNamecallMethod = getnamecallmethod;
local GetThreadIdentity = getthreadidentity;
local SetThreadIdentity = setthreadidentity;
local GetRawMetatable = getrawmetatable;
local GetConnections = getconnections;
local GetUpValues = getupvalues;
local GetUpValue = getupvalue;
local HookMetaMethod = hookmetamethod;
local SetMetatable = setmetatable;
local TableInsert = table.insert;
local MathRandom = math.random;
local TaskDelay = task.delay;
local DebugInfo = debug.info;
local Vector3Zero = Vector3.zero;
local Vector3New = Vector3.new;
local ToString = tostring;
local SetStack = setstack;
local GetStack = getstack;
local RawGet = rawget;
local Tick = tick;
local Next = next;
local MaxCastRange = 10 ^ 4;
-- Constants
const NonProjectileGeometry = Workspace.NonProjectileGeometry;
const CurrentCamera = Workspace.CurrentCamera;
const Characters = Workspace.Characters;
const LocalPlayer = Players.LocalPlayer;
-- Variables
local Modules, GameTick = { }, 0; do
for Index, Value in GetConnections( LocalPlayer : FindFirstChild( "Challenges", true ).ChildAdded ) do
local Function = Value.Function;
if ( not Function ) then
continue;
end
local TortoiseShell = GetUpValues( Function )[ 2 ];
if ( not TortoiseShell ) then
continue;
end
Modules = GetUpValue( GetRawMetatable( TortoiseShell ).__index, 1 );
end
end
-- Classes
local PlayerObject = { }; do
local SizeMap = { [ "UpperTorso" ] = Vector3New( 1.9, 1, 1.6 ), [ "Head" ] = Vector3New( 1.5, 1.6, 1.5 ) };
local InventoryMap = { [ 2 ] = "Secondary", [ 1 ] = "Primary", [ 0 ] = "Equipped" };
local Teams = Modules.Teams;
function PlayerObject : Initiate( Character, Player )
local ClassObject = SetMetatable( { }, PlayerObject ); do
ClassObject.Character = Character;
ClassObject.Player = Player;
end
return ClassObject;
end
function PlayerObject : GetWeapon( Slot )
local Character = self.Character;
if ( not Character ) then
return;
end
local Backpack = Character : FindFirstChild( "Backpack" );
if ( not Backpack ) then
return;
end
local Name = InventoryMap[ Slot ];
if ( not Name ) then
return;
end
local SlotObject = Backpack : FindFirstChild( Name );
if ( not SlotObject ) then
return;
end
return SlotObject.Value;
end
function PlayerObject : GetHitbox( Name )
local Character = self.Character;
if ( not Character ) then
return;
end
local Hitboxes = Character : FindFirstChild( "Hitbox" );
if ( not Hitboxes ) then
return;
end
for _, Hitbox in Hitboxes : QueryDescendants( "Part" ) do
if ( Hitbox.Size ~= SizeMap[ Name ] ) then
continue;
end
return Hitbox;
end
end
function PlayerObject : __index( Index )
local Character = self.Character;
if ( not Character ) then
return;
end
local ValueObject = Character : FindFirstChild( Index );
if ( ValueObject ) then
return ValueObject.Value;
end
return RawGet( PlayerObject, Index );
end
function PlayerObject : GetPart( Name )
local Character = self.Character;
if ( not Character ) then
return;
end
local Parts = Character : FindFirstChild( "Body" );
if ( not Parts ) then
return;
end
return Parts : FindFirstChild( Name );
end
function PlayerObject : IsProtected( )
local Character = self.Character;
if ( not Character ) then
return;
end
local RootPart = Character : FindFirstChild( "Root" );
if ( not RootPart ) then
return;
end
local ShieldEmitter = RootPart : FindFirstChild( "ShieldEmitter" );
return ( ShieldEmitter and ShieldEmitter.Enabled );
end
function PlayerObject : GetTeam( )
return Teams : GetPlayerTeam( self.Player );
end
PlayerObject.Character = nil;
PlayerObject.Player = nil;
end
-- Utilities
local Entities = { }; do
local Stamp = 0;
function Entities : GetPlayers( )
local Result = self.Players;
if ( ( GameTick - Stamp ) > 3 ) or ( not Next( Result ) ) then
Stamp = GameTick;
for Player, Character in self.Characters do
local Object = Result[ Player ];
if ( Object and Object.Character == Character ) then
continue;
end
Result[ Player ] = PlayerObject : Initiate( Character, Player );
end
self.Players = Result;
end
return Result;
end
Entities.Characters = GetUpValue( Modules.Characters.GetCharacter, 1 );
Entities.Players = { };
end
local Setters = { }; do
function Setters : Stepper( )
GameTick = Tick( ); Entities : GetPlayers( );
end
end
local Client = { }; do
local Input = Modules.Input;
function Client : GetObject( )
return Entities.Players[ LocalPlayer ];
end
function Client : GetOrigin( )
return self.Reticle : GetPosition( );
end
-- Would've made this a local variable, but I need to maintain my code style.
Client.Reticle = Input.Reticle;
end
local Weapon = { }; do
local Projectiles = Modules.Projectiles;
local Items = Modules.Items;
function Weapon : GetConfig( Model )
local ThreadIdentity = GetThreadIdentity( );
local WeaponModel = Model or self : Get( );
SetThreadIdentity( 2 ); -- This part disgusts me.
local Result = Items : GetConfig( WeaponModel );
SetThreadIdentity( ThreadIdentity );
return Result;
end
function Weapon : GetState( Model )
return ( Model or self : Get( ) ) : FindFirstChild( "State" );
end
function Weapon : GenerateID( )
local Counter = GetUpValue( Projectiles.GetID, 1 );
if ( Counter >= 1000 ) then
Counter = 0;
end
-- I do not like 'else' statements, feel free to freak out about this.
if ( Counter < 1000 ) then
Counter += 1;
end
return `{ LocalPlayer.Name }_{ ToString( Counter ) }`;
end
function Weapon : Effects( )
local WeaponModel = self : Get( );
if ( not WeaponModel ) then
return;
end
local Events = WeaponModel : FindFirstChild( "Events" );
if ( not Events ) then
return;
end
local OnEffect = GetConnections( Events.Shoot.Event )[ 1 ];
local Callback = ( OnEffect and OnEffect.Function );
if ( not Callback ) then
return;
end
Callback( );
end
function Weapon : Get( )
local ClientObject = Client : GetObject( );
if ( not ClientObject ) then
return;
end
return ClientObject : GetWeapon( 0 );
end
Weapon.ProjectileData = GetUpValue( Projectiles.InitProjectile, 1 );
Weapon.Projectiles = Projectiles;
end
-- Features
local Ragebot = { }; do
local Params, Stamp = RaycastParams.new( ), 0;
local ProjectileData = Weapon.ProjectileData;
local Network = Modules.Network;
function Ragebot : Shoot( Destination, HitPart, Origin )
local Model = Weapon : Get( );
if ( not Model ) then
return;
end
local State = Weapon : GetState( Model );
if ( not State ) then
return;
end
local FireMode = State : FindFirstChild( "FireMode" );
if ( not FireMode ) then
return;
end
local Config = Weapon : GetConfig( Model );
if ( GameTick - Stamp ) < ( ( 60 / ( Config.FireModes[ Config.FireModeList[ FireMode.Value ] ].FireRate or 1000 ) ) * .5 ) then
return;
end Stamp = GameTick;
local ProjectileConfig = Config.Projectile;
local Direction = ( Destination - Origin );
Direction += Vector3New( 0, ProjectileConfig.GravityCorrection * .001, 0 );
local Distance = Direction.Magnitude;
local Pellets = { }; do
for Index = 1, ProjectileConfig.Amount do
local PelletID = Weapon : GenerateID( );
TableInsert( Pellets, {
Direction.Unit * Distance,
PelletID,
Distance / ProjectileData[ ProjectileConfig.Template ].Speed, -- Time to hit target
} );
end
end
local NetworkFire = Network.Fire; do
NetworkFire( Network, "Item_Paintball", "Shoot", Model, Origin, Pellets );
NetworkFire( Network, "Item_Paintball", "Reload", Model );
end Weapon : Effects( );
for Index, Pellet in Pellets do
local Hitboxes = HitPart.Parent;
if ( not Hitboxes ) then
continue;
end
TaskDelay( Pellet[ 3 ], NetworkFire, Network, "Projectiles", "__Hit", Pellet[ 2 ], Destination, HitPart, Vector3New( MathRandom( ), MathRandom( ), MathRandom( ) ), Hitboxes.Parent, "" );
end
end
function Ragebot : GetTarget( Origin, Strict, Range )
local ClientObject = Client : GetObject( );
if ( not ClientObject ) then
return;
end Params.FilterDescendantsInstances = { NonProjectileGeometry, ClientObject.Character, CurrentCamera };
local Closest, ClosestDistance = nil, Range; do
for _, Player in Entities.Players do
local ClientTeam = ClientObject : GetTeam( );
if ( ( ClientTeam ~= "FFA" ) and ( Player : GetTeam( ) == ClientTeam ) ) or ( Player : IsProtected( ) ) then
continue;
end
local HitPart = Player : GetHitbox( "Head" );
if ( not HitPart ) then
continue;
end
local Direction = ( HitPart.Position - Origin );
local HitCast = Workspace : Raycast( Origin, Direction.Unit * MaxCastRange, Params );
local HitInstance = ( HitCast and HitCast.Instance );
if ( not HitInstance ) or ( not HitInstance : IsDescendantOf( ( Strict and Player.Character ) or Characters ) ) then -- Pass strict for guaranteed hits, but it is not needed.
continue;
end
local Distance = Direction.Magnitude;
if ( Distance <= ClosestDistance ) then
ClosestDistance, Closest = Distance, HitPart;
end
end
end
return Closest;
end
function Ragebot : Stepper( )
local Origin = Client : GetOrigin( );
local HitPart = self : GetTarget( Origin, false, 1000 );
local Destination = ( HitPart and HitPart.Position );
if ( not Destination ) then
return;
end
self : Shoot( Destination, HitPart, Origin );
end
end
-- Hooks
do
local __Namecall = nil; __Namecall = HookMetaMethod( Vector3Zero, "__namecall", function( Self, ... )
local Method = GetNamecallMethod( );
local Stack = GetStack( 3 );
if ( DebugInfo( 3, "l" ) == 955 ) and ( Method == "Lerp" ) and ( #Stack >= 4 ) then
SetStack( 3, 4, Stack[ 4 ] * 5 ); -- To make it a bit clearer as to what we are doing here: Vector3.Lerp is called after the result of GetMovementInput (Which returns the current MovementVector) has been assigned to a variable, we replace that value with the same value but multiplied by 3 via the stack to increase our walkspeed.
end
return __Namecall( Self, ... );
end )
end
-- Main
do
RunService.PreRender : Connect( function( )
Ragebot : Stepper( );
Setters : Stepper( );
end )
end