Tape to Tape Wiki All games ☕ Tip on Ko-fi

Passing, Puck Control and Faceoffs#

Passing (power, saucer/lob passes, interception), pokechecks, possession and loose pucks, rebounds, faceoffs and the assist rule.


1. Passing#

1.1 Pass types#

Events.PassType: Normal (0), Yoyo (1), Megalob (2), Uninterceptable (3).

In-game glossary: Pass: "Send the puck to a teammate. The last two passers before a goal are credited with assists." Saucer pass: "A pass lofted through the air, over sticks. Hold the pass button to perform one."

1.2 Pass power#

If no explicit power is given, Forward::Pass uses Skater::GetPassPower():

power = 29                                   (39 under an unidentified condition, possibly goalie/AI) (inferred)
      + ExpressDelivery relic                 (+5 at Lv1, +5+5 = +10 at Lv2)   "Increase the speed of your passes"
power = power × (1 + T/100)                   T = int % from an unidentified talent (field 0xC0) (inferred)

SkaterAbility::Pass then applies:

Condition Effect
Lobbed / saucer pass (not Yoyo/Megalob) power × 0.85
Lobbed pass while the team owns a particular relic (not Yoyo) power × 0.80 instead of 0.85 (relic not identified)
Normal pass and the passer has the QuickPasses talent power × QuickPasses.multiplier, and the pass becomes Uninterceptable
Passer is in their defensive zone and the team owns the zone relic pass becomes Uninterceptable (matches Invisible Thread: "Your passes are uninterceptable in your zone") (relic id inferred)

Requirements to pass (Forward::Pass): the skater must have the puck, _canPass must be true, and the game state must not be state 3 (a stoppage state). The receiver and lead point come from CalculatePass / EstimatePassExecutionTarget, which lead the receiver along their skating path (PassTargetMinConservatism = 0.88, StandardFrictionDecel = 0.625). Passes are kept out of your own net (AvoidOwnNetOnPass) and clamped for offside (ClampPassTargetForOffside). For CPU receivers, SkatingConfiguration predicts a stop zone in front of the opposing goalie (passReceiverGoalieRadius 2.5, passReceiverGoalLineHalfWidth 2.5, passReceiverMaxBrakeDeceleration 8).

Source: Skaters.Forward::Pass, Skaters.Skater::GetPassPower, Skaters.SkaterAbility::Pass, ::CalculatePass, Movements.SkatingConfiguration.

1.3 Interceptions#

Glossary: "Receiving an opponent's pass."

  • Each fixed update, a skater intercepts a moving puck when their stick-to-puck distance (Forward.currentStickPositionDistance) ≤ InterceptionDistance (Forward::Interception, OnFixedUpdate).
  • Right after a pass, the puck can't be intercepted for InterceptionImmunityAfterPass seconds (Puck::OnPass). Uninterceptable passes skip interception entirely.
  • Goalies read passes separately (goaliePassInterceptChance, reaction delays).

Values per difficulty (Data.DifficultyLevel). "Player" values apply to skaters on human-controlled teams and "CPU" values to CPU skaters facing a human team (selection rule inferred from DifficultyManager getters):

Difficulty Interception dist. Player / CPU Intercept immunity after pass Player / CPU (s) Goalie pass-intercept chance
training 0.15 / 0.85 0.50 / 0.06 0.10
pro 0.50 / 0.75 0.35 / 0.08 0.45
veteran 0.27 / 0.50 0.16 / 0.16 0.25
nightmare 0.27 / 0.50 0.16 / 0.16 0.65

1.4 Drop puck / flip#

Glossary: "Leave the puck on the ice, losing possession. Can be used as a drop pass to a trailing teammate. Hold the drop puck button to flip it into the air instead." Implemented by SkaterAbility::DropPuck(direction, duration) (the _DropPuck coroutine) and ThrowPuck(direction, xzForce, yForce) for the flip. MegaLob is a separate power-up pass type.


2. Pokechecks#

Glossary: "A stick jab that knocks the puck away from an opponent. Used automatically when a stick touches the puck."

  • Forward::Pokecheck fires automatically when the puck is possessed by an opponent and CanPokecheckCarrierForPrediction passes. The stick must reach within PokecheckDistance of the puck. Some difficulties also require the contact to hold for pokecheckConsecutiveFrames frames.
  • Possession immunity: a carrier can only be pokechecked when Time.time − timeWithPuck ≥ PokecheckImmunity, i.e. a short grace period after getting the puck. The asset field is named "Distance" but the code compares it against time (Forward::CanBePokeChecked). Carriers with the ImmuneToPokecheck status tag, or with _canBePokechecked false, can't be pokechecked. Referees have 999999 immunity.
  • After a pokecheck, the puck can't be picked up again for pokecheckReceptionCooldownOther 0.7 s (other skaters) / pokecheckReceptionCooldownPuckHolder 0.8 s (the skater who lost it) (SkatingConfiguration) (exact application inferred).
Difficulty Pokecheck dist. Player / CPU Pokecheck immunity Player / CPU (s) Consecutive frames
training 0.15 / 1.00 1.50 / 0.00 8
pro 0.80 / 1.05 1.00 / 0.25 6
veteran 0.55 / 0.55 0.75 / 0.20 3
nightmare 0.45 / 0.35 0.75 / 0.20 1

Immunity selection (verified in DifficultyManager::GetPokecheckImmunity): if the carrier's team has human players → Player value. Otherwise, if the opponent has humans → CPU value. Otherwise → Player value.

