mirror of
https://github.com/SashLilac/cambridge.git
synced 2025-05-13 20:21:25 -05:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36837a3af5 | ||
|
|
01b0f9f618 | ||
|
|
7c8c5bb11d | ||
|
|
acaa6bdbbf | ||
|
|
c37757f592 | ||
|
|
905e4bcc77 | ||
|
|
d956647678 | ||
|
|
10f032b49b | ||
|
|
5590e6c89b | ||
|
|
0393396d74 | ||
|
|
8c1eaec1aa | ||
|
|
957802a78e | ||
|
|
169a4e4d2f | ||
|
|
48aee18340 | ||
|
|
7b496d9412 | ||
|
|
7abb861446 | ||
|
|
21f8769228 | ||
|
|
44423fd2e8 | ||
|
|
351fb4cfe9 | ||
|
|
103f04ceaa | ||
|
|
88d2f0d8d1 | ||
|
|
e100289c82 | ||
|
|
e38da49180 | ||
|
|
b03473d2fe | ||
|
|
cf6e0be4e7 | ||
|
|
2bc9dc179c | ||
|
|
d626926d5a | ||
|
|
721acefea0 | ||
|
|
b9b71e90bb | ||
|
|
9f61b139fd | ||
|
|
3b0fdba27d | ||
|
|
d8fad3dc37 | ||
|
|
f9368fa806 | ||
|
|
189feb1802 | ||
|
|
dc09dabacb | ||
|
|
e13278c6a8 | ||
|
|
f7f11b0e22 |
38
README.md
38
README.md
@@ -28,12 +28,34 @@ The following people in no particular order also helped with the project:
|
|||||||
- [sinefuse](https://github.com/sinefuse)
|
- [sinefuse](https://github.com/sinefuse)
|
||||||
- [2Tie](https://github.com/2Tie)
|
- [2Tie](https://github.com/2Tie)
|
||||||
- [nightmareci](https://github.com/nightmareci)
|
- [nightmareci](https://github.com/nightmareci)
|
||||||
|
- [MyPasswordIsWeak](https://github.com/MyPasswordIsWeak)
|
||||||
|
- [Dr Ocelot](https://github.com/Dr-Ocelot)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Playing the game
|
Playing the game
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
You do not need LÖVE on Windows, as it comes bundled with the program.
|
||||||
|
|
||||||
|
To get the stable release, simply download the ZIP in the latest release. All assets needed are bundled with the executable.
|
||||||
|
|
||||||
|
If you want the bleeding edge version, or want mod pack support, download [this](https://github.com/SashLilac/cambridge/archive/master.zip).
|
||||||
|
|
||||||
|
Extract the ZIP, open a Command Prompt at the folder you extracted Cambridge to, then run this command:
|
||||||
|
|
||||||
|
dist\windows\love.exe .
|
||||||
|
|
||||||
|
Alternatively, if you're on a 32-bit system, run this instead:
|
||||||
|
|
||||||
|
dist\win32\love.exe .
|
||||||
|
|
||||||
|
32-bit systems do not support rich presence integration.
|
||||||
|
|
||||||
|
Then, check the mod pack section at the bottom of this page.
|
||||||
|
|
||||||
### macOS, Linux
|
### macOS, Linux
|
||||||
|
|
||||||
If you haven't already, install `love` with your favourite package manager (Homebrew on macOS, your system's default on Linux). **Make sure you're using LÖVE 11, because it won't work with earlier versions!**
|
If you haven't already, install `love` with your favourite package manager (Homebrew on macOS, your system's default on Linux). **Make sure you're using LÖVE 11, because it won't work with earlier versions!**
|
||||||
@@ -50,25 +72,11 @@ Then, navigate to the root directory that you just cloned, and type:
|
|||||||
|
|
||||||
It should run automatically!
|
It should run automatically!
|
||||||
|
|
||||||
### Windows
|
|
||||||
|
|
||||||
You do not need LÖVE on Windows, as it comes bundled with the program. Download the source code ZIP in the latest release, or if you want the bleeding edge version, download [this](https://github.com/SashLilac/cambridge/archive/master.zip).
|
|
||||||
|
|
||||||
Extract the ZIP, open a Command Prompt at the folder you extracted Cambridge to, then run this command:
|
|
||||||
|
|
||||||
dist\windows\love.exe .
|
|
||||||
|
|
||||||
Alternatively, if you're on a 32-bit system, run this instead:
|
|
||||||
|
|
||||||
dist\win32\love.exe .
|
|
||||||
|
|
||||||
32-bit systems do not support rich presence integration.
|
|
||||||
|
|
||||||
## Installing modpacks
|
## Installing modpacks
|
||||||
|
|
||||||
Simply drag your mode, ruleset, and randomizer Lua files into their respective directory, and they should appear automatically.
|
Simply drag your mode, ruleset, and randomizer Lua files into their respective directory, and they should appear automatically.
|
||||||
|
|
||||||
Alternatively, install [this](https://files.catbox.moe/66td2i.zip) mod pack to get a taste of the mod potential.
|
Alternatively, install [this](https://github.com/SashLilac/cambridge-modpack) mod pack to get a taste of the mod potential.
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|||||||
1
main.lua
1
main.lua
@@ -12,6 +12,7 @@ function love.load()
|
|||||||
config["side_next"] = false
|
config["side_next"] = false
|
||||||
config["reverse_rotate"] = true
|
config["reverse_rotate"] = true
|
||||||
config["fullscreen"] = false
|
config["fullscreen"] = false
|
||||||
|
config["das_last_key"] = false
|
||||||
|
|
||||||
love.window.setMode(love.graphics.getWidth(), love.graphics.getHeight(), {resizable = true});
|
love.window.setMode(love.graphics.getWidth(), love.graphics.getHeight(), {resizable = true});
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ ConfigScene.options = {
|
|||||||
{"manlock", "Manual locking",{"Per ruleset","Per gamemode","Harddrop", "Softdrop"}},
|
{"manlock", "Manual locking",{"Per ruleset","Per gamemode","Harddrop", "Softdrop"}},
|
||||||
{"piece_colour", "Piece Colours", {"Per ruleset","Arika" ,"TTC"}},
|
{"piece_colour", "Piece Colours", {"Per ruleset","Arika" ,"TTC"}},
|
||||||
{"world_reverse","A Button Rotation", {"Left" ,"Auto" ,"Right"}},
|
{"world_reverse","A Button Rotation", {"Left" ,"Auto" ,"Right"}},
|
||||||
|
{"das_last_key", "DAS Switch", {"Default", "Instant"}}
|
||||||
}
|
}
|
||||||
local optioncount = #ConfigScene.options
|
local optioncount = #ConfigScene.options
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ function ConfigScene:new()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function ConfigScene:update()
|
function ConfigScene:update()
|
||||||
|
config["das_last_key"] = config.gamesettings.das_last_key == 2
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfigScene:render()
|
function ConfigScene:render()
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ function ConfigScene:new()
|
|||||||
self.input_state = 1
|
self.input_state = 1
|
||||||
self.set_inputs = newSetInputs()
|
self.set_inputs = newSetInputs()
|
||||||
self.new_input = {}
|
self.new_input = {}
|
||||||
|
self.axis_timer = 0
|
||||||
|
|
||||||
DiscordRPC:update({
|
DiscordRPC:update({
|
||||||
details = "In menus",
|
details = "In menus",
|
||||||
@@ -63,6 +64,8 @@ function ConfigScene:render()
|
|||||||
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 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("function keys (F1, F2, etc.), escape, and tab can't be changed", 0, 20)
|
love.graphics.print("function keys (F1, F2, etc.), escape, and tab can't be changed", 0, 20)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self.axis_timer = self.axis_timer + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
local function addJoystick(input, name)
|
local function addJoystick(input, name)
|
||||||
@@ -118,7 +121,7 @@ function ConfigScene:onInputPress(e)
|
|||||||
self.new_input.joysticks[e.name].buttons[e.button] = configurable_inputs[self.input_state]
|
self.new_input.joysticks[e.name].buttons[e.button] = configurable_inputs[self.input_state]
|
||||||
self.input_state = self.input_state + 1
|
self.input_state = self.input_state + 1
|
||||||
elseif e.type == "joyaxis" then
|
elseif e.type == "joyaxis" then
|
||||||
if math.abs(e.value) >= 0.5 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)
|
addJoystick(self.new_input, e.name)
|
||||||
if not self.new_input.joysticks[e.name].axes then
|
if not self.new_input.joysticks[e.name].axes then
|
||||||
self.new_input.joysticks[e.name].axes = {}
|
self.new_input.joysticks[e.name].axes = {}
|
||||||
@@ -128,10 +131,12 @@ function ConfigScene:onInputPress(e)
|
|||||||
end
|
end
|
||||||
self.set_inputs[configurable_inputs[self.input_state]] =
|
self.set_inputs[configurable_inputs[self.input_state]] =
|
||||||
"jaxis " ..
|
"jaxis " ..
|
||||||
(e.value >= 0.5 and "+" or "-") .. e.axis ..
|
(e.value >= 1 and "+" or "-") .. e.axis ..
|
||||||
" " .. string.sub(e.name, 1, 10) .. (string.len(e.name) > 10 and "..." or "")
|
" " .. string.sub(e.name, 1, 10) .. (string.len(e.name) > 10 and "..." or "")
|
||||||
self.new_input.joysticks[e.name].axes[e.axis][e.value >= 0.5 and "positive" or "negative"] = configurable_inputs[self.input_state]
|
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.input_state = self.input_state + 1
|
||||||
|
self.last_axis = e.axis
|
||||||
|
self.axis_timer = 0
|
||||||
end
|
end
|
||||||
elseif e.type == "joyhat" then
|
elseif e.type == "joyhat" then
|
||||||
if e.direction ~= "c" then
|
if e.direction ~= "c" then
|
||||||
|
|||||||
@@ -171,6 +171,20 @@ function Grid:applyFourWide()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Grid:applyCeiling(lines)
|
||||||
|
for row = 1, lines do
|
||||||
|
for col = 1, 9 do
|
||||||
|
self.grid[row][col] = block
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Grid:clearSpecificRow(row)
|
||||||
|
for col = 1, 10 do
|
||||||
|
self.grid[row][col] = empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function Grid:applyPiece(piece)
|
function Grid:applyPiece(piece)
|
||||||
if piece.big then
|
if piece.big then
|
||||||
self:applyBigPiece(piece)
|
self:applyBigPiece(piece)
|
||||||
@@ -216,6 +230,15 @@ function Grid:checkForBravo(cleared_row_count)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Grid:checkStackHeight()
|
||||||
|
for i = 0, 23 do
|
||||||
|
for j = 0, 9 do
|
||||||
|
if self:isOccupied(j, i) then return 24 - i end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
function Grid:checkSecretGrade()
|
function Grid:checkSecretGrade()
|
||||||
local sgrade = 0
|
local sgrade = 0
|
||||||
for i=23,5,-1 do
|
for i=23,5,-1 do
|
||||||
@@ -296,7 +319,32 @@ function Grid:draw()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Grid:drawInvisible(opacity_function, garbage_opacity_function)
|
function Grid:drawOutline()
|
||||||
|
for y = 5, 24 do
|
||||||
|
for x = 1, 10 do
|
||||||
|
if self.grid[y][x] ~= empty then
|
||||||
|
love.graphics.setColor(0.8, 0.8, 0.8, 1)
|
||||||
|
love.graphics.setLineWidth(1)
|
||||||
|
if y > 1 and self.grid[y-1][x] == empty then
|
||||||
|
love.graphics.line(48.0+x*16, -0.5+y*16, 64.0+x*16, -0.5+y*16)
|
||||||
|
end
|
||||||
|
if y < 24 and self.grid[y+1][x] == empty then
|
||||||
|
love.graphics.line(48.0+x*16, 16.5+y*16, 64.0+x*16, 16.5+y*16)
|
||||||
|
end
|
||||||
|
if x > 1 and self.grid[y][x-1] == empty then
|
||||||
|
love.graphics.line(47.5+x*16, -0.0+y*16, 47.5+x*16, 16.0+y*16)
|
||||||
|
end
|
||||||
|
if x < 10 and self.grid[y][x+1] == empty then
|
||||||
|
love.graphics.line(64.5+x*16, -0.0+y*16, 64.5+x*16, 16.0+y*16)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Grid:drawInvisible(opacity_function, garbage_opacity_function, lock_flash, brightness)
|
||||||
|
lock_flash = lock_flash == nil and true or lock_flash
|
||||||
|
brightness = brightness == nil and 0.5 or brightness
|
||||||
for y = 5, 24 do
|
for y = 5, 24 do
|
||||||
for x = 1, 10 do
|
for x = 1, 10 do
|
||||||
if self.grid[y][x] ~= empty then
|
if self.grid[y][x] ~= empty then
|
||||||
@@ -307,22 +355,24 @@ function Grid:drawInvisible(opacity_function, garbage_opacity_function)
|
|||||||
else
|
else
|
||||||
opacity = opacity_function(self.grid_age[y][x])
|
opacity = opacity_function(self.grid_age[y][x])
|
||||||
end
|
end
|
||||||
love.graphics.setColor(0.5, 0.5, 0.5, opacity)
|
love.graphics.setColor(brightness, brightness, brightness, opacity)
|
||||||
love.graphics.draw(blocks[self.grid[y][x].skin][self.grid[y][x].colour], 48+x*16, y*16)
|
love.graphics.draw(blocks[self.grid[y][x].skin][self.grid[y][x].colour], 48+x*16, y*16)
|
||||||
if opacity > 0 and self.grid[y][x].colour ~= "X" then
|
if lock_flash then
|
||||||
love.graphics.setColor(0.64, 0.64, 0.64)
|
if opacity > 0 and self.grid[y][x].colour ~= "X" then
|
||||||
love.graphics.setLineWidth(1)
|
love.graphics.setColor(0.64, 0.64, 0.64)
|
||||||
if y > 1 and self.grid[y-1][x] == empty then
|
love.graphics.setLineWidth(1)
|
||||||
love.graphics.line(48.0+x*16, -0.5+y*16, 64.0+x*16, -0.5+y*16)
|
if y > 1 and self.grid[y-1][x] == empty then
|
||||||
end
|
love.graphics.line(48.0+x*16, -0.5+y*16, 64.0+x*16, -0.5+y*16)
|
||||||
if y < 24 and self.grid[y+1][x] == empty then
|
end
|
||||||
love.graphics.line(48.0+x*16, 16.5+y*16, 64.0+x*16, 16.5+y*16)
|
if y < 24 and self.grid[y+1][x] == empty then
|
||||||
end
|
love.graphics.line(48.0+x*16, 16.5+y*16, 64.0+x*16, 16.5+y*16)
|
||||||
if x > 1 and self.grid[y][x-1] == empty then
|
end
|
||||||
love.graphics.line(47.5+x*16, -0.0+y*16, 47.5+x*16, 16.0+y*16)
|
if x > 1 and self.grid[y][x-1] == empty then
|
||||||
end
|
love.graphics.line(47.5+x*16, -0.0+y*16, 47.5+x*16, 16.0+y*16)
|
||||||
if x < 10 and self.grid[y][x+1] == empty then
|
end
|
||||||
love.graphics.line(64.5+x*16, -0.0+y*16, 64.5+x*16, 16.0+y*16)
|
if x < 10 and self.grid[y][x+1] == empty then
|
||||||
|
love.graphics.line(64.5+x*16, -0.0+y*16, 64.5+x*16, 16.0+y*16)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -78,12 +78,15 @@ function Piece:setRelativeRotation(rot)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function Piece:moveInGrid(step, squares, grid)
|
function Piece:moveInGrid(step, squares, grid, instant)
|
||||||
local moved = false
|
local moved = false
|
||||||
for x = 1, squares do
|
for x = 1, squares do
|
||||||
if grid:canPlacePiece(self:withOffset(step)) then
|
if grid:canPlacePiece(self:withOffset(step)) then
|
||||||
moved = true
|
moved = true
|
||||||
self:setOffset(step)
|
self:setOffset(step)
|
||||||
|
if instant then
|
||||||
|
self:dropToBottom(grid)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ function MarathonA2Game:new()
|
|||||||
self.randomizer = History6RollsRandomizer()
|
self.randomizer = History6RollsRandomizer()
|
||||||
|
|
||||||
self.lock_drop = false
|
self.lock_drop = false
|
||||||
|
self.lock_hard_drop = false
|
||||||
self.enable_hold = false
|
self.enable_hold = false
|
||||||
self.next_queue_length = 1
|
self.next_queue_length = 1
|
||||||
end
|
end
|
||||||
@@ -124,7 +125,8 @@ function MarathonA2Game:onLineClear(cleared_row_count)
|
|||||||
self.grid:clear()
|
self.grid:clear()
|
||||||
self.roll_frames = -150
|
self.roll_frames = -150
|
||||||
end
|
end
|
||||||
if self.level >= 900 then self.lock_drop = true end
|
self.lock_drop = self.level >= 900
|
||||||
|
self.lock_hard_drop = self.level >= 900
|
||||||
end
|
end
|
||||||
|
|
||||||
function MarathonA2Game:updateScore(level, drop_bonus, cleared_lines)
|
function MarathonA2Game:updateScore(level, drop_bonus, cleared_lines)
|
||||||
@@ -248,7 +250,7 @@ end
|
|||||||
|
|
||||||
function MarathonA2Game:drawGrid(ruleset)
|
function MarathonA2Game:drawGrid(ruleset)
|
||||||
if self.clear and not (self.completed or self.game_over) then
|
if self.clear and not (self.completed or self.game_over) then
|
||||||
self.grid:drawInvisible(self.rollOpacityFunction)
|
self.grid:drawInvisible(self.rollOpacityFunction, nil, false)
|
||||||
else
|
else
|
||||||
self.grid:draw()
|
self.grid:draw()
|
||||||
if self.piece ~= nil and self.level < 100 then
|
if self.piece ~= nil and self.level < 100 then
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ function GameMode:new()
|
|||||||
self.draw_section_times = false
|
self.draw_section_times = false
|
||||||
self.draw_secondary_section_times = false
|
self.draw_secondary_section_times = false
|
||||||
self.big_mode = false
|
self.big_mode = false
|
||||||
|
self.irs = true
|
||||||
|
self.ihs = true
|
||||||
self.rpc_details = "In game"
|
self.rpc_details = "In game"
|
||||||
-- variables related to configurable parameters
|
-- variables related to configurable parameters
|
||||||
self.drop_locked = false
|
self.drop_locked = false
|
||||||
@@ -94,10 +96,20 @@ function GameMode:update(inputs, ruleset)
|
|||||||
if self.completed then return end
|
if self.completed then return end
|
||||||
|
|
||||||
-- advance one frame
|
-- advance one frame
|
||||||
if self:advanceOneFrame(inputs) == false then return end
|
if self:advanceOneFrame(inputs, ruleset) == false then return end
|
||||||
|
|
||||||
self:chargeDAS(inputs, self:getDasLimit(), self.getARR())
|
self:chargeDAS(inputs, self:getDasLimit(), self.getARR())
|
||||||
|
|
||||||
|
-- set attempt flags
|
||||||
|
if inputs["left"] or inputs["right"] then self:onAttemptPieceMove(self.piece) end
|
||||||
|
if
|
||||||
|
inputs["rotate_left"] or inputs["rotate_right"] or
|
||||||
|
inputs["rotate_left2"] or inputs["rotate_right2"] or
|
||||||
|
inputs["rotate_180"]
|
||||||
|
then
|
||||||
|
self:onAttemptPieceRotate(self.piece)
|
||||||
|
end
|
||||||
|
|
||||||
if self.piece == nil then
|
if self.piece == nil then
|
||||||
self:processDelays(inputs, ruleset)
|
self:processDelays(inputs, ruleset)
|
||||||
else
|
else
|
||||||
@@ -105,7 +117,7 @@ function GameMode:update(inputs, ruleset)
|
|||||||
self:whilePieceActive()
|
self:whilePieceActive()
|
||||||
local gravity = self:getGravity()
|
local gravity = self:getGravity()
|
||||||
|
|
||||||
if self.enable_hold and inputs["hold"] == true and self.held == false then
|
if self.enable_hold and inputs["hold"] == true and self.held == false and self.prev_inputs["hold"] == false then
|
||||||
self:hold(inputs, ruleset)
|
self:hold(inputs, ruleset)
|
||||||
self.prev_inputs = inputs
|
self.prev_inputs = inputs
|
||||||
return
|
return
|
||||||
@@ -198,6 +210,8 @@ end
|
|||||||
|
|
||||||
-- event functions
|
-- event functions
|
||||||
function GameMode:whilePieceActive() end
|
function GameMode:whilePieceActive() end
|
||||||
|
function GameMode:onAttemptPieceMove(piece) end
|
||||||
|
function GameMode:onAttemptPieceRotate(piece) end
|
||||||
function GameMode:onPieceLock(piece, cleared_row_count)
|
function GameMode:onPieceLock(piece, cleared_row_count)
|
||||||
playSE("lock")
|
playSE("lock")
|
||||||
end
|
end
|
||||||
@@ -221,30 +235,66 @@ function GameMode:onGameOver()
|
|||||||
switchBGM(nil)
|
switchBGM(nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GameMode:chargeDAS(inputs)
|
-- DAS functions
|
||||||
if inputs[self.das.direction] == true then
|
|
||||||
local das_frames = self.das.frames + 1
|
function GameMode:startRightDAS()
|
||||||
if das_frames >= self:getDasLimit() then
|
self.move = "right"
|
||||||
if self.das.direction == "left" then
|
self.das = { direction = "right", frames = 0 }
|
||||||
self.move = (self:getARR() == 0 and "speed" or "") .. "left"
|
if self:getDasLimit() == 0 then
|
||||||
self.das.frames = self:getDasLimit() - self:getARR()
|
self:continueDAS()
|
||||||
elseif self.das.direction == "right" then
|
end
|
||||||
self.move = (self:getARR() == 0 and "speed" or "") .. "right"
|
end
|
||||||
self.das.frames = self:getDasLimit() - self:getARR()
|
|
||||||
end
|
function GameMode:startLeftDAS()
|
||||||
else
|
self.move = "left"
|
||||||
self.move = "none"
|
self.das = { direction = "left", frames = 0 }
|
||||||
self.das.frames = das_frames
|
if self:getDasLimit() == 0 then
|
||||||
|
self:continueDAS()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function GameMode:continueDAS()
|
||||||
|
local das_frames = self.das.frames + 1
|
||||||
|
if das_frames >= self:getDasLimit() then
|
||||||
|
if self.das.direction == "left" then
|
||||||
|
self.move = (self:getARR() == 0 and "speed" or "") .. "left"
|
||||||
|
self.das.frames = self:getDasLimit() - self:getARR()
|
||||||
|
elseif self.das.direction == "right" then
|
||||||
|
self.move = (self:getARR() == 0 and "speed" or "") .. "right"
|
||||||
|
self.das.frames = self:getDasLimit() - self:getARR()
|
||||||
end
|
end
|
||||||
elseif inputs["right"] == true then
|
|
||||||
self.move = "right"
|
|
||||||
self.das = { direction = "right", frames = 0 }
|
|
||||||
elseif inputs["left"] == true then
|
|
||||||
self.move = "left"
|
|
||||||
self.das = { direction = "left", frames = 0 }
|
|
||||||
else
|
else
|
||||||
self.move = "none"
|
self.move = "none"
|
||||||
self.das = { direction = "none", frames = -1 }
|
self.das.frames = das_frames
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function GameMode:stopDAS()
|
||||||
|
self.move = "none"
|
||||||
|
self.das = { direction = "none", frames = -1 }
|
||||||
|
end
|
||||||
|
|
||||||
|
function GameMode:chargeDAS(inputs)
|
||||||
|
if config["das_last_key"] then
|
||||||
|
if inputs["right"] == true and self.das.direction ~= "right" and not self.prev_inputs["right"] then
|
||||||
|
self:startRightDAS()
|
||||||
|
elseif inputs["left"] == true and self.das.direction ~= "left" and not self.prev_inputs["left"] then
|
||||||
|
self:startLeftDAS()
|
||||||
|
elseif inputs[self.das.direction] == true then
|
||||||
|
self:continueDAS()
|
||||||
|
else
|
||||||
|
self:stopDAS()
|
||||||
|
end
|
||||||
|
else -- default behaviour, das first key pressed
|
||||||
|
if inputs[self.das.direction] == true then
|
||||||
|
self:continueDAS()
|
||||||
|
elseif inputs["right"] == true then
|
||||||
|
self:startRightDAS()
|
||||||
|
elseif inputs["left"] == true then
|
||||||
|
self:startLeftDAS()
|
||||||
|
else
|
||||||
|
self:stopDAS()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -268,6 +318,18 @@ function GameMode:processDelays(inputs, ruleset, drop_speed)
|
|||||||
end
|
end
|
||||||
elseif self.lcd > 0 then
|
elseif self.lcd > 0 then
|
||||||
self.lcd = self.lcd - 1
|
self.lcd = self.lcd - 1
|
||||||
|
if ruleset.are_cancel and
|
||||||
|
(self.move == "none" and not self.prev_inputs["up"] and
|
||||||
|
not self.prev_inputs["rotate_left"] and not self.prev_inputs["rotate_left2"] and
|
||||||
|
not self.prev_inputs["rotate_right"] and not self.prev_inputs["rotate_right2"] and
|
||||||
|
not self.prev_inputs["rotate_180"]) and
|
||||||
|
(inputs["left"] or inputs["right"] or inputs["up"] or
|
||||||
|
inputs["rotate_left"] or inputs["rotate_left2"] or
|
||||||
|
inputs["rotate_right"] or inputs["rotate_right2"] or
|
||||||
|
inputs["rotate_180"]) then
|
||||||
|
self.lcd = 0
|
||||||
|
self.are = 0
|
||||||
|
end
|
||||||
if self.lcd == 0 then
|
if self.lcd == 0 then
|
||||||
self.grid:clearClearedRows()
|
self.grid:clearClearedRows()
|
||||||
playSE("fall")
|
playSE("fall")
|
||||||
@@ -277,6 +339,17 @@ function GameMode:processDelays(inputs, ruleset, drop_speed)
|
|||||||
end
|
end
|
||||||
elseif self.are > 0 then
|
elseif self.are > 0 then
|
||||||
self.are = self.are - 1
|
self.are = self.are - 1
|
||||||
|
if ruleset.are_cancel and
|
||||||
|
(self.move == "none" and not self.prev_inputs["up"] and
|
||||||
|
not self.prev_inputs["rotate_left"] and not self.prev_inputs["rotate_left2"] and
|
||||||
|
not self.prev_inputs["rotate_right"] and not self.prev_inputs["rotate_right2"] and
|
||||||
|
not self.prev_inputs["rotate_180"]) and
|
||||||
|
(inputs["left"] or inputs["right"] or inputs["up"] or
|
||||||
|
inputs["rotate_left"] or inputs["rotate_left2"] or
|
||||||
|
inputs["rotate_right"] or inputs["rotate_right2"] or
|
||||||
|
inputs["rotate_180"]) then
|
||||||
|
self.are = 0
|
||||||
|
end
|
||||||
if self.are == 0 then
|
if self.are == 0 then
|
||||||
self:initializeOrHold(inputs, ruleset)
|
self:initializeOrHold(inputs, ruleset)
|
||||||
end
|
end
|
||||||
@@ -284,7 +357,7 @@ function GameMode:processDelays(inputs, ruleset, drop_speed)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function GameMode:initializeOrHold(inputs, ruleset)
|
function GameMode:initializeOrHold(inputs, ruleset)
|
||||||
if self.enable_hold and inputs["hold"] == true then
|
if self.ihs and self.enable_hold and inputs["hold"] == true then
|
||||||
self:hold(inputs, ruleset)
|
self:hold(inputs, ruleset)
|
||||||
else
|
else
|
||||||
self:initializeNextPiece(inputs, ruleset, self.next_queue[1])
|
self:initializeNextPiece(inputs, ruleset, self.next_queue[1])
|
||||||
@@ -324,7 +397,8 @@ function GameMode:initializeNextPiece(inputs, ruleset, piece_data, generate_next
|
|||||||
inputs, piece_data, self.grid, gravity,
|
inputs, piece_data, self.grid, gravity,
|
||||||
self.prev_inputs, self.move,
|
self.prev_inputs, self.move,
|
||||||
self:getLockDelay(), self:getDropSpeed(),
|
self:getLockDelay(), self:getDropSpeed(),
|
||||||
self.lock_drop, self.lock_hard_drop, self.big_mode
|
self.lock_drop, self.lock_hard_drop, self.big_mode,
|
||||||
|
self.irs
|
||||||
)
|
)
|
||||||
if self.lock_drop then
|
if self.lock_drop then
|
||||||
self.drop_locked = true
|
self.drop_locked = true
|
||||||
@@ -388,7 +462,7 @@ function GameMode:drawNextQueue(ruleset)
|
|||||||
drawPiece(next_piece, skin, ruleset.block_offsets[next_piece][rotation], -16+i*80, -32)
|
drawPiece(next_piece, skin, ruleset.block_offsets[next_piece][rotation], -16+i*80, -32)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if self.hold_queue ~= nil then
|
if self.hold_queue ~= nil and self.enable_hold then
|
||||||
local hold_color = self.held and 0.6 or 1
|
local hold_color = self.held and 0.6 or 1
|
||||||
self:setHoldOpacity(1, hold_color)
|
self:setHoldOpacity(1, hold_color)
|
||||||
drawPiece(
|
drawPiece(
|
||||||
@@ -445,7 +519,7 @@ function GameMode:drawSectionTimes(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 - self.section_start_time), section_x, 40 + 20 * current_section, 90, "left")
|
||||||
end
|
end
|
||||||
|
|
||||||
function GameMode:drawSectionTimesWithSecondary(current_section)
|
function GameMode:drawSectionTimesWithSecondary(current_section, section_colour_function)
|
||||||
local section_x = 530
|
local section_x = 530
|
||||||
local section_secondary_x = 440
|
local section_secondary_x = 440
|
||||||
|
|
||||||
@@ -456,6 +530,9 @@ function GameMode:drawSectionTimesWithSecondary(current_section)
|
|||||||
end
|
end
|
||||||
|
|
||||||
for section, time in pairs(self.secondary_section_times) do
|
for section, time in pairs(self.secondary_section_times) do
|
||||||
|
if self.section_colour_function then
|
||||||
|
love.graphics.setColor(self:section_colour_function(section))
|
||||||
|
end
|
||||||
if section > 0 then
|
if section > 0 then
|
||||||
love.graphics.printf(formatTime(time), section_secondary_x, 40 + 20 * section, 90, "left")
|
love.graphics.printf(formatTime(time), section_secondary_x, 40 + 20 * section, 90, "left")
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ function Marathon2020Game:advanceOneFrame()
|
|||||||
if self.roll_frames < 0 then
|
if self.roll_frames < 0 then
|
||||||
return false
|
return false
|
||||||
elseif self.roll_frames > 4000 then
|
elseif self.roll_frames > 4000 then
|
||||||
|
if self.grade >= 30 and self.section_cool_count >= 20 then self.grade = 31 end
|
||||||
self.completed = true
|
self.completed = true
|
||||||
end
|
end
|
||||||
elseif self.ready_frames == 0 then
|
elseif self.ready_frames == 0 then
|
||||||
@@ -248,6 +249,7 @@ function Marathon2020Game:updateGrade(cleared_lines)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Marathon2020Game:getTotalGrade()
|
function Marathon2020Game:getTotalGrade()
|
||||||
|
if self.grade + self.section_cool_count > 50 then return "GM" end
|
||||||
return self.grade + self.section_cool_count
|
return self.grade + self.section_cool_count
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -325,10 +327,10 @@ function Marathon2020Game:checkClear(level)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Marathon2020Game:updateSectionTimes(old_level, new_level)
|
function Marathon2020Game:updateSectionTimes(old_level, new_level)
|
||||||
function sectionCool()
|
function sectionCool(section)
|
||||||
self.section_cool_count = self.section_cool_count + 1
|
self.section_cool_count = self.section_cool_count + 1
|
||||||
self.delay_level = math.min(20, self.delay_level + 1)
|
self.delay_level = math.min(20, self.delay_level + 1)
|
||||||
table.insert(self.section_status, "cool")
|
if section < 10 then table.insert(self.section_status, "cool") end
|
||||||
self.cool_timer = 300
|
self.cool_timer = 300
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -346,7 +348,7 @@ function Marathon2020Game:updateSectionTimes(old_level, new_level)
|
|||||||
table.insert(self.section_times, section_time)
|
table.insert(self.section_times, section_time)
|
||||||
self.section_start_time = self.frames
|
self.section_start_time = self.frames
|
||||||
|
|
||||||
if section > 4 then self.delay_level = math.min(20, self.delay_level + 1) end
|
if section > 5 then self.delay_level = math.min(20, self.delay_level + 1) end
|
||||||
self:checkTorikan(section)
|
self:checkTorikan(section)
|
||||||
self:checkClear(new_level)
|
self:checkClear(new_level)
|
||||||
|
|
||||||
@@ -355,11 +357,11 @@ function Marathon2020Game:updateSectionTimes(old_level, new_level)
|
|||||||
self.secondary_section_times[section] < self.secondary_section_times[section - 1] + 120 and
|
self.secondary_section_times[section] < self.secondary_section_times[section - 1] + 120 and
|
||||||
self.secondary_section_times[section] < cool_cutoffs[section]
|
self.secondary_section_times[section] < cool_cutoffs[section]
|
||||||
) then
|
) then
|
||||||
sectionCool()
|
sectionCool(section)
|
||||||
elseif self.section_status[section - 1] == "cool" then
|
elseif self.section_status[section - 1] == "cool" then
|
||||||
table.insert(self.section_status, "none")
|
table.insert(self.section_status, "none")
|
||||||
elseif section <= 19 and self.secondary_section_times[section] < cool_cutoffs[section] then
|
elseif section <= 19 and self.secondary_section_times[section] < cool_cutoffs[section] then
|
||||||
sectionCool()
|
sectionCool(section)
|
||||||
else
|
else
|
||||||
table.insert(self.section_status, "none")
|
table.insert(self.section_status, "none")
|
||||||
end
|
end
|
||||||
@@ -392,7 +394,6 @@ Marathon2020Game.mRollOpacityFunction = function(age)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Marathon2020Game:qualifiesForMRoll()
|
function Marathon2020Game:qualifiesForMRoll()
|
||||||
return false -- until I actually have grading working
|
|
||||||
--[[
|
--[[
|
||||||
|
|
||||||
GM-roll requirements
|
GM-roll requirements
|
||||||
@@ -403,6 +404,8 @@ You qualify for the GM roll if you:
|
|||||||
- in less than 13:30.00 total.
|
- in less than 13:30.00 total.
|
||||||
|
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
|
return self.level >= 2020 and self:getTotalGrade() == 50 and self.frames <= frameTime(13,30)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Marathon2020Game:drawGrid()
|
function Marathon2020Game:drawGrid()
|
||||||
@@ -420,6 +423,14 @@ function Marathon2020Game:drawGrid()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Marathon2020Game:sectionColourFunction(section)
|
||||||
|
if self.section_status[section] == "cool" then
|
||||||
|
return { 0, 1, 0, 1 }
|
||||||
|
else
|
||||||
|
return { 1, 1, 1, 1 }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function Marathon2020Game:drawScoringInfo()
|
function Marathon2020Game:drawScoringInfo()
|
||||||
Marathon2020Game.super.drawScoringInfo(self)
|
Marathon2020Game.super.drawScoringInfo(self)
|
||||||
|
|
||||||
@@ -431,7 +442,7 @@ function Marathon2020Game:drawScoringInfo()
|
|||||||
love.graphics.printf("GRADE PTS.", text_x, 200, 90, "left")
|
love.graphics.printf("GRADE PTS.", text_x, 200, 90, "left")
|
||||||
love.graphics.printf("LEVEL", text_x, 320, 40, "left")
|
love.graphics.printf("LEVEL", text_x, 320, 40, "left")
|
||||||
|
|
||||||
self:drawSectionTimesWithSecondary(current_section)
|
self:drawSectionTimesWithSecondary(current_section, self.sectionColourFunction)
|
||||||
|
|
||||||
if (self.cool_timer > 0) then
|
if (self.cool_timer > 0) then
|
||||||
love.graphics.printf("COOL!!", 64, 400, 160, "center")
|
love.graphics.printf("COOL!!", 64, 400, 160, "center")
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ function MarathonA2Game:new()
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.lock_drop = false
|
self.lock_drop = false
|
||||||
|
self.lock_hard_drop = false
|
||||||
self.enable_hold = false
|
self.enable_hold = false
|
||||||
self.next_queue_length = 1
|
self.next_queue_length = 1
|
||||||
end
|
end
|
||||||
@@ -151,7 +152,8 @@ function MarathonA2Game:onLineClear(cleared_row_count)
|
|||||||
if self:qualifiesForMRoll() then self.grade = 32 end
|
if self:qualifiesForMRoll() then self.grade = 32 end
|
||||||
self.roll_frames = -150
|
self.roll_frames = -150
|
||||||
end
|
end
|
||||||
if self.level >= 900 then self.lock_drop = true end
|
self.lock_drop = self.level >= 900
|
||||||
|
self.lock_hard_drop = self.level >= 900
|
||||||
end
|
end
|
||||||
|
|
||||||
function MarathonA2Game:updateSectionTimes(old_level, new_level)
|
function MarathonA2Game:updateSectionTimes(old_level, new_level)
|
||||||
@@ -308,12 +310,12 @@ MarathonA2Game.mRollOpacityFunction = function(age)
|
|||||||
else return 1 - age / 4 end
|
else return 1 - age / 4 end
|
||||||
end
|
end
|
||||||
|
|
||||||
function MarathonA2Game:drawGrid(ruleset)
|
function MarathonA2Game:drawGrid()
|
||||||
if self.clear and not (self.completed or self.game_over) then
|
if self.clear and not (self.completed or self.game_over) then
|
||||||
if self:qualifiesForMRoll() then
|
if self:qualifiesForMRoll() then
|
||||||
self.grid:drawInvisible(self.mRollOpacityFunction)
|
self.grid:drawInvisible(self.mRollOpacityFunction, nil, false)
|
||||||
else
|
else
|
||||||
self.grid:drawInvisible(self.rollOpacityFunction)
|
self.grid:drawInvisible(self.rollOpacityFunction, nil, false)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self.grid:draw()
|
self.grid:draw()
|
||||||
|
|||||||
@@ -231,8 +231,8 @@ function MarathonA3Game:updateSectionTimes(old_level, new_level)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function MarathonA3Game:updateScore(level, drop_bonus, cleared_lines)
|
function MarathonA3Game:updateScore(level, drop_bonus, cleared_lines)
|
||||||
if not self.clear then
|
self:updateGrade(cleared_lines)
|
||||||
self:updateGrade(cleared_lines)
|
if not self.clear then
|
||||||
if cleared_lines > 0 then
|
if cleared_lines > 0 then
|
||||||
self.combo = self.combo + (cleared_lines - 1) * 2
|
self.combo = self.combo + (cleared_lines - 1) * 2
|
||||||
self.score = self.score + (
|
self.score = self.score + (
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ function MarathonAX4Game:new()
|
|||||||
self.section_clear = false
|
self.section_clear = false
|
||||||
|
|
||||||
self.lock_drop = true
|
self.lock_drop = true
|
||||||
|
self.lock_hard_drop = true
|
||||||
self.enable_hold = true
|
self.enable_hold = true
|
||||||
self.next_queue_length = 3
|
self.next_queue_length = 3
|
||||||
end
|
end
|
||||||
@@ -145,7 +146,7 @@ function MarathonAX4Game:drawScoringInfo()
|
|||||||
strTrueValues(self.prev_inputs)
|
strTrueValues(self.prev_inputs)
|
||||||
)
|
)
|
||||||
love.graphics.printf("NEXT", 64, 40, 40, "left")
|
love.graphics.printf("NEXT", 64, 40, 40, "left")
|
||||||
love.graphics.printf("TIME LEFT", 240, 250, 80, "left")
|
if self.lines < 150 then love.graphics.printf("TIME LEFT", 240, 250, 80, "left") end
|
||||||
love.graphics.printf("LINES", 240, 320, 40, "left")
|
love.graphics.printf("LINES", 240, 320, 40, "left")
|
||||||
|
|
||||||
local current_section = math.floor(self.lines / 10) + 1
|
local current_section = math.floor(self.lines / 10) + 1
|
||||||
@@ -160,7 +161,7 @@ function MarathonAX4Game:drawScoringInfo()
|
|||||||
if not self.game_over and not self.clear and time_left < frameTime(0,10) and time_left % 4 < 2 then
|
if not self.game_over and not self.clear and time_left < frameTime(0,10) and time_left % 4 < 2 then
|
||||||
love.graphics.setColor(1, 0.3, 0.3, 1)
|
love.graphics.setColor(1, 0.3, 0.3, 1)
|
||||||
end
|
end
|
||||||
love.graphics.printf(formatTime(time_left), 240, 270, 160, "left")
|
if self.lines < 150 then love.graphics.printf(formatTime(time_left), 240, 270, 160, "left") end
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ function PhantomManiaGame:new()
|
|||||||
PhantomManiaGame.super:new()
|
PhantomManiaGame.super:new()
|
||||||
|
|
||||||
self.lock_drop = true
|
self.lock_drop = true
|
||||||
|
self.lock_hard_drop = true
|
||||||
self.next_queue_length = 1
|
self.next_queue_length = 1
|
||||||
|
|
||||||
self.SGnames = {
|
self.SGnames = {
|
||||||
@@ -138,7 +139,7 @@ end
|
|||||||
|
|
||||||
function PhantomManiaGame:drawGrid()
|
function PhantomManiaGame:drawGrid()
|
||||||
if not (self.game_over or self.clear) then
|
if not (self.game_over or self.clear) then
|
||||||
self.grid:drawInvisible(self.rollOpacityFunction)
|
self.grid:drawInvisible(self.rollOpacityFunction, nil, false)
|
||||||
else
|
else
|
||||||
self.grid:draw()
|
self.grid:draw()
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ function PhantomMania2Game:new()
|
|||||||
self.randomizer = History6RollsRandomizer()
|
self.randomizer = History6RollsRandomizer()
|
||||||
|
|
||||||
self.lock_drop = true
|
self.lock_drop = true
|
||||||
|
self.lock_hard_drop = true
|
||||||
self.enable_hold = true
|
self.enable_hold = true
|
||||||
self.next_queue_length = 3
|
self.next_queue_length = 3
|
||||||
|
|
||||||
@@ -254,7 +255,7 @@ PhantomMania2Game.garbageOpacityFunction = function(age)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function PhantomMania2Game:drawGrid()
|
function PhantomMania2Game:drawGrid()
|
||||||
if not (self.game_over or (self.clear and self.level < 1300)) then
|
if not (self.game_over) then
|
||||||
self.grid:drawInvisible(self.rollOpacityFunction, self.garbageOpacityFunction)
|
self.grid:drawInvisible(self.rollOpacityFunction, self.garbageOpacityFunction)
|
||||||
else
|
else
|
||||||
self.grid:draw()
|
self.grid:draw()
|
||||||
|
|||||||
22
tetris/modes/phantom_mania_n.lua
Normal file
22
tetris/modes/phantom_mania_n.lua
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
local PhantomManiaGame = require 'tetris.modes.phantom_mania'
|
||||||
|
|
||||||
|
local PhantomManiaNGame = PhantomManiaGame:extend()
|
||||||
|
|
||||||
|
PhantomManiaNGame.name = "Phantom Mania N"
|
||||||
|
PhantomManiaNGame.hash = "PhantomManiaN"
|
||||||
|
PhantomManiaNGame.tagline = "The old mode from Nullpomino, for Ti-ARS and SRS support."
|
||||||
|
|
||||||
|
function PhantomManiaNGame:new()
|
||||||
|
PhantomManiaNGame.super:new()
|
||||||
|
|
||||||
|
self.SGnames = {
|
||||||
|
"M1", "M2", "M3", "M4", "M5", "M6", "M7", "M8", "M9",
|
||||||
|
"M10", "M11", "M12", "M13", "M14", "M15", "M16", "M17", "M18",
|
||||||
|
"GM"
|
||||||
|
}
|
||||||
|
|
||||||
|
self.next_queue_length = 3
|
||||||
|
self.enable_hold = true
|
||||||
|
end
|
||||||
|
|
||||||
|
return PhantomManiaNGame
|
||||||
@@ -27,6 +27,7 @@ function Survival2020Game:new()
|
|||||||
self.randomizer = History6RollsRandomizer()
|
self.randomizer = History6RollsRandomizer()
|
||||||
|
|
||||||
self.lock_drop = true
|
self.lock_drop = true
|
||||||
|
self.lock_hard_drop = true
|
||||||
self.enable_hold = true
|
self.enable_hold = true
|
||||||
self.next_queue_length = 3
|
self.next_queue_length = 3
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ function SurvivalA2Game:new()
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.lock_drop = true
|
self.lock_drop = true
|
||||||
|
self.lock_hard_drop = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function SurvivalA2Game:getARE()
|
function SurvivalA2Game:getARE()
|
||||||
@@ -160,6 +161,7 @@ function SurvivalA2Game:drawScoringInfo()
|
|||||||
if self.roll_frames > 2968 then love.graphics.setColor(1, 0.5, 0, 1)
|
if self.roll_frames > 2968 then love.graphics.setColor(1, 0.5, 0, 1)
|
||||||
elseif self.clear then love.graphics.setColor(0, 1, 0, 1) end
|
elseif self.clear then love.graphics.setColor(0, 1, 0, 1) end
|
||||||
if self:getLetterGrade() ~= "" then love.graphics.printf(self:getLetterGrade(), text_x, 140, 90, "left") end
|
if self:getLetterGrade() ~= "" then love.graphics.printf(self:getLetterGrade(), text_x, 140, 90, "left") end
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
love.graphics.printf(self.level, text_x, 340, 40, "right")
|
love.graphics.printf(self.level, text_x, 340, 40, "right")
|
||||||
love.graphics.printf(self:getSectionEndLevel(), text_x, 370, 40, "right")
|
love.graphics.printf(self:getSectionEndLevel(), text_x, 370, 40, "right")
|
||||||
if sg >= 5 then
|
if sg >= 5 then
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ function SurvivalA3Game:new()
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.lock_drop = true
|
self.lock_drop = true
|
||||||
|
self.lock_hard_drop = true
|
||||||
self.enable_hold = true
|
self.enable_hold = true
|
||||||
self.next_queue_length = 3
|
self.next_queue_length = 3
|
||||||
|
|
||||||
|
|||||||
@@ -112,9 +112,9 @@ end
|
|||||||
|
|
||||||
function ARS:get180RotationValue()
|
function ARS:get180RotationValue()
|
||||||
if config.gamesettings.world_reverse == 3 then
|
if config.gamesettings.world_reverse == 3 then
|
||||||
return 3
|
|
||||||
else
|
|
||||||
return 1
|
return 1
|
||||||
|
else
|
||||||
|
return 3
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,8 @@ function ARS:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
|||||||
|
|
||||||
if piece.shape == "I" then
|
if piece.shape == "I" then
|
||||||
-- special kick rules for I
|
-- special kick rules for I
|
||||||
if new_piece.rotation == 0 or new_piece.rotation == 2 then
|
if new_piece.rotation == 0 or new_piece.rotation == 2 and
|
||||||
|
(piece:isMoveBlocked(grid, {x=-1, y=0}) or piece:isMoveBlocked(grid, {x=1, y=0})) then
|
||||||
-- kick right, right2, left
|
-- kick right, right2, left
|
||||||
if grid:canPlacePiece(new_piece:withOffset({x=1, y=0})) then
|
if grid:canPlacePiece(new_piece:withOffset({x=1, y=0})) then
|
||||||
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
|
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
|
||||||
@@ -163,13 +164,16 @@ end
|
|||||||
|
|
||||||
function ARS:onPieceDrop(piece, grid)
|
function ARS:onPieceDrop(piece, grid)
|
||||||
piece.lock_delay = 0 -- step reset
|
piece.lock_delay = 0 -- step reset
|
||||||
|
if piece.floorkick >= 2 and piece:isDropBlocked(grid) then
|
||||||
|
piece.locked = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ARS:onPieceMove(piece, grid)
|
function ARS:onPieceMove(piece, grid)
|
||||||
piece.lock_delay = 0 -- move reset
|
piece.lock_delay = 0 -- move reset
|
||||||
if piece:isDropBlocked(grid) then
|
if piece:isDropBlocked(grid) then
|
||||||
piece.manipulations = piece.manipulations + 1
|
piece.manipulations = piece.manipulations + 1
|
||||||
if piece.manipulations >= 127 then
|
if piece.manipulations >= 128 then
|
||||||
piece.locked = true
|
piece.locked = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -179,17 +183,20 @@ function ARS:onPieceRotate(piece, grid)
|
|||||||
piece.lock_delay = 0 -- rotate reset
|
piece.lock_delay = 0 -- rotate reset
|
||||||
if piece:isDropBlocked(grid) then
|
if piece:isDropBlocked(grid) then
|
||||||
piece.manipulations = piece.manipulations + 1
|
piece.manipulations = piece.manipulations + 1
|
||||||
if piece.manipulations >= 127 then
|
if piece.manipulations >= 128 then
|
||||||
piece.locked = true
|
piece.locked = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if piece.floorkick >= 1 then
|
||||||
|
piece.floorkick = piece.floorkick + 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ARS:get180RotationValue()
|
function ARS:get180RotationValue()
|
||||||
if config.gamesettings.world_reverse == 3 then
|
if config.gamesettings.world_reverse == 3 then
|
||||||
return 3
|
|
||||||
else
|
|
||||||
return 1
|
return 1
|
||||||
|
else
|
||||||
|
return 3
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,8 @@ function ARS:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
|||||||
|
|
||||||
if piece.shape == "I" then
|
if piece.shape == "I" then
|
||||||
-- special kick rules for I
|
-- special kick rules for I
|
||||||
if new_piece.rotation == 0 or new_piece.rotation == 2 then
|
if new_piece.rotation == 0 or new_piece.rotation == 2 and
|
||||||
|
(piece:isMoveBlocked(grid, {x=-1, y=0}) or piece:isMoveBlocked(grid, {x=1, y=0})) then
|
||||||
-- kick right, right2, left
|
-- kick right, right2, left
|
||||||
if grid:canPlacePiece(new_piece:withOffset({x=1, y=0})) then
|
if grid:canPlacePiece(new_piece:withOffset({x=1, y=0})) then
|
||||||
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
|
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
|
||||||
@@ -150,13 +151,16 @@ end
|
|||||||
|
|
||||||
function ARS:onPieceDrop(piece, grid)
|
function ARS:onPieceDrop(piece, grid)
|
||||||
piece.lock_delay = 0 -- step reset
|
piece.lock_delay = 0 -- step reset
|
||||||
|
if piece.floorkick >= 2 and piece:isDropBlocked(grid) then
|
||||||
|
piece.locked = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ARS:onPieceMove(piece, grid)
|
function ARS:onPieceMove(piece, grid)
|
||||||
piece.lock_delay = 0 -- move reset
|
piece.lock_delay = 0 -- move reset
|
||||||
if piece:isDropBlocked(grid) then
|
if piece:isDropBlocked(grid) then
|
||||||
piece.manipulations = piece.manipulations + 1
|
piece.manipulations = piece.manipulations + 1
|
||||||
if piece.manipulations >= 127 then
|
if piece.manipulations >= 128 then
|
||||||
piece.locked = true
|
piece.locked = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -166,17 +170,20 @@ function ARS:onPieceRotate(piece, grid)
|
|||||||
piece.lock_delay = 0 -- rotate reset
|
piece.lock_delay = 0 -- rotate reset
|
||||||
if piece:isDropBlocked(grid) then
|
if piece:isDropBlocked(grid) then
|
||||||
piece.manipulations = piece.manipulations + 1
|
piece.manipulations = piece.manipulations + 1
|
||||||
if piece.manipulations >= 127 then
|
if piece.manipulations >= 128 then
|
||||||
piece.locked = true
|
piece.locked = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if piece.floorkick >= 1 then
|
||||||
|
piece.floorkick = piece.floorkick + 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ARS:get180RotationValue()
|
function ARS:get180RotationValue()
|
||||||
if config.gamesettings.world_reverse == 3 then
|
if config.gamesettings.world_reverse == 3 then
|
||||||
return 3
|
|
||||||
else
|
|
||||||
return 1
|
return 1
|
||||||
|
else
|
||||||
|
return 3
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,8 @@ function ARS:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
|||||||
|
|
||||||
if piece.shape == "I" then
|
if piece.shape == "I" then
|
||||||
-- special kick rules for I
|
-- special kick rules for I
|
||||||
if new_piece.rotation == 0 or new_piece.rotation == 2 then
|
if (new_piece.rotation == 0 or new_piece.rotation == 2) and
|
||||||
|
(piece:isMoveBlocked(grid, {x=-1, y=0}) or piece:isMoveBlocked(grid, {x=1, y=0})) then
|
||||||
-- kick right, right2, left
|
-- kick right, right2, left
|
||||||
if grid:canPlacePiece(new_piece:withOffset({x=1, y=0})) then
|
if grid:canPlacePiece(new_piece:withOffset({x=1, y=0})) then
|
||||||
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
|
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
|
||||||
@@ -149,13 +150,22 @@ end
|
|||||||
|
|
||||||
function ARS:onPieceDrop(piece, grid)
|
function ARS:onPieceDrop(piece, grid)
|
||||||
piece.lock_delay = 0 -- step reset
|
piece.lock_delay = 0 -- step reset
|
||||||
|
if piece.floorkick >= 2 and piece:isDropBlocked(grid) then
|
||||||
|
piece.locked = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ARS:onPieceRotate(piece, grid)
|
||||||
|
if piece.floorkick >= 1 then
|
||||||
|
piece.floorkick = piece.floorkick + 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ARS:get180RotationValue()
|
function ARS:get180RotationValue()
|
||||||
if config.gamesettings.world_reverse == 3 then
|
if config.gamesettings.world_reverse == 3 then
|
||||||
return 3
|
|
||||||
else
|
|
||||||
return 1
|
return 1
|
||||||
|
else
|
||||||
|
return 3
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ Ruleset.softdrop_lock = true
|
|||||||
Ruleset.harddrop_lock = false
|
Ruleset.harddrop_lock = false
|
||||||
|
|
||||||
Ruleset.enable_IRS_wallkicks = false
|
Ruleset.enable_IRS_wallkicks = false
|
||||||
|
Ruleset.are_cancel = false
|
||||||
|
|
||||||
-- Component functions.
|
-- Component functions.
|
||||||
|
|
||||||
@@ -127,16 +128,16 @@ function Ruleset:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
|||||||
-- do nothing in default ruleset
|
-- do nothing in default ruleset
|
||||||
end
|
end
|
||||||
|
|
||||||
function Ruleset:movePiece(piece, grid, move)
|
function Ruleset:movePiece(piece, grid, move, instant)
|
||||||
local x = piece.position.x
|
local x = piece.position.x
|
||||||
if move == "left" then
|
if move == "left" then
|
||||||
piece:moveInGrid({x=-1, y=0}, 1, grid)
|
piece:moveInGrid({x=-1, y=0}, 1, grid, false)
|
||||||
elseif move == "speedleft" then
|
|
||||||
piece:moveInGrid({x=-1, y=0}, 10, grid)
|
|
||||||
elseif move == "right" then
|
elseif move == "right" then
|
||||||
piece:moveInGrid({x=1, y=0}, 1, grid)
|
piece:moveInGrid({x=1, y=0}, 1, grid, false)
|
||||||
|
elseif move == "speedleft" then
|
||||||
|
piece:moveInGrid({x=-1, y=0}, 10, grid, instant)
|
||||||
elseif move == "speedright" then
|
elseif move == "speedright" then
|
||||||
piece:moveInGrid({x=1, y=0}, 10, grid)
|
piece:moveInGrid({x=1, y=0}, 10, grid, instant)
|
||||||
end
|
end
|
||||||
if piece.position.x ~= x then
|
if piece.position.x ~= x then
|
||||||
self:onPieceMove(piece, grid)
|
self:onPieceMove(piece, grid)
|
||||||
@@ -180,7 +181,7 @@ function Ruleset:getDefaultOrientation() return 1 end
|
|||||||
function Ruleset:initializePiece(
|
function Ruleset:initializePiece(
|
||||||
inputs, data, grid, gravity, prev_inputs,
|
inputs, data, grid, gravity, prev_inputs,
|
||||||
move, lock_delay, drop_speed,
|
move, lock_delay, drop_speed,
|
||||||
drop_locked, hard_drop_locked, big
|
drop_locked, hard_drop_locked, big, irs
|
||||||
)
|
)
|
||||||
local spawn_positions
|
local spawn_positions
|
||||||
if big then
|
if big then
|
||||||
@@ -196,7 +197,7 @@ function Ruleset:initializePiece(
|
|||||||
}, self.block_offsets, 0, 0, data.skin, colours[data.shape], big)
|
}, self.block_offsets, 0, 0, data.skin, colours[data.shape], big)
|
||||||
|
|
||||||
self:onPieceCreate(piece)
|
self:onPieceCreate(piece)
|
||||||
self:rotatePiece(inputs, piece, grid, {}, true)
|
if irs then self:rotatePiece(inputs, piece, grid, {}, true) end
|
||||||
self:dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked)
|
self:dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked)
|
||||||
return piece
|
return piece
|
||||||
end
|
end
|
||||||
@@ -211,7 +212,7 @@ function Ruleset:processPiece(
|
|||||||
hard_drop_enabled, additive_gravity
|
hard_drop_enabled, additive_gravity
|
||||||
)
|
)
|
||||||
self:rotatePiece(inputs, piece, grid, prev_inputs, false)
|
self:rotatePiece(inputs, piece, grid, prev_inputs, false)
|
||||||
self:movePiece(piece, grid, move)
|
self:movePiece(piece, grid, move, gravity >= 20)
|
||||||
self:dropPiece(
|
self:dropPiece(
|
||||||
inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked,
|
inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked,
|
||||||
hard_drop_enabled, additive_gravity
|
hard_drop_enabled, additive_gravity
|
||||||
|
|||||||
Reference in New Issue
Block a user