Extract almost all NPC fielding logic
This commit is contained in:
parent
80c15161e3
commit
30f2eada72
|
@ -94,7 +94,9 @@ C.ThrowMeterDrainPerSec = 150
|
|||
|
||||
--- Controls how hard the ball can be hit, and
|
||||
--- how fast the ball can be thrown.
|
||||
C.CrankPower = 3
|
||||
C.CrankPower = 10
|
||||
|
||||
C.PitchPower = 0.3
|
||||
|
||||
--- How fast baserunners move after a walk
|
||||
C.WalkedRunnerSpeed = 10
|
||||
|
|
83
src/main.lua
83
src/main.lua
|
@ -85,7 +85,7 @@ local teams <const> = {
|
|||
},
|
||||
}
|
||||
|
||||
local PlayerTeam <const> = teams.home
|
||||
local PlayerTeam <const> = teams.away
|
||||
local battingTeam = teams.away
|
||||
local outs = 0
|
||||
local inning = 1
|
||||
|
@ -206,18 +206,10 @@ local function pitch(pitchFlyTimeMs, pitchTypeIndex)
|
|||
secondsSincePitchAllowed = 0
|
||||
end
|
||||
|
||||
---@param base Base
|
||||
---@return Runner | nil
|
||||
local function getRunnerWithNextBase(base)
|
||||
return utils.first(runners, function(runner)
|
||||
return runner.nextBase == base
|
||||
end)
|
||||
end
|
||||
|
||||
local function updateForcedRunners()
|
||||
local stillForced = true
|
||||
for _, base in ipairs(C.Bases) do
|
||||
local runnerTargetingBase = getRunnerWithNextBase(base)
|
||||
local runnerTargetingBase = utils.getRunnerWithNextBase(runners, base)
|
||||
if runnerTargetingBase then
|
||||
if stillForced then
|
||||
runnerTargetingBase.forcedTo = base
|
||||
|
@ -287,66 +279,6 @@ local function score(runnerIndex)
|
|||
announcer:say("SCORE!")
|
||||
end
|
||||
|
||||
---@return Base[]
|
||||
local function npcGetForcedOutTargets()
|
||||
local targets = {}
|
||||
for _, base in ipairs(C.Bases) do
|
||||
local runnerTargetingBase = getRunnerWithNextBase(base)
|
||||
if runnerTargetingBase then
|
||||
targets[#targets + 1] = base
|
||||
else
|
||||
return targets
|
||||
end
|
||||
end
|
||||
return targets
|
||||
end
|
||||
|
||||
--- Returns the position,distance of the basest closest to the runner furthest from a base
|
||||
---@return Base | nil, number | nil
|
||||
local function getBaseOfStrandedRunner()
|
||||
local farRunnersBase, farDistance
|
||||
for _, runner in pairs(runners) do
|
||||
if runner ~= batter then
|
||||
local nearestBase, distance = utils.getNearestOf(C.Bases, runner.x, runner.y)
|
||||
if farRunnersBase == nil or farDistance < distance then
|
||||
farRunnersBase = nearestBase
|
||||
farDistance = distance
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return farRunnersBase, farDistance
|
||||
end
|
||||
|
||||
--- Returns x,y of the out target
|
||||
---@return number|nil, number|nil
|
||||
local function npcGetNextOutTarget()
|
||||
-- TODO: Handle missed throws, check for fielders at target, etc.
|
||||
local targets = npcGetForcedOutTargets()
|
||||
if #targets ~= 0 then
|
||||
return targets[#targets].x, targets[#targets].y
|
||||
end
|
||||
|
||||
local baseCloseToStrandedRunner = getBaseOfStrandedRunner()
|
||||
if baseCloseToStrandedRunner then
|
||||
return baseCloseToStrandedRunner.x, baseCloseToStrandedRunner.y
|
||||
end
|
||||
end
|
||||
|
||||
---@param fielder Fielder
|
||||
local function npcTryToMakeAnOut(fielder)
|
||||
local targetX, targetY = npcGetNextOutTarget()
|
||||
if targetX ~= nil and targetY ~= nil then
|
||||
local nearestFielder = utils.getNearestOf(Field.fielders, targetX, targetY)
|
||||
nearestFielder.target = utils.xy(targetX, targetY)
|
||||
if nearestFielder == fielder then
|
||||
ball.heldBy = fielder
|
||||
else
|
||||
throwBall(targetX, targetY, playdate.easingFunctions.linear, nil, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function readThrow()
|
||||
if throwMeter > C.ThrowMeterMax then
|
||||
return (C.PitchFlyMs / (throwMeter / C.ThrowMeterMax))
|
||||
|
@ -404,16 +336,17 @@ local function outEligibleRunners(fielder)
|
|||
return didOutRunner
|
||||
end
|
||||
|
||||
local function updateNpcFielder(fielder, outedSomeRunner)
|
||||
local function npcFielderAction(fielder, outedSomeRunner)
|
||||
if offenseMode ~= C.Offense.running then
|
||||
return
|
||||
end
|
||||
if outedSomeRunner then
|
||||
-- Delay a little before the next play
|
||||
playdate.timer.new(750, function()
|
||||
npcTryToMakeAnOut(fielder)
|
||||
npc.tryToMakeAPlay(fielder, runners, ball, throwBall)
|
||||
end)
|
||||
else
|
||||
npcTryToMakeAnOut(fielder)
|
||||
npc.tryToMakeAPlay(fielder, runners, ball, throwBall)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -617,7 +550,7 @@ local function updateGameState()
|
|||
|
||||
if playerOnDefense then
|
||||
throwMeter = math.max(0, throwMeter - (deltaSeconds * C.ThrowMeterDrainPerSec))
|
||||
throwMeter = throwMeter + math.abs(crankLimited)
|
||||
throwMeter = throwMeter + math.abs(crankLimited * C.PitchPower)
|
||||
end
|
||||
|
||||
if offenseMode == C.Offense.batting then
|
||||
|
@ -699,7 +632,7 @@ local function updateGameState()
|
|||
buttonControlledThrow(Field.fielders.pitcher, throwFly)
|
||||
end
|
||||
else
|
||||
updateNpcFielder(fielder, outedSomeRunner)
|
||||
npcFielderAction(fielder, outedSomeRunner)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
64
src/npc.lua
64
src/npc.lua
|
@ -30,6 +30,66 @@ function npc.runningSpeed(runners)
|
|||
return 0
|
||||
end
|
||||
|
||||
if not playdate then
|
||||
return utils
|
||||
---@return Base[]
|
||||
local function getForcedOutTargets(runners)
|
||||
local targets = {}
|
||||
for _, base in ipairs(C.Bases) do
|
||||
local runnerTargetingBase = utils.getRunnerWithNextBase(runners, base)
|
||||
if runnerTargetingBase then
|
||||
targets[#targets + 1] = base
|
||||
else
|
||||
return targets
|
||||
end
|
||||
end
|
||||
return targets
|
||||
end
|
||||
|
||||
--- Returns the position,distance of the basest closest to the runner furthest from a base
|
||||
---@return Base | nil, number | nil
|
||||
local function getBaseOfStrandedRunner(runners)
|
||||
local farRunnersBase, farDistance
|
||||
for _, runner in pairs(runners) do
|
||||
if runner ~= batter then
|
||||
local nearestBase, distance = utils.getNearestOf(C.Bases, runner.x, runner.y)
|
||||
if farRunnersBase == nil or farDistance < distance then
|
||||
farRunnersBase = nearestBase
|
||||
farDistance = distance
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return farRunnersBase, farDistance
|
||||
end
|
||||
|
||||
--- Returns x,y of the out target
|
||||
---@return number|nil, number|nil
|
||||
function npc.getNextOutTarget(runners)
|
||||
-- TODO: Handle missed throws, check for fielders at target, etc.
|
||||
local targets = getForcedOutTargets(runners)
|
||||
if #targets ~= 0 then
|
||||
return targets[#targets].x, targets[#targets].y
|
||||
end
|
||||
|
||||
local baseCloseToStrandedRunner = getBaseOfStrandedRunner(runners)
|
||||
if baseCloseToStrandedRunner then
|
||||
return baseCloseToStrandedRunner.x, baseCloseToStrandedRunner.y
|
||||
end
|
||||
end
|
||||
|
||||
---@param fielder Fielder
|
||||
function npc.tryToMakeAPlay(fielder, runners, ball, throwBall)
|
||||
local targetX, targetY = npc.getNextOutTarget(runners)
|
||||
if targetX ~= nil and targetY ~= nil then
|
||||
local nearestFielder = utils.getNearestOf(Field.fielders, targetX, targetY)
|
||||
nearestFielder.target = utils.xy(targetX, targetY)
|
||||
if nearestFielder == fielder then
|
||||
ball.heldBy = fielder
|
||||
else
|
||||
throwBall(targetX, targetY, playdate.easingFunctions.linear, nil, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not playdate then
|
||||
return npc
|
||||
end
|
||||
|
|
|
@ -142,6 +142,14 @@ function utils.isTouchingBase(x, y)
|
|||
end)
|
||||
end
|
||||
|
||||
---@param base Base
|
||||
---@return Runner | nil runner The runner whose next base matches the given base.
|
||||
function utils.getRunnerWithNextBase(runners, base)
|
||||
return utils.first(runners, function(runner)
|
||||
return runner.nextBase == base
|
||||
end)
|
||||
end
|
||||
|
||||
--- Returns true only if the point is below the given line, within the x bounds of said line, and above the bottomBound
|
||||
--- @return boolean
|
||||
function utils.pointDirectlyUnderLine(pointX, pointY, lineX1, lineY1, lineX2, lineY2, bottomBound)
|
||||
|
|
Loading…
Reference in New Issue