v0.3-pre2
parent
5c254cf853
commit
b50b573331
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,294 @@
|
|||
local GameMode = require 'tetris.modes.gamemode'
|
||||
|
||||
local HistoryRandomizer = require 'tetris.randomizers.history_6rolls_35bag'
|
||||
|
||||
local TheTrueHero = GameMode:extend()
|
||||
|
||||
bgm.undyne = love.audio.newSource("res/bgm/mus_x_undyne.mp3", "stream")
|
||||
|
||||
sounds.undyne = {
|
||||
ding = love.audio.newSource("res/se/000029aa.wav", "static"),
|
||||
pike = love.audio.newSource("res/se/0000299c.wav", "static"),
|
||||
damage = love.audio.newSource("res/se/000029c3.wav", "static")
|
||||
}
|
||||
|
||||
TheTrueHero.name = "The True Hero"
|
||||
TheTrueHero.hash = "TheTrueHero"
|
||||
TheTrueHero.tagline = "A tribute to the Puzzle Maker."
|
||||
|
||||
function TheTrueHero:new()
|
||||
self.super:new()
|
||||
|
||||
self.randomizer = HistoryRandomizer()
|
||||
|
||||
self.attacks = {
|
||||
"PIECE GOAL",
|
||||
"LINE GOAL",
|
||||
"GARBAGE",
|
||||
"HIDDEN PREVIEWS",
|
||||
"TO THE BEAT",
|
||||
"INVISIBLE"
|
||||
}
|
||||
|
||||
self.attack_number = 0
|
||||
self.current_attack = 0
|
||||
self.var = 0
|
||||
|
||||
self.section_frames = 0
|
||||
self.section_times = {
|
||||
385,
|
||||
385,
|
||||
385,
|
||||
386,
|
||||
386,
|
||||
385,
|
||||
381,
|
||||
384,
|
||||
384,
|
||||
384,
|
||||
384,
|
||||
385,
|
||||
385,
|
||||
384,
|
||||
384,
|
||||
288,
|
||||
288,
|
||||
288,
|
||||
288,
|
||||
288,
|
||||
288,
|
||||
288,
|
||||
288,
|
||||
288,
|
||||
288,
|
||||
288,
|
||||
290,
|
||||
}
|
||||
|
||||
self.queue_age = 0
|
||||
self.grounded_time = 0
|
||||
|
||||
self.lock_drop = true
|
||||
self.lock_hard_drop = true
|
||||
self.enable_hold = true
|
||||
self.next_queue_length = 5
|
||||
|
||||
self.irs = false
|
||||
self.ihs = false
|
||||
end
|
||||
|
||||
function TheTrueHero:getDropSpeed()
|
||||
return 20
|
||||
end
|
||||
|
||||
function TheTrueHero:getARR()
|
||||
return config.arr
|
||||
end
|
||||
|
||||
function TheTrueHero:getARE()
|
||||
return 0
|
||||
end
|
||||
|
||||
function TheTrueHero:getLineARE()
|
||||
return 0
|
||||
end
|
||||
|
||||
function TheTrueHero:getDasLimit()
|
||||
return config.das
|
||||
end
|
||||
|
||||
function TheTrueHero:getLineClearDelay()
|
||||
return 0
|
||||
end
|
||||
|
||||
function TheTrueHero:getLockDelay()
|
||||
return 30
|
||||
end
|
||||
|
||||
function TheTrueHero:getGravity()
|
||||
return self.current_attack == 5 and 20 or 1.1 ^ (self.attack_number - 1)
|
||||
end
|
||||
|
||||
function TheTrueHero:getDasCutDelay()
|
||||
return config.dcd
|
||||
end
|
||||
|
||||
function TheTrueHero:advanceOneFrame(inputs, ruleset)
|
||||
if self.ready_frames == 0 then
|
||||
if self.frames == 0 then
|
||||
switchBGMLoop("undyne")
|
||||
end
|
||||
if self.section_frames >= self.section_times[Mod1(self.attack_number, #self.section_times)] or self.frames == 0 then
|
||||
if (self.current_attack == 1 or self.current_attack == 2) and self.var > 0 then
|
||||
playSE("undyne", "damage")
|
||||
self.game_over = true
|
||||
return false
|
||||
end
|
||||
self.section_frames = 0
|
||||
self.attack_number = self.attack_number + 1
|
||||
local prev_attack = self.current_attack
|
||||
local attack_rolls = 0
|
||||
repeat
|
||||
attack_rolls = attack_rolls + 1
|
||||
if self.attack_number > 20 then
|
||||
self.current_attack = math.random(#self.attacks)
|
||||
else
|
||||
self.current_attack = math.random(4)
|
||||
end
|
||||
until prev_attack ~= self.current_attack and (
|
||||
self.current_attack ~= 5 or attack_rolls == 3
|
||||
)
|
||||
if self.current_attack == 1 then
|
||||
self.var = math.floor(3 + math.random(
|
||||
math.floor(self.attack_number / 4),
|
||||
math.floor(self.attack_number / 3)
|
||||
) *
|
||||
self.section_times[Mod1(self.attack_number, #self.section_times)] / 342)
|
||||
elseif self.current_attack == 2 then
|
||||
self.var = math.floor(1 + math.random(
|
||||
math.floor(self.attack_number / 6),
|
||||
math.floor(self.attack_number / 4)
|
||||
) *
|
||||
self.section_times[Mod1(self.attack_number, #self.section_times)] / 342)
|
||||
elseif self.current_attack == 3 then
|
||||
self.var = math.max(10 - math.random(
|
||||
math.floor(self.attack_number / 8),
|
||||
math.floor(self.attack_number / 4)
|
||||
), 3)
|
||||
end
|
||||
end
|
||||
self.frames = self.frames + 1
|
||||
self.section_frames = self.section_frames + 1
|
||||
if self.current_attack == 5 then
|
||||
self.lock_on_soft_drop = false
|
||||
self.lock_on_hard_drop = false
|
||||
if self.section_frames % 24 == 0 and self.section_frames >= 25 then
|
||||
self.piece.locked = true
|
||||
playSE("undyne", "pike")
|
||||
end
|
||||
else
|
||||
self.lock_on_soft_drop = ({ruleset.softdrop_lock, self.instant_soft_drop, false, true })[config.gamesettings.manlock]
|
||||
self.lock_on_hard_drop = ({ruleset.harddrop_lock, self.instant_hard_drop, true, false})[config.gamesettings.manlock]
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function TheTrueHero:onPieceEnter()
|
||||
self.queue_age = 0
|
||||
self.grounded_time = 0
|
||||
end
|
||||
|
||||
function TheTrueHero:onHold()
|
||||
self.grounded_time = 0
|
||||
end
|
||||
|
||||
function TheTrueHero:whilePieceActive()
|
||||
if self.piece:isDropBlocked(self.grid) then
|
||||
self.grounded_time = self.grounded_time + 1
|
||||
if self.grounded_time >= 120 then
|
||||
self.piece.locked = true
|
||||
end
|
||||
end
|
||||
self.queue_age = self.queue_age + 1
|
||||
end
|
||||
|
||||
function TheTrueHero:onPieceLock(piece, cleared_row_count)
|
||||
self.super:onPieceLock()
|
||||
if self.current_attack == 1 or self.current_attack == 3 then
|
||||
self.var = math.max(self.var - 1, 0)
|
||||
self:advanceBottomRow(1)
|
||||
playSE("undyne", "ding")
|
||||
elseif self.current_attack == 2 then
|
||||
self.var = math.max(self.var - cleared_row_count, 0)
|
||||
if cleared_row_count ~= 0 then
|
||||
playSE("undyne", "ding")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TheTrueHero:advanceBottomRow(dx)
|
||||
if self.var <= 0 and self.current_attack == 3 then
|
||||
self.grid:copyBottomRow()
|
||||
self.var = math.max(10 - math.random(
|
||||
math.floor(self.attack_number / 8),
|
||||
math.floor(self.attack_number / 4)
|
||||
), 3)
|
||||
playSE("undyne", "pike")
|
||||
end
|
||||
end
|
||||
|
||||
function TheTrueHero:setNextOpacity(i)
|
||||
if self.current_attack == 4 then
|
||||
local hidden_next_pieces = math.ceil(self.attack_number / 15)
|
||||
if i < hidden_next_pieces then
|
||||
love.graphics.setColor(1, 1, 1, 0)
|
||||
elseif i == hidden_next_pieces then
|
||||
love.graphics.setColor(1, 1, 1, 1 - math.min(1, self.queue_age / 15))
|
||||
else
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
else
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
|
||||
local function invisible(game, block, x, y, age)
|
||||
return 0.5, 0.5, 0.5, 1 - age / (300 - game.attack_number * 5.5), 0
|
||||
end
|
||||
|
||||
function TheTrueHero:drawGrid()
|
||||
if self.current_attack == 6 then
|
||||
self.grid:drawCustom(invisible, self)
|
||||
else
|
||||
self.grid:draw()
|
||||
end
|
||||
self:drawGhostPiece()
|
||||
end
|
||||
|
||||
function TheTrueHero:drawScoringInfo()
|
||||
self.super.drawScoringInfo(self)
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
|
||||
love.graphics.setFont(font_3x5_2)
|
||||
love.graphics.printf("ATTACK NUMBER", 240, 150, 200, "left")
|
||||
love.graphics.printf("ATTACK", 240, 230, 200, "left")
|
||||
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
if self.attack_number > 0 then
|
||||
love.graphics.printf(self.attack_number .. " - " .. (
|
||||
string.sub(formatTime(
|
||||
self.section_times[Mod1(self.attack_number, #self.section_times)] - self.section_frames
|
||||
), -4, -1)
|
||||
), 240, 170, 200, "left")
|
||||
end
|
||||
love.graphics.printf(
|
||||
self.attacks[self.current_attack] or "",
|
||||
240, 250, 200, "left"
|
||||
)
|
||||
|
||||
love.graphics.setFont(font_3x5_4)
|
||||
if self.current_attack >= 1 and self.current_attack <= 3 then
|
||||
love.graphics.setColor(
|
||||
(not self.game_over and self.frames % 4 < 2) and
|
||||
(
|
||||
self.var == 0 and {0.3, 1, 0.3, 1} or {1, 0.3, 0.3, 1}
|
||||
) or {1, 1, 1, 1}
|
||||
)
|
||||
love.graphics.printf(self.var, 240, 280, 200, "left")
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
|
||||
function TheTrueHero:getHighscoreData()
|
||||
return {
|
||||
frames = self.frames,
|
||||
}
|
||||
end
|
||||
|
||||
function TheTrueHero:getBackground()
|
||||
return math.max(0, self.attack_number - 1) % 20
|
||||
end
|
||||
|
||||
return TheTrueHero
|
|
@ -34,6 +34,7 @@ function MarathonGFGame:getLineARE() return 6 end
|
|||
function MarathonGFGame:getLineClearDelay() return 24 end
|
||||
function MarathonGFGame:getDasLimit() return config.das end
|
||||
function MarathonGFGame:getARR() return config.arr end
|
||||
function MarathonGFGame:getDasCutDelay() return config.dcd end
|
||||
|
||||
function MarathonGFGame:getGravity()
|
||||
if self.lines < 180 then
|
||||
|
|
|
@ -36,6 +36,7 @@ function NightOfNights:getLineARE() return 0 end
|
|||
function NightOfNights:getLineClearDelay() return 0 end
|
||||
function NightOfNights:getDasLimit() return config.das end
|
||||
function NightOfNights:getARR() return config.arr end
|
||||
function NightOfNights:getDasCutDelay() return config.dcd end
|
||||
function NightOfNights:getGravity() return 20 end
|
||||
|
||||
function NightOfNights:advanceOneFrame()
|
||||
|
|
|
@ -83,13 +83,12 @@ function PacerTest:getGravity()
|
|||
return 1/64
|
||||
end
|
||||
|
||||
function PacerTest:getSection()
|
||||
return math.floor(level / 100) + 1
|
||||
function PacerTest:getDasCutDelay()
|
||||
return config.dcd
|
||||
end
|
||||
|
||||
function PacerTest:onPieceEnter()
|
||||
self.irs = false
|
||||
self.ihs = false
|
||||
function PacerTest:getSection()
|
||||
return math.floor(level / 100) + 1
|
||||
end
|
||||
|
||||
function PacerTest:advanceOneFrame()
|
||||
|
|
|
@ -27,6 +27,7 @@ function ProGame:getLineARE() return 6 end
|
|||
function ProGame:getLineClearDelay() return 6 end
|
||||
function ProGame:getDasLimit() return config.das end
|
||||
function ProGame:getARR() return config.arr end
|
||||
function ProGame:getDasCutDelay() return config.dcd end
|
||||
function ProGame:getDropSpeed() return 20 end
|
||||
|
||||
function ProGame:getGravity()
|
||||
|
|
|
@ -70,6 +70,10 @@ function Race40Game:getGravity()
|
|||
return 1/64
|
||||
end
|
||||
|
||||
function Race40Game:getDasCutDelay()
|
||||
return config.dcd
|
||||
end
|
||||
|
||||
function Race40Game:advanceOneFrame()
|
||||
if self.clear then
|
||||
self.roll_frames = self.roll_frames + 1
|
||||
|
@ -83,11 +87,6 @@ function Race40Game:advanceOneFrame()
|
|||
return true
|
||||
end
|
||||
|
||||
function Race40Game:onPieceEnter()
|
||||
self.irs = false
|
||||
self.ihs = false
|
||||
end
|
||||
|
||||
function Race40Game:onPieceLock()
|
||||
self.super:onPieceLock()
|
||||
self.pieces = self.pieces + 1
|
||||
|
|
|
@ -39,6 +39,7 @@ function LudicrousSpeed:getLineARE() return 0 end
|
|||
function LudicrousSpeed:getLineClearDelay() return 0 end
|
||||
function LudicrousSpeed:getDasLimit() return config.das end
|
||||
function LudicrousSpeed:getARR() return config.arr end
|
||||
function LudicrousSpeed:getDasCutDelay() return config.dcd end
|
||||
function LudicrousSpeed:getDropSpeed() return 20 end
|
||||
|
||||
local function mean(t)
|
||||
|
@ -74,11 +75,6 @@ function LudicrousSpeed:advanceOneFrame()
|
|||
return true
|
||||
end
|
||||
|
||||
function LudicrousSpeed:onPieceEnter()
|
||||
self.irs = false
|
||||
self.ihs = false
|
||||
end
|
||||
|
||||
function LudicrousSpeed:onPieceLock()
|
||||
self.super:onPieceLock()
|
||||
self.pieces = self.pieces + 1
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
require 'funcs'
|
||||
|
||||
local Race40Game = require 'tetris.modes.race_40'
|
||||
|
||||
local ZenMode = Race40Game:extend()
|
||||
|
||||
ZenMode.name = "Marathon WZ"
|
||||
ZenMode.hash = "Zen"
|
||||
ZenMode.tagline = "Attempt to score as many points as you can!"
|
||||
|
||||
function ZenMode:new()
|
||||
self.super:new()
|
||||
|
||||
self.score = bigint.new(0)
|
||||
self.line_goal = 200
|
||||
self.pieces = 0
|
||||
self.bravos = 0
|
||||
self.combo = 0
|
||||
self.b2b = 0
|
||||
self.message_timer = 0
|
||||
self.immobile_spin_bonus = true
|
||||
end
|
||||
|
||||
function ZenMode:initialize(ruleset)
|
||||
self.super.initialize(self, ruleset)
|
||||
ruleset.onPieceDrop = function(self, piece) piece.lock_delay = 0 end
|
||||
ruleset.onPieceMove = function(self, piece) piece.lock_delay = 0 end
|
||||
ruleset.onPieceRotate = function(self, piece) piece.lock_delay = 0 end
|
||||
end
|
||||
|
||||
function ZenMode:onHardDrop(dropped_row_count)
|
||||
if dropped_row_count > 0 then
|
||||
self.score = self.score + bigint.new(dropped_row_count)
|
||||
end
|
||||
end
|
||||
|
||||
function ZenMode:getColor(i)
|
||||
local color_table = {
|
||||
{255/255, 128/255, 128/255, 1},
|
||||
{255/255, 191/255, 128/255, 1},
|
||||
{255/255, 255/255, 128/255, 1},
|
||||
{128/255, 255/255, 191/255, 1},
|
||||
{128/255, 255/255, 255/255, 1},
|
||||
{128/255, 128/255, 191/255, 1},
|
||||
{191/255, 128/255, 255/255, 1},
|
||||
}
|
||||
if i == 0 then
|
||||
return {1, 1, 1, 1}
|
||||
else
|
||||
return color_table[Mod1(i, #color_table)]
|
||||
end
|
||||
end
|
||||
|
||||
function ZenMode:updateScore(level, drop_bonus, cleared_row_count)
|
||||
local score_to_add = bigint.new(1)
|
||||
if cleared_row_count ~= 0 then
|
||||
if self.piece.spin then
|
||||
score_to_add = score_to_add * (
|
||||
bigint.new(400 + 400 * cleared_row_count) *
|
||||
(bigint.new(2) ^ bigint.new(self.b2b + self.combo))
|
||||
)
|
||||
self.b2b = self.b2b + 1
|
||||
elseif cleared_row_count >= 4 then
|
||||
score_to_add = score_to_add * (
|
||||
bigint.new(100 * (cleared_row_count * cleared_row_count / 4 + cleared_row_count) - 25 * (cleared_row_count % 2)) *
|
||||
(bigint.new(2) ^ bigint.new(self.b2b + self.combo))
|
||||
)
|
||||
self.b2b = self.b2b + 1
|
||||
else
|
||||
score_to_add = score_to_add * (
|
||||
bigint.new(({100, 300, 500})[cleared_row_count]) *
|
||||
(bigint.new(2) ^ bigint.new(self.combo))
|
||||
)
|
||||
self.b2b = 0
|
||||
end
|
||||
self.combo = self.combo + 1
|
||||
else
|
||||
if self.piece.spin then
|
||||
score_to_add = score_to_add * (
|
||||
bigint.new(2) ^ (bigint.new(self.b2b)) * (bigint.new(400))
|
||||
)
|
||||
else
|
||||
score_to_add = bigint.new(0)
|
||||
end
|
||||
self.combo = 0
|
||||
end
|
||||
self.score = self.score + score_to_add * bigint.new(16) ^ bigint.new(self.bravos)
|
||||
if self.grid:checkForBravo(cleared_row_count) then
|
||||
self.score = self.score + bigint.new(10 ^ 6) * bigint.new(16) ^ bigint.new(self.bravos)
|
||||
self.bravos = self.bravos + 1
|
||||
end
|
||||
end
|
||||
|
||||
function ZenMode:onPieceLock(piece, cleared_row_count)
|
||||
self.super:onPieceLock()
|
||||
self.pieces = self.pieces + 1
|
||||
self.score = self.score + bigint.new(self:getLockDelay() - piece.lock_delay)
|
||||
if self.grid:checkForBravo(cleared_row_count) then
|
||||
self.message = "ALL CLEAR!"
|
||||
elseif piece.spin then
|
||||
self.message = (self.b2b > 0 and cleared_row_count ~= 0 and "B2B " or "") ..
|
||||
(type(piece.shape) == "string" and piece.shape .. "-" or "") ..
|
||||
"SPIN " .. cleared_row_count .. "!"
|
||||
elseif cleared_row_count >= 4 then
|
||||
self.message = (self.b2b > 0 and "B2B " or "") ..
|
||||
string.upper(string.sub(number_names[cleared_row_count * 3 + 3], 1, -7)) .. "A!"
|
||||
else
|
||||
self.message = ""
|
||||
end
|
||||
self.message_timer = 60
|
||||
end
|
||||
|
||||
function ZenMode:drawScoringInfo()
|
||||
local text_x = config["side_next"] and 320 or 240
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.setFont(font_3x5_2)
|
||||
|
||||
if config["side_next"] then
|
||||
love.graphics.printf("NEXT", 240, 72, 40, "left")
|
||||
else
|
||||
love.graphics.printf("NEXT", 64, 40, 40, "left")
|
||||
end
|
||||
|
||||
love.graphics.print(
|
||||
self.das.direction .. " " ..
|
||||
self.das.frames .. " " ..
|
||||
strTrueValues(self.prev_inputs)
|
||||
)
|
||||
|
||||
love.graphics.printf("SCORE", text_x, 100, 40, "left")
|
||||
love.graphics.printf("PIECES", text_x, 280, 80, "left")
|
||||
love.graphics.printf("LINES", text_x, 340, 40, "left")
|
||||
love.graphics.printf("B2B / COMBO", text_x, 160, 160, "left")
|
||||
love.graphics.printf("PERFECT CLEARS", text_x, 220, 160, "left")
|
||||
if self.message_timer > 0 then
|
||||
love.graphics.printf(self.message, 64, 400, 160, "center")
|
||||
self.message_timer = self.message_timer - 1
|
||||
end
|
||||
local sg = self.grid:checkSecretGrade()
|
||||
if sg >= 7 or self.upstacked then
|
||||
love.graphics.printf("SECRET GRADE", 240, 430, 180, "left")
|
||||
end
|
||||
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
love.graphics.printf(
|
||||
{self:getColor(self.b2b), formatBigNum(bigint.unserialize(self.score, "s"))},
|
||||
text_x, 120, 400, "left"
|
||||
)
|
||||
love.graphics.printf(self.pieces, text_x, 300, 80, "left")
|
||||
love.graphics.printf(self.b2b .. " / " .. self.combo, text_x, 180, 80, "left")
|
||||
love.graphics.printf(self.bravos, text_x, 240, 80, "left")
|
||||
if sg >= 7 or self.upstacked then
|
||||
love.graphics.printf(self:getSecretGrade(sg), 240, 450, 180, "left")
|
||||
end
|
||||
|
||||
love.graphics.setFont(font_3x5_4)
|
||||
love.graphics.printf(math.max(0, self.line_goal - self.lines), text_x, 360, 80, "left")
|
||||
|
||||
love.graphics.setFont(font_8x11)
|
||||
love.graphics.printf(formatTime(self.frames), 64, 420, 160, "center")
|
||||
end
|
||||
|
||||
function ZenMode:getBackground()
|
||||
return math.floor(self.lines / 10) % 20
|
||||
end
|
||||
|
||||
function ZenMode:getHighscoreData()
|
||||
return {
|
||||
score = self.score,
|
||||
lines = self.lines,
|
||||
frames = self.frames,
|
||||
}
|
||||
end
|
||||
|
||||
return ZenMode
|
Loading…
Reference in New Issue