diff --git a/src/ball.lua b/src/ball.lua index 3077fef..392b5b1 100644 --- a/src/ball.lua +++ b/src/ball.lua @@ -4,12 +4,12 @@ ---@field z number ---@field size number ---@field heldBy Fielder | nil +---@field catchable boolean ---@field xAnimator SimpleAnimator ---@field yAnimator SimpleAnimator ---@field sizeAnimator SimpleAnimator ---@field floatAnimator SimpleAnimator ---@field private animatorLib pd_animator_lib ----@field private flyTimeMs number Ball = {} ---@param animatorLib pd_animator_lib @@ -20,6 +20,7 @@ function Ball.new(animatorLib) x = C.Center.x --[[@as number]], y = C.Center.y --[[@as number]], z = 0, + catchable = true, size = C.SmallestBallRadius, heldBy = nil --[[@type Runner | nil]], @@ -49,6 +50,13 @@ function Ball:updatePosition() end end +function Ball:markUncatchable() + self.catchable = false + playdate.timer.new(200, function() + self.catchable = true + end) +end + --- Launches the ball from its current position to the given destination. ---@param destX number ---@param destY number @@ -60,12 +68,13 @@ function Ball:launch(destX, destY, easingFunc, flyTimeMs, floaty, customBallScal throwMeter:reset() self.heldBy = nil + -- Prevent silly insta-catches + self:markUncatchable() + if not flyTimeMs then flyTimeMs = utils.distanceBetween(self.x, self.y, destX, destY) * C.DefaultLaunchPower end - self.flyTimeMs = flyTimeMs - if customBallScaler then self.sizeAnimator = customBallScaler else diff --git a/src/fielding.lua b/src/fielding.lua index a4b874e..3721d57 100644 --- a/src/fielding.lua +++ b/src/fielding.lua @@ -1,5 +1,4 @@ --- @class Fielder { ---- @field catchEligible boolean --- @field x number --- @field y number --- @field target XyPair | nil @@ -21,7 +20,6 @@ local function newFielder(name, speed) return { name = name, speed = speed * C.FielderRunMult, - catchEligible = true, } end @@ -77,9 +75,9 @@ end ---@param deltaSeconds number ---@param fielder Fielder ----@param ballPos XyPair ----@return boolean inCatchingRange -local function updateFielderPosition(deltaSeconds, fielder, ballPos) +---@param ball Ball +---@return boolean canCatch +local function updateFielderPosition(deltaSeconds, fielder, ball) if fielder.target ~= nil then if utils.pointIsSquarelyAboveLine(fielder, C.BottomOfOutfieldWall) @@ -89,7 +87,7 @@ local function updateFielderPosition(deltaSeconds, fielder, ballPos) end end - return utils.distanceBetweenPoints(fielder, ballPos) < C.BallCatchHitbox + return ball.catchable and utils.distanceBetweenPoints(fielder, ball) < C.BallCatchHitbox end -- TODO: Prevent multiple fielders covering the same base. @@ -115,16 +113,16 @@ function Fielding:haveSomeoneChase(ballDestX, ballDestY) end end ---- # Also updates `ball.heldby` +--- **Also updates `ball.heldby`** ---@param ball Ball ---@param deltaSeconds number ---@return Fielder | nil fielderHoldingBall nil if no fielder is currently touching the ball function Fielding:updateFielderPositions(ball, deltaSeconds) local fielderHoldingBall for _, fielder in pairs(self.fielders) do - local inCatchingRange = updateFielderPosition(deltaSeconds, fielder, ball) - if inCatchingRange and fielder.catchEligible then - -- TODO: Base this catch on fielder skill? + -- TODO: Base this catch on fielder skill? + local canCatch = updateFielderPosition(deltaSeconds, fielder, ball) + if canCatch then fielderHoldingBall = fielder ball.heldBy = fielder -- How much havoc will this wreak? end @@ -136,29 +134,6 @@ function Fielding:updateFielderPositions(ball, deltaSeconds) return fielderHoldingBall end ----@param fielder Fielder -function Fielding.markIneligible(fielder) - fielder.catchEligible = false - playdate.timer.new(500, function() - fielder.catchEligible = true - end) -end - -function Fielding:markAllEligible(eligible) - for _, fielder in pairs(self.fielders) do - fielder.catchEligible = eligible - end -end - -function Fielding:resetEligibility() - self:markAllEligible(false) - playdate.timer.new(750, function() - for _, fielder in pairs(self.fielders) do - fielder.catchEligible = true - end - end) -end - -- TODO? Start moving target fielders close sooner? ---@param field Fielding ---@param targetBase Base @@ -175,7 +150,6 @@ local function userThrowToCoroutine(field, targetBase, ball, throwFlyMs) closestFielder.target = targetBase ball:launch(targetBase.x, targetBase.y, playdate.easingFunctions.linear, throwFlyMs) - Fielding.markIneligible(field.fielderHoldingBall) return end diff --git a/src/main.lua b/src/main.lua index a4f58c7..dbfa2d1 100644 --- a/src/main.lua +++ b/src/main.lua @@ -197,7 +197,7 @@ end ---@param pitchFlyTimeMs number | nil ---@param pitchTypeIndex number | nil function Game:pitch(pitchFlyTimeMs, pitchTypeIndex) - Fielding.markIneligible(self.fielding.fielders.pitcher) + self.state.ball:markUncatchable() self.state.ball.heldBy = nil self.state.pitchIsOver = false self.state.offenseState = C.Offense.batting @@ -445,8 +445,6 @@ function Game:returnToPitcher() if not self.baserunning.batter then self.baserunning:pushNewBatter() end - self.fielding:resetEligibility() - self.fielding.fielders.pitcher.catchEligible = true self.state.ball:launch(C.PitchStart.x, C.PitchStart.y, playdate.easingFunctions.linear, nil, true) end) end @@ -572,7 +570,6 @@ function Game:updateGameState() while not self:pitcherIsReady() do coroutine.yield() end - self.fielding:markAllEligible(true) self.state.offenseState = C.Offense.batting end) end diff --git a/src/npc.lua b/src/npc.lua index b211035..6c657c3 100644 --- a/src/npc.lua +++ b/src/npc.lua @@ -124,15 +124,12 @@ end local function tryToMakeAPlay(fielders, fielder, runners, ball) local targetX, targetY = getNextOutTarget(runners) if targetX ~= nil and targetY ~= nil then - local nearestFielder = utils.getNearestOf(fielders, targetX, targetY, function(grabCandidate) - return grabCandidate.catchEligible - end) + local nearestFielder = utils.getNearestOf(fielders, targetX, targetY) nearestFielder.target = utils.xy(targetX, targetY) if nearestFielder == fielder then ball.heldBy = fielder else ball:launch(targetX, targetY, playdate.easingFunctions.linear, nil, true) - Fielding.markIneligible(nearestFielder) end end end