mirror of
https://github.com/SashLilac/cambridge.git
synced 2025-05-13 20:21:25 -05:00
Compare commits
18 Commits
v0.3-beta3
...
v0.3-beta4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83e498534c | ||
|
|
8f19c73e2a | ||
|
|
e36b855ff7 | ||
|
|
23b58951cb | ||
|
|
1d73916b7c | ||
|
|
3947e9f02f | ||
|
|
99b15803ee | ||
|
|
d350b25726 | ||
|
|
44e4d00172 | ||
|
|
31e2529265 | ||
|
|
ea7c75f0b3 | ||
|
|
714c6b5e99 | ||
|
|
6a5d5a9c88 | ||
|
|
03491ba151 | ||
|
|
6e22e3d15b | ||
|
|
66ab5992ad | ||
|
|
2c07c2a58c | ||
|
|
a4d3f3bffc |
18
README.md
18
README.md
@@ -5,9 +5,9 @@ Cambridge
|
||||
|
||||
Welcome to Cambridge, the next open-source falling-block game engine!
|
||||
|
||||
The project is written and maintained exclusively by [SashLilac](https://github.com/SashLilac), [joezeng](https://github.com/joezeng) and [Oshisaure](https://github.com/oshisaure)!
|
||||
The project is written and maintained exclusively by [SashLilac](https://github.com/SashLilac), [joezeng](https://github.com/joezeng) and [Oshisaure](https://github.com/oshisaure)!
|
||||
|
||||
Join our Discord server for help and a welcoming community! https://discord.gg/mteMJw4
|
||||
The game also has a website now with more detail than seen on this README: https://t-sp.in/cambridge
|
||||
|
||||
Credits
|
||||
-------
|
||||
@@ -17,19 +17,7 @@ Credits
|
||||
- [The Tetra Legends Discord](http://discord.com/invite/7hMx5r2) for supporting me and playtesting!
|
||||
- [The Absolute Plus](https://discord.gg/6Gf2awJ) for being another source of motivation!
|
||||
|
||||
The following people in no particular order also helped with the project:
|
||||
- [Hailey](https://github.com/haileylgbt)
|
||||
- CylinderKnot
|
||||
- MarkGamed7794
|
||||
- [Mizu](https://github.com/rexxt)
|
||||
- MattMayuga
|
||||
- Kitaru
|
||||
- switchpalacecorner
|
||||
- [sinefuse](https://github.com/sinefuse)
|
||||
- [2Tie](https://github.com/2Tie)
|
||||
- [nightmareci](https://github.com/nightmareci)
|
||||
- [MyPasswordIsWeak](https://github.com/MyPasswordIsWeak)
|
||||
- [Dr Ocelot](https://github.com/Dr-Ocelot)
|
||||
More special thanks can be found in-game, under the "Credits" menu.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
-- If this variable is true, then strict type checking is performed for all
|
||||
-- operations. This may result in slower code, but it will allow you to catch
|
||||
-- errors and bugs earlier.
|
||||
local strict = true
|
||||
local strict = false
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -33,12 +33,7 @@ function bigint.new(num)
|
||||
return bigint.add(lhs, rhs)
|
||||
end,
|
||||
__unm = function()
|
||||
if (self.sign == "+") then
|
||||
self.sign = "-"
|
||||
else
|
||||
self.sign = "+"
|
||||
end
|
||||
return self
|
||||
return bigint.negate(self)
|
||||
end,
|
||||
__sub = function(lhs, rhs)
|
||||
return bigint.subtract(lhs, rhs)
|
||||
@@ -98,6 +93,18 @@ function bigint.abs(big)
|
||||
return result
|
||||
end
|
||||
|
||||
-- Return a new big with the same digits but the opposite sign (negation)
|
||||
function bigint.negate(big)
|
||||
bigint.check(big)
|
||||
local result = big:clone()
|
||||
if (result.sign == "+") then
|
||||
result.sign = "-"
|
||||
else
|
||||
result.sign = "+"
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
-- Return the number of digits in the big
|
||||
function bigint.digits(big)
|
||||
bigint.check(big)
|
||||
|
||||
@@ -31,6 +31,7 @@ end
|
||||
|
||||
function ConfigScene:new()
|
||||
self.input_state = 1
|
||||
self.key = 1
|
||||
self.set_inputs = newSetInputs()
|
||||
self.new_input = {}
|
||||
self.axis_timer = 0
|
||||
@@ -62,7 +63,7 @@ function ConfigScene:render()
|
||||
if self.input_state > table.getn(configurable_inputs) then
|
||||
love.graphics.print("press enter to confirm, delete/backspace to retry" .. (config.input and ", escape to cancel" or ""))
|
||||
else
|
||||
love.graphics.print("press key or joystick input for " .. configurable_inputs[self.input_state] .. ", tab to skip" .. (config.input and ", escape to cancel" or ""), 0, 0)
|
||||
love.graphics.print("press " .. (self.key == 2 and "joystick" or "key") .. " input for " .. configurable_inputs[self.input_state] .. ", tab to skip" .. (config.input and ", escape to cancel" or ""), 0, 0)
|
||||
love.graphics.print("function keys (F1, F2, etc.), escape, and tab can't be changed", 0, 20)
|
||||
end
|
||||
|
||||
@@ -97,18 +98,28 @@ function ConfigScene:onInputPress(e)
|
||||
self.new_input = {}
|
||||
end
|
||||
elseif e.scancode == "tab" then
|
||||
self.set_inputs[configurable_inputs[self.input_state]] = "skipped"
|
||||
self.input_state = self.input_state + 1
|
||||
elseif e.scancode ~= "escape" then
|
||||
self.set_inputs[configurable_inputs[self.input_state]] =
|
||||
(
|
||||
self.set_inputs[configurable_inputs[self.input_state]] == false
|
||||
and "" or self.set_inputs[configurable_inputs[self.input_state]]
|
||||
) ..
|
||||
(self.key == 2 and " / " or "") .. "skipped"
|
||||
if self.key == 2 then
|
||||
self.input_state = self.input_state + 1
|
||||
self.key = 1
|
||||
else
|
||||
self.key = 2
|
||||
end
|
||||
elseif e.scancode ~= "escape" and self.key == 1 then
|
||||
-- all other keys can be configured
|
||||
if not self.new_input.keys then
|
||||
self.new_input.keys = {}
|
||||
end
|
||||
self.set_inputs[configurable_inputs[self.input_state]] = "key " .. love.keyboard.getKeyFromScancode(e.scancode) .. " (" .. e.scancode .. ")"
|
||||
self.new_input.keys[e.scancode] = configurable_inputs[self.input_state]
|
||||
self.input_state = self.input_state + 1
|
||||
self.key = 2
|
||||
end
|
||||
elseif string.sub(e.type, 1, 3) == "joy" then
|
||||
elseif string.sub(e.type, 1, 3) == "joy" and self.key == 2 then
|
||||
if self.input_state <= table.getn(configurable_inputs) then
|
||||
if e.type == "joybutton" then
|
||||
addJoystick(self.new_input, e.name)
|
||||
@@ -116,11 +127,13 @@ function ConfigScene:onInputPress(e)
|
||||
self.new_input.joysticks[e.name].buttons = {}
|
||||
end
|
||||
self.set_inputs[configurable_inputs[self.input_state]] =
|
||||
"jbtn " ..
|
||||
self.set_inputs[configurable_inputs[self.input_state]] ..
|
||||
" / jbtn " ..
|
||||
e.button ..
|
||||
" " .. string.sub(e.name, 1, 10) .. (string.len(e.name) > 10 and "..." or "")
|
||||
self.new_input.joysticks[e.name].buttons[e.button] = configurable_inputs[self.input_state]
|
||||
self.input_state = self.input_state + 1
|
||||
self.key = 1
|
||||
elseif e.type == "joyaxis" then
|
||||
if (e.axis ~= self.last_axis or self.axis_timer > 30) and math.abs(e.value) >= 1 then
|
||||
addJoystick(self.new_input, e.name)
|
||||
@@ -131,11 +144,13 @@ function ConfigScene:onInputPress(e)
|
||||
self.new_input.joysticks[e.name].axes[e.axis] = {}
|
||||
end
|
||||
self.set_inputs[configurable_inputs[self.input_state]] =
|
||||
"jaxis " ..
|
||||
self.set_inputs[configurable_inputs[self.input_state]] ..
|
||||
" / jaxis " ..
|
||||
(e.value >= 1 and "+" or "-") .. e.axis ..
|
||||
" " .. string.sub(e.name, 1, 10) .. (string.len(e.name) > 10 and "..." or "")
|
||||
self.new_input.joysticks[e.name].axes[e.axis][e.value >= 1 and "positive" or "negative"] = configurable_inputs[self.input_state]
|
||||
self.input_state = self.input_state + 1
|
||||
self.key = 1
|
||||
self.last_axis = e.axis
|
||||
self.axis_timer = 0
|
||||
end
|
||||
@@ -149,11 +164,13 @@ function ConfigScene:onInputPress(e)
|
||||
self.new_input.joysticks[e.name].hats[e.hat] = {}
|
||||
end
|
||||
self.set_inputs[configurable_inputs[self.input_state]] =
|
||||
"jhat " ..
|
||||
self.set_inputs[configurable_inputs[self.input_state]]
|
||||
" / jhat " ..
|
||||
e.hat .. " " .. e.direction ..
|
||||
" " .. string.sub(e.name, 1, 10) .. (string.len(e.name) > 10 and "..." or "")
|
||||
self.new_input.joysticks[e.name].hats[e.hat][e.direction] = configurable_inputs[self.input_state]
|
||||
self.input_state = self.input_state + 1
|
||||
self.key = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -117,11 +117,15 @@ function Piece:lockIfBottomed(grid)
|
||||
return self
|
||||
end
|
||||
|
||||
function Piece:addGravity(gravity, grid)
|
||||
function Piece:addGravity(gravity, grid, classic_lock)
|
||||
local new_gravity = self.gravity + gravity
|
||||
if self:isDropBlocked(grid) then
|
||||
self.gravity = math.min(1, new_gravity)
|
||||
self.lock_delay = self.lock_delay + 1
|
||||
if classic_lock then
|
||||
self.gravity = math.min(1, new_gravity)
|
||||
else
|
||||
self.gravity = 0
|
||||
self.lock_delay = self.lock_delay + 1
|
||||
end
|
||||
else
|
||||
local dropped_squares = math.floor(new_gravity)
|
||||
local new_frac_gravity = new_gravity - dropped_squares
|
||||
|
||||
@@ -137,7 +137,7 @@ function GameMode:update(inputs, ruleset)
|
||||
|
||||
-- set attempt flags
|
||||
if inputs["left"] or inputs["right"] then
|
||||
self:onAttemptPieceMove(self.piece)
|
||||
self:onAttemptPieceMove(self.piece, self.grid)
|
||||
if self.immobile_spin_bonus and self.piece ~= nil then
|
||||
if not self.piece:isMoveBlocked(self.grid, { x=-1, y=0 }) and
|
||||
not self.piece:isMoveBlocked(self.grid, { x=1, y=0 }) then
|
||||
@@ -150,7 +150,7 @@ function GameMode:update(inputs, ruleset)
|
||||
inputs["rotate_left2"] or inputs["rotate_right2"] or
|
||||
inputs["rotate_180"]
|
||||
then
|
||||
self:onAttemptPieceRotate(self.piece)
|
||||
self:onAttemptPieceRotate(self.piece, self.grid)
|
||||
if self.immobile_spin_bonus and self.piece ~= nil then
|
||||
if self.piece:isDropBlocked(self.grid) and
|
||||
self.piece:isMoveBlocked(self.grid, { x=-1, y=0 }) and
|
||||
@@ -193,6 +193,7 @@ function GameMode:update(inputs, ruleset)
|
||||
|
||||
-- diff vars to use in checks
|
||||
local piece_y = self.piece.position.y
|
||||
local piece_x = self.piece.position.x
|
||||
local piece_rot = self.piece.rotation
|
||||
|
||||
ruleset:processPiece(
|
||||
@@ -203,6 +204,7 @@ function GameMode:update(inputs, ruleset)
|
||||
)
|
||||
|
||||
local piece_dy = self.piece.position.y - piece_y
|
||||
local piece_dx = self.piece.position.x - piece_x
|
||||
local piece_drot = self.piece.rotation - piece_rot
|
||||
|
||||
-- das cut
|
||||
@@ -214,12 +216,13 @@ function GameMode:update(inputs, ruleset)
|
||||
inputs.rotate_180
|
||||
))
|
||||
) then
|
||||
self.das.frames = math.max(
|
||||
self.das.frames - self:getDasCutDelay(),
|
||||
-(self:getDasCutDelay() + 1)
|
||||
)
|
||||
self:dasCut()
|
||||
end
|
||||
|
||||
if (piece_dx ~= 0) then self:onPieceMove(self.piece, self.grid) end
|
||||
if (piece_drot ~= 0) then self:onPieceRotate(self.piece, self.grid) end
|
||||
if (piece_dy ~= 0) then self:onPieceDrop(self.piece, self.grid) end
|
||||
|
||||
if inputs["up"] == true and
|
||||
self.piece:isDropBlocked(self.grid) and
|
||||
not self.hard_drop_locked then
|
||||
@@ -294,8 +297,11 @@ end
|
||||
|
||||
-- event functions
|
||||
function GameMode:whilePieceActive() end
|
||||
function GameMode:onAttemptPieceMove(piece) end
|
||||
function GameMode:onAttemptPieceRotate(piece) end
|
||||
function GameMode:onAttemptPieceMove(piece, grid) end
|
||||
function GameMode:onAttemptPieceRotate(piece, grid) end
|
||||
function GameMode:onPieceMove(piece, grid) end
|
||||
function GameMode:onPieceRotate(piece, grid) end
|
||||
function GameMode:onPieceDrop(piece, grid) end
|
||||
function GameMode:onPieceLock(piece, cleared_row_count)
|
||||
playSE("lock")
|
||||
end
|
||||
@@ -390,6 +396,13 @@ function GameMode:chargeDAS(inputs)
|
||||
end
|
||||
end
|
||||
|
||||
function GameMode:dasCut()
|
||||
self.das.frames = math.max(
|
||||
self.das.frames - self:getDasCutDelay(),
|
||||
-(self:getDasCutDelay() + 1)
|
||||
)
|
||||
end
|
||||
|
||||
function GameMode:areCancel(inputs, ruleset)
|
||||
if ruleset.are_cancel and self.piece_hard_dropped and
|
||||
not self.prev_inputs.up and
|
||||
@@ -773,14 +786,15 @@ function GameMode:drawSectionTimesWithSplits(current_section, section_limit)
|
||||
|
||||
for section, time in pairs(self.section_times) do
|
||||
if section > 0 then
|
||||
love.graphics.setColor(self:sectionColourFunction(section))
|
||||
love.graphics.printf(formatTime(time), section_x, 40 + 20 * section, 90, "left")
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
split_time = split_time + time
|
||||
love.graphics.printf(formatTime(split_time), split_x, 40 + 20 * section, 90, "left")
|
||||
end
|
||||
end
|
||||
|
||||
if (current_section <= section_limit) then
|
||||
love.graphics.setColor(self:sectionColourFunction(current_section))
|
||||
love.graphics.printf(formatTime(self.frames - self.section_start_time), section_x, 40 + 20 * current_section, 90, "left")
|
||||
love.graphics.printf(formatTime(self.frames), split_x, 40 + 20 * current_section, 90, "left")
|
||||
end
|
||||
|
||||
@@ -52,23 +52,14 @@ function StrategyGame:getLineClearDelay()
|
||||
end
|
||||
|
||||
function StrategyGame:getLockDelay()
|
||||
if self.level < 500 then return 8
|
||||
elseif self.level < 700 then return 6
|
||||
else return 4 end
|
||||
if self.level < 700 then return 8
|
||||
else return 6 end
|
||||
end
|
||||
|
||||
function StrategyGame:getGravity()
|
||||
return 20
|
||||
end
|
||||
|
||||
function StrategyGame:getNextPiece(ruleset)
|
||||
return {
|
||||
skin = "2tie",
|
||||
shape = self.randomizer:nextPiece(),
|
||||
orientation = ruleset:getDefaultOrientation(),
|
||||
}
|
||||
end
|
||||
|
||||
function StrategyGame:advanceOneFrame()
|
||||
if self.clear then
|
||||
self.roll_frames = self.roll_frames + 1
|
||||
|
||||
@@ -94,12 +94,8 @@ function Survival2020Game:getGravity()
|
||||
return 20
|
||||
end
|
||||
|
||||
function Survival2020Game:getNextPiece(ruleset)
|
||||
return {
|
||||
skin = self.level >= 1000 and "bone" or "2tie",
|
||||
shape = self.randomizer:nextPiece(),
|
||||
orientation = ruleset:getDefaultOrientation(),
|
||||
}
|
||||
function Survival2020Game:getSkin()
|
||||
return self.level >= 1000 and "bone" or "2tie"
|
||||
end
|
||||
|
||||
function Survival2020Game:hitTorikan(old_level, new_level)
|
||||
|
||||
@@ -30,6 +30,11 @@ function SurvivalA2Game:new()
|
||||
self.lock_hard_drop = true
|
||||
end
|
||||
|
||||
function SurvivalA2Game:initialize(ruleset)
|
||||
SurvivalA2Game.super.initialize(self, ruleset)
|
||||
self.world = ruleset.world
|
||||
end
|
||||
|
||||
function SurvivalA2Game:getARE()
|
||||
if self.level < 100 then return 18
|
||||
elseif self.level < 300 then return 14
|
||||
@@ -69,7 +74,8 @@ function SurvivalA2Game:getGravity()
|
||||
end
|
||||
|
||||
function SurvivalA2Game:hitTorikan(old_level, new_level)
|
||||
if old_level < 500 and new_level >= 500 and self.frames > frameTime(3,25) then
|
||||
local torikan_time = self.world and frameTime(3,55) or frameTime(3,25)
|
||||
if old_level < 500 and new_level >= 500 and self.frames > torikan_time then
|
||||
self.level = 500
|
||||
return true
|
||||
end
|
||||
|
||||
@@ -21,14 +21,18 @@ SRS.spawn_above_field = true
|
||||
|
||||
SRS.MANIPULATIONS_MAX = 128
|
||||
|
||||
function SRS:onPieceRotate(piece, grid)
|
||||
function SRS:onPieceRotate(piece, grid, upward)
|
||||
piece.lock_delay = 0 -- rotate reset
|
||||
if piece:isDropBlocked(grid) then
|
||||
if upward or piece:isDropBlocked(grid) then
|
||||
piece.manipulations = piece.manipulations + 1
|
||||
if piece.manipulations >= self.MANIPULATIONS_MAX then
|
||||
if piece.manipulations >= self.MANIPULATIONS_MAX and piece:isDropBlocked(grid) then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SRS:canPieceRotate(piece)
|
||||
return piece.manipulations < self.MANIPULATIONS_MAX
|
||||
end
|
||||
|
||||
return SRS
|
||||
|
||||
@@ -96,6 +96,9 @@ end
|
||||
function ARS:onPieceRotate(piece, grid)
|
||||
if piece.floorkick >= 1 then
|
||||
piece.floorkick = piece.floorkick + 1
|
||||
if piece:isDropBlocked(grid) then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -115,7 +115,9 @@ function Ruleset:rotatePiece(inputs, piece, grid, prev_inputs, initial)
|
||||
|
||||
local was_drop_blocked = piece:isDropBlocked(grid)
|
||||
|
||||
self:attemptRotate(new_inputs, piece, grid, initial)
|
||||
if self:canPieceRotate(piece, grid) then
|
||||
self:attemptRotate(new_inputs, piece, grid, initial)
|
||||
end
|
||||
|
||||
if not was_drop_blocked and piece:isDropBlocked(grid) then
|
||||
playSE("bottom")
|
||||
@@ -160,28 +162,43 @@ function Ruleset:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||
end
|
||||
|
||||
function Ruleset:movePiece(piece, grid, move, instant)
|
||||
local x = piece.position.x
|
||||
if not self:canPieceMove(piece, grid) then return end
|
||||
local was_drop_blocked = piece:isDropBlocked(grid)
|
||||
local offset = ({x=0, y=0})
|
||||
local moves = 0
|
||||
if move == "left" then
|
||||
piece:moveInGrid({x=-1, y=0}, 1, grid, false)
|
||||
offset.x = -1
|
||||
moves = 1
|
||||
elseif move == "right" then
|
||||
piece:moveInGrid({x=1, y=0}, 1, grid, false)
|
||||
offset.x = 1
|
||||
moves = 1
|
||||
elseif move == "speedleft" then
|
||||
piece:moveInGrid({x=-1, y=0}, grid.width, grid, instant)
|
||||
offset.x = -1
|
||||
moves = grid.width
|
||||
elseif move == "speedright" then
|
||||
piece:moveInGrid({x=1, y=0}, grid.width, grid, instant)
|
||||
offset.x = 1
|
||||
moves = grid.width
|
||||
end
|
||||
if piece.position.x ~= x then
|
||||
self:onPieceMove(piece, grid)
|
||||
if not was_drop_blocked and piece:isDropBlocked(grid) then
|
||||
playSE("bottom")
|
||||
for i = 1, moves do
|
||||
local x = piece.position.x
|
||||
if moves ~= 1 then
|
||||
piece:moveInGrid(offset, 1, grid, instant)
|
||||
else
|
||||
piece:moveInGrid(offset, 1, grid, false)
|
||||
end
|
||||
if piece.position.x ~= x then
|
||||
self:onPieceMove(piece, grid)
|
||||
if piece.locked then break end
|
||||
end
|
||||
end
|
||||
if not was_drop_blocked and piece:isDropBlocked(grid) then
|
||||
playSE("bottom")
|
||||
end
|
||||
end
|
||||
|
||||
function Ruleset:dropPiece(
|
||||
inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked,
|
||||
hard_drop_enabled, additive_gravity
|
||||
hard_drop_enabled, additive_gravity, classic_lock
|
||||
)
|
||||
if piece.big then
|
||||
gravity = gravity / 2
|
||||
@@ -191,18 +208,18 @@ function Ruleset:dropPiece(
|
||||
local y = piece.position.y
|
||||
if inputs["down"] == true and drop_locked == false then
|
||||
if additive_gravity then
|
||||
piece:addGravity(gravity + drop_speed, grid)
|
||||
piece:addGravity(gravity + drop_speed, grid, classic_lock)
|
||||
else
|
||||
piece:addGravity(math.max(gravity, drop_speed), grid)
|
||||
piece:addGravity(math.max(gravity, drop_speed), grid, classic_lock)
|
||||
end
|
||||
elseif inputs["up"] == true and hard_drop_enabled == true then
|
||||
if hard_drop_locked == true or piece:isDropBlocked(grid) then
|
||||
piece:addGravity(gravity, grid)
|
||||
piece:addGravity(gravity, grid, classic_lock)
|
||||
else
|
||||
piece:dropToBottom(grid)
|
||||
end
|
||||
else
|
||||
piece:addGravity(gravity, grid)
|
||||
piece:addGravity(gravity, grid, classic_lock)
|
||||
end
|
||||
if piece.position.y ~= y then
|
||||
self:onPieceDrop(piece, grid)
|
||||
@@ -303,11 +320,13 @@ function Ruleset:processPiece(
|
||||
end
|
||||
self:dropPiece(
|
||||
inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked,
|
||||
hard_drop_enabled, additive_gravity
|
||||
hard_drop_enabled, additive_gravity, classic_lock
|
||||
)
|
||||
self:lockPiece(piece, grid, lock_delay, classic_lock)
|
||||
end
|
||||
|
||||
function Ruleset:canPieceMove(piece, grid) return true end
|
||||
function Ruleset:canPieceRotate(piece, grid) return true end
|
||||
function Ruleset:onPieceMove(piece) end
|
||||
function Ruleset:onPieceRotate(piece) end
|
||||
function Ruleset:onPieceDrop(piece) end
|
||||
|
||||
@@ -92,11 +92,14 @@ function SRS:onPieceRotate(piece, grid)
|
||||
piece.lock_delay = 0 -- rotate reset
|
||||
self:checkNewLow(piece)
|
||||
piece.manipulations = piece.manipulations + 1
|
||||
if piece:isDropBlocked(grid) then
|
||||
if piece.manipulations >= SRS.MANIPULATIONS_MAX then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
if piece.manipulations >= self.MANIPULATIONS_MAX then
|
||||
piece:moveInGrid({ x = 0, y = 1 }, 1, grid)
|
||||
if piece:isDropBlocked(grid) then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SRS:canPieceRotate() return true end
|
||||
|
||||
return SRS
|
||||
|
||||
@@ -54,7 +54,7 @@ function SRS:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||
if grid:canPlacePiece(kicked_piece) then
|
||||
piece:setRelativeRotation(rot_dir)
|
||||
piece:setOffset(offset)
|
||||
self:onPieceRotate(piece, grid)
|
||||
self:onPieceRotate(piece, grid, offset.y < 0)
|
||||
return
|
||||
end
|
||||
end
|
||||
@@ -69,7 +69,10 @@ end
|
||||
|
||||
function SRS:onPieceDrop(piece, grid)
|
||||
self:checkNewLow(piece)
|
||||
if piece.manipulations >= self.MANIPULATIONS_MAX and piece:isDropBlocked(grid) then
|
||||
if (
|
||||
piece.manipulations >= self.MANIPULATIONS_MAX or
|
||||
piece.rotations >= self.ROTATIONS_MAX
|
||||
) and piece:isDropBlocked(grid) then
|
||||
piece.locked = true
|
||||
else
|
||||
piece.lock_delay = 0 -- step reset
|
||||
@@ -86,16 +89,18 @@ function SRS:onPieceMove(piece, grid)
|
||||
end
|
||||
end
|
||||
|
||||
function SRS:onPieceRotate(piece, grid)
|
||||
function SRS:onPieceRotate(piece, grid, upward)
|
||||
piece.lock_delay = 0 -- rotate reset
|
||||
self:checkNewLow(piece)
|
||||
if piece.rotations >= self.ROTATIONS_MAX then
|
||||
piece.rotations = piece.rotations + 1
|
||||
piece:moveInGrid({ x = 0, y = 1 }, 1, grid)
|
||||
if piece:isDropBlocked(grid) then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
if upward or piece:isDropBlocked(grid) then
|
||||
piece.rotations = piece.rotations + 1
|
||||
if piece.rotations >= self.ROTATIONS_MAX and piece:isDropBlocked(grid) then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SRS:canPieceRotate(piece)
|
||||
return piece.rotations < self.ROTATIONS_MAX
|
||||
end
|
||||
|
||||
function SRS:get180RotationValue() return 2 end
|
||||
|
||||
@@ -150,9 +150,9 @@ function SRS:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||
for idx, offset in pairs(kicks) do
|
||||
kicked_piece = new_piece:withOffset(offset)
|
||||
if grid:canPlacePiece(kicked_piece) then
|
||||
self:onPieceRotate(piece, grid)
|
||||
piece:setRelativeRotation(rot_dir)
|
||||
piece:setOffset(offset)
|
||||
self:onPieceRotate(piece, grid, offset.y < 0)
|
||||
return
|
||||
end
|
||||
end
|
||||
@@ -182,16 +182,20 @@ function SRS:onPieceMove(piece, grid)
|
||||
end
|
||||
end
|
||||
|
||||
function SRS:onPieceRotate(piece, grid)
|
||||
function SRS:onPieceRotate(piece, grid, upward)
|
||||
piece.lock_delay = 0 -- rotate reset
|
||||
if piece:isDropBlocked(grid) then
|
||||
if upward or piece:isDropBlocked(grid) then
|
||||
piece.rotations = piece.rotations + 1
|
||||
if piece.rotations >= self.ROTATIONS_MAX then
|
||||
if piece.rotations >= self.ROTATIONS_MAX and piece:isDropBlocked(grid) then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SRS:canPieceRotate(piece)
|
||||
return piece.rotations < self.ROTATIONS_MAX
|
||||
end
|
||||
|
||||
function SRS:get180RotationValue() return 3 end
|
||||
|
||||
return SRS
|
||||
|
||||
Reference in New Issue
Block a user