Hello,
i came up with this topic when i wanted to show xParaDoX how he could write a simple Triggerbot with multiple options to set it up.
The Challenge:
Code a Triggerbot which has the following options to select:
- Triggerbot enabled / disabled
- Autoshoot / Hold a key
- Teamcheck enabled / disabled
- Use WriteProcessMemory / mouse_event
- Burstmode enabled / disabled
- Amount of shots in burst mode
- Time between burst shots
- Triggerdelay
So, when i coded my first Triggerbot, this was quite a challenge for me. I've never done something before, and not with so many options.
So that's the code i came up with:
Code:
void Triggerbot()
{
while (true)
{
if (Enabled)
{
if (Toggled)
{
if (inCross > 0 && inCross <= 64)
{
if (Teamcheck)
{
if (EnemyTeamID != LocalPlayerTeamID)
{
if (UseWPM)
{
if (Burst)
{
TriggerBurstWPM(AmountOfShots, TimeBetweenShots, TriggerDelay);
}
else
{
TriggerShotWPM();
}
}
else
{
if (Burst)
{
TriggerBurstME(AmountOfShots, TimeBetweenShots, TriggerDelay);
}
else
{
TriggerShotME();
}
}
}
}
else
{
if (UseWPM)
{
if (Burst)
{
TriggerBurstWPM(AmountOfShots, TimeBetweenShots, TriggerDelay);
}
else
{
TriggerShotWPM();
}
}
else
{
if (Burst)
{
TriggerBurstME(AmountOfShots, TimeBetweenShots, TriggerDelay);
}
else
{
TriggerShotME();
}
}
}
}
}
else
{
if (GetAsyncKeyState(TriggerKey))
{
if (inCross > 0 && inCross <= 64)
{
if (Teamcheck)
{
if (EnemyTeamID != LocalPlayerTeamID)
{
if (UseWPM)
{
if (Burst)
{
TriggerBurstWPM(AmountOfShots, TimeBetweenShots, TriggerDelay);
}
else
{
TriggerShotWPM();
}
}
else
{
if (Burst)
{
TriggerBurstME(AmountOfShots, TimeBetweenShots, TriggerDelay);
}
else
{
TriggerShotME();
}
}
}
}
else
{
if (UseWPM)
{
TriggerShotWPM();
}
else
{
TriggerShotME();
}
}
}
}
}
}
Sleep(1);
}
}
It was such a huge nested if statement mess, which was hard to maintain. I didn't even include the shoot functions. But it worked.
Sadly, i can't find the post of who told me a better method of doing it, but i believe it was masteraimer who told me on what i should take a look at and thebigben who posted an actual example of this. The thing we are going to use is called
Boolean Algebra,
more specific at a way of implementing the AND logic (
2 Input AND Gate).
Basically, if we take a look at the code posted above, if we fly over it, every if statement leads to the same results. -> Shoot.
Either shoot a burst (WriteProcessMemory or mouse_event) (which is basically just a for loop which executes ShootSingleShot()) or just shoot a single shot.
Now, with the help of the implementation of the AND logic, we can make ONE simple if statement, which has the same effect.
Code:
if ((LocalPlayer::GetCrosshairID() > 0 && LocalPlayer::GetCrosshairID() <= 64) &&
(!Entity::GetDormant(LocalPlayer::GetCrosshairID() - 1) && Entity::GetHealth(LocalPlayer::GetCrosshairID() - 1) > 0) &&
(Toggle || (!Toggle && GetAsyncKeyState(VK_TRIGGERKEY) & 0x8000)) &&
((Teamcheck && (Entity::GetTeam(LocalPlayer::GetCrosshairID() - 1) != LocalPlayer::GetTeam())) || !Teamcheck))
{
if (Burst)
Burst();
else
Shoot();
}
void Shoot()
{
if (!BurstEnabled)
Sleep(TriggerDelay);
if (UseWPM)
Client::SetAttack(5);
else
mouse_event(MOUSEEVENTF_LEFTDOWN, NULL, NULL, NULL, NULL);
Sleep(20);
if (UseWPM)
Client::SetAttack(4);
else
mouse_event(MOUSEEVENTF_LEFTUP, NULL, NULL, NULL, NULL);
}
void Burst()
{
for (int i = 0; i <= BurstShots; i++)
{
Shoot();
Sleep(BurstDelay);
}
}
Even though Sleep is not a good way of solving a delay function, he above code serves it's purpose.
So, before we break down the if statement above, we have to understand that i'll break it down into blocks of conditions, and each block has to be true to execute the shoot functions.
So what we want to see in the end is an if condition which looks like the following:
Code:
if(true &&
true &&
true || true &&
true || true)
So let's break the statement down.
Let's first show each block. I've created blocks using ( and ) in order to make sure that these things get executed before you do anything else. Just like in maths.
Block 1: ((LocalPlayer::GetCrosshairID() > 0 && LocalPlayer::GetCrosshairID() <= 64)
Block 2: (!Entity::GetDormant(LocalPlayer::GetCrosshairID() - 1) && Entity::GetHealth(LocalPlayer::GetCrosshairID() - 1) > 0)
Block 3: (Toggle || (!Toggle && GetAsyncKeyState(VK_TRIGGERKEY) & 0x8000))
Block 4: ((Teamcheck && (Entity::GetTeam(LocalPlayer::GetCrosshairID() - 1) != LocalPlayer::GetTeam())) || !Teamcheck))
I've left out the && at the end of the blocks, since they serve the purpose of telling that every block has to be true in order to execute the code after the if condition.
In order to explain the blocks of code, let's create a scenario.
We have an Enemy in our Crosshair, which has a valid EntityID (between 0 and 64), his dormant state is false and his Health is above 0.
Our Triggerbot Settings are Toggle Disabled, i'm currently pressing the Triggerbot Key, and Teamcheck is enabled.
Keep in mind, what we want to end up with is the following:
Code:
if(true &&
true &&
true || true &&
true || true)
Let's start:
Current output:
Code:
if ((LocalPlayer::GetCrosshairID() > 0 && LocalPlayer::GetCrosshairID() <= 64) &&
(!Entity::GetDormant(LocalPlayer::GetCrosshairID() - 1) && Entity::GetHealth(LocalPlayer::GetCrosshairID() - 1) > 0) &&
(Toggle || (!Toggle && GetAsyncKeyState(VK_TRIGGERKEY) & 0x8000)) &&
((Teamcheck && (Entity::GetTeam(LocalPlayer::GetCrosshairID() - 1) != LocalPlayer::GetTeam())) || !Teamcheck))
In order to make it clear again, let's break it down into blocks again.
Our first block is the following:
Code:
(LocalPlayer::GetCrosshairID() > 0 && LocalPlayer::GetCrosshairID() <= 64)
Since our Entity is valid (between 0 and 64) this statement is true.
Current output:
Code:
if (true &&
(!Entity::GetDormant(LocalPlayer::GetCrosshairID() - 1) && Entity::GetHealth(LocalPlayer::GetCrosshairID() - 1) > 0) &&
(Toggle || (!Toggle && GetAsyncKeyState(VK_TRIGGERKEY) & 0x8000)) &&
((Teamcheck && (Entity::GetTeam(LocalPlayer::GetCrosshairID() - 1) != LocalPlayer::GetTeam())) || !Teamcheck))
Our next block is the following:
Code:
(!Entity::GetDormant(LocalPlayer::GetCrosshairID() - 1) && Entity::GetHealth(LocalPlayer::GetCrosshairID() - 1) > 0)
Since our Entity's dormant state is false and his health is above 0 this statement is also true.
Current output:
Code:
if (true &&
true &&
(Toggle || (!Toggle && GetAsyncKeyState(VK_TRIGGERKEY) & 0x8000)) &&
((Teamcheck && (Entity::GetTeam(LocalPlayer::GetCrosshairID() - 1) != LocalPlayer::GetTeam())) || !Teamcheck))
Our next block is the following:
Code:
(Toggle || (!Toggle && GetAsyncKeyState(VK_TRIGGERKEY) & 0x8000))
In order to get true out of this condition we would have to either set Toggle to true ( (Toggle || Will be ignored since the first condition is already true) ) or set Trigger to false and hold down the Triggerbot Key.
In our scenario, Toggle is set to false and we are holding our Triggerbot Key. Because of the way the || works, either one of the following has to be true in order to get true out of it: ( (false || true) )
Since one of these conditions is true, the block will be true aswell.
Current output:
Code:
if (true &&
true &&
true &&
((Teamcheck && (Entity::GetTeam(LocalPlayer::GetCrosshairID() - 1) != LocalPlayer::GetTeam())) || !Teamcheck))
Our last block is the following:
Code:
((Teamcheck && (Entity::GetTeam(LocalPlayer::GetCrosshairID() - 1) != LocalPlayer::GetTeam())) || !Teamcheck)
The same rules apply to this one. Either one of those conditions (Either Teamcheck is true OR Teamcheck is false and the Entity in our Crosshair is an Enemy) has to be true in order to get true out of this condition.
Since our Entity is an enemy and we have Teamcheck enabled, the whole if statement will look like this:
Code:
if (true &&
true &&
true &&
true)
So now, since all of our options are ruled with one if statement, we can determine if we want to burst or not.
Code:
{
if (Burst)
Burst();
else
Shoot();
}
Now, we can either use WriteProcessMemory or mouse_event, based on what we selected before.
Code:
void Shoot()
{
if (!BurstEnabled)
Sleep(TriggerDelay);
if (UseWPM)
Client::SetAttack(5);
else
mouse_event(MOUSEEVENTF_LEFTDOWN, NULL, NULL, NULL, NULL);
Sleep(20);
if (UseWPM)
Client::SetAttack(4);
else
mouse_event(MOUSEEVENTF_LEFTUP, NULL, NULL, NULL, NULL);
}
or Burst:
Code:
void Burst()
{
for (int i = 0; i <= BurstShots; i++)
{
Shoot();
Sleep(BurstDelay);
}
}
So, this is one example on how we could use such a system in order to get much cleaner and maintainable code.
Thanks for reading!
Please keep in mind that this is not supposed to be a Tutorial on how to code a perfect Triggerbot, infact, Sleep() is a bad method of managing Delays.
The code above is just used as an example to show the initial thought of my Thread.
If you still want to post feedback or suggestions, feel free to do so!
