Item update 1/5
parent
b335a62309
commit
4de2640da1
68
arena.lua
68
arena.lua
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
22
main.lua
22
main.lua
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
13
player.lua
13
player.lua
|
@ -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
132
todo
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue