Item update 1/5

master
a327ex 2021-06-14 01:59:16 -03:00
parent b335a62309
commit 4de2640da1
7 changed files with 212 additions and 129 deletions

View File

@ -7,7 +7,7 @@ function Arena:init(name)
end
function Arena:on_enter(from, level, units, passives, shop_level, shop_xp)
function Arena:on_enter(from, level, units, passives, shop_level, shop_xp, lock)
self.hfx:add('condition1', 1)
self.hfx:add('condition2', 1)
self.level = level or 1
@ -15,6 +15,9 @@ function Arena:on_enter(from, level, units, passives, shop_level, shop_xp)
self.passives = passives
self.shop_level = shop_level or 1
self.shop_xp = shop_xp or 0
self.lock = lock
self.starting_units = table.copy(units)
if not state.mouse_control then
input:set_mouse_visible(false)
@ -448,11 +451,13 @@ function Arena:update(dt)
end}
self.video_button_1 = Button{group = self.ui, x = gw/2 - 86, y = gh - 125, force_update = true, button_text = 'window size-', fg_color = 'bg10', bg_color = 'bg', action = function()
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
sx, sy = sx - 1, sy - 1
love.window.setMode(480*sx, 270*sy)
state.sx, state.sy = sx, sy
state.fullscreen = false
if sx > 1 and sy > 1 then
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
sx, sy = sx - 1, sy - 1
love.window.setMode(480*sx, 270*sy)
state.sx, state.sy = sx, sy
state.fullscreen = false
end
end}
self.video_button_2 = Button{group = self.ui, x = gw/2, y = gh - 125, force_update = true, button_text = 'window size+', fg_color = 'bg10', bg_color = 'bg', action = function()
@ -617,18 +622,38 @@ function Arena:quit()
input:set_mouse_visible(true)
self.won = true
locked_state = nil
if current_new_game_plus == new_game_plus then
new_game_plus = new_game_plus + 1
state.new_game_plus = new_game_plus
end
current_new_game_plus = current_new_game_plus + 1
state.current_new_game_plus = current_new_game_plus
max_units = 7 + current_new_game_plus
system.save_run()
trigger:tween(1, _G, {slow_amount = 0}, math.linear, function() slow_amount = 0 end, 'slow_amount')
trigger:tween(4, camera, {x = gw/2, y = gh/2, r = 0}, math.linear, function() camera.x, camera.y, camera.r = gw/2, gh/2, 0 end)
self.win_text = Text2{group = self.ui, x = gw/2, y = gh/2 - 66, force_update = true, lines = {{text = '[wavy_mid, cbyc2]congratulations!', font = fat_font, alignment = 'center'}}}
self.win_text = Text2{group = self.ui, x = gw/2 + 40, y = gh/2 - 66, force_update = true, lines = {{text = '[wavy_mid, cbyc2]congratulations!', font = fat_font, alignment = 'center'}}}
trigger:after(2.5, function()
self.build_text = Text2{group = self.ui, x = 40, y = 20, force_update = true, lines = {{text = "[wavy_mid, fg]your build", font = pixul_font, alignment = 'center'}}}
for i, unit in ipairs(self.units) do
CharacterPart{group = self.ui, x = 40, y = 40 + (i-1)*19, character = unit.character, level = unit.level, force_update = true, cant_click = true, parent = self}
CharacterPart{group = self.ui, x = 20, y = 40 + (i-1)*19, character = unit.character, level = unit.level, force_update = true, cant_click = true, parent = self}
Text2{group = self.ui, x = 20 + 14 + pixul_font:get_text_width(unit.character)/2, y = 40 + (i-1)*19, force_update = true, lines = {
{text = '[' .. character_color_strings[unit.character] .. ']' .. unit.character, font = pixul_font, alignment = 'left'}
}}
end
if current_new_game_plus == 5 then
self.win_text2 = Text2{group = self.ui, x = gw/2, y = gh/2 + 30, force_update = true, lines = {
if current_new_game_plus == 6 then
if current_new_game_plus == new_game_plus then
new_game_plus = 5
state.new_game_plus = new_game_plus
end
current_new_game_plus = 5
state.current_new_game_plus = current_new_game_plus
max_units = 12
self.win_text2 = Text2{group = self.ui, x = gw/2 + 40, y = gh/2 + 30, force_update = true, lines = {
{text = "[fg]now you've really beaten the game!", font = pixul_font, alignment = 'center', height_multiplier = 1.24},
{text = "[fg]thanks a lot for playing it and completing it entirely!", font = pixul_font, alignment = 'center', height_multiplier = 1.24},
{text = "[fg]this game was inspired by:", font = pixul_font, alignment = 'center', height_multiplier = 4},
@ -636,7 +661,7 @@ function Arena:quit()
{text = "[fg]and to get more games like this in the future:", font = pixul_font, alignment = 'center', height_multiplier = 4},
{text = "[wavy_mid, yellow]thanks for playing!", font = pixul_font, alignment = 'center'},
}}
SteamFollowButton{group = self.ui, x = gw/2, y = gh/2 + 78, force_update = true}
SteamFollowButton{group = self.ui, x = gw/2 + 40, y = gh/2 + 78, force_update = true}
Button{group = self.ui, x = gw - 40, y = gh - 44, force_update = true, button_text = 'credits', fg_color = 'bg10', bg_color = 'bg', action = function() self:create_credits() end}
Button{group = self.ui, x = gw - 32, y = gh - 20, force_update = true, button_text = 'quit', fg_color = 'bg10', bg_color = 'bg', action = function() love.event.quit() end}
local open_url = function(b, url)
@ -646,10 +671,10 @@ function Arena:quit()
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
system.open_url(url)
end
Button{group = self.ui, x = gw/2 - 50, y = gh/2 + 12, force_update = true, button_text = 'nimble quest', fg_color = 'bluem5', bg_color = 'blue', action = function(b) open_url(b, 'https://store.steampowered.com/app/259780/Nimble_Quest/') end}
Button{group = self.ui, x = gw/2 + 50, y = gh/2 + 12, force_update = true, button_text = 'dota underlords', fg_color = 'bluem5', bg_color = 'blue', action = function(b) open_url(b, 'https://store.steampowered.com/app/1046930/Dota_Underlords/') end}
Button{group = self.ui, x = gw/2 - 50 + 40, y = gh/2 + 12, force_update = true, button_text = 'nimble quest', fg_color = 'bluem5', bg_color = 'blue', action = function(b) open_url(b, 'https://store.steampowered.com/app/259780/Nimble_Quest/') end}
Button{group = self.ui, x = gw/2 + 50 + 40, y = gh/2 + 12, force_update = true, button_text = 'dota underlords', fg_color = 'bluem5', bg_color = 'blue', action = function(b) open_url(b, 'https://store.steampowered.com/app/1046930/Dota_Underlords/') end}
else
self.win_text2 = Text2{group = self.ui, x = gw/2, y = gh/2 + 20, force_update = true, lines = {
self.win_text2 = Text2{group = self.ui, x = gw/2 + 40, y = gh/2 + 20, force_update = true, lines = {
{text = "[fg]you've beaten the game!", font = pixul_font, alignment = 'center', height_multiplier = 1.24},
{text = "[fg]i made this game in 3 months as a dev challenge", font = pixul_font, alignment = 'center', height_multiplier = 1.24},
{text = "[fg]and i'm happy with how it turned out!", font = pixul_font, alignment = 'center', height_multiplier = 1.24},
@ -657,7 +682,7 @@ function Arena:quit()
{text = "[fg]i will release more games this year, so stay tuned!", font = pixul_font, alignment = 'center', height_multiplier = 1.4},
{text = "[wavy_mid, yellow]thanks for playing!", font = pixul_font, alignment = 'center'},
}}
SteamFollowButton{group = self.ui, x = gw/2, y = gh/2 + 34, force_update = true}
SteamFollowButton{group = self.ui, x = gw/2 + 40, y = gh/2 + 34, force_update = true}
RestartButton{group = self.ui, x = gw - 40, y = gh - 20, force_update = true}
trigger:after(8, function()
self.try_ng_text = Text2{group = self.ui, x = gw - 210, y = gh - 20, force_update = true, lines = {
@ -789,9 +814,8 @@ function Arena:quit()
steam.userStats.storeStats()
end
local units = self.player:get_all_units()
local all_units_level_2 = true
for _, unit in ipairs(units) do
for _, unit in ipairs(self.starting_units) do
if unit.level ~= 2 then
all_units_level_2 = false
break
@ -806,7 +830,7 @@ function Arena:quit()
local units = self.player:get_all_units()
local all_units_level_3 = true
for _, unit in ipairs(units) do
for _, unit in ipairs(self.starting_units) do
if unit.level ~= 3 then
all_units_level_3 = false
break
@ -843,9 +867,9 @@ end
function Arena:set_passives(from_reroll)
if from_reroll then
self:restore_passives_to_pool(0)
self.cards[1].dead = true
self.cards[2].dead = true
self.cards[3].dead = true
if self.cards[1] then self.cards[1].dead = true end
if self.cards[2] then self.cards[2].dead = true end
if self.cards[3] then self.cards[3].dead = true end
self.cards = {}
end
@ -947,6 +971,7 @@ end
function Arena:die()
if not self.died_text and not self.won and not self.arena_clear_text then
input:set_mouse_visible(false)
self.t:cancel('divine_punishment')
self.died = true
locked_state = nil
@ -1057,6 +1082,7 @@ end
function Arena:transition()
self.transitioning = true
if not self.lock then locked_state = nil end
ui_transition2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
TransitionEffect{group = main.transitions, x = self.player.x, y = self.player.y, color = self.color, transition_action = function(t)
if self.level % 2 == 0 and self.shop_level < 5 then

View File

@ -65,7 +65,7 @@ function BuyScreen:on_enter(from, level, units, passives, shop_level, shop_xp)
self.locked = locked_state and locked_state.locked
LockButton{group = self.main, x = 205, y = 18, parent = self}
self:set_cards(nil, nil, true)
self:set_cards(self.shop_level, nil, true)
self:set_party_and_sets()
self:set_items()
@ -136,6 +136,7 @@ function BuyScreen:on_enter(from, level, units, passives, shop_level, shop_xp)
ui_transition2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
locked_state = nil
TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = fg[0], transition_action = function()
slow_amount = 1
gold = 3
@ -507,7 +508,7 @@ function RestartButton:init(args)
self:init_game_object(args)
self.shape = Rectangle(self.x, self.y, pixul_font:get_text_width('restart') + 4, pixul_font.h + 4)
self.interact_with_mouse = true
self.text = Text({{text = '[bg10]NG+' .. tostring(current_new_game_plus+1), font = pixul_font, alignment = 'center'}}, global_text_tags)
self.text = Text({{text = '[bg10]NG+' .. tostring(current_new_game_plus), font = pixul_font, alignment = 'center'}}, global_text_tags)
end
@ -532,13 +533,6 @@ function RestartButton:update(dt)
'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'},
[3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'},
}
if current_new_game_plus == new_game_plus then
new_game_plus = new_game_plus + 1
state.new_game_plus = new_game_plus
end
current_new_game_plus = current_new_game_plus + 1
state.current_new_game_plus = current_new_game_plus
max_units = 7 + current_new_game_plus
system.save_state()
main:add(BuyScreen'buy_screen')
system.save_run()
@ -561,14 +555,14 @@ function RestartButton:on_mouse_enter()
ui_hover1:play{pitch = random:float(1.3, 1.5), volume = 0.5}
pop2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
self.selected = true
self.text:set_text{{text = '[fgm5]NG+' .. tostring(current_new_game_plus+1), font = pixul_font, alignment = 'center'}}
self.text:set_text{{text = '[fgm5]NG+' .. tostring(current_new_game_plus), font = pixul_font, alignment = 'center'}}
self.spring:pull(0.2, 200, 10)
end
function RestartButton:on_mouse_exit()
if main.current.in_credits then return end
self.text:set_text{{text = '[bg10]NG+' .. tostring(current_new_game_plus+1), font = pixul_font, alignment = 'center'}}
self.text:set_text{{text = '[bg10]NG+' .. tostring(current_new_game_plus), font = pixul_font, alignment = 'center'}}
self.selected = false
end
@ -681,16 +675,17 @@ function GoButton:update(dt)
self.t:after(2, function() self.info_text:deactivate(); self.info_text.dead = true; self.info_text = nil end, 'info_text')
else
if self.parent.locked then locked_state = {locked = true, cards = {self.parent.cards[1] and self.parent.cards[1].unit, self.parent.cards[2] and self.parent.cards[2].unit, self.parent.cards[3] and self.parent.cards[3].unit}} end
locked_state = {locked = self.parent.locked, cards = {self.parent.cards[1] and self.parent.cards[1].unit, self.parent.cards[2] and self.parent.cards[2].unit, self.parent.cards[3] and self.parent.cards[3].unit}}
ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
self.spring:pull(0.2, 200, 10)
self.selected = true
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
ui_transition1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
self.transitioning = true
system.save_run(self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool_by_tiers, locked_state)
TransitionEffect{group = main.transitions, x = self.x, y = self.y, color = character_colors[random:table(self.parent.units).character], transition_action = function()
main:add(Arena'arena')
main:go_to('arena', ((self.parent.first_screen and 1) or (self.parent.level + 1)), self.parent.units, self.parent.passives, self.parent.shop_level, self.parent.shop_xp)
main:go_to('arena', ((self.parent.first_screen and 1) or (self.parent.level + 1)), self.parent.units, self.parent.passives, self.parent.shop_level, self.parent.shop_xp, self.parent.locked)
end, text = Text({{text = '[wavy, bg]level ' .. ((self.parent.first_screen and 1) or (self.parent.level + 1)) .. '/25', font = pixul_font, alignment = 'center'}}, global_text_tags)}
end
end
@ -922,7 +917,7 @@ function RerollButton:init(args)
self.free_reroll = true
self.text = Text({{text = '[bg10]reroll: [yellow]0', font = pixul_font, alignment = 'center'}}, global_text_tags)
else
self.text = Text({{text = '[bg10]reroll: [yellow]15', font = pixul_font, alignment = 'center'}}, global_text_tags)
self.text = Text({{text = '[bg10]reroll: [yellow]10', font = pixul_font, alignment = 'center'}}, global_text_tags)
end
end
end
@ -955,7 +950,7 @@ function RerollButton:update(dt)
system.save_run(self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool_by_tiers, locked_state)
end
elseif self.parent:is(Arena) then
if gold < 15 and not self.free_reroll then
if gold < 10 and not self.free_reroll then
self.spring:pull(0.2, 200, 10)
self.selected = true
error1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
@ -972,10 +967,10 @@ function RerollButton:update(dt)
self.parent:set_passives(true)
self.selected = true
self.spring:pull(0.2, 200, 10)
if not self.free_reroll then gold = gold - 15 end
if not self.free_reroll then gold = gold - 10 end
self.parent.shop_text:set_text{{text = '[fg, nudge_down]gold: [yellow, nudge_down]' .. gold, font = pixul_font, alignment = 'center'}}
self.free_reroll = false
self.text = Text({{text = '[bg10]reroll: [yellow]15', font = pixul_font, alignment = 'center'}}, global_text_tags)
self.text = Text({{text = '[bg10]reroll: [yellow]10', font = pixul_font, alignment = 'center'}}, global_text_tags)
end
end
end
@ -1004,7 +999,7 @@ function RerollButton:on_mouse_enter()
if self.free_reroll then
self.text:set_text{{text = '[fgm5]reroll: 0', font = pixul_font, alignment = 'center'}}
else
self.text:set_text{{text = '[fgm5]reroll: 15', font = pixul_font, alignment = 'center'}}
self.text:set_text{{text = '[fgm5]reroll: 10', font = pixul_font, alignment = 'center'}}
end
end
self.spring:pull(0.2, 200, 10)
@ -1018,7 +1013,7 @@ function RerollButton:on_mouse_exit()
if self.free_reroll then
self.text:set_text{{text = '[fgm5]reroll: [yellow]0', font = pixul_font, alignment = 'center'}}
else
self.text:set_text{{text = '[fgm5]reroll: [yellow]15', font = pixul_font, alignment = 'center'}}
self.text:set_text{{text = '[fgm5]reroll: [yellow]10', font = pixul_font, alignment = 'center'}}
end
end
self.selected = false
@ -1155,11 +1150,13 @@ function CharacterPart:update(dt)
table.remove(self.parent.units, self.i)
self:die()
self.parent:set_party_and_sets()
self.parent:refresh_cards()
else
self.parent.parent:gain_gold(self:get_sale_price())
self.parent.parent.units[self.i].reserve[self.level] = self.parent.parent.units[self.i].reserve[self.level] - 1
self:die()
self.parent.parent:set_party_and_sets()
self.parent.parent:refresh_cards()
end
end
@ -1195,8 +1192,8 @@ function CharacterPart:on_mouse_enter()
self.spring:pull(0.2, 200, 10)
self.info_text = InfoText{group = main.current.ui, force_update = self.force_update}
self.info_text:activate({
{text = '[' .. character_color_strings[self.character] .. ']' .. self.character:capitalize() .. '[fg] - [yellow]Lv.' .. self.level .. '[fg] - sells for [yellow]' .. self:get_sale_price(),
font = pixul_font, alignment = 'center', height_multiplier = 1.25},
{text = '[' .. character_color_strings[self.character] .. ']' .. self.character:capitalize() .. '[fg] - [yellow]Lv.' .. self.level .. '[fg], tier [yellow]' .. character_tiers[self.character] .. '[fg] - sells for [yellow]' ..
self:get_sale_price(), font = pixul_font, alignment = 'center', height_multiplier = 1.25},
{text = '[fg]Classes: ' .. character_class_strings[self.character], font = pixul_font, alignment = 'center', height_multiplier = 1.25},
{text = character_descriptions[self.character](self.level), font = pixul_font, alignment = 'center', height_multiplier = 2},
{text = '[' .. (self.level == 3 and 'yellow' or 'light_bg') .. ']Lv.3 [' .. (self.level == 3 and 'fg' or 'light_bg') .. ']Effect - ' ..
@ -1408,6 +1405,15 @@ function ItemCard:die()
end
function BuyScreen:refresh_cards()
for i = 1, 3 do
if self.cards[i] then
self.cards[i]:refresh()
end
end
end
ShopCard = Object:extend()
ShopCard:implement(GameObject)
@ -1425,6 +1431,24 @@ function ShopCard:init(args)
end
self.cost = character_tiers[self.unit]
self.spring:pull(0.2, 200, 10)
self:refresh()
end
function ShopCard:refresh()
self.owned = table.any(self.parent.units, function(v) return v.character == self.unit end)
if self.owned then
self.owned_n = 0
for _, unit in ipairs(self.parent.units) do
if unit.character == self.unit then
self.owned_n = self.owned_n + ((unit.level == 1 and 1) or (unit.level == 2 and 3) or (unit.level == 3 and 9))
if unit.reserve then
self.owned_n = self.owned_n + (unit.reserve[2] or 0)*3
self.owned_n = self.owned_n + (unit.reserve[1] or 0)
end
end
end
end
end
@ -1437,6 +1461,7 @@ function ShopCard:update(dt)
_G[random:table{'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
self:die()
self.parent.cards[self.i] = nil
self.parent:refresh_cards()
system.save_run(self.parent.level == 1 and 0 or self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool_by_tiers, locked_state)
else
error1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
@ -1475,6 +1500,36 @@ function ShopCard:draw()
if self.selected then
graphics.rectangle(self.x, self.y, self.w, self.h, 6, 6, bg[-1])
end
if self.owned then
local x, y = self.x + self.w/5, self.y - self.h/2 + 12
if self.owned_n == 1 then
graphics.rectangle(x, y, 2, 2, nil, nil, character_colors[self.unit])
elseif self.owned_n == 2 then
graphics.rectangle(x, y, 2, 2, nil, nil, character_colors[self.unit])
graphics.rectangle(x + 4, y, 2, 2, nil, nil, character_colors[self.unit])
elseif self.owned_n == 3 then
graphics.rectangle(x, y, 4, 4, nil, nil, character_colors[self.unit])
elseif self.owned_n == 4 then
graphics.rectangle(x, y, 4, 4, nil, nil, character_colors[self.unit])
graphics.rectangle(x + 5, y, 2, 2, nil, nil, character_colors[self.unit])
elseif self.owned_n == 5 then
graphics.rectangle(x, y, 4, 4, nil, nil, character_colors[self.unit])
graphics.rectangle(x + 5, y, 2, 2, nil, nil, character_colors[self.unit])
graphics.rectangle(x + 9, y, 2, 2, nil, nil, character_colors[self.unit])
elseif self.owned_n == 6 then
graphics.rectangle(x, y, 4, 4, nil, nil, character_colors[self.unit])
graphics.rectangle(x + 6, y, 4, 4, nil, nil, character_colors[self.unit])
elseif self.owned_n == 7 then
graphics.rectangle(x, y, 4, 4, nil, nil, character_colors[self.unit])
graphics.rectangle(x + 6, y, 4, 4, nil, nil, character_colors[self.unit])
graphics.rectangle(x + 11, y, 2, 2, nil, nil, character_colors[self.unit])
elseif self.owned_n == 8 then
graphics.rectangle(x, y, 4, 4, nil, nil, character_colors[self.unit])
graphics.rectangle(x + 6, y, 4, 4, nil, nil, character_colors[self.unit])
graphics.rectangle(x + 11, y, 2, 2, nil, nil, character_colors[self.unit])
graphics.rectangle(x + 15, y, 2, 2, nil, nil, character_colors[self.unit])
end
end
graphics.pop()
end

View File

@ -517,6 +517,7 @@ function Seeker:hit(damage, projectile)
if self.jester_cursed then
trigger:after(0.01, function()
if tostring(self.x) == tostring(0/0) or tostring(self.y) == tostring(0/0) then return end
_G[random:table{'scout1', 'scout2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.35}
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6}
local r = random:float(0, 2*math.pi)

View File

@ -554,7 +554,7 @@ function init()
['corruptor'] = function(lvl) return '[fg]spawn [yellow]3[fg] small critters if the corruptor kills an enemy' end,
['beastmaster'] = function(lvl) return '[fg]spawn [yellow]2[fg] small critters if the beastmaster crits' end,
['launcher'] = function(lvl) return '[fg]all nearby enemies are pushed after [yellow]4[fg] seconds, taking [yellow]' .. 2*get_character_stat('launcher', lvl, 'dmg') .. '[fg] damage on wall hit' end,
['jester'] = function(lvl) return "[fg]curses [yellow]6[fg] nearby enemies for [yellow]6[fg] seconds, they will explode into [yellow]3[fg] knives on death" end,
['jester'] = function(lvl) return "[fg]curses [yellow]6[fg] nearby enemies for [yellow]6[fg] seconds, they will explode into [yellow]4[fg] knives on death" end,
['assassin'] = function(lvl) return '[fg]throws a piercing knife that deals [yellow]' .. get_character_stat('assassin', lvl, 'dmg') .. '[fg] damage + [yellow]' ..
get_character_stat('assassin', lvl, 'dmg')/2 .. '[fg] damage per second' end,
['host'] = function(lvl) return '[fg]periodically spawn [yellow]1[fg] small critter' end,
@ -1465,14 +1465,18 @@ function init()
--[[
main:add(Arena'arena')
main:go_to('arena', 21, {
{character = 'plague_doctor', level = 2},
main:go_to('arena', 25, {
{character = 'swordsman', level = 3},
{character = 'barbarian', level = 2},
{character = 'outlaw', level = 2},
{character = 'warden', level = 2},
{character = 'juggernaut', level = 2},
{character = 'blade', level = 2},
{character = 'plague_doctor', level = 3},
{character = 'pyromancer', level = 3},
{character = 'witch', level = 3},
{character = 'arcanist', level = 3},
{character = 'usurer', level = 3},
{character = 'warden', level = 3},
{character = 'silencer', level = 3},
{character = 'vulcanist', level = 3},
{character = 'bane', level = 3},
{character = 'illusionist', level = 3},
}, passives)
]]--
@ -1565,7 +1569,7 @@ function update(dt)
end
--[[
if input.f12.pressed then
if input.f11.pressed then
steam.userStats.resetAllStats(true)
steam.userStats.storeStats()
end

View File

@ -232,13 +232,13 @@ function Unit:calculate_stats(first_run)
if current_new_game_plus == 0 then
if self.boss then
local x = self.level
local y = {0, 0, 3, 0, 0, 6, 0, 0, 9, 0, 0, 12, 0, 0, 18, 0, 0, 40, 0, 0, 32, 0, 0, 64, 96}
local y = {0, 0, 3, 0, 0, 6, 0, 0, 9, 0, 0, 12, 0, 0, 18, 0, 0, 40, 0, 0, 32, 0, 0, 64, 90}
self.base_hp = 100 + (current_new_game_plus*5) + (90 + current_new_game_plus*10)*y[x]
self.base_dmg = (12 + current_new_game_plus*2) + (2 + current_new_game_plus)*y[x]
self.base_mvspd = 35 + 1.5*y[x]
if x == 25 then
self.base_dmg = (12 + current_new_game_plus*2) + (1.25 + current_new_game_plus)*y[x]
self.base_mvspd = 35 + 1.2*y[x]
self.base_mvspd = 35 + 1.1*y[x]
end
else
local x = self.level
@ -250,12 +250,12 @@ function Unit:calculate_stats(first_run)
else
if self.boss then
local x = self.level
local y = {0, 0, 3, 0, 0, 6, 0, 0, 9, 0, 0, 12, 0, 0, 18, 0, 0, 40, 0, 0, 32, 0, 0, 64, 96}
local y = {0, 0, 3, 0, 0, 6, 0, 0, 9, 0, 0, 12, 0, 0, 18, 0, 0, 40, 0, 0, 32, 0, 0, 64, 84}
self.base_hp = 100 + (current_new_game_plus*5) + (90 + current_new_game_plus*10)*y[x]
self.base_dmg = (12 + current_new_game_plus*2) + (2 + current_new_game_plus)*y[x]
self.base_mvspd = 35 + 1.5*y[x]
if x == 25 then
self.base_dmg = (12 + current_new_game_plus*2) + (2 + 0.5*current_new_game_plus)*y[x]
self.base_dmg = (12 + current_new_game_plus*2) + (1.75 + 0.5*current_new_game_plus)*y[x]
self.base_mvspd = 35 + 1.2*y[x]
end
else

View File

@ -1125,12 +1125,13 @@ function Player:update(dt)
if input.move_right.pressed and not self.move_left_pressed then self.move_right_pressed = love.timer.getTime() end
if input.move_left.released then self.move_left_pressed = nil end
if input.move_right.released then self.move_right_pressed = nil end
if input.move_left.down then self.r = self.r - 1.66*math.pi*dt end
if input.move_right.down then self.r = self.r + 1.66*math.pi*dt end
if state.mouse_control then
local v = Vector(math.cos(self.r), math.sin(self.r)):perpendicular():dot(Vector(math.cos(self:angle_to_mouse()), math.sin(self:angle_to_mouse())))
self.r = self.r + math.sign(v)*1.66*math.pi*dt
else
if input.move_left.down then self.r = self.r - 1.66*math.pi*dt end
if input.move_right.down then self.r = self.r + 1.66*math.pi*dt end
end
local total_v = 0
@ -2521,6 +2522,7 @@ Volcano:implement(Physics)
function Volcano:init(args)
self:init_game_object(args)
if not self.group.world then self.dead = true; return end
if tostring(self.x) == tostring(0/0) or tostring(self.y) == tostring(0/0) then self.dead = true; return end
self:set_as_rectangle(9, 9, 'static', 'player')
self:set_restitution(0.5)
self.hfx:add('hit', 1)
@ -2562,6 +2564,7 @@ end
function Volcano:draw()
if self.hidden then return end
if not self.hfx.hit then return end
graphics.push(self.x, self.y, math.pi/4, self.spring.x, self.spring.x)
graphics.rectangle(self.x, self.y, 1.5*self.shape.w, 4, 2, 2, self.hfx.hit.f and fg[0] or self.color)
@ -2670,6 +2673,7 @@ end
function Pet:draw()
if not self.hfx.hit then return end
graphics.push(self.x, self.y, self.r, self.hfx.hit.x, self.hfx.hit.x)
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 3, 3, self.hfx.hit.f and fg[0] or self.color)
graphics.pop()
@ -2876,6 +2880,7 @@ Gold:implement(GameObject)
Gold:implement(Physics)
function Gold:init(args)
self:init_game_object(args)
if tostring(self.x) == tostring(0/0) or tostring(self.y) == tostring(0/0) then self.dead = true; return end
self:set_as_rectangle(3, 3, 'dynamic', 'ghost')
self:set_restitution(0.5)
local r = random:float(0, 2*math.pi)
@ -2897,6 +2902,7 @@ end
function Gold:draw()
if not self.hfx.hit then return end
graphics.push(self.x, self.y, self.r, self.hfx.hit.x, self.hfx.hit.x)
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 1, 1, self.hfx.hit.f and fg[0] or self.color)
graphics.pop()
@ -2920,6 +2926,7 @@ function Gold:on_trigger_enter(other, contact)
if th then
if th.level == 3 then
trigger:after(0.01, function()
if not main.current.main.world then return end
_G[random:table{'scout1', 'scout2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.35}
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6}
local r = random:float(0, 2*math.pi)
@ -2931,6 +2938,7 @@ function Gold:on_trigger_enter(other, contact)
end)
else
trigger:after(0.01, function()
if not main.current.main.world then return end
_G[random:table{'scout1', 'scout2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.35}
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6}
local r = random:float(0, 2*math.pi)
@ -3004,6 +3012,7 @@ end
function Critter:draw()
if not self.hfx.hit then return end
graphics.push(self.x, self.y, self.r, self.hfx.hit.x, self.hfx.hit.x)
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 2, 2, self.hfx.hit.f and fg[0] or self.color)
graphics.pop()

132
todo
View File

@ -1,89 +1,69 @@
Shop Update
New units
* Mercenaries (2/4) - +10/20% chance for enemies to drop gold on death
* Miner (tier 1 mercenary) - picking up gold releases 4 homing projectiles that deal X damage, Lv.3 - release 8 homing projectiles instead and they pierce twice
* Merchant (tier 2 mercenary) - gain +1 interest for every 10 gold, Lv.3 - your first item reroll is always free
* Usurer (tier 3 curser, mercenary, voider) - curses 3 nearby enemies indefinitely with debt, dealing X damage over time, Lv.3 - if the same enemy is cursed 3 times it takes 50X damage
* Gambler (tier 3 mercenary, sorcerer) - deal 2X damage to a single random enemy where X is how much gold you have, Lv.3 effect - 60%/40%/20% chance to cast the attack 2/3/4 times
* Thief (tier 4 mercenary, rogue) - throws a knife that deals 2X damage and chains 5 times, Lv.3 - if the knife crits it deals 10X damage, chains 10 times and grants 1 gold
Shop changes
* Shop level up
* Shop level visual
* Shop level up button
* Level up logic
* Level probabilities
* Hook probabilities into reroll
Item changes
* Sorcerer items
Unit changes
* Launcher - removed
* Jester - changed to 4 projectiles
Misc additions and changes
* Added sorcerer achievement
* Added mercenary achievement
QoL
* Removed restart button from end screen
* First item reroll is now free
* Gold is given right after the round ends in the arena rather than on the shop for easier item rerolls
* Added mouse follow control mode
* The cursor is now invisible during waves, unless mouse follow mode is enabled
* Added visuals for tank attack
Balance
* Decreased level 25 boss movement speed
* Change headbutters so they're less likely to kill multiple units at once
Bug fixes
* Fixed a crash when too many illusions would be spawned in short succession
* Fixed a bug where enemy critters would sometimes be unkillable
* Fixed a rare crash involving broken enemy critter state
* Fixed text for the illusionist's Lv.3 effect going outside the screen
* Fixed a crash when hovering over the Lich in the shop due to playing with a save before the sorcerer update
* Fixed a crash when warden's force field would spawn on top of enemies
* Fixed a crash when a volcano would spawn on top of enemies
* Fixed a crash when a pet would spawn on top of enemies
* Fixed a bug where the maximum number of units would be wrong on certain conditions
* Fixed a crash when clicking too fast after unpausing the game
* Fixed unit highlight when hovering over classes
* Fixed Lv.3 plague doctor moving all his created areas with him
* Fixed a bug where quitting on level 2 would go back to level 1
Sacrifice Update
Item Update
New mechanics
Sacrifice units to level items up
Items
New items
https://steamcommunity.com/app/915310/discussions/0/3106901028662504698/
Position X has +Y% attack speed
Position X has +Y% damage
Position X is 1 tier higher
Position X is also class Y
When a unit dies it explodes, launching enemies away
When a unit dies it explodes, releasing piercing projectiles
Reworked items
Items shouldn't just be more powerful versions of other items
Items should have drawbacks
Items that apply to a position on the snake (a good middle step between applying them to individual units like in Underlords)
Item discussions
https://steamcommunity.com/app/915310/discussions/0/3106901028662504698/
https://steamcommunity.com/app/915310/discussions/0/3106901665846294204/
https://steamcommunity.com/app/915310/discussions/0/4658391921151238820/
https://i.imgur.com/cfIyMBL.png
Balance
* Decreased shop reroll cost to 10
Decrease mercenary gold drop chance to 8/16% (from 10/20%)
QoL
Current items visible on item selection screen
Endless mode
Current snake/items visible on item selection screen
Volume slider
Add visuals for defensive ouroboros, divine intervention, fairy buff
Options menu from buy screen
https://i.imgur.com/JJUddT3.png
Improve volcano to not look like spawn marker - https://i.imgur.com/HuS15HG.png
Add option for mouse cursor to always be visible
Add main menu
Soundtrack button
Discord button
Arena run button
Options button
Quit button
* Added tier text to characters on the shop screen
* Added shop unit highlights/markers to make it easier to tell when you already own something
* Added unit names to the "your build" section of the end game screen
Bug fixes
Fix fullscreen with different resolutions that don't scale properly
Fix fullscreen with different resolutions that don't scale properly - https://steamcommunity.com/app/915310/discussions/0/3106901665841020282/
Fix enemies still spawning after arena clear (this happens with the extra enemy spawns that were blocked earlier)
https://i.imgur.com/ieVqYNI.png
https://i.imgur.com/3JCeFuZ.png
* Fixed a bug where passives would sometimes disappear from a run?
* Fixed a bug where clicking "window size-" too many times could bug out the game
* Fixed a bug where the shop would be rerolled after quitting in the arena
* Fixed multiple bugs related to locking the shop and quitting
* Fixed a bug where units could be duplicated in the shop by locking and quitting the game at certain steps
* Fixed a bug where quitting on level 2 would go back to level 1 shop (again)
* Fixed a bug where mouse cursor wasn't visible on death
* Fixed a bug where NG+ level wasn't increased when the game is beaten but only when the NG+ button was clicked
* Fixed a bug where level 2 and level 3 achievements (win with only level 2/3 units) were not triggering correctly sometimes
* Fixed a bug where shop level wasn't respected on the shop's first roll
* Fixed multiple crashes that would happen when picking up gold
* Fixed a crash when the jester's curse would trigger
* Fixed a crash when gold would be picked up with a Miner in the party
* Fixed a crash involving broken state for Pets, Critters or Volcanos
* Fixed a crash that happened after rerolling items too many times
Melee Update
New Units
Guardians - https://i.imgur.com/Ynu5Cdw.png
Assists (2/4) -
Ringmaster (tier 4 assist, nuker) - +15% to all stats to adjacent units, Lv.3 effect - create a cross that deals AoE damage 5 times for 10 seconds
Absorber (tier 2 assist, warrior) - absorbs 50% damage from adjacent units, Lv.3 effect - absorbs 75% damage from adjacent units and gives the absorber +25% defense
Pardoner (tier 3 assist, mercenary) -
Oracle (tier 1 assist) - +10% dodge chance to adjacent units, Lv.3 effect - +20% dodge chance to adjacent units
Seraph (tier 2 assist, healer) - periodically chooses 1 random unit and gives it +100% defense for 6 seconds, Lv.3 - choose 2 units instead
Endless Update
Endless mode
Units die permanently when they die
Slower scaling with less individually threatening units
Max snake size goes up every 10 levels
---
@ -95,6 +75,13 @@ Trappers:
Brawlers: units focused on crashing on enemies
https://i.imgur.com/5YubukS.png - unit idea
Conjurer unit that creates an unit that actively protects you from enemy projectiles
Guardians - https://i.imgur.com/Ynu5Cdw.png
Assists (2/4) -
Ringmaster (tier 4 assist, nuker) - +15% to all stats to adjacent units, Lv.3 effect - create a cross that deals AoE damage 5 times for 10 seconds
Absorber (tier 2 assist, warrior) - absorbs 50% damage from adjacent units, Lv.3 effect - absorbs 75% damage from adjacent units and gives the absorber +25% defense
Pardoner (tier 3 assist, mercenary) -
Oracle (tier 1 assist) - +10% dodge chance to adjacent units, Lv.3 effect - +20% dodge chance to adjacent units
Seraph (tier 2 assist, healer) - periodically chooses 1 random unit and gives it +100% defense for 6 seconds, Lv.3 - choose 2 units instead
Passive that makes critters and summons block enemy projectiles
Hexblaster? - curser that consumes curses to deal damage
Bench? - https://i.imgur.com/B1gNVKk.png
@ -120,13 +107,14 @@ Roguelite update:
Tavern (heal units)
Challenge + reward
Go through the labyrinth without hitting any walls
Go through the traps without getting hit
Units die permanently when they die (dead units can be stored in bench to be revived later)
Units can have items attached to them like in Underlords
Unit item ideas:
This unit's projectiles pierce/chain/fork/seek/split/stun/etc
This unit is a [class]
New stat system:
All stats are values from 1 to 10 (can be lower than 1 or higher than due to debuffs/buffs only) that represent consistent internal values between all units
All stats are values from 1 to 10 (can be lower than 1 or higher than 10 due to debuffs/buffs only) that represent consistent internal values between all units
i.e. 3 attack speed means the same internal attack rate value (like say 6 seconds) for the entire game
In general it's better if units don't have hidden internal multipliers on these stats, although sometimes that may be inevitable
Damage: