local ____exports = {}
--- - The `EntityPlayer` object stores a player's tear rate in the `MaxFireDelay` field. This is
--   equivalent to how many tears the player can shoot per frame.
-- - If you already have a "tears" stat and you want to convert it back to MaxFireDelay, then use
--   this function.
-- - In this context, the "tears stat" represents what is shown on the in-game stat UI.
function ____exports.getFireDelay(self, tearsStat)
    return math.max(30 / tearsStat - 1, -0.9999)
end
--- - The `EntityPlayer` object stores a player's tear rate in the `MaxFireDelay` field. This is
--   equivalent to how many tears the player can shoot per frame.
-- - If you want to convert this to the "tears" stat that is shown on the in-game stat UI, then use
--   this function.
function ____exports.getTearsStat(self, fireDelay)
    return 30 / (fireDelay + 1)
end
--- - Converts the specified amount of tears stat into the format of `EntityPlayer.MaxFireDelay` and
--   adds it to the player.
-- - This function should only be used inside the `EVALUATE_CACHE` callback.
-- - In this context, the "tears stat" represents what is shown on the in-game stat UI.
-- 
-- For example:
-- 
-- ```ts
-- function evaluateCacheTears(player: EntityPlayer) {
--   const numFoo = player.GetNumCollectible(CollectibleTypeCustom.FOO);
--   const tearsStat = numFoo * FOO_TEARS_STAT;
--   addTearsStat(player, tearsStat);
-- }
-- ```
function ____exports.addTearsStat(self, player, tearsStat)
    local existingTearsStat = ____exports.getTearsStat(nil, player.MaxFireDelay)
    local newTearsStat = existingTearsStat + tearsStat
    local newMaxFireDelay = ____exports.getFireDelay(nil, newTearsStat)
    player.MaxFireDelay = newMaxFireDelay
end
--- Helper function to check if a tear hit an enemy. A tear is considered to be missed if it hit the
-- ground, a wall, or a grid entity.
-- 
-- Note that tears are still considered to be missed if they hit a poop or fire, so you may want to
-- handle those separately using the `POST_GRID_ENTITY_COLLISION` and `POST_ENTITY_COLLISION`
-- callbacks, respectively.
-- 
-- Under the hood, this function uses the `Entity.IsDead` method. (Tears will not die if they hit an
-- enemy, but they will die if they hit a wall or object.)
function ____exports.isMissedTear(self, tear)
    return tear:IsDead()
end
--- Helper function to check if a given tear is from a familiar (as opposed to e.g. a player). This
-- is determined by looking at the parent.
-- 
-- For the special case of Incubus and Blood Babies, the parent of the tear is always the player,
-- but the spawner entity of the tear changes. On frame 0, the spawner entity is equal to the
-- player, and on frame 1, the spawner entity is equal to the familiar. For this reason, you can
-- only use this function in the `POST_TEAR_INIT_VERY_LATE` callback or on frame 1+.
-- 
-- If this function is called on frame 0, it will throw a run-time error.
-- 
-- Note that this function does not work properly when the tear is from a Lead Pencil barrage. In
-- this case, it will always appear as if the tear is coming from a player.
-- 
-- @param tear The tear to inspect.
-- @param familiarVariant Optional. Specify this to check if the tear came from a specific familiar
-- variant. Default is undefined, which checks for any familiar.
-- @param subType Optional. Specify this to check if the tear came from a specific familiar
-- sub-type. Default is undefined, which checks for any familiar.
function ____exports.isTearFromFamiliar(self, tear, familiarVariant, subType)
    if tear.FrameCount == 0 then
        error("Failed to check if the given tear was from a player since the tear's frame count was equal to 0. (The \"isTearFromFamiliar\" function must only be used in the \"POST_TEAR_INIT_VERY_LATE\" callback or on frame 1 and onwards.)")
    end
    if tear.SpawnerEntity == nil then
        return false
    end
    local familiar = tear.SpawnerEntity:ToFamiliar()
    if familiar == nil then
        return false
    end
    return (familiarVariant == nil or familiarVariant == familiar.Variant) and (subType == nil or subType == familiar.SubType)
end
--- Helper function to check if a given tear is from a player (as opposed to e.g. a familiar). This
-- is determined by looking at the `SpawnerEntity`.
-- 
-- For the special case of Incubus and Blood Babies, the `SpawnerEntity` of the tear is always the
-- player, but the spawner entity of the tear changes. On frame 0, the spawner entity is equal to
-- the player, and on frame 1, the spawner entity is equal to the familiar. For this reason, you can
-- only use this function in the `POST_TEAR_INIT_VERY_LATE` callback or on frame 1+.
-- 
-- If this function is called on frame 0, it will throw a run-time error.
-- 
-- Note that this function does not work properly when the tear is from a Lead Pencil barrage. In
-- this case, it will always appear as if the tear is coming from a player.
function ____exports.isTearFromPlayer(self, tear)
    if tear.FrameCount == 0 then
        error("Failed to check if the given tear was from a player since the tear's frame count was equal to 0. (The \"isTearFromPlayer\" function must only be used in the \"POST_TEAR_INIT_VERY_LATE\" callback or on frame 1 and onwards.)")
    end
    if tear.SpawnerEntity == nil then
        return false
    end
    local player = tear.SpawnerEntity:ToPlayer()
    return player ~= nil
end
return ____exports
