diff --git a/src/systems/filter-types.lua b/src/systems/filter-types.lua index 41a5327..3be261b 100644 --- a/src/systems/filter-types.lua +++ b/src/systems/filter-types.lua @@ -3,6 +3,9 @@ -- This file is composed of, essentially, "base types" +local SOME_TABLE = {} + +---@alias AnyComponent any ---@alias BitMask number ---@alias CanBeBounced { flat: XyPair, mult = XyPair } ---@alias CanSpawn { entityToSpawn: Entity } @@ -10,7 +13,10 @@ ---@alias Entity table ---@alias InRelations Entity[] ---@alias InputState { receivedInputThisFrame: boolean, aJustPressed: boolean, bJustPressed: boolean, upJustPressed: boolean, downJustPressed: boolean, leftJustPressed: boolean, rightJustPressed: boolean } +---@alias ReplaceRelation { entityToModify: Entity, replacement: Replacement } +---@alias Replacement { key: string, value: AnyComponent } ---@alias RoundStateAction "end" | "start" +---@alias Selectable { additions: Entity[] | nil, replacements: ReplaceRelation[] | nil, highlighted: boolean, navigateDown: Selectable | nil, navigateUp: Selectable | nil } ---@alias XyPair { x: number, y: number } @@ -19,7 +25,7 @@ T = { number = 0, numberArray = { 1, 2, 3 }, str = "", - marker = {}, + marker = SOME_TABLE, ---@type fun(self) SelfFunction = function() end, --- Actor @@ -29,28 +35,49 @@ T = { mult = XyPair, }, ---@type pd_image - pd_image = {}, + pd_image = SOME_TABLE, ---@type pd_font - pd_font = {}, + pd_font = SOME_TABLE, + + ---@type AnyComponent + AnyComponent = SOME_TABLE, + ---@type BitMask BitMask = 0, + ---@type CanBeBounced - CanBeBounced = {}, + CanBeBounced = SOME_TABLE, + ---@type CanSpawn - CanSpawn = {}, + CanSpawn = SOME_TABLE, + ---@type Collision - Collision = {}, + Collision = SOME_TABLE, + ---@type Entity - Entity = {}, + Entity = SOME_TABLE, + ---@type InRelations - InRelations = {}, + InRelations = SOME_TABLE, + ---@type InputState - InputState = {}, + InputState = SOME_TABLE, + + ---@type ReplaceRelation + ReplaceRelation = SOME_TABLE, + + ---@type Replacement + Replacement = SOME_TABLE, + ---@type RoundStateAction RoundStateAction = "start", + + ---@type Selectable + Selectable = SOME_TABLE, + ---@type XyPair - XyPair = {}, + XyPair = SOME_TABLE, } ---@generic T @@ -60,6 +87,13 @@ function Maybe(t) return { maybe = t } end +---@generic T +---@param t T +---@return T[] +function Arr(t) + return { arrOf = t } +end + TextStyle = { Inverted = "INVERTED", Bordered = "BORDERED", diff --git a/src/systems/filter-types.lua2p b/src/systems/filter-types.lua2p index b729f6a..7d7ebe4 100644 --- a/src/systems/filter-types.lua2p +++ b/src/systems/filter-types.lua2p @@ -12,7 +12,7 @@ function t(name, type, value) elseif type == "string" then value = "" else - value = "{}" + value = "SOME_TABLE" end end types[#types + 1] = { name = name, type = type, value = value } @@ -42,7 +42,7 @@ end function dumpTypeObjects() local ret = "" for _, v in ipairs(types) do - local line = "\n ---@type " .. v.name .. "\n " .. v.name .. " = " .. v.value .. "," + local line = "\n\n ---@type " .. v.name .. "\n " .. v.name .. " = " .. v.value .. "," ret = ret .. line end return ret @@ -51,6 +51,8 @@ end -- This file is composed of, essentially, "base types" +local SOME_TABLE = {} + !!(tMany({ Entity = "table", XyPair = "{ x: number, y: number }", @@ -58,10 +60,15 @@ end BitMask = "number", CanBeBounced = "{ flat: XyPair, mult: XyPair }", RoundStateAction = { '"end" | "start"', '"start"' }, + AnyComponent = "any", CanSpawn = "{ entityToSpawn: Entity }", InRelations = "Entity[]", CanBeBounced = "{ flat: XyPair, mult = XyPair }", InputState = "{ receivedInputThisFrame: boolean, aJustPressed: boolean, bJustPressed: boolean, upJustPressed: boolean, downJustPressed: boolean, leftJustPressed: boolean, rightJustPressed: boolean }", + + Replacement = "{ key: string, value: AnyComponent }", + ReplaceRelation = "{ entityToModify: Entity, replacement: Replacement }", + Selectable = "{ additions: Entity[] | nil, replacements: ReplaceRelation[] | nil, highlighted: boolean, navigateDown: Selectable | nil, navigateUp: Selectable | nil }", })) T = { @@ -69,7 +76,7 @@ T = { number = 0, numberArray = { 1, 2, 3 }, str = "", - marker = {}, + marker = SOME_TABLE, ---@type fun(self) SelfFunction = function() end, --- Actor @@ -79,9 +86,9 @@ T = { mult = XyPair, }, ---@type pd_image - pd_image = {}, + pd_image = SOME_TABLE, ---@type pd_font - pd_font = {}, + pd_font = SOME_TABLE, !!(dumpTypeObjects()) } @@ -92,6 +99,13 @@ function Maybe(t) return { maybe = t } end +---@generic T +---@param t T +---@return T[] +function Arr(t) + return { arrOf = t } +end + TextStyle = { Inverted = "INVERTED", Bordered = "BORDERED", diff --git a/src/systems/menu.lua b/src/systems/menu.lua index 310400d..6108581 100644 --- a/src/systems/menu.lua +++ b/src/systems/menu.lua @@ -1,17 +1,35 @@ ----@alias MenuItem { onSelect: fun(), highlighted: boolean, navigateDown: MenuItem | nil, navigateUp: MenuItem | nil } +---@param relation ReplaceRelation +---@param world World +local function applyReplacementRelation(relation, world) + printTable(relation.entityToModify) + relation.entityToModify[relation.replacement.key] = relation.replacement.value + world:addEntity(relation.entityToModify) + printTable(relation.entityToModify) +end ----@type MenuItem[] -local MenuItems = {} - -menuController = filteredSystem("menuController", { menuItems = MenuItems, inputState = T.InputState }, function(e, _, system) +menuController = filteredSystem("menuController", { menuItems = Arr(T.Selectable), inputState = T.InputState }, function(e, _, system) for _, menuItem in pairs(e.menuItems) do if menuItem.highlighted then if e.inputState.aJustPressed then - menuItem.onSelect(system.world) -- TODO: That's not very ECS of you! + -- Prepare to remove the menu and all menu items + system.world:removeEntity(e) for _, item in pairs(e.menuItems) do system.world:removeEntity(item) end - system.world:removeEntity(e) + + -- TODO: Larger menu that stays open for more purchases before the next round + world:addEntity({ roundAction = "start" }) + + if menuItem.replacements then + for _, v in ipairs(menuItem.replacements) do + applyReplacementRelation(v, system.world) + end + end + if menuItem.additions then + for _, v in ipairs(menuItem.additions) do + system.world:addEntity(v) + end + end end if e.inputState.downJustPressed and menuItem.navigateDown then diff --git a/src/systems/rounds.lua b/src/systems/rounds.lua index 70fd1cc..823f16b 100644 --- a/src/systems/rounds.lua +++ b/src/systems/rounds.lua @@ -102,6 +102,7 @@ roundSystem = filteredSystem("round", { roundAction = T.RoundStateAction, positi system.world:removeEntity(collectable) end + ---@type SpawnerUpgrade[] local availableUpgrades = Utils.getNDifferentValues(getAvailableSpawnerUpgrades(), 3) -- Sorting from shortest to longest sort of makes them look like a bun? table.sort(availableUpgrades, function(a, b) @@ -119,8 +120,9 @@ roundSystem = filteredSystem("round", { roundAction = T.RoundStateAction, positi i = i + 1 local collX, collY = 75, 21 y = y - collY - 15 - 15 + ---@type Selectable local upgradeEntity = { - onSelect = upgrade.apply, + replacements = { upgrade.replace }, drawAsText = { text = upgrade.name, style = TextStyle.Inverted, diff --git a/src/systems/spawner.lua b/src/systems/spawner.lua index 7aa4d37..30c5117 100644 --- a/src/systems/spawner.lua +++ b/src/systems/spawner.lua @@ -101,38 +101,43 @@ function addAllSpawners(world) }) end ----@alias Upgrade { name: string, apply = fun() } +---@alias SpawnerUpgrade { name: string, replace: ReplaceRelation } ----@return Upgrade[] +---@return SpawnerUpgrade[] function getAvailableSpawnerUpgrades() + ---@type SpawnerUpgrade[] local upgrades = {} for _, spawner in pairs(spawnerSystem.entities) do - if spawner.hasUpgradeSpeed then - -- upgrades[#upgrades + 1] = { hasUpgradeSpeed = spawner.hasUpgradeSpeed } - end + -- if spawner.hasUpgradeSpeed then + -- upgrades[#upgrades + 1] = { hasUpgradeSpeed = spawner.hasUpgradeSpeed } + -- end - if spawner.canSpawn.entityToSpawn.score then - local name = "Double " .. spawner.name .. " value" + local entityToSpawn = spawner.canSpawn.entityToSpawn + if entityToSpawn.score then upgrades[#upgrades + 1] = { - name = name, - apply = function(world) - print("Applying " .. name) - spawner.canSpawn.entityToSpawn.score = spawner.canSpawn.entityToSpawn.score * 2 - world:addEntity({ roundAction = "start" }) - end, + name = "Double " .. spawner.name .. " value", + replace = { + entityToModify = entityToSpawn, + replacement = { + key = "score", + value = entityToSpawn.score * 2, + }, + }, } end assert(spawner.odds, "Expected all spawners to have an `odds` field!") - local name = "Double " .. spawner.name .. " frequency" upgrades[#upgrades + 1] = { - name = name, - apply = function(world) - print("Applying " .. name) - spawner.odds = spawner.odds * 2 - world:addEntity({ roundAction = "start" }) - end, + name = "Double " .. spawner.name .. " frequency", + replace = { + entityToModify = entityToSpawn, + replacement = { + key = "odds", + value = entityToSpawn.odds, + } + }, } end + return upgrades end