From 9f71874272864c4383bd6efe4da32cd9347117f6 Mon Sep 17 00:00:00 2001 From: Sage Vaillancourt Date: Sat, 8 Mar 2025 12:54:25 -0500 Subject: [PATCH] Replace collectableDrop and afterDelayAdd systems with collision-chaining. Waits for one entity to collide to enable collision on the next entity in the chain. --- lib/tiny-debug.lua | 4 +- src/cart.lua | 15 +- src/main.lua | 45 ++++- src/systems/camera-pan.lua | 1 - src/systems/collision-detection.lua | 10 +- src/systems/collision-resolution.lua | 10 + src/systems/draw.lua | 26 ++- src/systems/gravity.lua | 4 +- src/systems/input.lua | 3 +- src/systems/menu.lua | 78 ++++---- src/systems/move-toward.lua | 40 ++-- src/systems/rounds.lua | 261 ++++++++++++--------------- src/systems/spawner.lua | 1 - src/systems/upgrade-utils.lua | 14 +- 14 files changed, 286 insertions(+), 226 deletions(-) diff --git a/lib/tiny-debug.lua b/lib/tiny-debug.lua index 0e9688e..066f6ec 100644 --- a/lib/tiny-debug.lua +++ b/lib/tiny-debug.lua @@ -3,7 +3,7 @@ if not playdate.isSimulator then end getCurrentTimeMilliseconds = playdate.getCurrentTimeMilliseconds -tinyTrackEntityAges = true +tinyTrackEntityAges = false ENTITY_INIT_MS = { "ENTITY_INIT_MS" } if tinyTrackEntityAges then @@ -12,7 +12,7 @@ if tinyTrackEntityAges then end end -tinyLogSystemUpdateTime = false +tinyLogSystemUpdateTime = true tinyLogSystemChanges = false tinyWarnWhenNonDataOnEntities = false diff --git a/src/cart.lua b/src/cart.lua index e310826..74c8345 100644 --- a/src/cart.lua +++ b/src/cart.lua @@ -49,10 +49,13 @@ function Cart.reset(o) end function Cart.new() - return setmetatable(Cart.reset({ - baseVelocity = { - x = 300, - y = -170, - } - }), { __index = Cart }) + return setmetatable( + Cart.reset({ + baseVelocity = { + x = 300, + y = -170, + }, + }), + { __index = Cart } + ) end diff --git a/src/main.lua b/src/main.lua index 3c9d874..b08fc82 100644 --- a/src/main.lua +++ b/src/main.lua @@ -67,7 +67,27 @@ function Score:draw() end world:addEntity(floor) -world:addEntity(Cart.new()) + +local scenarios = { + default = function() + world:addEntity(Cart.new()) + end , + manyCollectables = function() + local cart = Cart.new() + cart.velocity.x = 0 + cart.velocity.y = 1 + cart.position.x = 200 + cart.position.y = 200 + world:addEntity(cart) + local collectables = { LettuceSprite, TomatoSprite, MushroomSprite, CheeseSprite } + for _ = 1, 200 do + world:addEntity({ collected = collectables[math.random(#collectables)] }) + end + end, +} + +scenarios.manyCollectables() + addAllSpawners(world) world:addEntity(Ingredients.getFirst()) @@ -77,6 +97,29 @@ playdate.setAutoLockDisabled(true) local startMsOffset = -playdate.getCurrentTimeMilliseconds() +-- local maxBatcherLength = 10 +-- local root = {} +-- local physicsGroup = root +-- +-- function append(element) +-- if #physicsGroup < maxBatcherLength then +-- physicsGroup[#physicsGroup + 1] = element +-- else +-- physicsGroup = { element } +-- root[#root + 1] = physicsGroup +-- end +-- end +-- +-- for i = 1, 25 do +-- append(i) +-- end +-- +-- for i = 1, 10 do +-- +-- end +-- +-- printTable(root) + function playdate.update() local deltaSeconds = playdate.getElapsedTime() playdate.resetElapsedTime() diff --git a/src/systems/camera-pan.lua b/src/systems/camera-pan.lua index b9a2574..363f8c5 100644 --- a/src/systems/camera-pan.lua +++ b/src/systems/camera-pan.lua @@ -29,7 +29,6 @@ function cameraPanSystem:postProcess() for _, entity in pairs(expireBelowScreenSystem.entities) do if entity.position.y - (Camera.pan.y + 240) > entity.expireBelowScreenBy then - print("Entity expired - was too far below screen!") self.world:removeEntity(entity) end end diff --git a/src/systems/collision-detection.lua b/src/systems/collision-detection.lua index 8c47cdf..e0db9cb 100644 --- a/src/systems/collision-detection.lua +++ b/src/systems/collision-detection.lua @@ -6,12 +6,18 @@ collidingEntities = filteredSystem("collidingEntitites", { isSolid = Maybe(T.bool), }) -collisionDetection = filteredSystem("collisionDetection", +collisionDetection = filteredSystem( + "collisionDetection", { position = T.XyPair, size = T.XyPair, canBeCollidedBy = T.BitMask, isSolid = Maybe(T.bool) }, -- Here, the entity, e, refers to some entity that a moving object may be colliding *into* function(e, _, system) for _, collider in pairs(collidingEntities.entities) do - if (e ~= collider) and collider.canCollideWith and e.canBeCollidedBy and ((collider.canCollideWith & e.canBeCollidedBy) ~= 0) then + if + (e ~= collider) + and collider.canCollideWith + and e.canBeCollidedBy + and ((collider.canCollideWith & e.canBeCollidedBy) ~= 0) + then local colliderTop = collider.position.y local colliderBottom = collider.position.y + collider.size.y local entityTop = e.position.y diff --git a/src/systems/collision-resolution.lua b/src/systems/collision-resolution.lua index 02e94af..7071ecd 100644 --- a/src/systems/collision-resolution.lua +++ b/src/systems/collision-resolution.lua @@ -1,3 +1,5 @@ +---@alias CollisionChain { entityToGiveCollision: Entity, canCollideWith: BitMask, canBeCollidedBy: BitMask } + collisionResolution = filteredSystem("collisionResolution", { collisionBetween = T.Collision }, function(e, dt, system) local collidedInto, collider = e.collisionBetween[1], e.collisionBetween[2] local colliderTop = collidedInto.position.y @@ -20,6 +22,14 @@ collisionResolution = filteredSystem("collisionResolution", { collisionBetween = collider.velocity.y = collider.velocity.y * collidedInto.canBounce.mult.y * collider.canBeBounced.mult.y end + if collider.collisionChain then + ---@type CollisionChain + local chain = collider.collisionChain + chain.entityToGiveCollision.canCollideWith = chain.canCollideWith + chain.entityToGiveCollision.canBeCollidedBy = chain.canBeCollidedBy + system.world:addEntity(chain.entityToGiveCollision) + end + if collider.focusOnCollide then system.world:addEntity({ removeAtRoundStart = true, diff --git a/src/systems/draw.lua b/src/systems/draw.lua index 9208f0a..a88a438 100644 --- a/src/systems/draw.lua +++ b/src/systems/draw.lua @@ -1,16 +1,28 @@ local gfx = playdate.graphics -drawRectanglesSystem = filteredSystem("drawRectangles", { position = T.XyPair, drawAsRectangle = { size = T.XyPair } }, function(e, dt) - gfx.fillRect(e.position.x, e.position.y, e.drawAsRectangle.size.x, e.drawAsRectangle.size.y) -end) +drawRectanglesSystem = filteredSystem( + "drawRectangles", + { position = T.XyPair, drawAsRectangle = { size = T.XyPair } }, + function(e, dt) + gfx.fillRect(e.position.x, e.position.y, e.drawAsRectangle.size.x, e.drawAsRectangle.size.y) + end +) -drawSpriteSystem = filteredSystem("drawSprites", { position = T.XyPair, drawAsSprite = T.pd_image }, function(e, dt, system) - e.drawAsSprite:draw(e.position.x, e.position.y) -end) +drawSpriteSystem = filteredSystem( + "drawSprites", + { position = T.XyPair, drawAsSprite = T.pd_image }, + function(e) + if e.position.y < Camera.pan.y - 240 or e.position.y > Camera.pan.y + 480 then + return + end + e.drawAsSprite:draw(e.position.x, e.position.y) + end +) local xMargin = 4 -drawTextSystem = filteredSystem("drawText", +drawTextSystem = filteredSystem( + "drawText", { position = T.XyPair, drawAsText = { text = T.str, style = Maybe(T.str), font = Maybe(T.pd_font) } }, function(e) local font = e.drawAsText.font or AshevilleSans14Bold diff --git a/src/systems/gravity.lua b/src/systems/gravity.lua index 0fb8706..7d178be 100644 --- a/src/systems/gravity.lua +++ b/src/systems/gravity.lua @@ -8,8 +8,10 @@ filteredSystem("changeGravity", { changeGravityTo = T.number }, function(e, _, _ end end) +local min = math.min + fallSystem = filteredSystem("fall", { velocity = T.XyPair, mass = T.number }, function(e, dt) for _, ge in pairs(gravities.entities) do - e.velocity.y = e.velocity.y - (ge.gravity * dt * e.mass) - (0.5 * dt * dt) + e.velocity.y = min(400, e.velocity.y - (ge.gravity * dt * e.mass) - (0.5 * dt * dt)) end end) diff --git a/src/systems/input.lua b/src/systems/input.lua index c1c94f6..bb4ea1c 100644 --- a/src/systems/input.lua +++ b/src/systems/input.lua @@ -16,8 +16,7 @@ function inputSystem:preProcess() inputState.aJustPressed = buttonJustPressed(playdate.kButtonA) inputState.bJustPressed = buttonJustPressed(playdate.kButtonB) - inputState.receivedInputThisFrame = - inputState.upJustPressed + inputState.receivedInputThisFrame = inputState.upJustPressed or inputState.downJustPressed or inputState.rightJustPressed or inputState.leftJustPressed diff --git a/src/systems/menu.lua b/src/systems/menu.lua index 7a7a31b..3ac9f29 100644 --- a/src/systems/menu.lua +++ b/src/systems/menu.lua @@ -7,50 +7,54 @@ local function applyReplacementRelation(relation, world) world:addEntity(relation.entityToModify) end -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 - -- 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 +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 + -- 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 - -- TODO: Larger menu that stays open for more purchases before the next round - world:addEntity({ roundAction = "start" }) + -- 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) + 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 menuItem.additions then - for _, v in ipairs(menuItem.additions) do - system.world:addEntity(v) - end + + if e.inputState.downJustPressed and menuItem.navigateDown then + menuItem.highlighted = false + menuItem.navigateDown.highlighted = true + return + end + + if e.inputState.upJustPressed and menuItem.navigateUp then + menuItem.highlighted = false + menuItem.navigateUp.highlighted = true + return end end + end - if e.inputState.downJustPressed and menuItem.navigateDown then - menuItem.highlighted = false - menuItem.navigateDown.highlighted = true - return - end - - if e.inputState.upJustPressed and menuItem.navigateUp then - menuItem.highlighted = false - menuItem.navigateUp.highlighted = true - return + for _, menuItem in pairs(e.menuItems) do + if menuItem.highlighted then + menuItem.drawAsText.style = TextStyle.Inverted + else + menuItem.drawAsText.style = TextStyle.Bordered end end end - - for _, menuItem in pairs(e.menuItems) do - if menuItem.highlighted then - menuItem.drawAsText.style = TextStyle.Inverted - else - menuItem.drawAsText.style = TextStyle.Bordered - end - end -end) +) diff --git a/src/systems/move-toward.lua b/src/systems/move-toward.lua index 6b58daf..defb36e 100644 --- a/src/systems/move-toward.lua +++ b/src/systems/move-toward.lua @@ -15,24 +15,28 @@ local function normalizeVector(xy1, xy2) return x / distance, y / distance, distance end -moveTowardSystem = filteredSystem("moveToward", { moveToward = MoveToward, position = T.XyPair }, function(e, dt, system) - local xNorm, yNorm, distance = normalizeVector(e.position, e.moveToward.target) - if distance > e.moveToward.range then - return - end +moveTowardSystem = filteredSystem( + "moveToward", + { moveToward = MoveToward, position = T.XyPair }, + function(e, dt, system) + local xNorm, yNorm, distance = normalizeVector(e.position, e.moveToward.target) + if distance > e.moveToward.range then + return + end - -- TODO May be incorrect when signs are mismatched between vel and diff - local xVel = xNorm * e.moveToward.speed * dt - if abs(e.position.x - e.moveToward.target.x) < abs(xVel) then - e.position.x = e.moveToward.target.x - else - e.position.x = e.position.x + xVel - end + -- TODO May be incorrect when signs are mismatched between vel and diff + local xVel = xNorm * e.moveToward.speed * dt + if abs(e.position.x - e.moveToward.target.x) < abs(xVel) then + e.position.x = e.moveToward.target.x + else + e.position.x = e.position.x + xVel + end - local yVel = yNorm * e.moveToward.speed * dt - if abs(e.position.y - e.moveToward.target.y) < abs(yVel) then - e.position.y = e.moveToward.target.y - else - e.position.y = e.position.y + yVel + local yVel = yNorm * e.moveToward.speed * dt + if abs(e.position.y - e.moveToward.target.y) < abs(yVel) then + e.position.y = e.moveToward.target.y + else + e.position.y = e.position.y + yVel + end end -end) +) diff --git a/src/systems/rounds.lua b/src/systems/rounds.lua index 6829edb..f3276e1 100644 --- a/src/systems/rounds.lua +++ b/src/systems/rounds.lua @@ -2,160 +2,139 @@ collectedEntities = filteredSystem("collectedEntities", { collected = T.pd_image local onCollidingRemove = { "mass", "velocity", "canCollideWith" } -local Drop = { i = T.number, delay = T.number, startAt = T.XyPair } - -disableCollisionWhenRoundEnds = filteredSystem("disableCollisionWhenRoundEnds", { disableCollisionWhenRoundEnds = T.marker }) - -collectableDropSystem = filteredSystem("collectableDrop", { drop = Drop }, function(e, dt, system) - e.drop.delay = e.drop.delay - dt - if e.drop.delay > 0 then - return - end - local collX, collY = e.drop.sprite:getSize() - system.world:addEntity({ - drawAsSprite = e.drop.sprite, - size = { x = collX, y = collY / 2 }, - mass = 0.5, - velocity = { x = 0, y = 0 }, - position = { x = e.drop.startAt.x - (collX / 2), y = e.drop.startAt.y }, - canCollideWith = 2, - canBeCollidedBy = 2, - isSolid = true, - stopMovingOnCollision = true, - onCollidingRemove = onCollidingRemove, - focusOnCollide = e.drop.i, - expireBelowScreenBy = 5, - removeAtRoundStart = true, - }) - system.world:removeEntity(e) -end) +disableCollisionWhenRoundEnds = + filteredSystem("disableCollisionWhenRoundEnds", { disableCollisionWhenRoundEnds = T.marker }) removeAtRoundStart = filteredSystem("removeAtRoundStart", { removeAtRoundStart = T.bool }) -filteredSystem("afterDelayAdd", { afterDelayAdd = { entityToAdd = T.Entity, delay = T.number } }, function(e, dt, system) - e.afterDelayAdd.delay = e.afterDelayAdd.delay - dt - if e.afterDelayAdd.delay > 0 then - return - end - system.world:addEntity(e.afterDelayAdd.entityToAdd) - system.world:removeEntity(e) -end) +roundSystem = filteredSystem( + "round", + { roundAction = T.RoundStateAction, position = Maybe(T.XyPair) }, + function(e, _, system) + system.world:removeEntity(e) + if e.roundAction == "start" then + for _, cart in pairs(cartSystem.entities) do + Cart.reset(cart) + system.world:addEntity(cart) + end + for _, remove in pairs(removeAtRoundStart.entities) do + system.world:removeEntity(remove) + end + system.world:addSystem(spawnerSystem) + Ingredients.clearCache(system.world) + elseif e.roundAction == "end" then + system.world:removeSystem(spawnerSystem) + for _, toExpire in pairs(disableCollisionWhenRoundEnds.entities) do + toExpire.canCollideWith = nil + toExpire.canBeCollidedBy = nil + system.world:removeEntity(toExpire) + end + -- playdate.setAutoLockDisabled(false) -roundSystem = filteredSystem("round", { roundAction = T.RoundStateAction, position = Maybe(T.XyPair) }, function(e, _, system) - system.world:removeEntity(e) - if e.roundAction == "start" then - for _, cart in pairs(cartSystem.entities) do - Cart.reset(cart) - system.world:addEntity(cart) - end - for _, remove in pairs(removeAtRoundStart.entities) do - system.world:removeEntity(remove) - end - system.world:addSystem(spawnerSystem) - Ingredients.clearCache(system.world) - elseif e.roundAction == "end" then - system.world:removeSystem(spawnerSystem) - for _, toExpire in pairs(disableCollisionWhenRoundEnds.entities) do - toExpire.canCollideWith = nil - toExpire.canBeCollidedBy = nil - --system.world:addEntity(toExpire) - system.world:removeEntity(toExpire) - end - -- playdate.setAutoLockDisabled(false) + local y = e.position.y - 240 + local rectWidth = 150 + local plateSize = { x = rectWidth, y = 10 } - local y = e.position.y - 240 - local rectWidth = 150 - local plateSize = { x = rectWidth, y = 10 } - - system.world:addEntity({ - drawAsRectangle = { size = plateSize }, - size = plateSize, - mass = 0.5, - velocity = { x = 0, y = 0 }, - position = { x = e.position.x - (rectWidth / 2), y = y }, - canCollideWith = 2, - canBeCollidedBy = 2, - isSolid = true, - stopMovingOnCollision = true, - removeAtRoundStart = true, - }) - - -- TODO: Big ol' numbers displaying how many ingredients were collected? - -- TODO: Could layer ingredients in rows of three? Maybe just when it's higher? - local delayPerDrop = 0.100 - local delay = 0 - for i, collectable in ipairs(collectedEntities.entities) do - local _, collY = collectable.collected:getSize() - y = y - collY - 15 system.world:addEntity({ - drop = { - sprite = collectable.collected, - i = i, - delay = delay, - startAt = { - x = e.position.x, - y = y - } - }, - }) - delay = delay + delayPerDrop - system.world:removeEntity(collectable) - end - - ---@type NamedUpgrade[] - local availableUpgrades = Utils.getNDifferentValues(getAvailableUpgrades(), 3) - -- Sorting from shortest to longest sort of makes them look like a bun? - table.sort(availableUpgrades, function(a, b) - return #a.name > #b.name - end) - - y = y - 50 - local menuEntity = { - menuItems = {}, - canReceiveInput = T.marker, - } - local upgradeBelow - local i = #collectedEntities.entities - for _, upgrade in ipairs(availableUpgrades) do - i = i + 1 - local collX, collY = 75, 21 - y = y - collY - 15 - 15 - ---@type Selectable - local upgradeEntity = { - replacements = { upgrade.replace }, - drawAsText = { - text = upgrade.name, - style = TextStyle.Inverted, - }, - size = { x = collX, y = collY }, + drawAsRectangle = { size = plateSize }, + size = plateSize, mass = 0.5, velocity = { x = 0, y = 0 }, - position = { x = e.position.x, y = y }, + position = { x = e.position.x - (rectWidth / 2), y = y }, canCollideWith = 2, canBeCollidedBy = 2, isSolid = true, stopMovingOnCollision = true, - onCollidingRemove = onCollidingRemove, - focusOnCollide = i, - navigateDown = upgradeBelow, - highlighted = true, removeAtRoundStart = true, - } - if upgradeBelow then - upgradeBelow.navigateUp = upgradeEntity - upgradeBelow.highlighted = false - upgradeBelow.drawAsText.style = TextStyle.Bordered - end - upgradeBelow = upgradeEntity - menuEntity.menuItems[#menuEntity.menuItems + 1] = upgradeEntity - delay = delay + delayPerDrop - system.world:addEntity({ - afterDelayAdd = { - delay = delay, - entityToAdd = upgradeEntity - }, }) - system.world:addEntity(menuEntity) + + -- TODO: Big ol' numbers displaying how many ingredients were collected? + -- TODO: Could layer ingredients in rows of three? Maybe just when it's higher? + local delayPerDrop = 0.100 + local previousEntity + local collectables = collectedEntities.entities + for i, collectable in ipairs(collectables) do + local collX, collY = collectable.collected:getSize() + y = y - collY - 15 + local currentEntity = { + drawAsSprite = collectable.collected, + size = { x = collX, y = collY / 2 }, + mass = 0.5, + velocity = { x = 0, y = 0 }, + position = { x = e.position.x - (collX / 2), y = y }, + isSolid = true, + stopMovingOnCollision = true, + onCollidingRemove = onCollidingRemove, + focusOnCollide = i, + expireBelowScreenBy = 5, + removeAtRoundStart = true, + } + if previousEntity then + -- Don't enable collision on this drop until the previous entity collides. + previousEntity.collisionChain = { + entityToGiveCollision = currentEntity, + canCollideWith = 2, + canBeCollidedBy = 2, + } + else + -- Enable collision on the first entity + currentEntity.canBeCollidedBy = 2 + currentEntity.canCollideWith = 2 + end + previousEntity = currentEntity + system.world:addEntity(currentEntity) + system.world:removeEntity(collectable) + end + + ---@type NamedUpgrade[] + local availableUpgrades = Utils.getNDifferentValues(getAvailableUpgrades(), 3) + -- Sorting from shortest to longest sort of makes them look like a bun? + table.sort(availableUpgrades, function(a, b) + return #a.name > #b.name + end) + + y = y - 50 + local menuEntity = { + menuItems = {}, + canReceiveInput = T.marker, + } + local upgradeBelow + local i = #collectedEntities.entities + for _, upgrade in ipairs(availableUpgrades) do + i = i + 1 + local collX, collY = 75, 21 + y = y - collY - 15 - 15 + ---@type Selectable + local upgradeEntity = { + replacements = { upgrade.replace }, + drawAsText = { + text = upgrade.name, + style = TextStyle.Inverted, + }, + size = { x = collX, y = collY }, + mass = 0.5, + velocity = { x = 0, y = 0 }, + position = { x = e.position.x, y = y }, + canCollideWith = 2, + canBeCollidedBy = 2, + isSolid = true, + stopMovingOnCollision = true, + onCollidingRemove = onCollidingRemove, + focusOnCollide = i, + navigateDown = upgradeBelow, + highlighted = true, + removeAtRoundStart = true, + } + if upgradeBelow then + upgradeBelow.navigateUp = upgradeEntity + upgradeBelow.highlighted = false + upgradeBelow.drawAsText.style = TextStyle.Bordered + end + upgradeBelow = upgradeEntity + menuEntity.menuItems[#menuEntity.menuItems + 1] = upgradeEntity + system.world:addEntity(upgradeEntity) + system.world:addEntity(menuEntity) + end end end -end) +) diff --git a/src/systems/spawner.lua b/src/systems/spawner.lua index cc031f6..3837efb 100644 --- a/src/systems/spawner.lua +++ b/src/systems/spawner.lua @@ -100,4 +100,3 @@ function addAllSpawners(world) mult = { x = 0.7, y = -0.5 }, }) end - diff --git a/src/systems/upgrade-utils.lua b/src/systems/upgrade-utils.lua index edfd435..7ac63b8 100644 --- a/src/systems/upgrade-utils.lua +++ b/src/systems/upgrade-utils.lua @@ -28,7 +28,7 @@ function getAvailableSpawnerUpgrades(upgrades) entityToModify = spawner, replacement = { odds = spawner.odds, - } + }, }, } end @@ -43,8 +43,8 @@ function getAvailableCartUpgrades(upgrades) replace = { entityToModify = cart, replacement = { - mass = cart.mass * 0.9 - } + mass = cart.mass * 0.9, + }, }, } upgrades[#upgrades + 1] = { @@ -52,8 +52,8 @@ function getAvailableCartUpgrades(upgrades) replace = { entityToModify = cart.baseVelocity, replacement = { - x = cart.baseVelocity.x * 1.2 - } + x = cart.baseVelocity.x * 1.2, + }, }, } upgrades[#upgrades + 1] = { @@ -61,8 +61,8 @@ function getAvailableCartUpgrades(upgrades) replace = { entityToModify = cart.baseVelocity, replacement = { - y = cart.baseVelocity.y * 1.2 - } + y = cart.baseVelocity.y * 1.2, + }, }, } end