mirror of
https://github.com/SashLilac/cambridge.git
synced 2025-05-13 20:21:25 -05:00
Compare commits
44 Commits
v0.3-beta6
...
v0.3-beta7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffd808e6a0 | ||
|
|
dd96db170e | ||
|
|
7fa547c307 | ||
| b2d0838f90 | |||
|
|
42375cb2b8 | ||
|
|
fe162ed215 | ||
|
|
dda116f00f | ||
|
|
2d3aeeb47d | ||
|
|
784c768c57 | ||
|
|
c18e7ed244 | ||
|
|
9df6bb9989 | ||
|
|
f5873c97bc | ||
|
|
fabdad056e | ||
|
|
0e82a8758c | ||
|
|
e78df19112 | ||
|
|
49775b9578 | ||
|
|
6a3c6ecac0 | ||
|
|
90cf2ebef5 | ||
|
|
799a905a9c | ||
|
|
985f73c39d | ||
|
|
b5db5bbdc3 | ||
|
|
438acde2e2 | ||
|
|
0e1f40ad30 | ||
|
|
6cf6568a57 | ||
|
|
dafc113038 | ||
|
|
923f3d3696 | ||
|
|
db4132bf31 | ||
|
|
c58018dd51 | ||
|
|
c7d0034f9b | ||
|
|
ed5ea72e66 | ||
|
|
dc3ad825dc | ||
|
|
40cba83003 | ||
| a1b3f73787 | |||
|
|
4243d6b2ba | ||
| 33b3ad2889 | |||
|
|
adab1df480 | ||
|
|
711fa830a3 | ||
|
|
c434a3406b | ||
|
|
769b5043e3 | ||
|
|
713c62d807 | ||
|
|
c3f6e34518 | ||
|
|
4d0f6ab9fc | ||
|
|
594aa2620f | ||
|
|
199b535f70 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
*.sav
|
||||
*.love
|
||||
*.zip
|
||||
dist/*.zip
|
||||
dist/**/cambridge.exe
|
||||
dist/**/libs
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2018-2019 Joe Zeng
|
||||
Copyright (c) 2018-2021 Joe Zeng, Ishaan Bhardwaj
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -98,12 +98,14 @@ Other Notable Games
|
||||
- [ZTrix](https://discord.gg/MGhqCBDGNH) by Electra
|
||||
- [Shiromino](https://github.com/shiromino/shiromino) by Felicity/nightmareci/kdex
|
||||
- [Cursed Blocks](https://github.com/Manabender/Cursed-Blocks) by Manabender
|
||||
- Picoris 1/2 by MarkGamed
|
||||
- [Picoris 2](https://www.lexaloffle.com/bbs/?tid=41733) by MarkGamed
|
||||
- [Tetra Online](https://github.com/Juan-Cartes/Tetra-Offline) by Mine
|
||||
- [Techmino](https://discord.gg/6Yuww44tq8) by MrZ
|
||||
- [Example Block Game](https://github.com/oshisaure/example-block-game) by Oshisaure
|
||||
- [TETR.IO](https://tetr.io) by osk
|
||||
- [Master of Blocks](https://discord.gg/72FZ49mjWh) by Phoenix Flare
|
||||
- [Spirit Drop](https://rayblastgames.com/spiritdrop.php) by RayRay26
|
||||
- [Puzzle Trial](https://kagamine-rin.itch.io/puzzle-trial) by Rin
|
||||
- [stackfuse](https://github.com/sinefuse/stackfuse) by sinefuse
|
||||
|
||||

|
||||
|
||||
50
SOURCES.md
50
SOURCES.md
@@ -169,4 +169,52 @@ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
discord-rpc (https://github.com/discord/discord-rpc)
|
||||
--------------------
|
||||
|
||||
Copyright 2017 Discord, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
lua-discordRPC (https://github.com/pfirsich/lua-discordRPC)
|
||||
--------------------
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Joel Schumacher
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -7,5 +7,11 @@
|
||||
@del dist\win32\SOURCES.md
|
||||
@del dist\win32\LICENSE.md
|
||||
@rmdir /Q /S dist\win32\libs
|
||||
@del dist\other\cambridge.love
|
||||
@del dist\other\SOURCES.md
|
||||
@del dist\other\LICENSE.md
|
||||
@rmdir /Q /S dist\other\libs
|
||||
@rmdir /Q /S dist\other
|
||||
@del dist\cambridge-windows.zip
|
||||
@del dist\cambridge-win32.zip
|
||||
@del dist\cambridge-win32.zip
|
||||
@del dist\cambridge-other.zip
|
||||
18
funcs.lua
18
funcs.lua
@@ -1,10 +1,20 @@
|
||||
function copy(t)
|
||||
-- returns deep copy of t (as opposed to the shallow copy you get from var = t)
|
||||
-- returns top-layer shallow copy of t
|
||||
if type(t) ~= "table" then return t end
|
||||
local meta = getmetatable(t)
|
||||
local target = {}
|
||||
for k, v in pairs(t) do target[k] = v end
|
||||
setmetatable(target, meta)
|
||||
for k, v in next, t do target[k] = v end
|
||||
setmetatable(target, getmetatable(t))
|
||||
return target
|
||||
end
|
||||
|
||||
function deepcopy(t)
|
||||
-- returns infinite-layer deep copy of t
|
||||
if type(t) ~= "table" then return t end
|
||||
local target = {}
|
||||
for k, v in next, t do
|
||||
target[deepcopy(k)] = deepcopy(v)
|
||||
end
|
||||
setmetatable(target, deepcopy(getmetatable(t)))
|
||||
return target
|
||||
end
|
||||
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
-- 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 = false
|
||||
local strict = true
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local bigint = {}
|
||||
setmetatable(bigint, {__call = function(_, arg) return bigint.new(arg) end})
|
||||
|
||||
local mt = {
|
||||
__add = function(lhs, rhs)
|
||||
@@ -76,7 +77,7 @@ function bigint.new(num)
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
return bigint.strip(self)
|
||||
end
|
||||
|
||||
-- Check the type of a big
|
||||
@@ -96,6 +97,14 @@ function bigint.check(big, force)
|
||||
return true
|
||||
end
|
||||
|
||||
-- Strip leading zeroes from a big, but don't remove the last zero
|
||||
function bigint.strip(big)
|
||||
while (#big.digits > 1) and (big.digits[1] == 0) do
|
||||
table.remove(big.digits, 1)
|
||||
end
|
||||
return big
|
||||
end
|
||||
|
||||
-- Return a new big with the same digits but with a positive sign (absolute
|
||||
-- value)
|
||||
function bigint.abs(big)
|
||||
@@ -329,12 +338,7 @@ function bigint.subtract_raw(big1, big2)
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
|
||||
-- Strip leading zeroes if any, but not if 0 is the only digit
|
||||
while (#result.digits > 1) and (result.digits[1] == 0) do
|
||||
table.remove(result.digits, 1)
|
||||
end
|
||||
|
||||
return result
|
||||
return bigint.strip(result)
|
||||
end
|
||||
|
||||
-- FRONTEND: Addition and subtraction operations, accounting for signs
|
||||
@@ -364,6 +368,7 @@ function bigint.add(big1, big2)
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
function bigint.subtract(big1, big2)
|
||||
-- Type checking is done by bigint.compare in bigint.add
|
||||
-- Subtracting is like adding a negative
|
||||
@@ -460,7 +465,7 @@ end
|
||||
function bigint.exponentiate(big, power)
|
||||
-- Type checking for big done by bigint.multiply
|
||||
assert(bigint.compare(power, bigint.new(0), ">="),
|
||||
" negative powers are not supported")
|
||||
"negative powers are not supported")
|
||||
local exp = power:clone()
|
||||
|
||||
if (bigint.compare(exp, bigint.new(0), "==")) then
|
||||
@@ -530,12 +535,7 @@ function bigint.divide_raw(big1, big2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove leading zeros from result
|
||||
while (result.digits[1] == 0) do
|
||||
table.remove(result.digits, 1)
|
||||
end
|
||||
|
||||
return result, dividend
|
||||
return bigint.strip(result), dividend
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -24,6 +24,59 @@ if osname == "Linux" then
|
||||
elseif osname == "OS X" then
|
||||
discordRPClib = ffi.load(source.."/libs/discord-rpc.dylib")
|
||||
elseif osname == "Windows" then
|
||||
-- I would strongly advise never touching this. It was not trivial to get correct. -nightmareci
|
||||
|
||||
ffi.cdef[[
|
||||
typedef uint32_t DWORD;
|
||||
typedef char CHAR;
|
||||
typedef CHAR *LPSTR;
|
||||
typedef const CHAR *LPCSTR;
|
||||
typedef wchar_t WCHAR;
|
||||
typedef WCHAR *LPWSTR;
|
||||
typedef LPWSTR PWSTR;
|
||||
typedef const WCHAR *LPCWSTR;
|
||||
|
||||
static const DWORD CP_UTF8 = 65001;
|
||||
int32_t MultiByteToWideChar(
|
||||
DWORD CodePage,
|
||||
DWORD dwFlags,
|
||||
LPCSTR lpMultiByteStr,
|
||||
int32_t cbMultiByte,
|
||||
LPWSTR lpWideCharStr,
|
||||
int32_t cchWideChar
|
||||
);
|
||||
|
||||
int32_t WideCharToMultiByte(
|
||||
DWORD CodePage,
|
||||
DWORD dwFlags,
|
||||
LPCWSTR lpWideCharStr,
|
||||
int32_t cchWideChar,
|
||||
LPSTR lpMultiByteStr,
|
||||
int32_t cbMultiByte,
|
||||
void* lpDefaultChar,
|
||||
void* lpUsedDefaultChar
|
||||
);
|
||||
|
||||
DWORD GetShortPathNameW(
|
||||
LPCWSTR lpszLongPath,
|
||||
LPWSTR lpszShortPath,
|
||||
DWORD cchBuffer
|
||||
);
|
||||
]]
|
||||
|
||||
local originalWideSize = ffi.C.MultiByteToWideChar(ffi.C.CP_UTF8, 0, source, -1, nil, 0)
|
||||
local originalWide = ffi.new('WCHAR[?]', originalWideSize)
|
||||
ffi.C.MultiByteToWideChar(ffi.C.CP_UTF8, 0, source, -1, originalWide, originalWideSize)
|
||||
|
||||
local sourceSize = ffi.C.GetShortPathNameW(originalWide, nil, 0)
|
||||
local sourceWide = ffi.new('WCHAR[?]', sourceSize)
|
||||
ffi.C.GetShortPathNameW(originalWide, sourceWide, sourceSize)
|
||||
|
||||
local sourceChar = ffi.new('char[?]', sourceSize)
|
||||
ffi.C.WideCharToMultiByte(ffi.C.CP_UTF8, 0, sourceWide, sourceSize, sourceChar, sourceSize, nil, nil)
|
||||
|
||||
source = ffi.string(sourceChar)
|
||||
|
||||
discordRPClib = ffi.load(source.."/libs/discord-rpc.dll")
|
||||
else
|
||||
-- Else it crashes later on
|
||||
|
||||
14
load/bgm.lua
14
load/bgm.lua
@@ -7,6 +7,7 @@ bgm = {
|
||||
|
||||
local current_bgm = nil
|
||||
local bgm_locked = false
|
||||
local unfocused = false
|
||||
|
||||
function switchBGM(sound, subsound)
|
||||
if current_bgm ~= nil then
|
||||
@@ -56,7 +57,7 @@ end
|
||||
function resetBGMFadeout(time)
|
||||
current_bgm:setVolume(config.bgm_volume)
|
||||
fading_bgm = false
|
||||
current_bgm:play()
|
||||
resumeBGM()
|
||||
end
|
||||
|
||||
function processBGMFadeout(dt)
|
||||
@@ -70,13 +71,20 @@ function processBGMFadeout(dt)
|
||||
end
|
||||
end
|
||||
|
||||
function pauseBGM()
|
||||
function pauseBGM(f)
|
||||
if f then
|
||||
unfocused = true
|
||||
end
|
||||
if current_bgm ~= nil then
|
||||
current_bgm:pause()
|
||||
end
|
||||
end
|
||||
|
||||
function resumeBGM()
|
||||
function resumeBGM(f)
|
||||
if f and scene.paused and unfocused then
|
||||
unfocused = false
|
||||
return
|
||||
end
|
||||
if current_bgm ~= nil then
|
||||
current_bgm:play()
|
||||
end
|
||||
|
||||
@@ -25,6 +25,15 @@ backgrounds = {
|
||||
game_config = love.graphics.newImage("res/backgrounds/options-game.png"),
|
||||
}
|
||||
|
||||
-- in order, the colors are:
|
||||
-- red, orange, yellow, green, cyan, blue
|
||||
-- magenta (or purple), white, black
|
||||
-- the next three don't have colors tied to them
|
||||
-- F is used for lock flash
|
||||
-- A is a garbage block
|
||||
-- X is an invisible "block"
|
||||
-- don't use these for piece colors when making a ruleset
|
||||
-- all the others are fine to use
|
||||
blocks = {
|
||||
["2tie"] = {
|
||||
R = love.graphics.newImage("res/img/s1.png"),
|
||||
@@ -34,6 +43,8 @@ blocks = {
|
||||
C = love.graphics.newImage("res/img/s2.png"),
|
||||
B = love.graphics.newImage("res/img/s4.png"),
|
||||
M = love.graphics.newImage("res/img/s5.png"),
|
||||
W = love.graphics.newImage("res/img/s9.png"),
|
||||
D = love.graphics.newImage("res/img/s8.png"),
|
||||
F = love.graphics.newImage("res/img/s9.png"),
|
||||
A = love.graphics.newImage("res/img/s8.png"),
|
||||
X = love.graphics.newImage("res/img/s9.png"),
|
||||
@@ -46,6 +57,8 @@ blocks = {
|
||||
C = love.graphics.newImage("res/img/bone.png"),
|
||||
B = love.graphics.newImage("res/img/bone.png"),
|
||||
M = love.graphics.newImage("res/img/bone.png"),
|
||||
W = love.graphics.newImage("res/img/bone.png"),
|
||||
D = love.graphics.newImage("res/img/bone.png"),
|
||||
F = love.graphics.newImage("res/img/bone.png"),
|
||||
A = love.graphics.newImage("res/img/bone.png"),
|
||||
X = love.graphics.newImage("res/img/bone.png"),
|
||||
@@ -58,13 +71,16 @@ blocks = {
|
||||
C = love.graphics.newImage("res/img/gem2.png"),
|
||||
B = love.graphics.newImage("res/img/gem4.png"),
|
||||
M = love.graphics.newImage("res/img/gem5.png"),
|
||||
W = love.graphics.newImage("res/img/gem9.png"),
|
||||
D = love.graphics.newImage("res/img/gem9.png"),
|
||||
F = love.graphics.newImage("res/img/gem9.png"),
|
||||
A = love.graphics.newImage("res/img/gem9.png"),
|
||||
X = love.graphics.newImage("res/img/gem9.png"),
|
||||
},
|
||||
["square"] = {
|
||||
F = love.graphics.newImage("res/img/squares.png"),
|
||||
W = love.graphics.newImage("res/img/squares.png"),
|
||||
Y = love.graphics.newImage("res/img/squareg.png"),
|
||||
F = love.graphics.newImage("res/img/squares.png"),
|
||||
X = love.graphics.newImage("res/img/squares.png"),
|
||||
}
|
||||
}
|
||||
@@ -87,7 +103,7 @@ ColourSchemes = {
|
||||
Z = "R",
|
||||
O = "Y",
|
||||
T = "M",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
for name, blockset in pairs(blocks) do
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
local binser = require 'libs.binser'
|
||||
|
||||
function loadSave()
|
||||
local info = love.filesystem.getInfo(
|
||||
love.filesystem.getSaveDirectory(), "directory"
|
||||
)
|
||||
if not info then
|
||||
love.filesystem.remove(love.filesystem.getSaveDirectory())
|
||||
love.filesystem.createDirectory(love.filesystem.getSaveDirectory())
|
||||
end
|
||||
config = loadFromFile(
|
||||
love.filesystem.getSaveDirectory() .. '/config.sav'
|
||||
)
|
||||
highscores = loadFromFile(
|
||||
love.filesystem.getSaveDirectory() .. '/highscores.sav'
|
||||
)
|
||||
config = loadFromFile('config.sav')
|
||||
highscores = loadFromFile('highscores.sav')
|
||||
end
|
||||
|
||||
function loadFromFile(filename)
|
||||
local save_data, len = binser.readFile(filename)
|
||||
local file_data = love.filesystem.read(filename)
|
||||
if file_data == nil then
|
||||
return {} -- new object
|
||||
end
|
||||
local save_data = binser.deserialize(file_data)
|
||||
if save_data == nil then
|
||||
return {} -- new object
|
||||
end
|
||||
@@ -51,13 +44,13 @@ function initConfig()
|
||||
end
|
||||
|
||||
function saveConfig()
|
||||
binser.writeFile(
|
||||
love.filesystem.getSaveDirectory() .. '/config.sav', config
|
||||
love.filesystem.write(
|
||||
'config.sav', binser.serialize(config)
|
||||
)
|
||||
end
|
||||
|
||||
function saveHighscores()
|
||||
binser.writeFile(
|
||||
love.filesystem.getSaveDirectory() .. '/highscores.sav', highscores
|
||||
love.filesystem.write(
|
||||
'highscores.sav', binser.serialize(highscores)
|
||||
)
|
||||
end
|
||||
|
||||
17
main.lua
17
main.lua
@@ -10,6 +10,7 @@ function love.load()
|
||||
require "load.bigint"
|
||||
require "load.version"
|
||||
loadSave()
|
||||
require "funcs"
|
||||
require "scene"
|
||||
|
||||
--config["side_next"] = false
|
||||
@@ -36,14 +37,14 @@ function initModules()
|
||||
game_modes = {}
|
||||
mode_list = love.filesystem.getDirectoryItems("tetris/modes")
|
||||
for i=1,#mode_list do
|
||||
if(mode_list[i] ~= "gamemode.lua" and mode_list[i] ~= "unrefactored_modes") then
|
||||
if(mode_list[i] ~= "gamemode.lua" and string.sub(mode_list[i], -4) == ".lua") then
|
||||
game_modes[#game_modes+1] = require ("tetris.modes."..string.sub(mode_list[i],1,-5))
|
||||
end
|
||||
end
|
||||
rulesets = {}
|
||||
rule_list = love.filesystem.getDirectoryItems("tetris/rulesets")
|
||||
for i=1,#rule_list do
|
||||
if(rule_list[i] ~= "ruleset.lua" and rule_list[i] ~= "unrefactored_rulesets") then
|
||||
if(rule_list[i] ~= "ruleset.lua" and string.sub(rule_list[i], -4) == ".lua") then
|
||||
rulesets[#rulesets+1] = require ("tetris.rulesets."..string.sub(rule_list[i],1,-5))
|
||||
end
|
||||
end
|
||||
@@ -82,7 +83,7 @@ end
|
||||
|
||||
function love.keypressed(key, scancode)
|
||||
-- global hotkeys
|
||||
if scancode == "f4" then
|
||||
if scancode == "f11" then
|
||||
config["fullscreen"] = not config["fullscreen"]
|
||||
saveConfig()
|
||||
love.window.setFullscreen(config["fullscreen"])
|
||||
@@ -258,11 +259,15 @@ function love.joystickhat(joystick, hat, direction)
|
||||
end
|
||||
end
|
||||
|
||||
function love.wheelmoved(x, y)
|
||||
scene:onInputPress({input=nil, type="wheel", x=x, y=y})
|
||||
end
|
||||
|
||||
function love.focus(f)
|
||||
if f and (scene.title ~= "Game" or not scene.paused) then
|
||||
resumeBGM()
|
||||
if f then
|
||||
resumeBGM(true)
|
||||
else
|
||||
pauseBGM()
|
||||
pauseBGM(true)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
4
release
4
release
@@ -2,8 +2,10 @@
|
||||
mkdir dist
|
||||
mkdir dist/windows
|
||||
mkdir dist/win32
|
||||
cp cambridge.love dist/
|
||||
mkdir dist/other
|
||||
cat dist/windows/love.exe cambridge.love > dist/windows/cambridge.exe
|
||||
zip dist/cambridge-windows.zip dist/windows/* SOURCES.md LICENSE.md
|
||||
cat dist/win32/love.exe cambridge.love > dist/win32/cambridge.exe
|
||||
zip dist/cambridge-win32.zip dist/win32/* SOURCES.md LICENSE.md
|
||||
cp cambridge.love dist/other/
|
||||
zip dist/cambridge-other.zip cambridge.love libs/discord-rpc.* SOURCES.md LICENSE.md
|
||||
10
release.bat
10
release.bat
@@ -5,17 +5,23 @@ mkdir dist\windows
|
||||
mkdir dist\windows\libs
|
||||
mkdir dist\win32
|
||||
mkdir dist\win32\libs
|
||||
mkdir dist\other
|
||||
mkdir dist\other\libs
|
||||
|
||||
copy /b dist\windows\love.exe+cambridge.love dist\windows\cambridge.exe
|
||||
copy /b dist\win32\love.exe+cambridge.love dist\win32\cambridge.exe
|
||||
copy /b cambridge.love dist\other\cambridge.love
|
||||
|
||||
copy libs\discord-rpc.dll dist\windows\libs
|
||||
copy libs\discord-rpc.dll dist\win32\libs
|
||||
copy libs\discord-rpc.* dist\other\libs
|
||||
|
||||
copy SOURCES.md dist\windows
|
||||
copy LICENSE.md dist\windows
|
||||
copy SOURCES.md dist\win32
|
||||
copy LICENSE.md dist\win32
|
||||
copy SOURCES.md dist\other
|
||||
copy LICENSE.md dist\other
|
||||
|
||||
cd dist\windows
|
||||
tar -a -c -f ..\cambridge-windows.zip cambridge.exe *.dll libs *.md
|
||||
@@ -23,4 +29,8 @@ cd ..\..
|
||||
|
||||
cd dist\win32
|
||||
tar -a -c -f ..\cambridge-win32.zip cambridge.exe *.dll libs *.md
|
||||
cd ..\..
|
||||
|
||||
cd dist\other
|
||||
tar -a -c -f ..\cambridge-other.zip cambridge.love libs *.md
|
||||
cd ..\..
|
||||
BIN
res/img/bone.png
BIN
res/img/bone.png
Binary file not shown.
|
Before Width: | Height: | Size: 188 B After Width: | Height: | Size: 151 B |
Binary file not shown.
|
Before Width: | Height: | Size: 153 B After Width: | Height: | Size: 151 B |
Binary file not shown.
|
Before Width: | Height: | Size: 926 B After Width: | Height: | Size: 1.1 KiB |
@@ -5,7 +5,7 @@ CreditsScene.title = "Credits"
|
||||
function CreditsScene:new()
|
||||
self.frames = 0
|
||||
-- higher = slower
|
||||
self.scroll_speed = 1.9
|
||||
self.scroll_speed = 1.85
|
||||
switchBGM("credit_roll", "gm3")
|
||||
end
|
||||
|
||||
@@ -34,14 +34,14 @@ function CreditsScene:render()
|
||||
|
||||
love.graphics.setFont(font_3x5_4)
|
||||
love.graphics.print("Cambridge Credits", 320, 500 - offset)
|
||||
love.graphics.print("THANK YOU\nFOR PLAYING!", 320, math.max(2010 - offset, 240))
|
||||
love.graphics.print("THANK YOU\nFOR PLAYING!", 320, math.max(2030 - offset, 240))
|
||||
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
love.graphics.print("Game Developers", 320, 550 - offset)
|
||||
love.graphics.print("Project Heads", 320, 640 - offset)
|
||||
love.graphics.print("Notable Game Developers", 320, 730 - offset)
|
||||
love.graphics.print("Special Thanks", 320, 980 - offset)
|
||||
love.graphics.print("- Milla", 320, math.max(2090 - offset, 320))
|
||||
love.graphics.print("Special Thanks", 320, 1000 - offset)
|
||||
love.graphics.print("- Milla", 320, math.max(2110 - offset, 320))
|
||||
|
||||
love.graphics.setFont(font_3x5_2)
|
||||
love.graphics.print("Oshisaure\nJoe Zeng", 320, 590 - offset)
|
||||
@@ -51,7 +51,7 @@ function CreditsScene:render()
|
||||
"Electra - ZTrix\nFelicity/nightmareci/kdex - Shiromino\n" ..
|
||||
"Mine - Tetra Online\nMrZ - Techmino\nosk - TETR.IO\n" ..
|
||||
"Phoenix Flare - Master of Blocks\nRayRay26 - Spirit Drop\n" ..
|
||||
"sinefuse - stackfuse",
|
||||
"Rin - Puzzle Trial\nsinefuse - stackfuse",
|
||||
320, 770 - offset
|
||||
)
|
||||
love.graphics.print(
|
||||
@@ -69,7 +69,7 @@ function CreditsScene:render()
|
||||
"Tetra Legends Discord\nTetra Online Discord\nMultimino Discord\n" ..
|
||||
"Hard Drop Discord\nRusty's Systemspace\nCambridge Discord\n" ..
|
||||
"And to you, the player!",
|
||||
320, 1020 - offset
|
||||
320, 1040 - offset
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -100,9 +100,10 @@ function ConfigScene:onInputPress(e)
|
||||
local option = ConfigScene.options[self.highlight]
|
||||
config.gamesettings[option[1]] = Mod1(config.gamesettings[option[1]]-1, #option[4])
|
||||
else
|
||||
playSE("cursor")
|
||||
sld = self[self.options[self.highlight][4]]
|
||||
local sld = self[self.options[self.highlight][4]]
|
||||
sld.value = math.max(sld.min, math.min(sld.max, (sld:getValue() - 5) / (sld.max - sld.min)))
|
||||
sld:update()
|
||||
playSE("cursor")
|
||||
end
|
||||
elseif e.input == "right" or e.scancode == "right" then
|
||||
if not self.options[self.highlight][3] then
|
||||
@@ -110,9 +111,10 @@ function ConfigScene:onInputPress(e)
|
||||
local option = ConfigScene.options[self.highlight]
|
||||
config.gamesettings[option[1]] = Mod1(config.gamesettings[option[1]]+1, #option[4])
|
||||
else
|
||||
playSE("cursor")
|
||||
sld = self[self.options[self.highlight][4]]
|
||||
sld.value = math.max(sld.min, math.min(sld.max, (sld:getValue() + 5) / (sld.max - sld.min)))--math.max(0, (math.floor(sld:getValue())+2)/(sld.max-sld.min))
|
||||
sld.value = math.max(sld.min, math.min(sld.max, (sld:getValue() + 5) / (sld.max - sld.min)))
|
||||
sld:update()
|
||||
playSE("cursor")
|
||||
end
|
||||
elseif e.input == "menu_back" or e.scancode == "delete" or e.scancode == "backspace" then
|
||||
loadSave()
|
||||
|
||||
@@ -6,6 +6,22 @@ current_mode = 1
|
||||
current_ruleset = 1
|
||||
|
||||
function ModeSelectScene:new()
|
||||
-- reload custom modules
|
||||
initModules()
|
||||
if table.getn(game_modes) == 0 or table.getn(rulesets) == 0 then
|
||||
self.display_warning = true
|
||||
current_mode = 1
|
||||
current_ruleset = 1
|
||||
else
|
||||
self.display_warning = false
|
||||
if current_mode > table.getn(game_modes) then
|
||||
current_mode = 1
|
||||
end
|
||||
if current_ruleset > table.getn(rulesets) then
|
||||
current_ruleset = 1
|
||||
end
|
||||
end
|
||||
|
||||
self.menu_state = {
|
||||
mode = current_mode,
|
||||
ruleset = current_ruleset,
|
||||
@@ -19,6 +35,7 @@ function ModeSelectScene:new()
|
||||
rotate_180 = false,
|
||||
hold = false,
|
||||
}
|
||||
self.das = 0
|
||||
DiscordRPC:update({
|
||||
details = "In menus",
|
||||
state = "Choosing a mode",
|
||||
@@ -27,6 +44,17 @@ end
|
||||
|
||||
function ModeSelectScene:update()
|
||||
switchBGM(nil) -- experimental
|
||||
|
||||
if self.das_up or self.das_down then
|
||||
self.das = self.das + 1
|
||||
else
|
||||
self.das = 0
|
||||
end
|
||||
|
||||
if self.das >= 15 then
|
||||
self:changeOption(self.das_up and -1 or 1)
|
||||
self.das = self.das - 4
|
||||
end
|
||||
end
|
||||
|
||||
function ModeSelectScene:render()
|
||||
@@ -36,6 +64,23 @@ function ModeSelectScene:render()
|
||||
0.5, 0.5
|
||||
)
|
||||
|
||||
love.graphics.draw(misc_graphics["select_mode"], 20, 40)
|
||||
|
||||
if self.display_warning then
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
love.graphics.printf(
|
||||
"You have no modes or rulesets.",
|
||||
80, 200, 480, "center"
|
||||
)
|
||||
love.graphics.setFont(font_3x5_2)
|
||||
love.graphics.printf(
|
||||
"Come back to this menu after getting more modes or rulesets. " ..
|
||||
"Press any button to return to the main menu.",
|
||||
80, 250, 480, "center"
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
if self.menu_state.select == "mode" then
|
||||
love.graphics.setColor(1, 1, 1, 0.5)
|
||||
elseif self.menu_state.select == "ruleset" then
|
||||
@@ -52,8 +97,6 @@ function ModeSelectScene:render()
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
|
||||
love.graphics.draw(misc_graphics["select_mode"], 20, 40)
|
||||
|
||||
love.graphics.setFont(font_3x5_2)
|
||||
for idx, mode in pairs(game_modes) do
|
||||
if(idx >= self.menu_state.mode-9 and idx <= self.menu_state.mode+9) then
|
||||
@@ -68,23 +111,37 @@ function ModeSelectScene:render()
|
||||
end
|
||||
|
||||
function ModeSelectScene:onInputPress(e)
|
||||
if e.input == "menu_decide" or e.scancode == "return" then
|
||||
if self.display_warning and e.input then
|
||||
scene = TitleScene()
|
||||
elseif e.type == "wheel" then
|
||||
if e.x % 2 == 1 then
|
||||
self:switchSelect()
|
||||
end
|
||||
if e.y ~= 0 then
|
||||
self:changeOption(-e.y)
|
||||
end
|
||||
elseif e.input == "menu_decide" or e.scancode == "return" then
|
||||
current_mode = self.menu_state.mode
|
||||
current_ruleset = self.menu_state.ruleset
|
||||
config.current_mode = current_mode
|
||||
config.current_ruleset = current_ruleset
|
||||
playSE("mode_decide")
|
||||
saveConfig()
|
||||
scene = GameScene(game_modes[self.menu_state.mode], rulesets[self.menu_state.ruleset], self.secret_inputs)
|
||||
scene = GameScene(
|
||||
game_modes[self.menu_state.mode],
|
||||
rulesets[self.menu_state.ruleset],
|
||||
self.secret_inputs
|
||||
)
|
||||
elseif e.input == "up" or e.scancode == "up" then
|
||||
self:changeOption(-1)
|
||||
playSE("cursor")
|
||||
self.das_up = true
|
||||
self.das_down = nil
|
||||
elseif e.input == "down" or e.scancode == "down" then
|
||||
self:changeOption(1)
|
||||
playSE("cursor")
|
||||
self.das_down = true
|
||||
self.das_up = nil
|
||||
elseif e.input == "left" or e.input == "right" or e.scancode == "left" or e.scancode == "right" then
|
||||
self:switchSelect()
|
||||
playSE("cursor_lr")
|
||||
elseif e.input == "menu_back" or e.scancode == "delete" or e.scancode == "backspace" then
|
||||
scene = TitleScene()
|
||||
elseif e.input then
|
||||
@@ -95,6 +152,10 @@ end
|
||||
function ModeSelectScene:onInputRelease(e)
|
||||
if e.input == "hold" or (e.input and string.sub(e.input, 1, 7) == "rotate_") then
|
||||
self.secret_inputs[e.input] = false
|
||||
elseif e.input == "up" or e.scancode == "up" then
|
||||
self.das_up = nil
|
||||
elseif e.input == "down" or e.scancode == "down" then
|
||||
self.das_down = nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -104,24 +165,26 @@ function ModeSelectScene:changeOption(rel)
|
||||
elseif self.menu_state.select == "ruleset" then
|
||||
self:changeRuleset(rel)
|
||||
end
|
||||
playSE("cursor")
|
||||
end
|
||||
|
||||
function ModeSelectScene:switchSelect(rel)
|
||||
function ModeSelectScene:switchSelect()
|
||||
if self.menu_state.select == "mode" then
|
||||
self.menu_state.select = "ruleset"
|
||||
elseif self.menu_state.select == "ruleset" then
|
||||
self.menu_state.select = "mode"
|
||||
end
|
||||
playSE("cursor_lr")
|
||||
end
|
||||
|
||||
function ModeSelectScene:changeMode(rel)
|
||||
local len = table.getn(game_modes)
|
||||
self.menu_state.mode = (self.menu_state.mode + len + rel - 1) % len + 1
|
||||
self.menu_state.mode = Mod1(self.menu_state.mode + rel, len)
|
||||
end
|
||||
|
||||
function ModeSelectScene:changeRuleset(rel)
|
||||
local len = table.getn(rulesets)
|
||||
self.menu_state.ruleset = (self.menu_state.ruleset + len + rel - 1) % len + 1
|
||||
self.menu_state.ruleset = Mod1(self.menu_state.ruleset + rel, len)
|
||||
end
|
||||
|
||||
return ModeSelectScene
|
||||
|
||||
@@ -349,7 +349,7 @@ function Grid:markSquares()
|
||||
elseif i == 2 then
|
||||
for j = 0, 3 do
|
||||
for k = 0, 3 do
|
||||
self.grid[y+j][x+k].colour = "F"
|
||||
self.grid[y+j][x+k].colour = "W"
|
||||
self.grid[y+j][x+k].skin = "square"
|
||||
end
|
||||
|
||||
|
||||
@@ -126,9 +126,6 @@ function GameMode:update(inputs, ruleset)
|
||||
if inputs["left"] or inputs["right"] then
|
||||
inputs["up"] = false
|
||||
inputs["down"] = false
|
||||
elseif inputs["up"] or inputs["down"] then
|
||||
inputs["left"] = false
|
||||
inputs["right"] = false
|
||||
end
|
||||
end
|
||||
|
||||
@@ -490,20 +487,15 @@ end
|
||||
|
||||
function GameMode:initializeOrHold(inputs, ruleset)
|
||||
if (
|
||||
(self.frames == 0 or (ruleset.are and self:getARE() ~= 0)) and self.ihs or false
|
||||
(self.frames == 0 or (ruleset.are and self:getARE() ~= 0))
|
||||
and self.ihs or false
|
||||
) and self.enable_hold and inputs["hold"] == true then
|
||||
self:hold(inputs, ruleset, true)
|
||||
else
|
||||
self:initializeNextPiece(inputs, ruleset, self.next_queue[1])
|
||||
end
|
||||
self:onPieceEnter()
|
||||
if not self.grid:canPlacePiece(self.piece) then
|
||||
self.game_over = true
|
||||
end
|
||||
ruleset:dropPiece(
|
||||
inputs, self.piece, self.grid, self:getGravity(),
|
||||
self:getDropSpeed(), self.drop_locked, self.hard_drop_locked
|
||||
)
|
||||
self:onEnterOrHold(inputs, ruleset)
|
||||
end
|
||||
|
||||
function GameMode:hold(inputs, ruleset, ihs)
|
||||
@@ -516,7 +508,7 @@ function GameMode:hold(inputs, ruleset, ihs)
|
||||
self.hold_queue = {
|
||||
skin = self.piece.skin,
|
||||
shape = self.piece.shape,
|
||||
orientation = ruleset:getDefaultOrientation(),
|
||||
orientation = ruleset:getDefaultOrientation(self.piece.shape),
|
||||
}
|
||||
end
|
||||
if data == nil then
|
||||
@@ -525,21 +517,35 @@ function GameMode:hold(inputs, ruleset, ihs)
|
||||
self:initializeNextPiece(inputs, ruleset, data, false)
|
||||
end
|
||||
self.held = true
|
||||
if ihs then playSE("ihs")
|
||||
else playSE("hold") end
|
||||
self:onHold()
|
||||
if not self.grid:canPlacePiece(self.piece) then
|
||||
self.game_over = true
|
||||
if ihs then
|
||||
playSE("ihs")
|
||||
else
|
||||
playSE("hold")
|
||||
self:onEnterOrHold(inputs, ruleset)
|
||||
end
|
||||
end
|
||||
|
||||
function GameMode:initializeNextPiece(inputs, ruleset, piece_data, generate_next_piece)
|
||||
if not self.buffer_soft_drop and self.lock_drop or (
|
||||
function GameMode:onEnterOrHold(inputs, ruleset)
|
||||
if not self.grid:canPlacePiece(self.piece) then
|
||||
self.game_over = true
|
||||
return
|
||||
end
|
||||
ruleset:dropPiece(
|
||||
inputs, self.piece, self.grid, self:getGravity(),
|
||||
self:getDropSpeed(), self.drop_locked, self.hard_drop_locked
|
||||
)
|
||||
end
|
||||
|
||||
function GameMode:initializeNextPiece(
|
||||
inputs, ruleset, piece_data, generate_next_piece
|
||||
)
|
||||
if not inputs.hold and not self.buffer_soft_drop and self.lock_drop or (
|
||||
not ruleset.are or self:getARE() == 0
|
||||
) then
|
||||
self.drop_locked = true
|
||||
end
|
||||
if not self.buffer_hard_drop and self.lock_hard_drop or (
|
||||
if not inputs.hold and not self.buffer_hard_drop and self.lock_hard_drop or (
|
||||
not ruleset.are or self:getARE() == 0
|
||||
) then
|
||||
self.hard_drop_locked = true
|
||||
@@ -683,7 +689,9 @@ function GameMode:drawPiece()
|
||||
end
|
||||
|
||||
function GameMode:drawGhostPiece(ruleset)
|
||||
if self.piece == nil then return end
|
||||
if self.piece == nil or not self.grid:canPlacePiece(self.piece) then
|
||||
return
|
||||
end
|
||||
local ghost_piece = self.piece:withOffset({x=0, y=0})
|
||||
ghost_piece.ghost = true
|
||||
ghost_piece:dropToBottom(self.grid)
|
||||
@@ -853,15 +861,7 @@ function GameMode:drawFrame()
|
||||
-- game frame
|
||||
if self.grid.width == 10 and self.grid.height == 24 then
|
||||
love.graphics.draw(misc_graphics["frame"], 48, 64)
|
||||
end
|
||||
|
||||
love.graphics.setColor(0, 0, 0, 200)
|
||||
love.graphics.rectangle(
|
||||
"fill", 64, 80,
|
||||
16 * self.grid.width, 16 * (self.grid.height - 4)
|
||||
)
|
||||
|
||||
if self.grid.width ~= 10 or self.grid.height ~= 24 then
|
||||
else
|
||||
love.graphics.setColor(174/255, 83/255, 76/255, 1)
|
||||
love.graphics.setLineWidth(8)
|
||||
love.graphics.line(
|
||||
@@ -881,6 +881,11 @@ function GameMode:drawFrame()
|
||||
60,76
|
||||
)
|
||||
love.graphics.setLineWidth(1)
|
||||
love.graphics.setColor(0, 0, 0, 200)
|
||||
love.graphics.rectangle(
|
||||
"fill", 64, 80,
|
||||
16 * self.grid.width, 16 * (self.grid.height - 4)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -897,7 +902,20 @@ end
|
||||
|
||||
function GameMode:drawCustom() end
|
||||
|
||||
function GameMode:drawIfPaused()
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
love.graphics.printf("GAME PAUSED!", 64, 160, 160, "center")
|
||||
end
|
||||
|
||||
-- transforms specified in here will transform the whole screen
|
||||
-- if you want a transform for a particular component, push the
|
||||
-- default transform by using love.graphics.push(), do your
|
||||
-- transform, and then love.graphics.pop() at the end of that
|
||||
-- component's draw call!
|
||||
function GameMode:transformScreen() end
|
||||
|
||||
function GameMode:draw(paused)
|
||||
self:transformScreen()
|
||||
self:drawBackground()
|
||||
self:drawFrame()
|
||||
self:drawGrid()
|
||||
@@ -919,9 +937,8 @@ function GameMode:draw(paused)
|
||||
)
|
||||
end
|
||||
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
if paused then
|
||||
love.graphics.printf("GAME PAUSED!", 64, 160, 160, "center")
|
||||
self:drawIfPaused()
|
||||
end
|
||||
|
||||
if self.completed then
|
||||
|
||||
@@ -290,10 +290,10 @@ function Marathon2020Game:sectionPassed(old_level, new_level)
|
||||
end
|
||||
|
||||
function Marathon2020Game:checkTorikan(section)
|
||||
if section == 5 and self.frames < frameTime(6,00,00) then self.torikan_passed[500] = true end
|
||||
if section == 9 and self.frames < frameTime(8,30,00) then self.torikan_passed[900] = true end
|
||||
if section == 10 and self.frames < frameTime(8,45,00) then self.torikan_passed[1000] = true end
|
||||
if section == 15 and self.frames < frameTime(11,30,00) then self.torikan_passed[1500] = true end
|
||||
if section == 5 and self.frames < frameTime(8,00,00) then self.torikan_passed[500] = true end
|
||||
if section == 9 and self.frames < frameTime(10,30,00) then self.torikan_passed[900] = true end
|
||||
if section == 10 and self.frames < frameTime(10,45,00) then self.torikan_passed[1000] = true end
|
||||
if section == 15 and self.frames < frameTime(12,30,00) then self.torikan_passed[1500] = true end
|
||||
if section == 19 and self.frames < frameTime(13,15,00) then self.torikan_passed[1900] = true end
|
||||
end
|
||||
|
||||
@@ -354,7 +354,7 @@ function Marathon2020Game:updateSectionTimes(old_level, new_level)
|
||||
|
||||
if (
|
||||
self.section_status[section - 1] == "cool" and
|
||||
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[self.delay_level]
|
||||
) then
|
||||
sectionCool(section)
|
||||
@@ -407,11 +407,12 @@ GM-roll requirements
|
||||
You qualify for the GM roll if you:
|
||||
- Reach level 2020
|
||||
- with a grade of 50
|
||||
- and at least 25,000 grade points
|
||||
- in less than 13:30.00 total.
|
||||
|
||||
]]--
|
||||
|
||||
return self.level >= 2020 and self:getTotalGrade() == 50 and self.frames <= frameTime(13,30)
|
||||
return self.level >= 2020 and self:getTotalGrade() == 50 and self.grade_points >= 25000 and self.frames <= frameTime(13,30)
|
||||
end
|
||||
|
||||
function Marathon2020Game:drawGrid()
|
||||
|
||||
@@ -218,16 +218,11 @@ function MarathonA3Game:updateSectionTimes(old_level, new_level)
|
||||
section_70_time = self.frames - self.section_start_time
|
||||
table.insert(self.secondary_section_times, section_70_time)
|
||||
|
||||
if section <= 9 and self.section_status[section - 1] == "cool" and
|
||||
self.secondary_section_times[section] < self.secondary_section_times[section - 1] + 120 then
|
||||
if section <= 9 and self.secondary_section_times[section] < cool_cutoffs[section] and
|
||||
(section == 1 or self.secondary_section_times[section] <= self.secondary_section_times[section - 1] + 120) then
|
||||
self.section_cool = true
|
||||
self.coolregret_message = "COOL!!"
|
||||
self.coolregret_timer = 300
|
||||
elseif self.section_status[section - 1] == "cool" then self.section_cool = false
|
||||
elseif section <= 9 and self.secondary_section_times[section] < cool_cutoffs[section] then
|
||||
self.section_cool = true
|
||||
self.coolregret_message = "COOL!!"
|
||||
self.coolregret_timer = 300
|
||||
self.coolregret_timer = 300
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -41,7 +41,7 @@ function PhantomManiaGame:getARE()
|
||||
end
|
||||
|
||||
function PhantomManiaGame:getLineARE()
|
||||
if self.level < 100 then return 18
|
||||
if self.level < 100 then return 14
|
||||
elseif self.level < 400 then return 8
|
||||
elseif self.level < 500 then return 7
|
||||
else return 6 end
|
||||
|
||||
@@ -179,7 +179,7 @@ function PhantomMania2Game:onPieceLock(piece, cleared_row_count)
|
||||
end
|
||||
|
||||
function PhantomMania2Game:onHold()
|
||||
self.super.onHold()
|
||||
self.super:onHold()
|
||||
self.hold_age = 0
|
||||
end
|
||||
|
||||
@@ -287,7 +287,8 @@ function PhantomMania2Game:setHoldOpacity()
|
||||
if self.level > 1000 and self.level < 1300 then
|
||||
love.graphics.setColor(1, 1, 1, 1 - math.min(1, self.hold_age / 15))
|
||||
else
|
||||
self.super:setHoldOpacity(1, self.held and 0.6 or 1)
|
||||
local colour = self.held and 0.6 or 1
|
||||
love.graphics.setColor(colour, colour, colour, 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -97,14 +97,13 @@ end
|
||||
function SurvivalA2Game:onLineClear(cleared_row_count)
|
||||
if not self.clear then
|
||||
local new_level = math.min(self.level + cleared_row_count, 999)
|
||||
if self.level == 999 or self:hitTorikan(self.level, new_level) then
|
||||
if new_level == 999 or self:hitTorikan(self.level, new_level) then
|
||||
self.clear = true
|
||||
if self.level < 999 then
|
||||
if new_level < 999 then
|
||||
self.game_over = true
|
||||
end
|
||||
else
|
||||
self.level = new_level
|
||||
end
|
||||
self.level = new_level
|
||||
end
|
||||
end
|
||||
|
||||
@@ -158,7 +157,7 @@ function SurvivalA2Game:drawScoringInfo()
|
||||
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
love.graphics.printf(self.score, text_x, 220, 90, "left")
|
||||
if self.roll_frames > 2968 then love.graphics.setColor(1, 0.5, 0, 1)
|
||||
if self.roll_frames > 1800 then love.graphics.setColor(1, 0.5, 0, 1)
|
||||
elseif self.level >= 999 and 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
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
|
||||
@@ -47,18 +47,11 @@ function Ruleset:new(game_mode)
|
||||
else
|
||||
bones = config.gamesettings.piece_colour == 3 and "w" or ""
|
||||
end
|
||||
blocks.bone = {
|
||||
R = love.graphics.newImage("res/img/bone" .. bones .. ".png"),
|
||||
O = love.graphics.newImage("res/img/bone" .. bones .. ".png"),
|
||||
Y = love.graphics.newImage("res/img/bone" .. bones .. ".png"),
|
||||
G = love.graphics.newImage("res/img/bone" .. bones .. ".png"),
|
||||
C = love.graphics.newImage("res/img/bone" .. bones .. ".png"),
|
||||
B = love.graphics.newImage("res/img/bone" .. bones .. ".png"),
|
||||
M = love.graphics.newImage("res/img/bone" .. bones .. ".png"),
|
||||
F = love.graphics.newImage("res/img/bone" .. bones .. ".png"),
|
||||
A = love.graphics.newImage("res/img/bone" .. bones .. ".png"),
|
||||
X = love.graphics.newImage("res/img/bone" .. bones .. ".png"),
|
||||
}
|
||||
for colour in pairs(blocks["2tie"]) do
|
||||
blocks.bone[colour] = love.graphics.newImage(
|
||||
"res/img/bone" .. bones .. ".png"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
function Ruleset:rotatePiece(inputs, piece, grid, prev_inputs, initial)
|
||||
@@ -162,18 +155,18 @@ function Ruleset:dropPiece(
|
||||
hard_drop_enabled, additive_gravity, classic_lock
|
||||
)
|
||||
local y = piece.position.y
|
||||
if inputs["down"] == true and drop_locked == false then
|
||||
if additive_gravity then
|
||||
piece:addGravity(gravity + drop_speed, grid, classic_lock)
|
||||
else
|
||||
piece:addGravity(math.max(gravity, drop_speed), grid, classic_lock)
|
||||
end
|
||||
elseif inputs["up"] == true and hard_drop_enabled == true then
|
||||
if inputs["up"] == true and hard_drop_enabled == true then
|
||||
if hard_drop_locked == true or piece:isDropBlocked(grid) then
|
||||
piece:addGravity(gravity, grid, classic_lock)
|
||||
else
|
||||
piece:dropToBottom(grid)
|
||||
end
|
||||
elseif inputs["down"] == true and drop_locked == false then
|
||||
if additive_gravity then
|
||||
piece:addGravity(gravity + drop_speed, grid, classic_lock)
|
||||
else
|
||||
piece:addGravity(math.max(gravity, drop_speed), grid, classic_lock)
|
||||
end
|
||||
else
|
||||
piece:addGravity(gravity, grid, classic_lock)
|
||||
end
|
||||
@@ -221,7 +214,7 @@ function Ruleset:initializePiece(
|
||||
colours = self.colourscheme
|
||||
end
|
||||
|
||||
local spawn_x = math.floor(spawn_positions[data.shape].x / 10 * grid.width)
|
||||
local spawn_x = math.floor(spawn_positions[data.shape].x * grid.width / 10)
|
||||
|
||||
local spawn_dy
|
||||
if (config.gamesettings.spawn_positions == 1) then
|
||||
@@ -237,7 +230,7 @@ function Ruleset:initializePiece(
|
||||
end
|
||||
|
||||
local piece = Piece(data.shape, data.orientation - 1, {
|
||||
x = spawn_x or spawn_positions[data.shape].x,
|
||||
x = spawn_x,
|
||||
y = spawn_positions[data.shape].y - spawn_dy
|
||||
}, self.block_offsets, 0, 0, data.skin, colours[data.shape], big)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user