Goalie pokechecks (Goaltender.GoaltenderStates.PokecheckState) use goaliePokecheckDistanceMin/Max 0.5–1.75 and goaliePokecheckForceMin/Max 0.4–0.7. The multiplier is 0.5 on training and 1.0 elsewhere.

Source: Skaters.Forward::Pokecheck, ::CanBePokeChecked, DifficultyManager::GetPokecheckImmunity/GetPokecheckDistance/GetInterceptionDistance, Data.DifficultyLevel assets.


3. Possession and loose pucks#

  • Glossary: "A puck no one controls. The first skater to reach it takes possession."
  • Pickup is handled in Forward::PickupPuck. It checks Puck::IsPossessed, game state, current pass info, and line of sight (HasObstacleBetweenSkaterAndPuck). It tracks the closest stick-to-puck approach over frames. Pucks moving at ≥ 35 speed use a frame-sampled closest-approach test, and slower pucks are picked up directly (inferred). A miss can still nudge a loose puck (TryPushLoosePuckWithSwing).
  • Losing the puck: Skater::LosePuckPossession(force, puckPosition, pickupLockDuration) stops the skater from re-picking it for pickupLockDuration. Puck::DisableCollision(skater, time = 0.4, …) disables puck collision for a skater (default 0.4 s) after shots and passes.
  • Forward._timeWithPuck records when possession started. It drives pokecheck immunity and the first-touch shot window (0.15 s, see shooting.md).

4. Rebounds#

  • Glossary: "A puck the goalie stopped but couldn't hold, left loose in front of the net." "Some saves keep the puck; others leave a rebound."
  • Scripted rebound speed caps (Tape2Tape.Puck constants):
Contact Max XZ speed Max Y speed
Blocker 18 8.5
Glove 10 8
Body 7 7.5
Skater (shot block) 32 8
  • Hard blue-line shots (shot speed 50–65 from the point, ShotQualityCalculator) add up to +0.1 rebound chance and +2 rebound threshold.
  • Crease Grease (FastRebound) gives +20% crit chance to shots taken within 2 s of a teammate's shot (see critical-shots.md).

5. Faceoffs#

Glossary: "Press the pass button just as the referee drops the puck on the ice to win the faceoff."

5.1 Resolution (FaceoffWithReferee::StandardFaceoffUpdate)#

  • Each frame, after the puck is live (isPuckLive; a 15 s total-time fallback also enables the check), the game reads each center's swipe-animation time (FaceoffState::GetTimeInAnim). This is the time since that center pressed (StickOnIce), or 500 if they haven't pressed.
  • The faceoff resolves on the first frame where either center's swipe time is in [0, 0.06) s.
  • Winner: the center with the smaller swipe time. If only one center pressed, that center wins, since the other reads 500. If both pressed inside the 0.06 s window, the later presser wins (literal reading of the compare; edge case). The winner passes via FaceoffWithReferee::Pass (Puck::ReleaseFromFaceoff, then Forward::Pass).
  • Pressing before the puck is live does nothing, because StickOnIce only works once _canPass is set.

5.2 CPU timing#

Context CPU press delay
Normal games Countdown timer. On expiry the CPU presses and resets to Random.Range(0.15, 1.0) s
Campaign, pre-drop delay (act 1 / 2 / 3) Random(0.2, 0.65) / Random(0.35, 0.95) / Random(0.5, 1.2) s (branches: act == 1, act == 2, else)
Campaign, drop reaction (act 1 / 2 / 3) Random(0.16, 0.30) / Random(0.09, 0.20) / Random(0.045, 0.13) s
Campaign, retry delay (act 1 / 2 / 3) Random(0.12, 0.25) / Random(0.08, 0.18) / Random(0.05, 0.12) s

CPU centers react faster after the drop in later campaign acts, but wait longer before attempting.

5.3 Faceoff spots (Arena.FaceoffPreset)#

Each preset stores the puck position, the positions of all 10 skaters (C/LW/RW/LD/RD for North and South), two referee spots and a FaceoffZone.

Preset Puck (x, z) Zone
center_faceoff (0, 0) CENTER
north_left_faceoff (−7.22, 20.93) TOP_LEFT
north_right_faceoff (7.01, 20.93) TOP_RIGHT
south_left_faceoff (−7.22, −21.64) BOTTOM_LEFT
south_right_faceoff (7.01, −21.64) BOTTOM_RIGHT
shootout_faceoff (0, 1.5) CENTER

There are also scenario/tutorial presets (scenario1–9, practice_spot, onboard_spot, last_pass_scenario, national_anthem). After a stoppage, a preset is chosen by a per-preset score (<OnAfterStoppage>b__35_0), most likely nearest to the stoppage point (inferred). Other faceoff types: RiggedFaceoff, corner faceoffs (StartCornerFaceoff) and power-ups such as BananaFaceoff and FrogOnFaceoff.


6. Assists#

  • Glossary: "The last two skaters on your team to touch the puck before the goal scorer are awarded an assist."
  • Code: State.LastTouches keeps an ordered list of touches (TouchSkater { skater, touchType }). Touches include pickups, tip/headshot/body deflections, goalie pickups and faceoff launches. GetAssists() returns list entries [1] and [2]: entry [0] is the scorer, and up to two previous touchers get assists. The list is filtered by team and de-duplicated on pickup (OnPickup, OnReset) (exact filter inferred).
  • Goalies are recorded as touchers (OnPickupGoalie), so a goalie can earn an assist.

Source: State.LastTouches::GetAssists, ::OnPickup, State.TouchType, GameStats.lastAssists.