Sorcerer update 4/4
parent
521ce0cca5
commit
2276925f34
68
arena.lua
68
arena.lua
|
@ -327,6 +327,7 @@ function Arena:update(dt)
|
|||
main_song_instance = _G[random:table{'song1', 'song2', 'song3', 'song4', 'song5'}]:play{volume = 0.5}
|
||||
end
|
||||
|
||||
if self.shop_text then self.shop_text:update(dt) end
|
||||
-- print(self.enemy_spawns_prevented)
|
||||
|
||||
if input.escape.pressed and not self.transitioning and not self.in_credits and not self.choosing_passives then
|
||||
|
@ -338,7 +339,7 @@ function Arena:update(dt)
|
|||
self.paused_t2 = Text2{group = self.ui, x = gw/2, y = gh/2 - 92, lines = {{text = '[bg10]turn left turn right', font = pixul_font, alignment = 'center'}}}
|
||||
self.ng_t = Text2{group = self.ui, x = gw/2 + 63, y = gh - 50, lines = {{text = '[bg10]current: ' .. current_new_game_plus, font = pixul_font, alignment = 'center'}}}
|
||||
|
||||
self.resume_button = Button{group = self.ui, x = gw/2, y = gh - 200, force_update = true, button_text = 'resume game (esc)', fg_color = 'bg10', bg_color = 'bg', action = function(b)
|
||||
self.resume_button = Button{group = self.ui, x = gw/2, y = gh - 225, force_update = true, button_text = 'resume game (esc)', fg_color = 'bg10', bg_color = 'bg', action = function(b)
|
||||
trigger:tween(0.25, _G, {slow_amount = 1}, math.linear, function()
|
||||
slow_amount = 1
|
||||
self.paused = false
|
||||
|
@ -357,14 +358,16 @@ function Arena:update(dt)
|
|||
if self.video_button_3 then self.video_button_3.dead = true; self.video_button_3 = nil end
|
||||
if self.quit_button then self.quit_button.dead = true; self.quit_button = nil end
|
||||
if self.screen_shake_button then self.screen_shake_button.dead = true; self.screen_shake_button = nil end
|
||||
if self.screen_movement_button then self.screen_movement_button.dead = true; self.screen_movement_button = nil end
|
||||
if self.cooldown_snake_button then self.cooldown_snake_button.dead = true; self.cooldown_snake_button = nil end
|
||||
if self.arrow_snake_button then self.arrow_snake_button.dead = true; self.arrow_snake_button = nil end
|
||||
if self.ng_plus_plus_button then self.ng_plus_plus_button.dead = true; self.ng_plus_plus_button = nil end
|
||||
if self.ng_plus_minus_button then self.ng_plus_minus_button.dead = true; self.ng_plus_minus_button = nil end
|
||||
system.save_state()
|
||||
end, 'pause')
|
||||
end}
|
||||
|
||||
self.restart_button = Button{group = self.ui, x = gw/2, y = gh - 175, force_update = true, button_text = 'restart run (r)', fg_color = 'bg10', bg_color = 'bg', action = function(b)
|
||||
self.restart_button = Button{group = self.ui, x = gw/2, y = gh - 200, force_update = true, button_text = 'restart run (r)', fg_color = 'bg10', bg_color = 'bg', action = function(b)
|
||||
self.transitioning = true
|
||||
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}
|
||||
|
@ -389,7 +392,7 @@ function Arena:update(dt)
|
|||
end, text = Text({{text = '[wavy, bg]restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)}
|
||||
end}
|
||||
|
||||
self.sfx_button = Button{group = self.ui, x = gw/2, y = gh - 150, force_update = true, button_text = 'toggle sfx (n)', fg_color = 'bg10', bg_color = 'bg', action = function(b)
|
||||
self.sfx_button = Button{group = self.ui, x = gw/2, y = gh - 175, force_update = true, button_text = 'toggle sfx (n)', fg_color = 'bg10', bg_color = 'bg', action = function(b)
|
||||
ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
b.spring:pull(0.2, 200, 10)
|
||||
b.selected = true
|
||||
|
@ -401,7 +404,7 @@ function Arena:update(dt)
|
|||
end
|
||||
end}
|
||||
|
||||
self.music_button = Button{group = self.ui, x = gw/2, y = gh - 125, force_update = true, button_text = 'toggle music (m)', fg_color = 'bg10', bg_color = 'bg', action = function(b)
|
||||
self.music_button = Button{group = self.ui, x = gw/2, y = gh - 150, force_update = true, button_text = 'toggle music (m)', fg_color = 'bg10', bg_color = 'bg', action = function(b)
|
||||
ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
b.spring:pull(0.2, 200, 10)
|
||||
b.selected = true
|
||||
|
@ -413,7 +416,7 @@ function Arena:update(dt)
|
|||
end
|
||||
end}
|
||||
|
||||
self.video_button_1 = Button{group = self.ui, x = gw/2 - 86, y = gh - 100, force_update = true, button_text = 'window size-', fg_color = 'bg10', bg_color = 'bg', action = function()
|
||||
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)
|
||||
|
@ -421,7 +424,7 @@ function Arena:update(dt)
|
|||
state.fullscreen = false
|
||||
end}
|
||||
|
||||
self.video_button_2 = Button{group = self.ui, x = gw/2, y = gh - 100, force_update = true, button_text = 'window size+', fg_color = 'bg10', bg_color = 'bg', action = function()
|
||||
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()
|
||||
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)
|
||||
|
@ -429,7 +432,7 @@ function Arena:update(dt)
|
|||
state.fullscreen = false
|
||||
end}
|
||||
|
||||
self.video_button_3 = Button{group = self.ui, x = gw/2 + 79, y = gh - 100, force_update = true, button_text = 'fullscreen', fg_color = 'bg10', bg_color = 'bg', action = function()
|
||||
self.video_button_3 = Button{group = self.ui, x = gw/2 + 79, y = gh - 125, force_update = true, button_text = 'fullscreen', fg_color = 'bg10', bg_color = 'bg', action = function()
|
||||
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
local _, _, flags = love.window.getMode()
|
||||
local window_width, window_height = love.window.getDesktopDimensions(flags.display)
|
||||
|
@ -439,20 +442,38 @@ function Arena:update(dt)
|
|||
state.fullscreen = true
|
||||
end}
|
||||
|
||||
self.screen_shake_button = Button{group = self.ui, x = gw/2 - 57, y = gh - 75, w = 110, force_update = true, button_text = '[bg10]screen shake: ' .. tostring(state.no_screen_shake and 'no' or 'yes'),
|
||||
self.screen_shake_button = Button{group = self.ui, x = gw/2 - 57, y = gh - 100, w = 110, force_update = true, button_text = '[bg10]screen shake: ' .. tostring(state.no_screen_shake and 'no' or 'yes'),
|
||||
fg_color = 'bg10', bg_color = 'bg', action = function(b)
|
||||
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
state.no_screen_shake = not state.no_screen_shake
|
||||
b:set_text('screen shake: ' .. tostring(state.no_screen_shake and 'no' or 'yes'))
|
||||
end}
|
||||
|
||||
self.cooldown_snake_button = Button{group = self.ui, x = gw/2 + 75, y = gh - 75, w = 145, force_update = true, button_text = '[bg10]cooldowns on snake: ' .. tostring(state.cooldown_snake and 'yes' or 'no'),
|
||||
self.cooldown_snake_button = Button{group = self.ui, x = gw/2 + 75, y = gh - 100, w = 145, force_update = true, button_text = '[bg10]cooldowns on snake: ' .. tostring(state.cooldown_snake and 'yes' or 'no'),
|
||||
fg_color = 'bg10', bg_color = 'bg', action = function(b)
|
||||
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
state.cooldown_snake = not state.cooldown_snake
|
||||
b:set_text('cooldowns on snake: ' .. tostring(state.cooldown_snake and 'yes' or 'no'))
|
||||
end}
|
||||
|
||||
self.arrow_snake_button = Button{group = self.ui, x = gw/2 + 65, y = gh - 75, w = 125, force_update = true, button_text = '[bg10]arrow on snake: ' .. tostring(state.arrow_snake and 'yes' or 'no'),
|
||||
fg_color = 'bg10', bg_color = 'bg', action = function(b)
|
||||
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
state.arrow_snake = not state.arrow_snake
|
||||
b:set_text('arrow on snake: ' .. tostring(state.arrow_snake and 'yes' or 'no'))
|
||||
end}
|
||||
|
||||
self.screen_movement_button = Button{group = self.ui, x = gw/2 - 69, y = gh - 75, w = 135, force_update = true, button_text = '[bg10]screen movement: ' .. tostring(state.no_screen_movement and 'no' or 'yes'),
|
||||
fg_color = 'bg10', bg_color = 'bg', action = function(b)
|
||||
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
state.no_screen_movement = not state.no_screen_movement
|
||||
if state.no_screen_movement then
|
||||
camera.x, camera.y = gw/2, gh/2
|
||||
camera.r = 0
|
||||
end
|
||||
b:set_text('screen movement: ' .. tostring(state.no_screen_movement and 'no' or 'yes'))
|
||||
end}
|
||||
|
||||
self.ng_plus_minus_button = Button{group = self.ui, x = gw/2 - 58, y = gh - 50, force_update = true, button_text = 'NG+ down', fg_color = 'bg10', bg_color = 'bg', action = function(b)
|
||||
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
b.spring:pull(0.2, 200, 10)
|
||||
|
@ -495,7 +516,9 @@ function Arena:update(dt)
|
|||
if self.video_button_2 then self.video_button_2.dead = true; self.video_button_2 = nil end
|
||||
if self.video_button_3 then self.video_button_3.dead = true; self.video_button_3 = nil end
|
||||
if self.screen_shake_button then self.screen_shake_button.dead = true; self.screen_shake_button = nil end
|
||||
if self.screen_movement_button then self.screen_movement_button.dead = true; self.screen_movement_button = nil end
|
||||
if self.cooldown_snake_button then self.cooldown_snake_button.dead = true; self.cooldown_snake_button = nil end
|
||||
if self.arrow_snake_button then self.arrow_snake_button.dead = true; self.arrow_snake_button = nil end
|
||||
if self.quit_button then self.quit_button.dead = true; self.quit_button = nil end
|
||||
if self.ng_plus_plus_button then self.ng_plus_plus_button.dead = true; self.ng_plus_plus_button = nil end
|
||||
if self.ng_plus_minus_button then self.ng_plus_minus_button.dead = true; self.ng_plus_minus_button = nil end
|
||||
|
@ -787,6 +810,26 @@ function Arena:quit()
|
|||
self.arena_clear_text.dead = true
|
||||
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:set_passives()
|
||||
RerollButton{group = main.current.ui, x = 40, y = 40, parent = self, force_update = true}
|
||||
self.shop_text = Text({{text = '[wavy_mid, fg]gold: [yellow]' .. gold, font = pixul_font, alignment = 'center'}}, global_text_tags)
|
||||
else
|
||||
self:transition()
|
||||
end
|
||||
end, 'transition')
|
||||
end
|
||||
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
|
||||
self.cards = {}
|
||||
end
|
||||
|
||||
local card_w, card_h = 100, 100
|
||||
local w = 3*card_w + 2*20
|
||||
self.choosing_passives = true
|
||||
|
@ -813,11 +856,6 @@ function Arena:quit()
|
|||
if not passive_1 and not passive_2 and not passive_3 then
|
||||
self:transition()
|
||||
end
|
||||
else
|
||||
self:transition()
|
||||
end
|
||||
end, 'transition')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -881,6 +919,8 @@ function Arena:draw()
|
|||
if self.choosing_passives or self.won or self.paused or self.died then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent) end
|
||||
self.ui:draw()
|
||||
|
||||
if self.shop_text then self.shop_text:draw(40, 20) end
|
||||
|
||||
if self.in_credits then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent_2) end
|
||||
self.credits:draw()
|
||||
end
|
||||
|
|
|
@ -773,9 +773,14 @@ RerollButton = Object:extend()
|
|||
RerollButton:implement(GameObject)
|
||||
function RerollButton:init(args)
|
||||
self:init_game_object(args)
|
||||
self.shape = Rectangle(self.x, self.y, 54, 16)
|
||||
self.interact_with_mouse = true
|
||||
if self.parent:is(BuyScreen) then
|
||||
self.shape = Rectangle(self.x, self.y, 54, 16)
|
||||
self.text = Text({{text = '[bg10]reroll: [yellow]2', font = pixul_font, alignment = 'center'}}, global_text_tags)
|
||||
elseif self.parent:is(Arena) then
|
||||
self.shape = Rectangle(self.x, self.y, 60, 16)
|
||||
self.text = Text({{text = '[bg10]reroll: [yellow]15', font = pixul_font, alignment = 'center'}}, global_text_tags)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -783,6 +788,7 @@ function RerollButton:update(dt)
|
|||
self:update_game_object(dt)
|
||||
|
||||
if self.selected and input.m1.pressed then
|
||||
if self.parent:is(BuyScreen) then
|
||||
if gold < 2 then
|
||||
self.spring:pull(0.2, 200, 10)
|
||||
self.selected = true
|
||||
|
@ -804,6 +810,28 @@ function RerollButton:update(dt)
|
|||
self.parent.shop_text:set_text{{text = '[wavy_mid, fg]shop [fg]- [fg, nudge_down]gold: [yellow, nudge_down]' .. gold, font = pixul_font, alignment = 'center'}}
|
||||
system.save_run(self.parent.level == 1 and 0 or self.parent.level, gold, self.parent.units, passives, run_passive_pool_by_tiers, locked_state)
|
||||
end
|
||||
elseif self.parent:is(Arena) then
|
||||
if gold < 15 then
|
||||
self.spring:pull(0.2, 200, 10)
|
||||
self.selected = true
|
||||
error1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
if not self.info_text then
|
||||
self.info_text = InfoText{group = main.current.ui, force_update = true}
|
||||
self.info_text:activate({
|
||||
{text = '[fg]not enough gold', font = pixul_font, alignment = 'center'},
|
||||
}, nil, nil, nil, nil, 16, 4, nil, 2)
|
||||
self.info_text.x, self.info_text.y = gw/2, gh/2 + 10
|
||||
end
|
||||
self.t:after(2, function() self.info_text:deactivate(); self.info_text.dead = true; self.info_text = nil end, 'info_text')
|
||||
else
|
||||
ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
self.parent:set_passives(true)
|
||||
self.selected = true
|
||||
self.spring:pull(0.2, 200, 10)
|
||||
gold = gold - 15
|
||||
self.parent.shop_text:set_text{{text = '[fg, nudge_down]gold: [yellow, nudge_down]' .. gold, font = pixul_font, alignment = 'center'}}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -820,13 +848,21 @@ function RerollButton: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
|
||||
if self.parent:is(BuyScreen) then
|
||||
self.text:set_text{{text = '[fgm5]reroll: 2', font = pixul_font, alignment = 'center'}}
|
||||
elseif self.parent:is(Arena) then
|
||||
self.text:set_text{{text = '[fgm5]reroll: 15', font = pixul_font, alignment = 'center'}}
|
||||
end
|
||||
self.spring:pull(0.2, 200, 10)
|
||||
end
|
||||
|
||||
|
||||
function RerollButton:on_mouse_exit()
|
||||
if self.parent:is(BuyScreen) then
|
||||
self.text:set_text{{text = '[bg10]reroll: [yellow]2', font = pixul_font, alignment = 'center'}}
|
||||
elseif self.parent:is(Arena) then
|
||||
self.text:set_text{{text = '[fgm5]reroll: [yellow]15', font = pixul_font, alignment = 'center'}}
|
||||
end
|
||||
self.selected = false
|
||||
end
|
||||
|
||||
|
@ -1106,7 +1142,6 @@ function PassiveCard:update(dt)
|
|||
|
||||
if self.selected and input.m1.pressed and self.arena.choosing_passives then
|
||||
self.arena.choosing_passives = false
|
||||
table.insert(passives, self.passive)
|
||||
table.insert(self.arena.passives, self.passive)
|
||||
self.arena:restore_passives_to_pool(self.card_i)
|
||||
trigger:tween(0.25, _G, {slow_amount = 1}, math.linear, function()
|
||||
|
@ -1324,7 +1359,6 @@ function CharacterIcon:init(args)
|
|||
self:init_game_object(args)
|
||||
self.shape = Rectangle(self.x, self.y, 40, 20)
|
||||
self.interact_with_mouse = true
|
||||
print(character_color_strings[self.character])
|
||||
self.character_text = Text({{text = '[' .. character_color_strings[self.character] .. ']' .. string.lower(character_names[self.character]), font = pixul_font, alignment = 'center'}}, global_text_tags)
|
||||
end
|
||||
|
||||
|
@ -1480,7 +1514,11 @@ function ClassIcon:draw()
|
|||
local next_n
|
||||
if self.parent:is(ShopCard) then
|
||||
next_n = n+1
|
||||
if k then
|
||||
if next_n > k then next_n = nil end
|
||||
else
|
||||
if next_n > j then next_n = nil end
|
||||
end
|
||||
if table.any(self.units, function(v) return v.character == self.character end) then next_n = nil end
|
||||
end
|
||||
|
||||
|
|
44
enemies.lua
44
enemies.lua
|
@ -23,7 +23,7 @@ function Seeker:init(args)
|
|||
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = green[0], duration = 0.1}
|
||||
for _, enemy in ipairs(enemies) do
|
||||
LightningLine{group = main.current.effects, src = self, dst = enemy, color = green[0]}
|
||||
enemy:speed_boost(3 + self.level*0.05 + current_new_game_plus*0.2)
|
||||
enemy:speed_boost(3 + self.level*0.025 + current_new_game_plus*0.1)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
@ -85,7 +85,7 @@ function Seeker:init(args)
|
|||
enemy:hit(10000)
|
||||
critter1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
critter3:play{pitch = random:float(0.95, 1.05), volume = 0.6}
|
||||
for i = 1, random:int(4, 6) do EnemyCritter{group = main.current.main, x = enemy.x, y = enemy.y, color = purple[0], r = random:float(0, 2*math.pi), v = 5 + 0.1*enemy.level, dmg = enemy.dmg} end
|
||||
for i = 1, random:int(4, 6) do EnemyCritter{group = main.current.main, x = enemy.x, y = enemy.y, color = purple[0], r = random:float(0, 2*math.pi), v = 8 + 0.1*enemy.level, dmg = 2*enemy.dmg} end
|
||||
end
|
||||
end)
|
||||
|
||||
|
@ -100,7 +100,7 @@ function Seeker:init(args)
|
|||
LightningLine{group = main.current.effects, src = self, dst = enemy, color = blue[0]}
|
||||
enemy:hit(10000)
|
||||
shoot1:play{pitch = random:float(0.95, 1.05), volume = 0.4}
|
||||
local n = 8 + current_new_game_plus*2
|
||||
local n = math.floor(8 + current_new_game_plus*1.5)
|
||||
for i = 1, n do EnemyProjectile{group = main.current.main, x = enemy.x, y = enemy.y, color = blue[0], r = (i-1)*math.pi/(n/2), v = 120 + 5*enemy.level, dmg = (1 + 0.1*current_new_game_plus)*enemy.dmg} end
|
||||
end
|
||||
end)
|
||||
|
@ -119,7 +119,7 @@ function Seeker:init(args)
|
|||
enemy:hit(10000)
|
||||
shoot1:play{pitch = random:float(0.95, 1.05), volume = 0.4}
|
||||
local n = 8 + current_new_game_plus*2
|
||||
for i = 1, n do EnemyProjectile{group = main.current.main, x = enemy.x, y = enemy.y, color = blue[0], r = (i-1)*math.pi/(n/2), v = 150 + 5*enemy.level, dmg = (1 + 0.2*current_new_game_plus)*enemy.dmg} end
|
||||
for i = 1, n do EnemyProjectile{group = main.current.main, x = enemy.x, y = enemy.y, color = blue[0], r = (i-1)*math.pi/(n/2), v = 125 + 5*enemy.level, dmg = (1 + 0.2*current_new_game_plus)*enemy.dmg} end
|
||||
end
|
||||
elseif attack == 'swarm' then
|
||||
local enemies = self:get_objects_in_shape(Circle(self.x, self.y, 128), {Seeker})
|
||||
|
@ -130,7 +130,7 @@ function Seeker:init(args)
|
|||
enemy:hit(10000)
|
||||
critter1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
critter3:play{pitch = random:float(0.95, 1.05), volume = 0.6}
|
||||
for i = 1, random:int(4, 6) do EnemyCritter{group = main.current.main, x = enemy.x, y = enemy.y, color = purple[0], r = random:float(0, 2*math.pi), v = 5 + 0.1*enemy.level, dmg = enemy.dmg} end
|
||||
for i = 1, random:int(4, 6) do EnemyCritter{group = main.current.main, x = enemy.x, y = enemy.y, color = purple[0], r = random:float(0, 2*math.pi), v = 8 + 0.1*enemy.level, dmg = 2*enemy.dmg} end
|
||||
end
|
||||
elseif attack == 'force' then
|
||||
local enemies = self:get_objects_in_shape(Circle(self.x, self.y, 64), {Seeker})
|
||||
|
@ -150,7 +150,7 @@ function Seeker:init(args)
|
|||
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = green[0], duration = 0.1}
|
||||
for _, enemy in ipairs(enemies) do
|
||||
LightningLine{group = main.current.effects, src = self, dst = enemy, color = green[0]}
|
||||
enemy:speed_boost(3 + self.level*0.05 + current_new_game_plus*0.2)
|
||||
enemy:speed_boost(3 + self.level*0.025 + current_new_game_plus*0.1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -186,7 +186,7 @@ function Seeker:init(args)
|
|||
self.color = orange[0]:clone()
|
||||
self.last_headbutt_time = 0
|
||||
local n = math.remap(current_new_game_plus, 0, 5, 1, 0.5)
|
||||
self.t:every(function() return math.distance(self.x, self.y, main.current.player.x, main.current.player.y) < 64 and love.timer.getTime() - self.last_headbutt_time > 10*n end, function()
|
||||
self.t:every(function() return math.distance(self.x, self.y, main.current.player.x, main.current.player.y) < 76 and love.timer.getTime() - self.last_headbutt_time > 10*n end, function()
|
||||
if self.silenced then return end
|
||||
if self.headbutt_charging or self.headbutting then return end
|
||||
self.headbutt_charging = true
|
||||
|
@ -198,16 +198,24 @@ function Seeker:init(args)
|
|||
self.last_headbutt_time = love.timer.getTime()
|
||||
self:set_damping(0)
|
||||
self:apply_steering_impulse(300, self:angle_to_object(main.current.player), 0.75)
|
||||
self.t:after(0.5, function()
|
||||
self.t:after(0.75, function()
|
||||
self.headbutting = false
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
elseif self.tank then
|
||||
self.color = yellow[0]:clone()
|
||||
self.buff_hp_m = 1.25 + (0.025*self.level) + (0.2*current_new_game_plus)
|
||||
self.buff_hp_m = 1.25 + (0.1*self.level) + (0.4*current_new_game_plus)
|
||||
self:calculate_stats()
|
||||
self.hp = self.max_hp
|
||||
local n = math.remap(current_new_game_plus, 0, 5, 1, 0.75)
|
||||
self.t:every({3*n, 5*n}, function()
|
||||
local enemy = self:get_closest_object_in_shape(Circle(self.x, self.y, 128), main.current.enemies)
|
||||
if enemy then
|
||||
wizard1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
enemy:push(random:float(40, 80), enemy:angle_to_object(main.current.player), true)
|
||||
end
|
||||
end)
|
||||
elseif self.shooter then
|
||||
self.color = fg[0]:clone()
|
||||
local n = math.remap(current_new_game_plus, 0, 5, 1, 0.5)
|
||||
|
@ -221,7 +229,7 @@ function Seeker:init(args)
|
|||
self.hfx:use('hit', 0.25, 200, 10, 0.1)
|
||||
local r = self.r
|
||||
HitCircle{group = main.current.effects, x = self.x + 0.8*self.shape.w*math.cos(r), y = self.y + 0.8*self.shape.w*math.sin(r), rs = 6}
|
||||
EnemyProjectile{group = main.current.main, x = self.x + 1.6*self.shape.w*math.cos(r), y = self.y + 1.6*self.shape.w*math.sin(r), color = fg[0], r = r, v = 150 + 5*self.level + 8*current_new_game_plus,
|
||||
EnemyProjectile{group = main.current.main, x = self.x + 1.6*self.shape.w*math.cos(r), y = self.y + 1.6*self.shape.w*math.sin(r), color = fg[0], r = r, v = 140 + 5*self.level + 4*current_new_game_plus,
|
||||
dmg = (current_new_game_plus*0.1 + 1)*self.dmg}
|
||||
end)
|
||||
end
|
||||
|
@ -257,8 +265,8 @@ function Seeker:update(dt)
|
|||
if self.headbutt_charging or self.headbutting then self.buff_def_m = 3 end
|
||||
|
||||
if self.speed_boosting then
|
||||
local n = math.remap(love.timer.getTime() - self.speed_boosting, 0, (3 + 0.05*self.level + current_new_game_plus*0.2), 1, 0.5)
|
||||
self.speed_boosting_mvspd_m = (3 + 0.05*self.level + 0.2*current_new_game_plus)*n
|
||||
local n = math.remap(love.timer.getTime() - self.speed_boosting, 0, (3 + 0.025*self.level + current_new_game_plus*0.1), 1, 0.5)
|
||||
self.speed_boosting_mvspd_m = (3 + 0.025*self.level + 0.1*current_new_game_plus)*n
|
||||
if not self.speed_booster and not self.exploder and not self.headbutter and not self.tank and not self.shooter and not self.spawner then
|
||||
self.color.r = math.remap(n, 1, 0.5, green[0].r, red[0].r)
|
||||
self.color.g = math.remap(n, 1, 0.5, green[0].g, red[0].g)
|
||||
|
@ -269,7 +277,7 @@ function Seeker:update(dt)
|
|||
if self.slowed then self.slow_mvspd_m = self.slowed
|
||||
else self.slow_mvspd_m = 1 end
|
||||
|
||||
self.buff_mvspd_m = (self.speed_boosting_mvspd_m or 1)*(self.slow_mvspd_m or 1)*(self.temporal_chains_mvspd_m or 1)
|
||||
self.buff_mvspd_m = (self.speed_boosting_mvspd_m or 1)*(self.slow_mvspd_m or 1)*(self.temporal_chains_mvspd_m or 1)*(self.tank and 0.35 or 1)
|
||||
|
||||
self:calculate_stats()
|
||||
|
||||
|
@ -368,6 +376,10 @@ function Seeker:on_collision_enter(other, contact)
|
|||
end
|
||||
end
|
||||
|
||||
if self.headbutter and self.headbutting then
|
||||
self.headbutting = false
|
||||
end
|
||||
|
||||
elseif table.any(main.current.enemies, function(v) return other:is(v) end) then
|
||||
if self.being_pushed and math.length(self:get_velocity()) > 60 then
|
||||
other:hit(math.floor(self.push_force/4))
|
||||
|
@ -382,9 +394,11 @@ function Seeker:on_collision_enter(other, contact)
|
|||
HitCircle{group = main.current.effects, x = x, y = y, rs = 6, color = fg[0], duration = 0.1}
|
||||
for i = 1, 2 do HitParticle{group = main.current.effects, x = x, y = y, color = self.color} end
|
||||
hit2:play{pitch = random:float(0.95, 1.05), volume = 0.35}
|
||||
if other:is(Seeker) then self.headbutting = false end
|
||||
end
|
||||
|
||||
elseif other:is(Turret) then
|
||||
self.headbutting = false
|
||||
_G[random:table{'player_hit1', 'player_hit2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.35}
|
||||
self:hit(0)
|
||||
self:push(random:float(2.5, 7), other:angle_to_object(self))
|
||||
|
@ -443,9 +457,9 @@ function Seeker:hit(damage, projectile)
|
|||
if self.silenced then return end
|
||||
shoot1:play{pitch = random:float(0.95, 1.05), volume = 0.4}
|
||||
trigger:after(0.01, function()
|
||||
local n = 8 + current_new_game_plus*2
|
||||
local n = math.floor(8 + current_new_game_plus*1.5)
|
||||
for i = 1, n do
|
||||
EnemyProjectile{group = main.current.main, x = self.x, y = self.y, color = blue[0], r = (i-1)*math.pi/(n/2), v = 120 + 5*self.level, dmg = 2*self.dmg}
|
||||
EnemyProjectile{group = main.current.main, x = self.x, y = self.y, color = blue[0], r = (i-1)*math.pi/(n/2), v = 120 + 5*self.level, dmg = 1.5*self.dmg}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
|
63
main.lua
63
main.lua
|
@ -29,7 +29,7 @@ function init()
|
|||
thunder1 = Sound('399656__bajko__sfx-thunder-blast.ogg', s)
|
||||
flagellant1 = Sound('Whipping Horse 3.ogg', s)
|
||||
bard2 = Sound('376532__womb-affliction__flute-trill.ogg', s)
|
||||
bard1 = Sound('Magical Impact 12.ogg', s)
|
||||
arcane2 = Sound('Magical Impact 12.ogg', s)
|
||||
frost1 = Sound('Frost Bolt 20.ogg', s)
|
||||
arcane1 = Sound('Magical Impact 26.ogg', s)
|
||||
pyro1 = Sound('Fire bolt 5.ogg', s)
|
||||
|
@ -383,7 +383,7 @@ function init()
|
|||
['elementor'] = {'mage', 'nuker'},
|
||||
['saboteur'] = {'rogue', 'conjurer', 'nuker'},
|
||||
['stormweaver'] = {'enchanter'},
|
||||
['sage'] = {'forcer', 'nuker'},
|
||||
['sage'] = {'nuker', 'forcer'},
|
||||
['squire'] = {'warrior', 'enchanter'},
|
||||
['cannoneer'] = {'ranger', 'nuker'},
|
||||
['dual_gunner'] = {'ranger', 'rogue'},
|
||||
|
@ -435,7 +435,7 @@ function init()
|
|||
['elementor'] = '[blue]Mage, [red]Nuker',
|
||||
['saboteur'] = '[red]Rogue, [orange]Conjurer, [red]Nuker',
|
||||
['stormweaver'] = '[blue]Enchanter',
|
||||
['sage'] = '[red]Nuker',
|
||||
['sage'] = '[red]Nuker, [yellow]Forcer',
|
||||
['squire'] = '[yellow]Warrior, [blue]Enchanter',
|
||||
['cannoneer'] = '[green]Ranger, [red]Nuker',
|
||||
['dual_gunner'] = '[green]Ranger, [red]Rogue',
|
||||
|
@ -494,7 +494,7 @@ function init()
|
|||
['swordsman'] = function(lvl) return '[fg]deals [yellow]' .. get_character_stat('swordsman', lvl, 'dmg') .. '[fg] damage in an area, deals extra [yellow]' ..
|
||||
math.round(get_character_stat('swordsman', lvl, 'dmg')*0.15, 2) .. '[fg] damage per unit hit' end,
|
||||
['wizard'] = function(lvl) return '[fg]shoots a projectile that deals [yellow]' .. get_character_stat('wizard', lvl, 'dmg') .. ' AoE[fg] damage' end,
|
||||
['magician'] = function(lvl) return '[fg]creates a small area that deals [yellow]' .. get_character_stat('magician', lvl, 'dmg') .. 'AoE[fg] damage' end,
|
||||
['magician'] = function(lvl) return '[fg]creates a small area that deals [yellow]' .. get_character_stat('magician', lvl, 'dmg') .. ' AoE[fg] damage' end,
|
||||
['archer'] = function(lvl) return '[fg]shoots an arrow that deals [yellow]' .. get_character_stat('archer', lvl, 'dmg') .. '[fg] damage and pierces' end,
|
||||
['scout'] = function(lvl) return '[fg]throws a knife that deals [yellow]' .. get_character_stat('scout', lvl, 'dmg') .. '[fg] damage and chains [yellow]3[fg] times' end,
|
||||
['cleric'] = function(lvl) return '[fg]heals a unit for [yellow]20%[fg] of its max hp when it drops below [yellow]50%[fg] max hp' end,
|
||||
|
@ -538,16 +538,16 @@ function init()
|
|||
['illusionist'] = function(lvl) return '[fg]launches a projectile that deals [yellow]' .. get_character_stat('illusionist', lvl, 'dmg') .. '[fg] damage and creates copies that do the same' end,
|
||||
['witch'] = function(lvl) return '[fg]creates an area that ricochets around the arena and deals [yellow]' .. get_character_stat('witch', lvl, 'dmg') .. '[fg] damage per second' end,
|
||||
['silencer'] = function(lvl) return '[fg]curses [yellow]5[fg] nearby enemies for [yellow]6[fg] seconds, preventing them from using special attacks' end,
|
||||
['vulcanist'] = function(lvl) return '[fg]creates a volcano that explodes the nearby area [yellow]4[fg] times, dealing [yellow]' .. get_character_stat('vulcanist', lvl, 'dmg') .. 'AoE [fg]damage' end,
|
||||
['vulcanist'] = function(lvl) return '[fg]creates a volcano that explodes the nearby area [yellow]4[fg] times, dealing [yellow]' .. get_character_stat('vulcanist', lvl, 'dmg') .. ' AoE [fg]damage' end,
|
||||
['warden'] = function(lvl) return '[fg]creates a force field around a random unit that prevents enemies from entering' end,
|
||||
['psychic'] = function(lvl) return '[fg]creates a small area that deals [yellow]' .. get_character_stat('psychic', lvl, 'dmg') .. 'AoE[fg] damage' end,
|
||||
['psychic'] = function(lvl) return '[fg]creates a small area that deals [yellow]' .. get_character_stat('psychic', lvl, 'dmg') .. ' AoE[fg] damage' end,
|
||||
}
|
||||
|
||||
character_effect_names = {
|
||||
['vagrant'] = '[fg]Champion',
|
||||
['swordsman'] = '[yellow]Cleave',
|
||||
['wizard'] = '[blue]Magic Missile',
|
||||
['magician'] = '[blue]Teleportation',
|
||||
['magician'] = '[blue]Ethereal Form',
|
||||
['archer'] = '[green]Bounce Shot',
|
||||
['scout'] = '[red]Dagger Resonance',
|
||||
['cleric'] = '[green]Mass Heal ',
|
||||
|
@ -599,7 +599,7 @@ function init()
|
|||
['vagrant'] = '[light_bg]Champion',
|
||||
['swordsman'] = '[light_bg]Cleave',
|
||||
['wizard'] = '[light_bg]Magic Missile',
|
||||
['magician'] = '[light_bg]Teleportation',
|
||||
['magician'] = '[light_bg]Ethereal Form',
|
||||
['archer'] = '[light_bg]Bounce Shot',
|
||||
['scout'] = '[light_bg]Dagger Resonance',
|
||||
['cleric'] = '[light_bg]Mass Heal ',
|
||||
|
@ -651,7 +651,7 @@ function init()
|
|||
['vagrant'] = function() return '[yellow]+10%[fg] damage and [yellow]+10%[fg] attack speed per active set' end,
|
||||
['swordsman'] = function() return "[fg]the swordsman's damage is [yellow]doubled" end,
|
||||
['wizard'] = function() return '[fg]the projectile chains [yellow]2[fg] times' end,
|
||||
['magician'] = function() return '[fg]the magician becomes invulnerable for [yellow]6[fg] seconds' end,
|
||||
['magician'] = function() return '[fg]the magician becomes invulnerable for [yellow]6[fg] seconds but also cannot attack' end,
|
||||
['archer'] = function() return '[fg]the arrow ricochets off walls [yellow]3[fg] times' end,
|
||||
['scout'] = function() return '[yellow]+25%[fg] damage per chain and [yellow]+3[fg] chains' end,
|
||||
['cleric'] = function() return '[fg]heals all units' end,
|
||||
|
@ -690,20 +690,20 @@ function init()
|
|||
['priest'] = function() return '[fg]picks [yellow]3[fg] units at random and grants them a buff that prevents death once' end,
|
||||
['infestor'] = function() return '[fg][yellow]triples[fg] the number of critters released' end,
|
||||
['flagellant'] = function() return '[fg]deals [yellow]' .. 2*get_character_stat('flagellant', 3, 'dmg') .. '[fg] damage to all allies and grants [yellow]+12%[fg] damage to all allies per cast' end,
|
||||
['arcanist'] = function() return '[yellow]+100%[fg] attack speed for the orb and [yellow]2[fg] projectiles are released per cast' end,
|
||||
['arcanist'] = function() return '[yellow]+50%[fg] attack speed for the orb and [yellow]2[fg] projectiles are released per cast' end,
|
||||
['illusionist'] = function() return '[yellow]doubles[fg] the number of copies created and they release [yellow]12[fg] projectiles on death that pierce and ricochet once' end,
|
||||
['witch'] = function() return '[fg]the area periodically releases projectiles, each dealing [yellow]' .. get_character_stat('witch', 3, 'dmg') .. '[fg] damage and chaining once' end,
|
||||
['silencer'] = function() return '[fg]the curse also deals [yellow]' .. get_character_stat('silencer', 3, 'dmg') .. '[fg] damage per second' end,
|
||||
['vulcanist'] = function() return '[fg]the number and speed of explosions is [yellow]doubled[fg]' end,
|
||||
['warden'] = function() return '[fg]creates the force field around [yellow]2[fg] units, and they are always the [yellow]head[fg] and [yellow]tail[fg] of the snake' end,
|
||||
['psychic'] = function() return '[fg]the attack can happen from any distance and deals [yellow]double[fg] damage' end,
|
||||
['warden'] = function() return '[fg]creates the force field around [yellow]2[fg] units' end,
|
||||
['psychic'] = function() return '[fg]the attack can happen from any distance and repeats once' end,
|
||||
}
|
||||
|
||||
character_effect_descriptions_gray = {
|
||||
['vagrant'] = function() return '[light_bg]+10% damage and +10% attack speed per active set' end,
|
||||
['swordsman'] = function() return "[light_bg]the swordsman's damage is doubled" end,
|
||||
['wizard'] = function() return '[light_bg]the projectile chains 3 times' end,
|
||||
['magician'] = function() return '[light_bg]the magician becomes invulnerable for 6 seconds' end,
|
||||
['magician'] = function() return '[light_bg]the magician becomes invulnerable for 6 seconds but also cannot attack' end,
|
||||
['archer'] = function() return '[light_bg]the arrow ricochets off walls 3 times' end,
|
||||
['scout'] = function() return '[light_bg]+25% damage per chain and +3 chains' end,
|
||||
['cleric'] = function() return '[light_bg]heals all units' end,
|
||||
|
@ -742,13 +742,13 @@ function init()
|
|||
['priest'] = function() return '[light_bg]picks 3 units at random and grants them a buff that prevents death once' end,
|
||||
['infestor'] = function() return '[light_bg]triples the number of critters released' end,
|
||||
['flagellant'] = function() return '[light_bg]deals ' .. 2*get_character_stat('flagellant', 3, 'dmg') .. ' damage to all allies and grants +12% damage to all allies per cast' end,
|
||||
['arcanist'] = function() return '[light_bg]+100% attack speed for the orb and 2 projectiles are released per cast' end,
|
||||
['arcanist'] = function() return '[light_bg]+50% attack speed for the orb and 2 projectiles are released per cast' end,
|
||||
['illusionist'] = function() return '[light_bg]doubles the number of copies created and they release 12 projectiles on death that pierce and ricochet once' end,
|
||||
['witch'] = function() return '[light_bg]the area periodically releases projectiles, each dealing ' .. get_character_stat('witch', 3, 'dmg') .. ' damage and chaining once' end,
|
||||
['silencer'] = function() return '[light_bg]the curse also deals ' .. get_character_stat('silencer', 3, 'dmg') .. ' damage per second' end,
|
||||
['vulcanist'] = function() return '[light_bg]the number and speed of explosions is doubled' end,
|
||||
['warden'] = function() return '[light_bg]creates the force field around 2 units, and they are always the head and tail of the snake' end,
|
||||
['psychic'] = function() return '[light_bg]the attack can happen from any distance and deals double damage' end,
|
||||
['warden'] = function() return '[light_bg]creates the force field around 2 units' end,
|
||||
['psychic'] = function() return '[light_bg]the attack can happen from any distance and repeats once' end,
|
||||
}
|
||||
|
||||
character_stats = {
|
||||
|
@ -1196,12 +1196,12 @@ function init()
|
|||
[4] = {3, 5},
|
||||
[5] = {4, 7},
|
||||
[6] = {6, 10},
|
||||
[7] = {6, 7},
|
||||
[8] = {7, 8},
|
||||
[9] = {10, 16},
|
||||
[10] = {10, 12},
|
||||
[11] = {12, 14},
|
||||
[12] = {18, 20},
|
||||
[7] = {10, 14},
|
||||
[8] = {12, 16},
|
||||
[9] = {14, 18},
|
||||
[10] = {10, 14},
|
||||
[11] = {12, 16},
|
||||
[12] = {20, 24},
|
||||
[13] = {12, 16},
|
||||
[14] = {14, 18},
|
||||
[15] = {16, 20},
|
||||
|
@ -1234,13 +1234,13 @@ function init()
|
|||
[3] = {10},
|
||||
[4] = {4, 4},
|
||||
[5] = {4, 3, 2},
|
||||
[6] = {14},
|
||||
[6] = {12},
|
||||
[7] = {5, 3, 2},
|
||||
[8] = {6, 3, 3, 3},
|
||||
[9] = {18},
|
||||
[9] = {14},
|
||||
[10] = {8, 4},
|
||||
[11] = {8, 6, 2},
|
||||
[12] = {18},
|
||||
[12] = {16},
|
||||
[13] = {8, 8},
|
||||
[14] = {12, 6},
|
||||
[15] = {18},
|
||||
|
@ -1319,14 +1319,21 @@ function init()
|
|||
|
||||
main:add(BuyScreen'buy_screen')
|
||||
main:go_to('buy_screen', run.level or 0, run.units or {}, passives)
|
||||
-- main:go_to('buy_screen', 2, run.units or {}, passives)
|
||||
|
||||
--[[
|
||||
main:add(Arena'arena')
|
||||
main:go_to('arena', 14, {
|
||||
{character = 'magician', level = 3},
|
||||
main:go_to('arena', 1, {
|
||||
{character = 'dual_gunner', level = 1},
|
||||
{character = 'scout', level = 1},
|
||||
}, passives)
|
||||
]]--
|
||||
|
||||
--[[
|
||||
main:add(Media'media')
|
||||
main:go_to('media')
|
||||
]]--
|
||||
|
||||
trigger:every(2, function()
|
||||
if debugging_memory then
|
||||
for k, v in pairs(system.type_count()) do
|
||||
|
@ -1336,6 +1343,8 @@ function init()
|
|||
print()
|
||||
end
|
||||
end)
|
||||
|
||||
print(table.tostring(love.graphics.getSupported()))
|
||||
end
|
||||
|
||||
|
||||
|
|
13
media.lua
13
media.lua
|
@ -11,7 +11,11 @@ function Media:on_enter(from)
|
|||
self.effects = Group()
|
||||
self.ui = Group()
|
||||
|
||||
graphics.set_background_color(fg[0])
|
||||
graphics.set_background_color(blue2[0])
|
||||
Text2{group = self.ui, x = gw/2, y = gh/2, lines = {
|
||||
{text = '[fg]SNKRX', font = fat_font, alignment = 'center', height_offset = -15},
|
||||
{text = '[fg]sorcerer update', font = pixul_font, alignment = 'center'},
|
||||
}}
|
||||
end
|
||||
|
||||
|
||||
|
@ -27,10 +31,3 @@ function Media:draw()
|
|||
self.effects:draw()
|
||||
self.ui:draw()
|
||||
end
|
||||
|
||||
--[[
|
||||
build your party: hire heroes, rank them up and defeat endless waves of enemies
|
||||
make synergies: combine heroes of the same class to unlock unique class passives
|
||||
find passive items: further enhance your party with powerful passive items
|
||||
create your build: explore the possibilities and combinations to create your own unique build
|
||||
]]--
|
||||
|
|
|
@ -232,7 +232,7 @@ 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, 24, 0, 0, 32, 0, 0, 40, 48}
|
||||
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}
|
||||
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]
|
||||
|
@ -246,7 +246,7 @@ 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, 24, 0, 0, 32, 0, 0, 40, 48}
|
||||
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}
|
||||
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]
|
||||
|
@ -254,7 +254,7 @@ function Unit:calculate_stats(first_run)
|
|||
local x = self.level
|
||||
local y = {0, 1, 3, 3, 4, 6, 5, 6, 9, 7, 8, 12, 10, 11, 15, 12, 13, 18, 16, 17, 21, 17, 20, 24, 25}
|
||||
self.base_hp = 22 + (current_new_game_plus*3) + (15 + current_new_game_plus*2.7)*y[x]
|
||||
self.base_dmg = (4 + current_new_game_plus*1.25) + (2 + current_new_game_plus*1.2)*y[x]
|
||||
self.base_dmg = (4 + current_new_game_plus*1.15) + (2 + current_new_game_plus*1)*y[x]
|
||||
self.base_mvspd = 70 + 3*y[x]
|
||||
end
|
||||
end
|
||||
|
|
23
player.lua
23
player.lua
|
@ -41,6 +41,7 @@ function Player:init(args)
|
|||
elseif self.character == 'magician' then
|
||||
self.attack_sensor = Circle(self.x, self.y, 96)
|
||||
self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
|
||||
if self.magician_invulnerable then return end
|
||||
local enemy = self:get_random_object_in_shape(self.attack_sensor, main.current.enemies)
|
||||
if enemy then
|
||||
self:attack(32, {x = enemy.x, y = enemy.y})
|
||||
|
@ -91,7 +92,7 @@ function Player:init(args)
|
|||
elseif self.character == 'arcanist' then
|
||||
self.sorcerer_count = 0
|
||||
self.attack_sensor = Circle(self.x, self.y, 128)
|
||||
self.t:cooldown(3, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
|
||||
self.t:cooldown(4, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
|
||||
local closest_enemy = self:get_closest_object_in_shape(self.attack_sensor, main.current.enemies)
|
||||
if closest_enemy then
|
||||
self:shoot(self:angle_to_object(closest_enemy), {pierce = 1000, v = 40})
|
||||
|
@ -838,7 +839,6 @@ function Player:init(args)
|
|||
local unit_1 = random:table_remove(units)
|
||||
local unit_2 = random:table_remove(units)
|
||||
local unit_3 = random:table_remove(units)
|
||||
print(unit_1, unit_2, unit_3)
|
||||
if unit_1 then unit_1.t:every(2, function() unit_1:hit(0.05*unit_1.max_hp) end) end
|
||||
if unit_2 then unit_2.t:every(2, function() unit_2:hit(0.05*unit_2.max_hp) end) end
|
||||
if unit_3 then unit_3.t:every(2, function() unit_3:hit(0.05*unit_3.max_hp) end) end
|
||||
|
@ -889,6 +889,7 @@ function Player:update(dt)
|
|||
if class_levels.forcer >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if class_levels.swarmer >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if class_levels.voider >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if class_levels.sorcerer >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
self.vagrant_dmg_m = 1 + 0.1*number_of_active_sets
|
||||
self.vagrant_aspd_m = 1 + 0.1*number_of_active_sets
|
||||
end
|
||||
|
@ -953,6 +954,7 @@ function Player:update(dt)
|
|||
if class_levels.forcer >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if class_levels.swarmer >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if class_levels.voider >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if class_levels.sorcerer >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if main.current.psyker_level == 2 then
|
||||
self.psyker_dmg_m = 1 + 0.2*number_of_active_sets
|
||||
self.psyker_aspd_m = 1 + 0.2*number_of_active_sets
|
||||
|
@ -1021,11 +1023,13 @@ function Player:update(dt)
|
|||
for _, unit in ipairs(units) do
|
||||
total_v = total_v + unit.max_v
|
||||
end
|
||||
total_v = total_v/#units
|
||||
total_v = math.floor(total_v/#units)
|
||||
self.total_v = total_v
|
||||
|
||||
self:set_velocity(total_v*math.cos(self.r), total_v*math.sin(self.r))
|
||||
|
||||
if not main.current.won and not main.current.choosing_passives then
|
||||
if not state.no_screen_movement then
|
||||
local vx, vy = self:get_velocity()
|
||||
local hd = math.remap(math.abs(self.x - gw/2), 0, 192, 1, 0)
|
||||
local vd = math.remap(math.abs(self.y - gh/2), 0, 108, 1, 0)
|
||||
|
@ -1037,6 +1041,7 @@ function Player:update(dt)
|
|||
elseif input.move_up.down then camera.r = math.lerp_angle_dt(0.01, dt, camera.r, -math.pi/256)
|
||||
else camera.r = math.lerp_angle_dt(0.005, dt, camera.r, 0) end
|
||||
end
|
||||
end
|
||||
|
||||
self:set_angle(self.r)
|
||||
|
||||
|
@ -1049,7 +1054,7 @@ function Player:update(dt)
|
|||
local distance_to_previous = math.distance(previous.x, previous.y, point.x, point.y)
|
||||
distance_sum = distance_sum + distance_to_previous
|
||||
if distance_sum >= target_distance then
|
||||
p = point
|
||||
p = self.parent.previous_positions[i-1]
|
||||
break
|
||||
end
|
||||
previous = point
|
||||
|
@ -1079,6 +1084,12 @@ function Player:draw()
|
|||
else
|
||||
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 3, 3, (self.hfx.hit.f or self.hfx.shoot.f) and fg[0] or self.color)
|
||||
end
|
||||
|
||||
if self.leader and state.arrow_snake then
|
||||
local x, y = self.x + 0.9*self.shape.w, self.y
|
||||
graphics.line(x + 3, y, x, y - 3, character_colors[self.character], 1)
|
||||
graphics.line(x + 3, y, x, y + 3, character_colors[self.character], 1)
|
||||
end
|
||||
end
|
||||
graphics.pop()
|
||||
end
|
||||
|
@ -1148,7 +1159,7 @@ function Player:hit(damage)
|
|||
self.hfx:use('hit', 0.25, 200, 10)
|
||||
self:show_hp()
|
||||
|
||||
local actual_damage = self:calculate_damage(damage)
|
||||
local actual_damage = math.max(self:calculate_damage(damage), 0)
|
||||
self.hp = self.hp - actual_damage
|
||||
_G[random:table{'player_hit1', 'player_hit2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
camera:shake(4, 0.5)
|
||||
|
@ -1221,6 +1232,7 @@ function Player:hit(damage)
|
|||
self.hp = 1
|
||||
end
|
||||
else
|
||||
self.dead = true
|
||||
if self.leader then self:recalculate_followers()
|
||||
else self.parent:recalculate_followers() end
|
||||
end
|
||||
|
@ -1546,6 +1558,7 @@ function Projectile:init(args)
|
|||
self.t:every(self.parent.level == 3 and 0.54 or 0.8, function()
|
||||
local enemies = table.head(self:get_objects_in_shape(Circle(self.x, self.y, 128), main.current.enemies), self.level == 3 and 2 or 1)
|
||||
for _, enemy in ipairs(enemies) do
|
||||
arcane2:play{pitch = random:float(0.7, 1.3), volume = 0.15}
|
||||
self.hfx:use('hit', 0.5)
|
||||
local r = self:angle_to_object(enemy)
|
||||
local t = {group = main.current.main, x = self.x + 8*math.cos(r), y = self.y + 8*math.sin(r), v = 250, r = r, color = self.parent.color, dmg = self.parent.dmg, pierce = 1000, character = 'arcanist_projectile',
|
||||
|
|
46
todo
46
todo
|
@ -1,23 +1,3 @@
|
|||
Sorcerer update
|
||||
Options
|
||||
Option to have an arrow at the head of the snake - https://imgur.com/a/poXVsoN
|
||||
Option to turn off camera movement
|
||||
Options menu from buy screen
|
||||
Volume slider
|
||||
Fix fullscreen with different resolutions that don't scale properly
|
||||
QoL
|
||||
Item reroll for 15 gold
|
||||
Fix highlight colors and highlight reserve
|
||||
Rename tutorial to guide or manual
|
||||
Add visuals for defensive ouroboros
|
||||
Unlock automatically on shop enter
|
||||
Balance
|
||||
Buff tanks, maybe add a simple forcer ability to them
|
||||
Buff 24/25 HP again
|
||||
Buff headbutter (+ trigger range)
|
||||
Bugs
|
||||
Fix leader (snake head) distance being off by 1 or 2 pixels on certain snake speeds
|
||||
|
||||
Sorcerer update patch notes
|
||||
Summary: This update adds 1 new class with 8 new units, implements more QoL features, further balance changes and lots of bug fixes.
|
||||
Added sorcerer class: sorcerers repeat their attacks once every 4/3/2 attacks
|
||||
|
@ -56,15 +36,21 @@ Summary: This update adds 1 new class with 8 new units, implements more QoL feat
|
|||
Fixed a crash whenever the Fairy would try to select a unit that just died this or last frame
|
||||
Fixed a crash that would happen when trying to restart the game through the menu on the passive selection screen
|
||||
Fixed a bug where you could die and win at the same time
|
||||
Fixed a crash triggered by infested enemies on death rarely
|
||||
Fixed a crash triggered rarely by infested enemies on death
|
||||
Fixed a bug where quitting on level 1 would automatically jump to level 2
|
||||
Fixed a bug where lock state would carry over after a run death/win/restart
|
||||
Fixed a bug where items from a previous restarted run would remain after the 1st round
|
||||
|
||||
Fixed a bug where the shop's lock state would carry over after a run death/win/restart
|
||||
Fixed a bug where items from a previous restarted run would remain after the 1st round of a new run
|
||||
Fixed a bug where the leader's (snake head) distance was off by 1 or 2 pixels on certain snake speeds
|
||||
Added item reroll for 15 gold
|
||||
Buffed tank (yellow enemy) and added a special attack
|
||||
Buffed boss HP for levels 18, 24 and 25 (again)
|
||||
Added an option to have an arrow at the head of the snake
|
||||
Added an option to turn off camera movement
|
||||
Slightly decreased enemy damage across all difficulties
|
||||
|
||||
---
|
||||
|
||||
Future ideas:
|
||||
Future updates:
|
||||
Chaos related classes
|
||||
Invoker - shoots a projectile with random properties, Lv.3 effect - ???
|
||||
Trappers:
|
||||
|
@ -83,7 +69,15 @@ Hide cursor during waves
|
|||
Mouse follow control?
|
||||
Visuals for divine intervertion, fairy buff
|
||||
Fix enemies still spawning after arena clear (this happens with the extra enemy spawns that were blocked earlier)
|
||||
Fix highlight colors and highlight reserve
|
||||
Add visuals for defensive ouroboros
|
||||
Options menu from buy screen
|
||||
Volume slider
|
||||
Fix fullscreen with different resolutions that don't scale properly
|
||||
|
||||
Roguelite update:
|
||||
Slay the Spire-like node selection map (copy code from SHOOTRX repo as this is already implemented there)
|
||||
Hades-like no map system, this is more elegant and requires way less work than something like Isaac or StS
|
||||
Units die permanently when they die
|
||||
Units can have items attached to them like in Underlords
|
||||
Unit item ideas:
|
||||
This unit's projectiles pierce/chain/fork/seek/split/stun/etc
|
||||
|
|
Loading…
Reference in New Issue