Master of skill checks and tapping in Friday the 13th: The Game

I had to speed things up last time due to double XP weekend. Today I will cover more basics. This time we will create a "helper" bot for automating stuff for us while we actively play the game. If this is your first time here, make sure you have familiarized yourself with absolute basics covered in The journey begins. Let's get to it!

How to pass quick time events like a boss

Friday the 13th: The Game is using quick time events (QTE) aka skill checks to introduce additional pressure when completing most of the objectives. Here is how it looks like:

Every time progress bar enters QTE window you have a limited time to press left or right mouse button. QTE window size depends on your character's repair skill (A.J. Mason in above example has repair 7 out of 10). If you fail, Jason will hear distinctive sound notification, which will most likely bring him on your ass. Our goal is to detect which button must be clicked and send proper input.

This is really simple one. Button to press is marked with red color with little to none transparency so we can just check the color of specific pixel on the screen. However we want to make sure that we are actually during skill check, so whenever something red is on the screen we don't spam mouse buttons ^^ Thankfully there is also second mouse button on the screen, which is marked with gray color. That way we can check color of two pixels and send mouse clicks only when one is grey and the other one is red.

What I usually do is I grab a screenshot. Open it in paint.net and probe color and coordinates of desired pixels.

On the code side, we need to implement functions for detecting whenever mouse button must be pressed.

Dim $RED = [ 237, 49, 37 ]
Dim $GRAY = [ 87, 86, 81 ]

;1680x1050 resolution
Dim $LMB_COORDS = [ 824, 494 ]
Dim $RMB_COORDS = [ 854, 494 ]

Func IsPixelColor($coords, $color, $tolerance)
    $c = _ColorGetRGB(PixelGetColor($coords[0], $coords[1]))
    return $c[0] > ($color[0] - $tolerance) and $c[0] < ($color[0] + $tolerance) and _ ;compare R
           $c[1] > ($color[1] - $tolerance) and $c[1] < ($color[1] + $tolerance) and _ ;compare G
           $c[2] > ($color[2] - $tolerance) and $c[2] < ($color[2] + $tolerance) ;compare B
EndFunc

Func IsPixelGray($coords)
    return IsPixelColor($coords, $GRAY, 20)
EndFunc

Func IsPixelRed($coords)
    return IsPixelColor($coords, $RED, 20)
EndFunc

Func IsLMBGray()
    return IsPixelGray($LMB_COORDS)
EndFunc

Func IsLMBRed()
    return IsPixelRed($LMB_COORDS)
EndFunc

Func IsRMBGray()
    return IsPixelGray($RMB_COORDS)
EndFunc

Func IsRMBRed()
    return IsPixelRed($RMB_COORDS)
EndFunc

Due to partial transparency I had to use rather high shade tolerance. Now as we can read the game state, we can proceed to implementing some decision making and inputs handling.

While True
    Sleep(20) ;don't utilize 100% CPU when nothing needs to be done

    ;don't do anything when game window is not the active one
    If WinActive("SummerCamp  - B6363 CL46118") Then
        If IsLMBRed() and IsRMBGray() Then
            Local $pos = MouseGetPos()
            MouseClick("left", $pos[0], $pos[1])
            Sleep(250) ;give game some time to process input
        EndIf

        If IsLMBGray() and IsRMBRed() Then
            Local $pos = MouseGetPos()
            MouseClick("right", $pos[0], $pos[1])
            Sleep(250)
        EndIf
    EndIf
WEnd

This kind of automating scripts I personally call helpers as they are supposed to augment you as a player when actively playing the game.In that case it's a good practice to check whenever game window is active, otherwise you may end up clicking all over the place when you switch to the code editor or other window. Window name can be acquired using AutoIt Window Info tool. I strongly advise to verify this name after each patch as they are adding numbers to it, which look like build number and Perforce changelist number.

Here is script in action for a counselor with repair 1/10

Tapping the EZ way

Personally, I hate tapping checks. Spamming a key takes no skill it's pure endurance test. We can definitely have some advantage, as for an average player it's impossible to press a key 25 times per second. Here is how tapping check looks in Friday the 13th:

The best thing is that HUD is the same for both Jason and counselors, so we can write single function working for all cases. First, we need to detect presence of tapping HUD. Luckily it's bright gray which stands out from most of the environment. I decided to check 2 pixels to minimize chance of false positive test result.

As long as those 2 pixels are gray-ish we need to tap E like crazy motherf%#&r. Here is the code:

Dim $TAP_BAR_LEFT_CORNER_COORDS = [ 737, 943 ]
Dim $TAP_BAR_RIGHT_CORNER_COORDS = [ 941, 943 ]

Func IsTapActive()
    Local $color = [ 196, 190, 204 ]
    return IsPixelColor($TAP_BAR_LEFT_CORNER_COORDS, $color, 5) and _
           IsPixelColor($TAP_BAR_RIGHT_CORNER_COORDS, $color, 5)
EndFunc

Now we just need to add following code to the main loop and we are good to go.

If IsTapActive() Then
    Send("{e down}")
    Sleep(20)
    Send("{e up}")
EndIf

Cheat detection probability

Virtually none. We don't touch game process and whatever dll's we use are not commonly recognized as cheating software by anti-cheat systems. The only option to track us down is to keep statistics of intervals between key presses in tapping check or response time after button has been shown in a skill check. We can circumvent that by adding randomness to Sleep functions.

That would be all for today. Next week we will take a look at Dead by Daylight. Have phun!

Full source code (AutoIt and C#) is available for patrons on https://www.patreon.com/bottersgonnabot