Item update 4/5

master
a327ex 2021-06-18 02:32:19 -03:00
parent 31a7a403e3
commit 408eaaf54e
7 changed files with 314 additions and 124 deletions

View File

@ -398,7 +398,7 @@ function Arena:update(dt)
main_song_instance:stop()
run_passive_pool = {
'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'shoot_5', 'death_6', 'lasting_7',
'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'pandemic', 'whispers_of_doom',
'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom',
'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment',
'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism',
'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance'
@ -586,7 +586,7 @@ function Arena:update(dt)
main_song_instance:stop()
run_passive_pool = {
'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'shoot_5', 'death_6', 'lasting_7',
'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'pandemic', 'whispers_of_doom',
'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom',
'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment',
'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism',
'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance'
@ -999,7 +999,7 @@ function Arena:die()
main_song_instance:stop()
run_passive_pool = {
'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'shoot_5', 'death_6', 'lasting_7',
'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'pandemic', 'whispers_of_doom',
'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom',
'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment',
'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism',
'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance'

View File

Before

Width:  |  Height:  |  Size: 483 B

After

Width:  |  Height:  |  Size: 483 B

View File

@ -144,7 +144,7 @@ function BuyScreen:on_enter(from, level, units, passives, shop_level, shop_xp)
main_song_instance:stop()
run_passive_pool = {
'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'shoot_5', 'death_6', 'lasting_7',
'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'pandemic', 'whispers_of_doom',
'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom',
'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment',
'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism',
'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance'
@ -531,7 +531,7 @@ function RestartButton:update(dt)
main_song_instance:stop()
run_passive_pool = {
'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'shoot_5', 'death_6', 'lasting_7',
'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'pandemic', 'whispers_of_doom',
'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom',
'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment',
'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism',
'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance'
@ -1361,13 +1361,14 @@ function ItemCard:init(args)
self.shape = Rectangle(self.x, self.y, self.w, self.h)
self.interact_with_mouse = true
self.max_xp = (self.level == 0 and 0) or (self.level == 1 and 2) or (self.level == 2 and 3) or (self.level == 3 and 0)
self.unlevellable = table.any(unlevellable_items, function(v) return v == self.passive end)
end
function ItemCard:update(dt)
self:update_game_object(dt)
if self.selected and input.m1.pressed then
if self.selected and input.m1.pressed and not self.unlevellable then
if self.level >= 3 then return end
if gold < 5 then
self.spring:pull(0.2, 200, 10)
@ -1418,14 +1419,16 @@ function ItemCard:draw()
graphics.rectangle(self.x, self.y, self.w, self.h, 6, 6, bg[-1])
end
_G[self.passive]:draw(self.x, self.y, 0, 0.8, 0.7, 0, 0, fg[0])
local x, y = self.x + self.w/2.5, self.y - self.h/2.5
if self.level == 1 then
graphics.rectangle(x - 2, y, 2, 2, nil, nil, self.xp >= 1 and fg[0] or bg[5])
graphics.rectangle(x + 2, y, 2, 2, nil, nil, bg[5])
elseif self.level == 2 then
graphics.rectangle(x - 4, y, 2, 2, nil, nil, self.xp >= 1 and fg[0] or bg[5])
graphics.rectangle(x, y, 2, 2, nil, nil, self.xp >= 2 and fg[0] or bg[5])
graphics.rectangle(x + 4, y, 2, 2, nil, nil, bg[5])
if not self.unlevellable then
local x, y = self.x + self.w/2.5, self.y - self.h/2.5
if self.level == 1 then
graphics.rectangle(x - 2, y, 2, 2, nil, nil, self.xp >= 1 and fg[0] or bg[5])
graphics.rectangle(x + 2, y, 2, 2, nil, nil, bg[5])
elseif self.level == 2 then
graphics.rectangle(x - 4, y, 2, 2, nil, nil, self.xp >= 1 and fg[0] or bg[5])
graphics.rectangle(x, y, 2, 2, nil, nil, self.xp >= 2 and fg[0] or bg[5])
graphics.rectangle(x + 4, y, 2, 2, nil, nil, bg[5])
end
end
graphics.pop()
end
@ -1437,7 +1440,7 @@ function ItemCard:create_info_text()
self.info_text.dead = true
end
self.info_text = nil
if self.level == 3 then
if self.level == 3 or self.unlevellable then
self.info_text = InfoText{group = main.current.ui, force_update = true}
self.info_text:activate({
{text = '[fg]' .. passive_names[self.passive] .. ', [yellow]Lv.' .. self.level, font = pixul_font, alignment = 'center',

View File

@ -259,6 +259,7 @@ function Seeker:init(args)
end
self.usurer_count = 0
self.curses = {}
end
@ -283,7 +284,8 @@ 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.tank and 0.35 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.deceleration_mvspd_m or 1)
self.buff_def_m = (self.seeping_def_m or 1)
self:calculate_stats()
@ -382,6 +384,23 @@ function Seeker:on_collision_enter(other, contact)
end
end
if main.current.player.tremor then
if self.being_pushed then
camera:shake(2, 0.5)
earth1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = 0.75*self.push_force*(main.current.player.area_size_m or 1), color = yellow[0], dmg = self.push_force/2, parent = main.current.player}
end
end
if main.current.player.fracture then
trigger:after(0.01, function()
earth2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
for i = 1, 6 do
Projectile{group = main.current.main, x = self.x, y = self.y, color = red[0], r = (i-1)*math.pi/3, v = 200, dmg = 30, parent = main.current.player, pierce = 1}
end
end)
end
if self.headbutter and self.headbutting then
self.headbutting = false
end
@ -412,7 +431,7 @@ function Seeker:on_collision_enter(other, contact)
end
function Seeker:hit(damage, projectile)
function Seeker:hit(damage, projectile, dot)
local pyrod = self.pyrod
self.pyrod = false
if self.dead then return end
@ -426,6 +445,18 @@ function Seeker:hit(damage, projectile)
if self.hp > self.max_hp then self.hp = self.max_hp end
main.current.damage_dealt = main.current.damage_dealt + actual_damage
if dot then
self.seeping_def_m = (main.current.player.seeping == 1 and 0.85) or (main.current.player.seeping == 2 and 0.75) or (main.current.player.seeping == 3 and 0.65) or 1
self.t:after(1, function()
self.seeping_def_m = 1
end, 'seeping')
self.deceleration_mvspd_m = (main.current.player.deceleration == 1 and 0.85) or (main.current.player.deceleration == 2 and 0.75) or (main.current.player.deceleration == 3 and 0.65) or 1
self.t:after(1, function()
self.deceleration_mvspd_m = 1
end, 'deceleration')
end
if projectile and projectile.spawn_critters_on_hit then
critter1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
trigger:after(0.01, function()
@ -576,14 +607,20 @@ function Seeker:curse(curse, duration, arg1, arg2, arg3)
if main.current.player.whispers_of_doom then
if not self.doom then self.doom = 0 end
self.doom = self.doom + 1
if self.doom == 4 then
if self.doom == ((main.current.player.whispers_of_doom == 1 and 4) or (main.current.player.whispers_of_doom == 2 and 3) or (main.current.player.whispers_of_doom == 3 and 2)) then
self.doom = 0
self:hit(200)
self:hit((main.current.player.whispers_of_doom == 1 and 100) or (main.current.player.whispers_of_doom == 2 and 150) or (main.current.player.whispers_of_doom == 3 and 200))
buff1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
end
end
if main.current.player.hextouch then
local p = main.current.player
local dmg = (p.hextouch == 1 and 10) or (p.hextouch == 2 and 15) or (p.hextouch == 3 and 20)
self:apply_dot(dmg*(p.dot_dmg_m or 1)*(main.current.chronomancer_dot or 1), 3)
end
buff1:play{pitch = random:float(0.65, 0.75), volume = 0.25}
if curse == 'launcher' then
self.t:after(duration*curse_m, function()
@ -627,7 +664,7 @@ end
function Seeker:apply_dot(dmg, duration)
self.t:every(0.25, function()
hit2:play{pitch = random:float(0.8, 1.2), volume = 0.2}
self:hit(dmg/4)
self:hit(dmg/4, nil, true)
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = fg[0], duration = 0.1}
for i = 1, 1 do HitParticle{group = main.current.effects, x = self.x, y = self.y, color = self.color} end
for i = 1, 1 do HitParticle{group = main.current.effects, x = self.x, y = self.y, color = purple[0]} end
@ -887,5 +924,11 @@ function EnemyProjectile:on_trigger_enter(other, contact)
if other:is(Player) then
self:die(self.x, self.y, nil, random:int(2, 3))
other:hit(self.dmg)
elseif other:is(Critter) then
if main.current.player.meat_shield then
self:die(self.x, self.y, nil, random:int(2, 3))
other:hit(1000)
end
end
end

View File

@ -167,7 +167,7 @@ function init()
deceleration = Image('deceleration')
annihilation = Image('annihilation')
malediction = Image('malediction')
pandemic = Image('pandemic')
hextouch = Image('hextouch')
whispers_of_doom = Image('whispers_of_doom')
tremor = Image('tremor')
heavy_impact = Image('heavy_impact')
@ -1136,7 +1136,7 @@ function init()
['deceleration'] = 'Deceleration',
['annihilation'] = 'Annihilation',
['malediction'] = 'Malediction',
['pandemic'] = 'Pandemic',
['hextouch'] = 'Hextouch',
['whispers_of_doom'] = 'Whispers of Doom',
['tremor'] = 'Tremor',
['heavy_impact'] = 'Heavy Impact',
@ -1189,15 +1189,15 @@ function init()
['kinetic_bomb'] = '[fg]when an ally dies it explodes, launching enemies away',
['porcupine_technique'] = '[fg]when an ally dies it explodes, releasing piercing and ricocheting projectiles',
['last_stand'] = '[fg]the last unit alive is fully healed and receives a [yellow]+20%[fg] bonus to all stats',
['seeping'] = '[fg]enemies taking DoT damage take [yellow]+15/20/25%[fg] damage for [yellow]6[fg] seconds',
['deceleration'] = '[fg]enemies damaged by voiders have their movement speed reduced by [yellow]15/20/25%',
['seeping'] = '[fg]enemies taking DoT damage have [yellow]-15/25/35%[fg] defense',
['deceleration'] = '[fg]enemies taking DoT damage have [yellow]-15/25/35%[fg] movement speed',
['annihilation'] = '[fg]when a voider dies deal its DoT damage to all enemies for [yellow]3[fg] seconds',
['malediction'] = '[fg]cursed enemies take [yellow]+15/25/35%[fg] damage and deal [yellow]-15/25/35%[fg] damage',
['pandemic'] = '[fg]when a cursed enemy dies its curse spreads',
['malediction'] = '[yellow]+1/3/5[fg] max curse targets to all allied cursers',
['hextouch'] = '[fg]enemies take [yellow]10/15/20[fg] damage per second for [yellow]3[fg] seconds when cursed',
['whispers_of_doom'] = '[fg]curses apply doom, deal [yellow]100/150/200[fg] damage every [yellow]4/3/2[fg] doom instances',
['tremor'] = '[fg]when enemies die from hitting walls they create an area based on the knockback force',
['tremor'] = '[fg]when enemies hit walls they create an area based on the knockback force',
['heavy_impact'] = '[fg]when enemies hit walls they take damage based on the knockback force',
['fracture'] = '[fg]when enemies die from hitting walls they explode into projectiles',
['fracture'] = '[fg]when enemies hit walls they explode into projectiles',
['meat_shield'] = '[fg]critters [yellow]block[fg] enemy projectiles',
['hive'] = '[fg]critters have [yellow]+1/2/3[fg] HP',
['baneling_burst'] = '[fg]critters die immediately on contact but also deal [yellow]50/100/150[fg] AoE damage',
@ -1218,7 +1218,7 @@ function init()
['enchanted'] = '[yellow]+10/20/30%[fg] attack speed to a random unit with at least two enchanters',
['freezing_field'] = '[fg]creates an area that slows enemies by [yellow]50%[fg] for [yellow]2[fg] seconds on sorcerer spell repeat',
['burning_field'] = '[fg]creates an area that deals [yellow]30[fg] dps for [yellow]2[fg] seconds on sorcerer spell repeat',
['gravity_field'] = '[fg]creates an area that pulls enemies in for [yellow]2[fg] seconds on sorcerer spell repeat',
['gravity_field'] = '[fg]creates an area that pulls enemies in for [yellow]1[fg] seconds on sorcerer spell repeat',
['magnetism'] = '[fg]gold coins are attracted to the snake',
['insurance'] = "[fg]heroes have [yellow]4[fg] times the chance of mercenary's bonus to drop [yellow]2[fg] gold on death",
['dividends'] = '[fg]mercenaries deal [yellow]+X%[fg] damage, where X is how much gold you have',
@ -1247,15 +1247,15 @@ function init()
['kinetic_bomb'] = function(lvl) return '[fg]when an ally dies it explodes, launching enemies away' end,
['porcupine_technique'] = function(lvl) return '[fg]when an ally dies it explodes, releasing piercing projectiles' end,
['last_stand'] = function(lvl) return '[fg]the last unit alive is fully healed and receives a [yellow]+20%[fg] bonus to all stats' end,
['seeping'] = function(lvl) return '[fg]enemies taking DoT damage take ' .. ts(lvl, '+15%', '20%', '25%') .. ' damage for [yellow]6[fg] seconds' end,
['deceleration'] = function(lvl) return '[fg]enemies damaged by voiders have their movement speed reduced by ' .. ts(lvl, '15%', '20%', '25%') end,
['seeping'] = function(lvl) return '[fg]enemies taking DoT damage have ' .. ts(lvl, '-15%', '25%', '35%') .. ' defense' end,
['deceleration'] = function(lvl) return '[fg]enemies taking DoT damage have ' .. ts(lvl, '-15%', '25%', '35%') .. ' movement speed' end,
['annihilation'] = function(lvl) return '[fg]when a voider dies deal its DoT damage to all enemies for [yellow]3[fg] seconds' end,
['malediction'] = function(lvl) return '[fg]cursed enemies take ' .. ts(lvl, '+15%', '25%', '35%') .. ' damage and deal ' .. ts(lvl, '-15%', '25%', '35%') .. ' damage' end,
['pandemic'] = function(lvl) return '[fg]when a cursed enemy dies its curse spreads' end,
['malediction'] = function(lvl) return ts(lvl, '+1', '3', '5') .. ' max curse targets to all allied cursers' end,
['hextouch'] = function(lvl) return '[fg]enemies take ' .. ts(lvl, '10', '15', '20') .. 'damage per second for [yellow]3[fg] seconds when cursed' end,
['whispers_of_doom'] = function(lvl) return '[fg]curses apply doom, deal ' .. ts(lvl, '100', '150', '200') .. ' every ' .. ts(lvl, '4', '3', '2') .. ' doom instances' end,
['tremor'] = function(lvl) return '[fg]when enemies die from hitting walls they create an area based to the knockback force' end,
['tremor'] = function(lvl) return '[fg]when enemies hit walls they create an area based to the knockback force' end,
['heavy_impact'] = function(lvl) return '[fg]when enemies hit walls they take damage based on the knockback force' end,
['fracture'] = function(lvl) return '[fg]when enemies die from hitting walls they explode into projectiles' end,
['fracture'] = function(lvl) return '[fg]when enemies hit walls they explode into projectiles' end,
['meat_shield'] = function(lvl) return '[fg]critters [yellow]block[fg] enemy projectiles' end,
['hive'] = function(lvl) return '[fg]critters have ' .. ts(lvl, '+1', '2', '3') .. ' HP' end,
['baneling_burst'] = function(lvl) return '[fg]critters die immediately on contact but also deal ' .. ts(lvl, '50', '100', '150') .. ' AoE damage' end,
@ -1276,7 +1276,7 @@ function init()
['enchanted'] = function(lvl) return ts(lvl, '+10%', '20%', '30%') .. ' attack speed to a random unit with at least two enchanters' end,
['freezing_field'] = function(lvl) return '[fg]creates an area that slows enemies by [yellow]50%[fg] for [yellow]2[fg] seconds on sorcerer spell repeat' end,
['burning_field'] = function(lvl) return '[fg]creates an area that deals [yellow]30[fg] dps for [yellow]2[fg] seconds on sorcerer spell repeat' end,
['gravity_field'] = function(lvl) return '[fg]creates an area that pulls enemies in for [yellow]2[fg] seconds on sorcerer spell repeat' end,
['gravity_field'] = function(lvl) return '[fg]creates an area that pulls enemies in for [yellow]1[fg] seconds on sorcerer spell repeat' end,
['magnetism'] = function(lvl) return '[fg]gold coins are attracted to the snake' end,
['insurance'] = function(lvl) return "[fg]heroes have [yellow]4[fg] times the chance of mercenary's bonus to drop [yellow]2[fg] gold on death" end,
['dividends'] = function(lvl) return '[fg]mercenaries deal [yellow]+X%[fg] damage, where X is how much gold you have' end,
@ -1467,10 +1467,16 @@ function init()
end
end
unlevellable_items = {
'speed_3', 'damage_4', 'shoot_5', 'death_6', 'lasting_7', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'annihilation',
'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'divine_punishment', 'unleash', 'freezing_field', 'burning_field', 'gravity_field',
'magnetism', 'insurance', 'dividends'
}
local run = system.load_run()
run_passive_pool = run.run_passive_pool or {
'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'shoot_5', 'death_6', 'lasting_7',
'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'pandemic', 'whispers_of_doom',
'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom',
'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment',
'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism',
'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance'
@ -1498,15 +1504,12 @@ function init()
--[[
main:add(Arena'arena')
main:go_to('arena', 13, {
{character = 'witch', level = 1},
{character = 'stormweaver', level = 1},
{character = 'chronomancer', level = 1},
{character = 'miner', level = 1},
main:go_to('arena', 3, {
{character = 'merchant', level = 1},
{character = 'sage', level = 1},
{character = 'magician', level = 1},
}, {{passive = 'last_stand', level = 1}})
{character = 'miner', level = 1},
{character = 'thief', level = 1},
{character = 'gambler', level = 1},
}, passives)
]]--
--[[

View File

@ -64,6 +64,7 @@ function Player:init(args)
if main.current.sorcerer_level > 0 then
self.sorcerer_count = self.sorcerer_count + 1
if self.sorcerer_count >= ((main.current.sorcerer_level == 3 and 2) or (main.current.sorcerer_level == 2 and 3) or (main.current.sorcerer_level == 1 and 4)) then
self:sorcerer_repeat()
self.sorcerer_count = 0
self.t:after(0.25, function()
local enemy = table.shuffle(main.current.main:get_objects_by_classes(main.current.enemies))[1]
@ -161,6 +162,7 @@ function Player:init(args)
if main.current.sorcerer_level > 0 then
self.sorcerer_count = self.sorcerer_count + 1
if self.sorcerer_count >= ((main.current.sorcerer_level == 3 and 2) or (main.current.sorcerer_level == 2 and 3) or (main.current.sorcerer_level == 1 and 4)) then
self:sorcerer_repeat()
self.sorcerer_count = 0
self.t:after(0.25, function()
self:shoot(self:angle_to_object(closest_enemy), {pierce = 1000, v = 40})
@ -180,6 +182,7 @@ function Player:init(args)
if main.current.sorcerer_level > 0 then
self.sorcerer_count = self.sorcerer_count + 1
if self.sorcerer_count >= ((main.current.sorcerer_level == 3 and 2) or (main.current.sorcerer_level == 2 and 3) or (main.current.sorcerer_level == 1 and 4)) then
self:sorcerer_repeat()
self.sorcerer_count = 0
self.t:after(0.25, function()
self:shoot(self:angle_to_object(closest_enemy))
@ -199,6 +202,7 @@ function Player:init(args)
if main.current.sorcerer_level > 0 then
self.sorcerer_count = self.sorcerer_count + 1
if self.sorcerer_count >= ((main.current.sorcerer_level == 3 and 2) or (main.current.sorcerer_level == 2 and 3) or (main.current.sorcerer_level == 1 and 4)) then
self:sorcerer_repeat()
self.sorcerer_count = 0
self.t:after(0.25, function()
SpawnEffect{group = main.current.effects, x = self.x, y = self.y, color = self.color, action = function(x, y)
@ -262,6 +266,7 @@ function Player:init(args)
self.sorcerer_count = self.sorcerer_count + 1
if self.sorcerer_count >= ((main.current.sorcerer_level == 3 and 2) or (main.current.sorcerer_level == 2 and 3) or (main.current.sorcerer_level == 1 and 4)) then
self.sorcerer_count = 0
self:sorcerer_repeat()
self.t:after(0.1, function()
strike()
end)
@ -337,6 +342,7 @@ function Player:init(args)
self.sorcerer_count = self.sorcerer_count + 1
if self.sorcerer_count >= ((main.current.sorcerer_level == 3 and 2) or (main.current.sorcerer_level == 2 and 3) or (main.current.sorcerer_level == 1 and 4)) then
self.sorcerer_count = 0
self:sorcerer_repeat()
self.t:after(0.5, function()
volcano()
end)
@ -421,6 +427,7 @@ function Player:init(args)
self.sorcerer_count = self.sorcerer_count + 1
if self.sorcerer_count >= ((main.current.sorcerer_level == 3 and 2) or (main.current.sorcerer_level == 2 and 3) or (main.current.sorcerer_level == 1 and 4)) then
self.sorcerer_count = 0
self:sorcerer_repeat()
self.t:after(0.25, function()
self:dot_attack(42, {duration = random:float(12, 16)})
end)
@ -496,7 +503,7 @@ function Player:init(args)
self.wide_attack_sensor = Circle(self.x, self.y, 128)
self.t:cooldown(6, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
buff1:play{pitch = random:float(0.9, 1.1), volume = 0.5}
local enemies = table.first(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 6)
local enemies = table.first2(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 6 + ((self.malediction == 1 and 1) or (self.malediction == 2 and 3) or (self.malediction == 3 and 5) or 0))
for _, enemy in ipairs(enemies) do
if self:distance_to_object(enemy) < 128 then
enemy:curse('jester', 6*(self.hex_duration_m or 1), self.level == 3, self)
@ -511,7 +518,7 @@ function Player:init(args)
self.wide_attack_sensor = Circle(self.x, self.y, 128)
self.t:cooldown(6, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
buff1:play{pitch = random:float(0.9, 1.1), volume = 0.5}
local enemies = table.first2(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 3)
local enemies = table.first2(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 3 + ((self.malediction == 1 and 1) or (self.malediction == 2 and 3) or (self.malediction == 3 and 5) or 0))
for _, enemy in ipairs(enemies) do
enemy:curse('usurer', 10000, self.level == 3, self)
enemy:apply_dot(self.dmg*(self.dot_dmg_m or 1)*(main.current.chronomancer_dot or 1), 10000)
@ -527,7 +534,7 @@ function Player:init(args)
self.t:cooldown(6, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
local curse = function()
buff1:play{pitch = random:float(0.9, 1.1), volume = 0.5}
local enemies = table.first(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 6)
local enemies = table.first2(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 6 + ((self.malediction == 1 and 1) or (self.malediction == 2 and 3) or (self.malediction == 3 and 5) or 0))
for _, enemy in ipairs(enemies) do
enemy:curse('silencer', 6*(self.hex_duration_m or 1), self.level == 3, self)
if self.level == 3 then
@ -546,6 +553,7 @@ function Player:init(args)
self.sorcerer_count = self.sorcerer_count + 1
if self.sorcerer_count >= ((main.current.sorcerer_level == 3 and 2) or (main.current.sorcerer_level == 2 and 3) or (main.current.sorcerer_level == 1 and 4)) then
self.sorcerer_count = 0
self:sorcerer_repeat()
self.t:after(0.5, function()
curse()
end)
@ -587,7 +595,7 @@ function Player:init(args)
self.wide_attack_sensor = Circle(self.x, self.y, 128)
self.t:cooldown(6, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
buff1:play{pitch = random:float(0.9, 1.1), volume = 0.5}
local enemies = table.first(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 6)
local enemies = table.first2(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 6 + ((self.malediction == 1 and 1) or (self.malediction == 2 and 3) or (self.malediction == 3 and 5) or 0))
for _, enemy in ipairs(enemies) do
enemy:curse('bane', 6*(self.hex_duration_m or 1), self.level == 3, self)
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = purple[0], duration = 0.1}
@ -719,6 +727,7 @@ function Player:init(args)
self.sorcerer_count = self.sorcerer_count + 1
if self.sorcerer_count >= ((main.current.sorcerer_level == 3 and 2) or (main.current.sorcerer_level == 2 and 3) or (main.current.sorcerer_level == 1 and 4)) then
self.sorcerer_count = 0
self:sorcerer_repeat()
self.t:after(0.5, function()
ward()
end)
@ -750,7 +759,7 @@ function Player:init(args)
self.wide_attack_sensor = Circle(self.x, self.y, 128)
self.t:cooldown(6, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
buff1:play{pitch = random:float(0.9, 1.1), volume = 0.5}
local enemies = table.first(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 8)
local enemies = table.first2(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 8 + ((self.malediction == 1 and 1) or (self.malediction == 2 and 3) or (self.malediction == 3 and 5) or 0))
for _, enemy in ipairs(enemies) do
enemy:curse('infestor', 6*(self.hex_duration_m or 1), (self.level == 3 and 6 or 2), self.dmg, self)
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = orange[0], duration = 0.1}
@ -837,8 +846,8 @@ function Player:init(args)
end
if self.chronomancy then
if table.any(self.classes, function(v) return v == 'mage' end) or table.any(self.classes, function(v) return v == 'sorcerer' end) then
self.chronomancy_aspd_m = 1.25
if table.any(self.classes, function(v) return v == 'mage' end) then
self.chronomancy_aspd_m = (self.chronomancy == 1 and 1.15) or (self.chronomancy == 2 and 1.25) or (self.chronomancy == 3 and 1.35)
end
end
@ -847,14 +856,14 @@ function Player:init(args)
local units = self:get_all_units()
local mages = {}
for _, unit in ipairs(units) do
if table.any(unit.classes, function(v) return v == 'mage' end) or table.any(unit.classes, function(v) return v == 'sorcerer' end) then
if table.any(unit.classes, function(v) return v == 'mage' end) then
table.insert(mages, unit)
end
end
local mage = random:table(mages)
if mage then
mage.awakening_aspd_m = 2
mage.awakening_dmg_m = 2
mage.awakening_aspd_m = (self.awakening == 1 and 1.5) or (self.awakening == 2 and 1.75) or (self.awakening == 3 and 2)
mage.awakening_dmg_m = (self.awakening == 1 and 1.5) or (self.awakening == 2 and 1.75) or (self.awakening == 3 and 2)
end
end)
end
@ -864,14 +873,14 @@ function Player:init(args)
local units = self:get_all_units()
local mages = {}
for _, unit in ipairs(units) do
if table.any(unit.classes, function(v) return v == 'mage' end) or table.any(unit.classes, function(v) return v == 'sorcerer' end) then
if table.any(unit.classes, function(v) return v == 'mage' end) then
table.insert(mages, unit)
end
end
local leader = main.current.player:get_leader()
local enemies = main.current.main:get_objects_by_classes(main.current.enemies)
if #enemies > 0 then
thunder1:play{volume = 0.4}
thunder1:play{volume = 0.3}
camera:shake(4, 0.5)
end
for _, enemy in ipairs(enemies) do
@ -885,15 +894,15 @@ function Player:init(args)
if self.unwavering_stance and table.any(self.classes, function(v) return v == 'warrior' end) then
self.unwavering_stance_def_m = 1
self.t:every(5, function()
self.unwavering_stance_def_m = self.unwavering_stance_def_m + 0.05
self.unwavering_stance_def_m = self.unwavering_stance_def_m + ((self.unwavering_stance == 1 and 0.04) or (self.unwavering_stance == 2 and 0.08) or (self.unwavering_stance == 3 and 0.12))
end)
end
if self.magnify then
self.magnify_area_size_m = 1.25
self.magnify_area_size_m = (self.magnify == 1 and 1.2) or (self.magnify == 2 and 1.35) or (self.magnify == 3 and 1.5)
end
if self.unleash then
if self.unleash and table.any(self.classes, function(v) return v == 'nuker' end) then
self.unleash_area_dmg_m = 1
self.unleash_area_size_m = 1
self.t:every(1, function()
@ -916,13 +925,32 @@ function Player:init(args)
end
end
if any_enchanter then
self.reinforce_dmg_m = 1.1
self.reinforce_def_m = 1.1
self.reinforce_aspd_m = 1.1
local v = (self.reinforce == 1 and 1.1) or (self.reinforce == 2 and 1.2) or (self.reinforce == 3 and 1.3) or 1
self.reinforce_dmg_m = v
self.reinforce_def_m = v
self.reinforce_aspd_m = v
end
end)
end
if self.enchanted then
main.current.t:after(0.1, function()
local units = self:get_all_units()
local enchanter_amount = 0
for _, unit in ipairs(units) do
if table.any(unit.classes, function(v) return v == 'enchanter' end) then
enchanter_amount = enchanter_amount + 1
end
end
if enchanter_amount >= 2 then
local unit = random:table(units)
unit.enchanted_aspd_m = (self.enchanted == 1 and 1.1) or (self.enchanted == 2 and 1.2) or (self.enchanted == 3 and 1.3)
end
end)
end
if self.payback then
self.payback_dmg_m = 1
end
@ -931,6 +959,10 @@ function Player:init(args)
self.hex_duration_m = 1.25
end
if self.unrelenting_stance then
self.unrelenting_stance_def_m = 1
end
if self.leader and self.immolation then
main.current.t:after(0.1, function()
local units = self:get_all_units()
@ -1128,7 +1160,7 @@ function Player:update(dt)
end
if self.berserking and table.any(self.classes, function(v) return v == 'warrior' end) then
self.berserking_aspd_m = math.remap(self.hp/self.max_hp, 0, 1, 1.5, 1)
self.berserking_aspd_m = math.remap(self.hp/self.max_hp, 0, 1, (self.berserking == 1 and 1.5) or (self.berserking == 2 and 1.75) or (self.berserking == 3 and 2), 1)
end
if self.speed_3 and self.follower_index == 2 then
@ -1164,10 +1196,14 @@ function Player:update(dt)
self.last_stand_mvspd_m = 1.2
end
if self.dividends and table.any(self.classes, function(v) return v == 'mercenary' end) then
self.dividends_dmg_m = (1 + gold/100)
end
self.buff_def_a = (self.warrior_def_a or 0)
self.buff_aspd_m = (self.chronomancer_aspd_m or 1)*(self.vagrant_aspd_m or 1)*(self.outlaw_aspd_m or 1)*(self.fairy_aspd_m or 1)*(self.psyker_aspd_m or 1)*(self.chronomancy_aspd_m or 1)*(self.awakening_aspd_m or 1)*(self.berserking_aspd_m or 1)*(self.reinforce_aspd_m or 1)*(self.squire_aspd_m or 1)*(self.speed_3_aspd_m or 1)*(self.last_stand_aspd_m or 1)
self.buff_dmg_m = (self.squire_dmg_m or 1)*(self.vagrant_dmg_m or 1)*(self.enchanter_dmg_m or 1)*(self.swordsman_dmg_m or 1)*(self.flagellant_dmg_m or 1)*(self.psyker_dmg_m or 1)*(self.ballista_dmg_m or 1)*(self.awakening_dmg_m or 1)*(self.reinforce_dmg_m or 1)*(self.payback_dmg_m or 1)*(self.immolation_dmg_m or 1)*(self.damage_4_dmg_m or 1)*(self.offensive_stance_dmg_m or 1)*(self.last_stand_dmg_m or 1)
self.buff_def_m = (self.squire_def_m or 1)*(self.ouroboros_def_m or 1)*(self.unwavering_stance_def_m or 1)*(self.reinforce_def_m or 1)*(self.defensive_stance_def_m or 1)*(self.last_stand_def_m or 1)
self.buff_aspd_m = (self.chronomancer_aspd_m or 1)*(self.vagrant_aspd_m or 1)*(self.outlaw_aspd_m or 1)*(self.fairy_aspd_m or 1)*(self.psyker_aspd_m or 1)*(self.chronomancy_aspd_m or 1)*(self.awakening_aspd_m or 1)*(self.berserking_aspd_m or 1)*(self.reinforce_aspd_m or 1)*(self.squire_aspd_m or 1)*(self.speed_3_aspd_m or 1)*(self.last_stand_aspd_m or 1)*(self.enchanted_aspd_m or 1)
self.buff_dmg_m = (self.squire_dmg_m or 1)*(self.vagrant_dmg_m or 1)*(self.enchanter_dmg_m or 1)*(self.swordsman_dmg_m or 1)*(self.flagellant_dmg_m or 1)*(self.psyker_dmg_m or 1)*(self.ballista_dmg_m or 1)*(self.awakening_dmg_m or 1)*(self.reinforce_dmg_m or 1)*(self.payback_dmg_m or 1)*(self.immolation_dmg_m or 1)*(self.damage_4_dmg_m or 1)*(self.offensive_stance_dmg_m or 1)*(self.last_stand_dmg_m or 1)*(self.dividends_dmg_m or 1)
self.buff_def_m = (self.squire_def_m or 1)*(self.ouroboros_def_m or 1)*(self.unwavering_stance_def_m or 1)*(self.reinforce_def_m or 1)*(self.defensive_stance_def_m or 1)*(self.last_stand_def_m or 1)*(self.unrelenting_stance_def_m or 1)
self.buff_area_size_m = (self.nuker_area_size_m or 1)*(self.magnify_area_size_m or 1)*(self.unleash_area_size_m or 1)*(self.last_stand_area_size_m or 1)
self.buff_area_dmg_m = (self.nuker_area_dmg_m or 1)*(self.amplify_area_dmg_m or 1)*(self.unleash_area_dmg_m or 1)*(self.last_stand_area_dmg_m or 1)
self.buff_mvspd_m = (self.wall_rider_mvspd_m or 1)*(self.centipede_mvspd_m or 1)*(self.squire_mvspd_m or 1)*(self.last_stand_mvspd_m or 1)
@ -1350,7 +1386,19 @@ function Player:hit(damage, from_undead)
main.current.damage_taken = main.current.damage_taken + actual_damage
if self.payback and table.any(self.classes, function(v) return v == 'enchanter' end) then
self.payback_dmg_m = self.payback_dmg_m + 0.05
local units = self:get_all_units()
for _, unit in ipairs(units) do
if not unit.payback_dmg_m then unit.payback_dmg_m = 1 end
unit.payback_dmg_m = unit.payback_dmg_m + ((self.payback == 1 and 0.02) or (self.payback == 2 and 0.05) or (self.payback == 3 and 0.08) or 0)
end
end
if self.unrelenting_stance and table.any(self.classes, function(v) return v == 'warrior' end) then
local units = self:get_all_units()
for _, unit in ipairs(units) do
if not unit.unrelenting_stance_def_m then unit.unrelenting_stance_def_m = 1 end
unit.unrelenting_stance_def_m = unit.unrelenting_stance_def_m + ((self.unrelenting_stance == 1 and 0.02) or (self.unrelenting_stance == 2 and 0.05) or (self.unrelenting_stance == 3 and 0.08) or 0)
end
end
if self.character == 'beastmaster' and self.level == 3 then
@ -1452,12 +1500,57 @@ function Player:hit(damage, from_undead)
end)
end
if self.annihilation and table.any(self.classes, function(v) return v == 'voider' end) then
local enemies = self.group:get_objects_by_classes({Seeker, EnemyCritter})
for _, enemy in ipairs(enemies) do
enemy:apply_dot(self.dmg*(self.dot_dmg_m or 1)*(main.current.chronomancer_dot or 1), 3)
end
end
if self.insurance then
if random:bool(4*((main.current.mercenary_level == 2 and 20) or (main.current.mercenary_level == 1 and 10) or 0)) then
main.current.t:after(0.01, function()
Gold{group = main.current.main, x = self.x, y = self.y}
Gold{group = main.current.main, x = self.x, y = self.y}
end)
end
end
if self.dot_area then self.dot_area.dead = true; self.dot_area = nil end
end
end
end
function Player:sorcerer_repeat()
local enemies = self.group:get_objects_by_classes(main.current.enemies)
if not enemies then return end
local enemy = random:table(enemies)
if enemy then
if self.gravity_field then
ForceArea{group = main.current.effects, x = enemy.x, y = enemy.y, rs = self.area_size_m*24, color = fg[0], character = 'gravity_field', parent = self}
end
end
local enemy = random:table(enemies)
if enemy then
if self.burning_field then
fire1:play{pitch = random:float(0.9, 1.1), volume = 0.5}
DotArea{group = main.current.effects, x = enemy.x, y = enemy.y, rs = self.area_size_m*24, color = red[0], dmg = 30*self.area_dmg_m*(self.dot_dmg_m or 1), duration = 2, character = 'burning_field'}
end
end
local enemy = random:table(enemies)
if enemy then
if self.freezing_field then
frost1:play{pitch = random:float(0.8, 1.2), volume = 0.3}
elementor1:play{pitch = random:float(0.9, 1.1), volume = 0.3}
Area{group = main.current.effects, x = enemy.x, y = enemy.y, w = self.area_size_m*36, color = fg[0], character = 'freezing_field', parent = self}
end
end
end
function Player:heal(amount)
local hp = self.hp
@ -1542,7 +1635,7 @@ function Player:shoot(r, mods)
local dmg_m = 1
local crit = false
if self.chance_to_crit and random:bool(self.chance_to_crit) then dmg_m = (self.assassination and 8 or 4); crit = true end
if self.chance_to_crit and random:bool(self.chance_to_crit) then dmg_m = ((self.assassination == 1 and 8) or (self.assassination == 2 and 10) or (self.assassination == 3 and 12) or 4); crit = true end
if self.assassination and table.any(self.classes, function(v) return v == 'rogue' end) then
if not crit then
dmg_m = 0.5
@ -1805,9 +1898,9 @@ function Projectile:init(args)
end
if self.parent.divine_machine_arrow and table.any(self.parent.classes, function(v) return v == 'ranger' end) then
if random:bool(40) then
if random:bool((self.parent.divine_machine_arrow == 1 and 10) or (self.parent.divine_machine_arrow == 2 and 20) or (self.parent.divine_machine_arrow == 3 and 30)) then
self.homing = true
self.pierce = 4
self.pierce = self.parent.divine_machine_arrow or 0
end
end
@ -1823,13 +1916,13 @@ function Projectile:init(args)
self.distance_dmg_m = 1
if self.parent.blunt_arrow and table.any(self.parent.classes, function(v) return v == 'ranger' end) then
if random:bool(20) then
if random:bool((self.parent.blunt_arrow == 1 and 10) or (self.parent.blunt_arrow == 2 and 20) or (self.parent.blunt_arrow == 3 and 30)) then
self.knockback = 10
end
end
if self.parent.flying_daggers and table.any(self.parent.classes, function(v) return v == 'rogue' end) then
self.chain = self.chain + 2
self.chain = self.chain + ((self.parent.flying_daggers == 1 and 2) or (self.parent.flying_daggers == 2 and 3) or (self.parent.flying_daggers == 3 and 4))
end
end
@ -2022,7 +2115,7 @@ function Projectile:on_trigger_enter(other, contact)
self.dmg = self.dmg*1.25
end
if self.parent.ultimatum then
self.dmg = self.dmg*1.25
self.dmg = self.dmg*((self.parent.ultimatum == 1 and 1.1) or (self.parent.ultimatum == 2 and 1.2) or (self.parent.ultimatum == 3 and 1.3))
end
end
end
@ -2109,10 +2202,11 @@ function Projectile:on_trigger_enter(other, contact)
end
if self.parent.explosive_arrow and table.any(self.parent.classes, function(v) return v == 'ranger' end) then
if random:bool(30) then
if random:bool((self.parent.explosive_arrow == 1 and 10) or (self.parent.explosive_arrow == 2 and 20) or (self.parent.explosive_arrow == 3 and 30)) then
_G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
Area{group = main.current.effects, x = self.x, y = self.y, r = self.r + random:float(0, 2*math.pi), w = self.parent.area_size_m*32, color = self.color,
dmg = 0.2*self.parent.area_dmg_m*self.dmg, character = self.character, level = self.level, parent = self, void_rift = self.parent.void_rift, echo_barrage = self.parent.echo_barrage}
dmg = ((self.parent.explosive_arrow == 1 and 0.1) or (self.parent.explosive_arrow == 2 and 0.2) or (self.parent.explosive_arrow == 3 and 0.3))*self.parent.area_dmg_m*self.dmg, character = self.character,
level = self.level, parent = self, void_rift = self.parent.void_rift, echo_barrage = self.parent.echo_barrage}
end
end
@ -2154,6 +2248,8 @@ function Area:init(args)
elseif self.character == 'launcher' then
if self.parent.resonance then resonance_dmg = (self.level == 3 and 6*self.dmg*0.05*#enemies or 2*self.dmg*0.05*#enemies) end
enemy:curse('launcher', 4*(self.hex_duration_m or 1), (self.level == 3 and 6*self.dmg or 2*self.dmg) + resonance_dmg, self.parent)
elseif self.character == 'freezing_field' then
enemy:slow(0.5, 2)
else
if self.parent.resonance then resonance_dmg = self.dmg*resonance_m*#enemies end
enemy:hit(self.dmg + resonance_dmg, self)
@ -2197,12 +2293,12 @@ function Area:init(args)
end
end
if p.echo_barrage and not self.echo_barrage_area then
if random:bool(20) then
if random:bool((p.echo_barrage == 1 and 10) or (p.echo_barrage == 2 and 20) or (p.echo_barrage == 3 and 30)) then
p.t:every(0.3, function()
_G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
Area{group = main.current.effects, x = self.x + random:float(-32, 32), y = self.y + random:float(-32, 32), r = self.r + random:float(0, 2*math.pi), w = p.area_size_m*48, color = p.color,
dmg = 0.5*p.area_dmg_m*self.dmg, character = self.character, level = p.level, parent = p, echo_barrage_area = true}
end, 3)
end, p.echo_barrage)
end
end
else
@ -2213,12 +2309,12 @@ function Area:init(args)
end
end
if self.parent.echo_barrage and not self.echo_barrage_area then
if random:bool(20) then
if random:bool((self.parent.echo_barrage == 1 and 10) or (self.parent.echo_barrage == 2 and 20) or (self.parent.echo_barrage == 3 and 30)) then
self.parent.t:every(0.3, function()
_G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
Area{group = main.current.effects, x = self.x + random:float(-32, 32), y = self.y + random:float(-32, 32), r = self.r + random:float(0, 2*math.pi), w = self.parent.area_size_m*48, color = self.parent.color,
dmg = 0.5*self.parent.area_dmg_m*self.dmg, character = self.character, level = self.parent.level, parent = self.parent, echo_barrage_area = true}
end, 3)
end, self.parent.echo_barrage)
end
end
end
@ -2267,7 +2363,7 @@ function DotArea:init(args)
self.shape = Circle(self.x, self.y, self.rs)
self.closest_sensor = Circle(self.x, self.y, 128)
if self.character == 'plague_doctor' or self.character == 'pyromancer' or self.character == 'witch' then
if self.character == 'plague_doctor' or self.character == 'pyromancer' or self.character == 'witch' or self.character == 'burning_field' then
self.t:every(0.2, function()
local enemies = main.current.main:get_objects_in_shape(self.shape, main.current.enemies)
if #enemies > 0 then self.spring:pull(0.05, 200, 10) end
@ -2279,7 +2375,7 @@ function DotArea:init(args)
enemy.pyrod = self
end
end
enemy:hit((self.dot_dmg_m or 1)*self.dmg/5, self)
enemy:hit((self.dot_dmg_m or 1)*self.dmg/5, self, true)
HitCircle{group = main.current.effects, x = enemy.x, y = enemy.y, rs = 6, color = fg[0], duration = 0.1}
for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = self.color} end
for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = enemy.color} end
@ -2297,7 +2393,7 @@ function DotArea:init(args)
if self.level == 3 then
enemy:slow(0.4, 4)
end
enemy:hit((self.dot_dmg_m or 1)*2*self.dmg, self)
enemy:hit((self.dot_dmg_m or 1)*2*self.dmg, self, true)
HitCircle{group = main.current.effects, x = enemy.x, y = enemy.y, rs = 6, color = fg[0], duration = 0.1}
for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = self.color} end
for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = enemy.color} end
@ -2333,7 +2429,7 @@ function DotArea:init(args)
if #enemies > 0 then self.spring:pull(0.05, 200, 10) end
for _, enemy in ipairs(enemies) do
hit2:play{pitch = random:float(0.8, 1.2), volume = 0.2}
enemy:hit((self.dot_dmg_m or 1)*self.dmg/5, self)
enemy:hit((self.dot_dmg_m or 1)*self.dmg/5, self, true)
HitCircle{group = main.current.effects, x = enemy.x, y = enemy.y, rs = 6, color = fg[0], duration = 0.1}
for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = self.color} end
for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = enemy.color} end
@ -2463,6 +2559,21 @@ function ForceArea:init(args)
end
end
end)
elseif self.character == 'gravity_field' then
elementor1:play{pitch = random:float(0.9, 1.1), volume = 0.4}
self.t:tween(1, self, {dvr = 0}, math.linear)
self.t:during(1, function()
local enemies = main.current.main:get_objects_in_shape(self.shape, main.current.enemies)
local t = self.t:get_during_elapsed_time('gravity_field')
for _, enemy in ipairs(enemies) do
enemy:apply_steering_force(400*(1-t), enemy:angle_to_point(self.x, self.y))
end
end, nil, 'gravity_field')
self.t:after(1 - 0.35, function()
self.t:every_immediate(0.05, function() self.hidden = not self.hidden end, 7, function() self.dead = true end)
end)
end
end
@ -2992,13 +3103,32 @@ function Gold:init(args)
self:set_angular_damping(5)
self.color = yellow2[0]
self.hfx:add('hit', 1)
self.cant_be_picked_up = true
self.t:after(0.5, function() self.cant_be_picked_up = false end)
gold1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
self.magnet_sensor = Circle(self.x, self.y, 32)
end
function Gold:update(dt)
self:update_game_object(dt)
self.r = self:get_angle()
if main.current.player.magnetism then
local players = self:get_objects_in_shape(self.magnet_sensor, {Player})
if players and #players > 0 then
local x, y = 0, 0
for _, p in ipairs(players) do
x = x + p.x
y = y + p.y
end
x = x/#players
y = y/#players
local r = self:angle_to_point(x, y)
self:apply_force(20*math.cos(r), 20*math.sin(r))
end
end
self.magnet_sensor:move_to(self.x, self.y)
end
@ -3010,6 +3140,8 @@ function Gold:draw()
end
function Gold:on_trigger_enter(other, contact)
if self.cant_be_picked_up then return end
if other:is(Player) then
main.current.gold_picked_up = main.current.gold_picked_up + 1
self.dead = true
@ -3077,7 +3209,7 @@ function Critter:init(args)
self.t:after(0.5, function() self.invulnerable = false end)
self.dmg = args.dmg or self.parent.dmg
self.hp = 1 + ((main.current.swarmer_level == 2 and 3) or (main.current.swarmer_level == 1 and 1) or 0) + (self.parent.spawning_pool and 1 or 0) + (self.parent.hive and 2 or 0)
self.hp = 1 + ((main.current.swarmer_level == 2 and 3) or (main.current.swarmer_level == 1 and 1) or 0) + (self.parent.hive or 0)
end
@ -3125,7 +3257,11 @@ function Critter:hit(damage)
self.hfx:use('hit', 0.25, 200, 10)
self.hp = self.hp - 1
-- self:show_hp()
if self.hp <= 0 then self:die() end
if main.current.player.baneling_burst then
self:die()
else
if self.hp <= 0 then self:die() end
end
end
@ -3150,6 +3286,12 @@ function Critter:die(x, y, r, n)
self.dead = true
_G[random:table{'enemy_die1', 'enemy_die2'}]:play{pitch = random:float(0.9, 1.1), volume = 0.5}
critter2:play{pitch = random:float(0.95, 1.05), volume = 0.2}
if main.current.player.baneling_burst then
camera:shake(2, 0.5)
Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*24, color = self.color, dmg = self.parent.dmg*self.parent.area_dmg_m*0.25, parent = self.parent}
_G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
end
end

75
todo
View File

@ -25,54 +25,53 @@ Item Update
* Porcupine Technique - when a unit dies it explodes, releasing piercing projectiles
* Last Stand - the last unit alive is fully healed and receives a +20% bonus to all stats
Voider:
vt Seeping - enemies taking DoT damage take +15/20/25% damage from all sources for 6 seconds
vt Deceleration - enemies damaged by voiders have their movement speed reduced by 15/20/25%
vt Annihilation - when a voider dies deal its DoT damage to all enemies for 3 seconds
* Seeping - enemies taking DoT damage take +15/20/25% damage from all sources for 6 seconds
* Deceleration - enemies damaged by voiders have their movement speed reduced by 15/20/25%
* Annihilation - when a voider dies deal its DoT damage to all enemies for 3 seconds
Curser:
change one of these for +1/3/5 curse targets
vt Malediction - cursed enemies take 15/25/35% more damage and deal 15/25/35% less damage
vt Pandemic - when a cursed enemy dies its curse spreads
vt Whispers of Doom - curses apply doom, when 4/3/2 doom instances are reached they deal 100/150/200
* Malediction - +1/3/5 max curse targets to all allied cursers
* Hextouch - enemies take 10/15/20 damage per second for 3 seconds when cursed
* Whispers of Doom - curses apply doom, when 4/3/2 doom instances are reached they deal 100/150/200
Forcer:
vt Tremor - when enemies die from hitting walls they create a damaging area with size according to the knockback force
vt Heavy Impact - when enemies hit walls they take damage according to the knockback force
vt Fracture - when enemies die from hitting walls explode into projectiles
* Tremor - when enemies die from hitting walls they create a damaging area with size according to the knockback force
* Heavy Impact - when enemies hit walls they take damage according to the knockback force
* Fracture - when enemies die from hitting walls explode into projectiles
Swarmer:
vt Meat Shield - critters block enemy projectiles
vt Hive - critters have +1/2/3 HP
vt Baneling Burst - critters die immediately on contact but also deal AoE damage
* Meat Shield - critters block enemy projectiles
* Hive - critters have +1/2/3 HP
* Baneling Burst - critters die immediately on contact but also deal AoE damage
Ranger:
vt Blunt Arrow - arrows fired by rangers have a 10/20/30% chance to knockback
vt Explosive Arrow - arrows fired by rangers have a 10/20/30% chance to explode, dealing 10/20/30% AoE damage
vt Divine Machine Arrow - arrows fired by rangers have a 10/20/30% chance to seek enemies and pierce 1/2/3 times
* Blunt Arrow - arrows fired by rangers have a 10/20/30% chance to knockback
* Explosive Arrow - arrows fired by rangers have a 10/20/30% chance to explode, dealing 10/20/30% AoE damage
* Divine Machine Arrow - arrows fired by rangers have a 10/20/30% chance to seek enemies and pierce 1/2/3 times
Mage:
vt Chronomancy - mages cast their spells 15/25/35% faster
vt Awakening - +50/75/100% attack speed and damage to 1 mage every round for that round
vt Divine Punishment - repeatedly deal damage to all enemies based on how many mages you have
* Chronomancy - mages cast their spells 15/25/35% faster
* Awakening - +50/75/100% attack speed and damage to 1 mage every round for that round
* Divine Punishment - repeatedly deal damage to all enemies based on how many mages you have
Rogue:
vt Assassination - crits from rogues deal 8/10/12x damage but normal attacks deal half damage
vt Flying Daggers - all projectiles thrown by rogues chain +2/3/4 times
vt Ultimatum - projectiles that chain gain +10/20/30% damage with each chain
* Assassination - crits from rogues deal 8/10/12x damage but normal attacks deal half damage
* Flying Daggers - all projectiles thrown by rogues chain +2/3/4 times
* Ultimatum - projectiles that chain gain +10/20/30% damage with each chain
Nuker:
vt Magnify - +20/35/50% area size
vt Echo Barrage - 10/20/30% chance to create 1/2/3 secondary AoEs on AoE hit
vt Unleash - all nukers gain +1% area size and damage every second
* Magnify - +20/35/50% area size
* Echo Barrage - 10/20/30% chance to create 1/2/3 secondary AoEs on AoE hit
* Unleash - all nukers gain +1% area size and damage every second
Enchanter:
vt Reinforce - +10/20/30% damage, defense and attack speed to all allies with at leats one enchanter
vt Payback - +2/5/8% damage to all allies whenever an enchanter is hit
vt Enchanted - when enemies die they have a 10/20/30% release X homing projectiles, where X is how many enchanters you have
* Reinforce - +10/20/30% damage, defense and attack speed to all allies with at leats one enchanter
* Payback - +2/5/8% damage to all allies whenever an enchanter is hit
* Enchanted - when enemies die they have a 10/20/30% release X homing projectiles, where X is how many enchanters you have
Sorcerer:
vt Freezing Field - Create an area that slows enemies by 50% for 2 seconds whenever a sorcerer repeats a spell
vt Burning Field - Create an area that deals 30 damage per second for 2 seconds whenever a sorcerer repeats a spell
vt Gravity Field - Create an area that sucks enemies in for 2 seconds whenever a sorcerer repeats a spell
* Freezing Field - Create an area that slows enemies by 50% for 2 seconds whenever a sorcerer repeats a spell
* Burning Field - Create an area that deals 30 damage per second for 2 seconds whenever a sorcerer repeats a spell
* Gravity Field - Create an area that sucks enemies in for 2 seconds whenever a sorcerer repeats a spell
Mercenary:
vt Magnetism - Gold coins are attracted to the snake
vt Insurance - Dying heroes have 4 times the chance of mercenary's bonus to drop 2 gold on death
vt Dividends - Mercenaries deal +X% extra damage, where X is how much gold you have
* Magnetism - Gold coins are attracted to the snake
* Insurance - Dying heroes have 4 times the chance of mercenary's bonus to drop 2 gold on death
* Dividends - Mercenaries deal +X% extra damage, where X is how much gold you have
Warrior:
vt Berserking - all warriors have up to +50/75/100% attack speed based on missing HP
vt Unwavering Stance - all warriors gain +4/8/12% defense every 5 seconds
vt Unrelenting Stance - +2/5/8% defense to all allies whenever a warrior is hit
* Berserking - all warriors have up to +50/75/100% attack speed based on missing HP
* Unwavering Stance - all warriors gain +4/8/12% defense every 5 seconds
* Unrelenting Stance - +2/5/8% defense to all allies whenever a warrior is hit
Removed items
* Wall Echo
* Wall Rider
@ -115,13 +114,13 @@ Item Update
https://i.imgur.com/1CwmFYX.png
https://i.imgur.com/qrExpq5.png
https://i.imgur.com/DNHUST1.png
Fixed multiple bugs related to locking the shop and quitting
* Fixed ouroboros technique passives not working with mouse controls
* Fixed mouse not showing up on death
* Fixed NG+5 achievement not triggering (this happened only between last Sunday night and Monday morning due to a small update I pushed breaking it)
* Fixed a bug where the nuker class was not counting towards Vagrant's and Psyker's active set bonus
* 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 multiple bugs related to locking the shop and quitting
* Fixed a bug where the shop would be rerolled after quitting in the arena
* 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)