Item update 3/5

master
a327ex 2021-06-17 02:45:14 -03:00
parent e99644a45b
commit 31a7a403e3
8 changed files with 297 additions and 109 deletions

View File

@ -397,7 +397,7 @@ function Arena:update(dt)
passives = {}
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', 'level_5', 'death_6', 'lasting_7',
'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',
'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',
@ -585,7 +585,7 @@ function Arena:update(dt)
passives = {}
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', 'level_5', 'death_6', 'lasting_7',
'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',
'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',
@ -998,7 +998,7 @@ function Arena:die()
passives = {}
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', 'level_5', 'death_6', 'lasting_7',
'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',
'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',

View File

Before

Width:  |  Height:  |  Size: 440 B

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

Binary file not shown.

View File

@ -143,7 +143,7 @@ function BuyScreen:on_enter(from, level, units, passives, shop_level, shop_xp)
passives = {}
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', 'level_5', 'death_6', 'lasting_7',
'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',
'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',
@ -384,7 +384,7 @@ function BuyScreen:set_items()
local y = 182
for k, passive in ipairs(self.passives) do
local i, j = math.index_to_coordinates(k, 4)
table.insert(self.items, ItemCard{group = self.main, x = 45 + (i-1)*60, y = y + (j-1)*50, w = 40, h = 50, passive = passive.passive , level = passive.level, xp = passive.xp})
table.insert(self.items, ItemCard{group = self.main, x = 45 + (i-1)*60, y = y + (j-1)*50, w = 40, h = 50, passive = passive.passive , level = passive.level, xp = passive.xp, parent = self})
end
end
@ -530,7 +530,7 @@ function RestartButton:update(dt)
passives = {}
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', 'level_5', 'death_6', 'lasting_7',
'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',
'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',
@ -853,7 +853,7 @@ function LevelButton:create_info_text()
local t41, t42 = get_shop_odds(self.parent.shop_level, 4), get_shop_odds(self.parent.shop_level+1, 4)
self.info_text = InfoText{group = main.current.ui}
self.info_text:activate({
{text = '[yellow]Lv.' .. self.parent.shop_level .. '[fg] shop, XP: [yellow]' .. self.shop_xp .. '/' .. self.max_xp, font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[yellow]Lv.' .. self.parent.shop_level .. '[fg] shop, XP: [yellow]' .. self.shop_xp .. '/' .. self.max_xp .. '[fg], +1 XP cost: [yellow]5', font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[bg10]chances of units appearing on the shop', font = pixul_font, alignment = 'center', height_multiplier = 1.25},
{text = '[yellow]current shop level [fgm10]next shop level', font = pixul_font, alignment = 'left', height_multiplier = 1.25},
{text = '[fg]tier 1: ' .. t11 .. '%' .. tostring(t11 < 10 and ' ' or '') .. ' [fgm8]tier 1: ' .. t12 .. '%', font = pixul_font, alignment = 'left', height_multiplier = 1.25},
@ -869,7 +869,7 @@ function LevelButton:create_info_text()
local t41 = get_shop_odds(self.parent.shop_level, 4)
self.info_text = InfoText{group = main.current.ui}
self.info_text:activate({
{text = '[yellow]Lv.' .. self.parent.shop_level .. '[fg] shop, XP: [yellow]' .. self.shop_xp .. '/' .. self.max_xp, font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[yellow]Lv.' .. self.parent.shop_level .. '[fg] shop', font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[bg10]chances of units appearing on the shop', font = pixul_font, alignment = 'center', height_multiplier = 1.25},
{text = '[yellow]current shop level', font = pixul_font, alignment = 'left', height_multiplier = 1.25},
{text = '[fg]tier 1: ' .. t11 .. '%', font = pixul_font, alignment = 'left', height_multiplier = 1.25},
@ -1360,11 +1360,55 @@ function ItemCard:init(args)
self:init_game_object(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)
end
function ItemCard:update(dt)
self:update_game_object(dt)
if self.selected and input.m1.pressed then
if self.level >= 3 then return end
if gold < 5 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_2 then
self.info_text_2 = InfoText{group = main.current.ui}
self.info_text_2:activate({
{text = '[fg]not enough gold', font = pixul_font, alignment = 'center'},
}, nil, nil, nil, nil, 16, 4, nil, 2)
self.info_text_2.x, self.info_text_2.y = gw/2, gh/2 + 30
end
self.t:after(2, function() self.info_text_2:deactivate(); self.info_text_2.dead = true; self.info_text_2 = nil end, 'info_text_2')
else
ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
self.xp = self.xp + 1
if self.xp >= self.max_xp then
self.xp = 0
self.level = self.level + 1
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)
if self.level == 2 then spawn_mark1:play{pitch = 1, volume = 0.6} end
if self.level == 3 then
spawn_mark1:play{pitch = 1.2, volume = 0.6}
level_up1:play{pitch = 1, volume = 0.5}
end
end
self:create_info_text()
self.selected = true
self.spring:pull(0.2, 200, 10)
gold = gold - 5
for _, passive in ipairs(passives) do
if passive.passive == self.passive then
passive.level = self.level
passive.xp = self.xp
end
end
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'}}
self.text = Text({{text = '[bg10]' .. tostring(self.parent.shop_level), font = pixul_font, alignment = 'center'}}, global_text_tags)
system.save_run(self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool, locked_state)
end
end
end
@ -1374,20 +1418,50 @@ 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])
end
graphics.pop()
end
function ItemCard:create_info_text()
if self.info_text then
self.info_text:deactivate()
self.info_text.dead = true
end
self.info_text = nil
if self.level == 3 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',
height_multiplier = 1.25},
{text = passive_descriptions_level[self.passive](self.level), font = pixul_font, alignment = 'center', height_multiplier = 1.25},
}, nil, nil, nil, nil, 16, 4, nil, 2)
self.info_text.x, self.info_text.y = gw/2, gh/2 + 10
else
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 .. '[fg], XP: [yellow]' .. self.xp .. '/' .. self.max_xp .. '[fg], +1 XP cost: [yellow]5', font = pixul_font, alignment = 'center',
height_multiplier = 1.25},
{text = passive_descriptions_level[self.passive](self.level), font = pixul_font, alignment = 'center', height_multiplier = 1.25},
}, nil, nil, nil, nil, 16, 4, nil, 2)
self.info_text.x, self.info_text.y = gw/2, gh/2 + 10
end
end
function ItemCard:on_mouse_enter()
self.selected = true
ui_hover1:play{pitch = random:float(1.3, 1.5), volume = 0.5}
self.spring:pull(0.2, 200, 10)
self.info_text = InfoText{group = main.current.ui, force_update = true}
self.info_text:activate({
{text = '[fg]' .. passive_names[self.passive], font = pixul_font, alignment = 'center', height_multiplier = 1.25},
{text = passive_descriptions_level[self.passive](self.level), font = pixul_font, alignment = 'center', height_multiplier = 1.25},
}, nil, nil, nil, nil, 16, 4, nil, 2)
self.info_text.x, self.info_text.y = gw/2, gh/2 + 10
self:create_info_text()
end

View File

@ -18,6 +18,8 @@ function init()
input:bind('enter', {'space', 'return', 'fleft', 'fdown', 'fright'})
local s = {tags = {sfx}}
level_up1 = Sound('Buff 4.ogg', s)
unlock1 = Sound('Unlock 3.ogg', s)
gambler1 = Sound('Collect 5.ogg', s)
usurer1 = Sound('Shadow Punch 2.ogg', s)
gold1 = Sound('Collect 5.ogg', s)
@ -153,7 +155,7 @@ function init()
crucio = Image('crucio')
speed_3 = Image('speed_3')
damage_4 = Image('damage_4')
level_5 = Image('level_5')
shoot_5 = Image('shoot_5')
death_6 = Image('death_6')
lasting_7 = Image('lasting_7')
defensive_stance = Image('defensive_stance')
@ -588,7 +590,7 @@ function init()
['psychic'] = function(lvl) return '[fg]creates a small area that deals [yellow]' .. get_character_stat('psychic', lvl, 'dmg') .. ' AoE[fg] damage' end,
['miner'] = function(lvl) return '[fg]picking up gold releases [yellow]4[fg] homing projectiles that each deal [yellow]' .. get_character_stat('miner', lvl, 'dmg') .. ' [fg]damage' end,
['merchant'] = function(lvl) return '[fg]gain [yellow]+1[fg] interest for every [yellow]10[fg] gold' end,
['usurer'] = function(lvl) return '[fg]curses [yellow]3[fg] nearby enemies indefinitely with [yellow]debt[fg], dealing [yellow]' .. get_character_stat('usurer', lvl, 'dmg') .. '[fg] damage per second' end,
['usurer'] = function(lvl) return '[fg]curses [yellow]3[fg] nearby enemies indefinitely with debt, dealing [yellow]' .. get_character_stat('usurer', lvl, 'dmg') .. '[fg] damage per second' end,
['gambler'] = function(lvl) return '[fg]deal [yellow]2X[fg] damage to a single random enemy where X is how much gold you have' end,
['thief'] = function(lvl) return '[fg]throws a knife that deals [yellow]' .. 2*get_character_stat('thief', lvl, 'dmg') .. '[fg] damage and chains [yellow]5[fg] times' end,
}
@ -725,7 +727,7 @@ function init()
['cannoneer'] = function() return '[fg]showers the hit area in [yellow]7[fg] additional cannon shots that deal [yellow]' .. get_character_stat('cannoneer', 3, 'dmg')/2 .. '[fg] AoE damage' end,
['dual_gunner'] = function() return '[fg]every 5th attack shoot in rapid succession for [yellow]2[fg] seconds' end,
['hunter'] = function() return '[fg]summons [yellow]3[fg] pets and the pets ricochet off walls once' end,
['chronomancer'] = function() return '[fg]enemies take damave over time [yellow]50%[fg] faster' end,
['chronomancer'] = function() return '[fg]enemies take damage over time [yellow]50%[fg] faster' end,
['spellblade'] = function() return '[fg]faster projectile speed and tighter turns' end,
['psykeeper'] = function() return '[fg]also redistributes damage taken as damage to all enemies at [yellow]double[fg] value' end,
['engineer'] = function() return '[fg]drops [yellow]2[fg] additional turrets and grants all turrets [yellow]+50%[fg] damage and attack speed' end,
@ -782,7 +784,7 @@ function init()
['cannoneer'] = function() return '[light_bg]showers the hit area in 7 additional cannon shots that deal ' .. get_character_stat('cannoneer', 3, 'dmg')/2 .. ' AoE damage' end,
['dual_gunner'] = function() return '[light_bg]every 5th attack shoot in rapid succession for 2 seconds' end,
['hunter'] = function() return '[light_bg]summons 3 pets and the pets ricochet off walls once' end,
['chronomancer'] = function() return '[light_bg]enemies take damave over time 50% faster' end,
['chronomancer'] = function() return '[light_bg]enemies take damage over time 50% faster' end,
['spellblade'] = function() return '[light_bg]faster projectile speed and tighter turns' end,
['psykeeper'] = function() return '[light_bg]also redistributes damage taken as damage to all enemies at double value' end,
['engineer'] = function() return '[light_bg]drops 2 additional turrets and grants all turrets +50% damage and attack speed' end,
@ -901,13 +903,13 @@ function init()
}
local ylb1 = function(lvl)
if lvl == 3 then return 'fg'
elseif lvl == 2 then return 'fg'
if lvl == 3 then return 'light_bg'
elseif lvl == 2 then return 'light_bg'
elseif lvl == 1 then return 'yellow'
else return 'light_bg' end
end
local ylb2 = function(lvl)
if lvl == 3 then return 'fg'
if lvl == 3 then return 'light_bg'
elseif lvl == 2 then return 'yellow'
else return 'light_bg' end
end
@ -928,7 +930,7 @@ function init()
['curser'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+25%[light_bg]/[' .. ylb2(lvl) .. ']+50% [fg]curse duration' end,
['forcer'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+25%[light_bg]/[' .. ylb2(lvl) .. ']+50% [fg]knockback force to all allies' end,
['swarmer'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+1[light_bg]/[' .. ylb2(lvl) .. ']+3 [fg]hits to critters' end,
['voider'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+15%[light_bg]/[' .. ylb2(lvl) .. ']+25% [fg]damage over time to allied voiders' end,
['voider'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+20%[light_bg]/[' .. ylb2(lvl) .. ']+40% [fg]damage over time to allied voiders' end,
['sorcerer'] = function(lvl)
return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4[light_bg]/[' .. ylb3(lvl) .. ']6 [fg]- sorcerers repeat their attacks once every [' ..
ylb1(lvl) .. ']4[light_bg]/[' .. ylb2(lvl) .. ']3[light_bg]/[' .. ylb3(lvl) .. ']2[fg] attacks'
@ -1003,6 +1005,12 @@ function init()
['thief'] = 4,
}
launches_projectiles = function(character)
local classes = {'vagrant', 'archer', 'scout', 'outlaw', 'blade', 'wizard', 'cannoneer', 'dual_gunner', 'hunter', 'spellblade', 'engineer', 'corruptor', 'beastmaster', 'jester', 'assassin', 'barrager',
'arcanist', 'illusionist', 'miner', 'thief'}
return table.any(classes, function(v) return v == character end)
end
get_number_of_units_per_class = function(units)
local rangers = 0
local warriors = 0
@ -1116,7 +1124,7 @@ function init()
['crucio'] = 'Crucio',
['speed_3'] = 'Speed 3',
['damage_4'] = 'Damage 4',
['level_5'] = 'Level 5',
['shoot_5'] = 'Shoot 5',
['death_6'] = 'Death 6',
['lasting_7'] = 'Lasting 7',
['defensive_stance'] = 'Defensive Stance',
@ -1173,13 +1181,13 @@ function init()
['crucio'] = '[fg]taking damage also shares that across all enemies at [yellow]20/30/40%[fg] its value',
['speed_3'] = '[fg]position [yellow]3[fg] has [yellow]+50%[fg] attack speed',
['damage_4'] = '[fg]position [yellow]4[fg] has [yellow]+30%[fg] damage',
['level_5'] = '[fg]position [yellow]5[fg] is [yellow]1[fg] level higher',
['shoot_5'] = '[fg]position [yellow]5[fg] shoots [yellow]3[fg] projectiles per second',
['death_6'] = '[fg]position [yellow]6[fg] takes [yellow]10%[fg] of its health as damage every [yellow]3[fg] seconds',
['lasting_7'] = '[fg]position [yellow]7[fg] will stay alive for [yellow]10[fg] seconds after dying',
['defensive_stance'] = '[fg]first and last positions have [yellow]+10/20/30%[fg] defense',
['offensive_stance'] = '[fg]first and last positions have [yellow]+10/20/30%[fg] damage',
['kinetic_bomb'] = '[fg]when a unit dies it explodes, launching enemies away',
['porcupine_technique'] = '[fg]when a unit dies it explodes, releasing piercing projectiles',
['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%',
@ -1231,13 +1239,13 @@ function init()
['crucio'] = function(lvl) return '[fg]taking damage also shares that across all enemies at ' .. ts(lvl, '20%', '30%', '40%') .. ' its value' end,
['speed_3'] = function(lvl) return '[fg]position [yellow]3[fg] has [yellow]+50%[fg] attack speed' end,
['damage_4'] = function(lvl) return '[fg]position [yellow]4[fg] has [yellow]+30%[fg] damage' end,
['level_5'] = function(lvl) return '[fg]position [yellow]5[fg] is [yellow]1[fg] level higher' end,
['shoot_5'] = function(lvl) return '[fg]position [yellow]5[fg] shoots [yellow]3[fg] projectiles per second' end,
['death_6'] = function(lvl) return '[fg]position [yellow]6[fg] takes [yellow]10%[fg] of its health as damage every [yellow]3[fg] seconds' end,
['lasting_7'] = function(lvl) return '[fg]position [yellow]7[fg] will stay alive for [yellow]10[fg] seconds after dying' end,
['defensive_stance'] = function(lvl) return '[fg]first and last positions have ' .. ts(lvl, '+10%', '20%', '30%') .. ' defense' end,
['offensive_stance'] = function(lvl) return '[fg]first and last positions have ' .. ts(lvl, '+10%', '20%', '30%') .. ' damage' end,
['kinetic_bomb'] = function(lvl) return '[fg]when a unit dies it explodes, launching enemies away' end,
['porcupine_technique'] = function(lvl) return '[fg]when a unit dies it explodes, releasing piercing projectiles' end,
['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,
@ -1461,7 +1469,7 @@ function init()
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', 'level_5', 'death_6', 'lasting_7',
'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',
'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',
@ -1490,19 +1498,15 @@ function init()
--[[
main:add(Arena'arena')
main:go_to('arena', 25, {
{character = 'swordsman', level = 3},
{character = 'scout', level = 3},
{character = 'thief', level = 3},
{character = 'blade', level = 3},
{character = 'dual_gunner', level = 3},
{character = 'saboteur', level = 3},
{character = 'spellblade', level = 3},
{character = 'jester', level = 3},
{character = 'assassin', level = 3},
{character = 'barrager', level = 3},
{character = 'cannoneer', level = 3},
}, passives)
main:go_to('arena', 13, {
{character = 'witch', level = 1},
{character = 'stormweaver', level = 1},
{character = 'chronomancer', level = 1},
{character = 'miner', level = 1},
{character = 'merchant', level = 1},
{character = 'sage', level = 1},
{character = 'magician', level = 1},
}, {{passive = 'last_stand', level = 1}})
]]--
--[[

View File

@ -805,8 +805,8 @@ function Player:init(args)
if self.ouroboros_technique_r then
self.t:after(0.01, function()
self.t:every(0.4 - (0.02*#self:get_all_units()), function()
if self.move_right_pressed and love.timer.getTime() - self.move_right_pressed > 1 then
self.t:every((self.ouroboros_technique_r == 1 and 0.5) or (self.ouroboros_technique_r == 2 and 0.33) or (self.ouroboros_technique_r == 3 and 0.25), function()
if self.leader and (state.mouse_control and table.all(self.mouse_control_v_buffer, function(v) return v >= 0.5 end)) or (self.move_right_pressed and love.timer.getTime() - self.move_right_pressed > 1) then
local target = self:get_closest_object_in_shape(Circle(self.x, self.y, 96), main.current.enemies)
if target then
local units = self:get_all_units()
@ -829,20 +829,11 @@ function Player:init(args)
end)
end
if self.centipede then self.centipede_mvspd_m = 1.2 end
if self.amplify then self.amplify_area_dmg_m = 1.25 end
if self.amplify_x then self.amplify_x_area_dmg_m = 1.5 end
if self.centipede then self.centipede_mvspd_m = (self.centipede == 1 and 1.1) or (self.centipede == 2 and 1.2) or (self.centipede == 3 and 1.3) end
if self.amplify then self.amplify_area_dmg_m = (self.amplify == 1 and 1.2) or (self.amplify == 2 and 1.35) or (self.amplify == 3 and 1.5) end
if self.ballista then
if table.any(self.classes, function(v) return v == 'ranger' end) or table.any(self.classes, function(v) return v == 'rogue' end) then
self.ballista_dmg_m = 1.25
end
end
if self.ballista_x then
if table.any(self.classes, function(v) return v == 'ranger' end) or table.any(self.classes, function(v) return v == 'rogue' end) then
self.ballista_x_dmg_m = 1.5
end
if self.ballista and launches_projectiles(self.character) then
self.ballista_dmg_m = (self.ballista == 1 and 1.2) or (self.ballista == 2 and 1.35) or (self.ballista == 3 and 1.5)
end
if self.chronomancy then
@ -956,6 +947,39 @@ function Player:init(args)
end
end)
end
if self.leader and self.shoot_5 then
main.current.t:after(0.1, function()
self.t:every(0.33, function()
local units = self:get_all_units()
local unit = units[5]
if unit then
local target = unit:get_closest_object_in_shape(Circle(unit.x, unit.y, 96), main.current.enemies)
if target then
unit:barrage(unit:angle_to_object(target), 1)
else
unit:barrage(random:float(0, 2*math.pi), 1)
end
end
end)
end)
end
if self.leader and self.death_6 then
main.current.t:after(0.1, function()
self.t:every(3, function()
flagellant1:play{pitch = random:float(0.95, 1.05), volume = 0.4}
local units = self:get_all_units()
local unit = units[6]
if unit then
hit2:play{pitch = random:float(0.95, 1.05), volume = 0.4}
unit:hit(0.1*unit.max_hp)
end
end)
end)
end
self.mouse_control_v_buffer = {}
end
@ -1084,17 +1108,17 @@ function Player:update(dt)
if self.force_push then self.knockback_m = self.knockback_m*1.25 end
if table.any(self.classes, function(v) return v == 'voider' end) then
if main.current.voider_level == 2 then self.dot_dmg_m = 1.25
elseif main.current.voider_level == 1 then self.dot_dmg_m = 1.15
if main.current.voider_level == 2 then self.dot_dmg_m = 1.4
elseif main.current.voider_level == 1 then self.dot_dmg_m = 1.2
else self.dot_dmg_m = 1 end
end
if self.call_of_the_void then self.dot_dmg_m = (self.dot_dmg_m or 1)*1.25 end
if self.call_of_the_void then self.dot_dmg_m = (self.dot_dmg_m or 1)*((self.call_of_the_void == 1 and 1.3) or (self.call_of_the_void == 2 and 1.6) or (self.call_of_the_void == 3 and 1.9) or 1) end
if self.ouroboros_technique_l and self.leader then
local units = self:get_all_units()
if self.move_left_pressed and love.timer.getTime() - self.move_left_pressed > 1 then
if (state.mouse_control and table.all(self.mouse_control_v_buffer, function(v) return v <= -0.5 end)) or (self.move_left_pressed and love.timer.getTime() - self.move_left_pressed > 1) then
for _, unit in ipairs(units) do
unit.ouroboros_def_m = 1.25
unit.ouroboros_def_m = (self.ouroboros_technique_l == 1 and 1.15) or (self.ouroboros_technique_l == 2 and 1.25) or (self.ouroboros_technique_l == 3 and 1.35)
end
else
for _, unit in ipairs(units) do
@ -1107,13 +1131,46 @@ function Player:update(dt)
self.berserking_aspd_m = math.remap(self.hp/self.max_hp, 0, 1, 1.5, 1)
end
if self.speed_3 and self.follower_index == 2 then
self.speed_3_aspd_m = 1.5
end
if self.damage_4 and self.follower_index == 3 then
self.damage_4_dmg_m = 1.3
end
if self.defensive_stance and self.leader then
self.defensive_stance_def_m = (self.defensive_stance == 1 and 1.1) or (self.defensive_stance == 2 and 1.2) or (self.defensive_stance == 3 and 1.3)
end
if self.defensive_stance and not self.leader and self.follower_index == #self.parent.followers then
self.defensive_stance_def_m = (self.defensive_stance == 1 and 1.1) or (self.defensive_stance == 2 and 1.2) or (self.defensive_stance == 3 and 1.3)
end
if self.offensive_stance and self.leader then
self.offensive_stance_dmg_m = (self.offensive_stance == 1 and 1.1) or (self.offensive_stance == 2 and 1.2) or (self.offensive_stance == 3 and 1.3)
end
if self.offensive_stance and not self.leader and self.follower_index == #self.parent.followers then
self.offensive_stance_dmg_m = (self.offensive_stance == 1 and 1.1) or (self.offensive_stance == 2 and 1.2) or (self.offensive_stance == 3 and 1.3)
end
if self.leader and #self.followers == 0 and self.last_stand then
self.last_stand_dmg_m = 1.2
self.last_stand_def_m = 1.2
self.last_stand_aspd_m = 1.2
self.last_stand_area_size_m = 1.2
self.last_stand_area_dmg_m = 1.2
self.last_stand_mvspd_m = 1.2
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.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.ballista_x_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.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.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.buff_area_dmg_m = (self.nuker_area_dmg_m or 1)*(self.amplify_area_dmg_m or 1)*(self.amplify_x_area_dmg_m or 1)*(self.unleash_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.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_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)
self:calculate_stats()
if self.attack_sensor then self.attack_sensor:move_to(self.x, self.y) end
@ -1129,8 +1186,10 @@ function Player:update(dt)
if input.move_right.released then self.move_right_pressed = nil end
if state.mouse_control then
local v = Vector(math.cos(self.r), math.sin(self.r)):perpendicular():dot(Vector(math.cos(self:angle_to_mouse()), math.sin(self:angle_to_mouse())))
self.r = self.r + math.sign(v)*1.66*math.pi*dt
self.mouse_control_v = Vector(math.cos(self.r), math.sin(self.r)):perpendicular():dot(Vector(math.cos(self:angle_to_mouse()), math.sin(self:angle_to_mouse())))
self.r = self.r + math.sign(self.mouse_control_v)*1.66*math.pi*dt
table.insert(self.mouse_control_v_buffer, 1, self.mouse_control_v)
if #self.mouse_control_v_buffer > 64 then self.mouse_control_v_buffer[65] = nil end
else
if input.move_left.down then self.r = self.r - 1.66*math.pi*dt end
if input.move_right.down then self.r = self.r + 1.66*math.pi*dt end
@ -1199,6 +1258,8 @@ function Player:draw()
if self.visual_shape == 'rectangle' then
if self.magician_invulnerable then
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 3, 3, blue_transparent)
elseif self.undead then
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 3, 3, self.color, 1)
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
@ -1208,6 +1269,10 @@ function Player:draw()
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
if self.ouroboros_def_m and self.ouroboros_def_m > 1 then
graphics.rectangle(self.x, self.y, 1.25*self.shape.w, 1.25*self.shape.h, 3, 3, yellow_transparent)
end
end
graphics.pop()
end
@ -1271,9 +1336,10 @@ function Player:on_collision_enter(other, contact)
end
function Player:hit(damage)
function Player:hit(damage, from_undead)
if self.dead then return end
if self.magician_invulnerable then return end
if self.undead and not from_undead then return end
self.hfx:use('hit', 0.25, 200, 10)
self:show_hp()
@ -1299,7 +1365,7 @@ function Player:hit(damage)
if self.crucio then
local enemies = main.current.main:get_objects_by_classes(main.current.enemies)
for _, enemy in ipairs(enemies) do
enemy:hit(0.25*actual_damage)
enemy:hit(((self.crucio == 1 and 0.2) or (self.crucio == 2 and 0.3) or (self.crucio == 3 and 0.4))*actual_damage)
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = fg[0], duration = 0.1}
end
end
@ -1338,6 +1404,10 @@ function Player:hit(damage)
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 12}:scale_down(0.3):change_color(0.5, self.color)
self.divined = false
elseif self.lasting_7 and self.follower_index == 6 and not self.undead then
self.undead = true
self.t:after(10, function() self:hit(0, true) end)
else
hit4:play{pitch = random:float(0.95, 1.05), volume = 0.5}
slow(0.25, 1)
@ -1353,6 +1423,33 @@ function Player:hit(damage)
self.dead = true
if self.leader then self:recalculate_followers()
else self.parent:recalculate_followers() end
if #main.current.player.followers == 0 and main.current.player.last_stand then
heal1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
buff1:play{pitch == random:float(0.9, 1.1), volume = 0.5}
main.current.player:heal(10000)
end
end
if self.kinetic_bomb then
elementor1:play{pitch = random:float(0.9, 1.1), volume = 0.5}
local enemies = self:get_objects_in_shape(Circle(self.x, self.y, 96), main.current.enemies)
for _, enemy in ipairs(enemies) do
enemy:push(random:float(30, 50)*(self.knockback_m or 1), self:angle_to_object(enemy))
end
end
if self.porcupine_technique then
main.current.t:after(0.01, function()
local r = 0
for i = 1, 8 do
archer1:play{pitch = random:float(0.95, 1.05), volume = 0.35}
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}
local t = {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), v = 250, r = r, color = self.color, dmg = self.dmg,
parent = self, character = 'barrage', level = self.level, pierce = 1000, ricochet = 2}
Projectile(table.merge(t, mods or {}))
r = r + math.pi/4
end
end)
end
if self.dot_area then self.dot_area.dead = true; self.dot_area = nil end
@ -1416,6 +1513,7 @@ function Player:recalculate_followers()
follower.parent = new_leader
follower.follower_index = i
end
else
for i = #self.followers, 1, -1 do
if self.followers[i].dead then
@ -1590,7 +1688,7 @@ function Player:dot_attack(area, mods)
mods = mods or {}
camera:shake(2, 0.5)
self.hfx:use('shoot', 0.25)
local t = {group = main.current.effects, x = mods.x or self.x, y = mods.y or self.y, r = self.r, rs = self.area_size_m*(area or 64), color = self.color, dmg = self.area_dmg_m*self.dmg,
local t = {group = main.current.effects, x = mods.x or self.x, y = mods.y or self.y, r = self.r, rs = self.area_size_m*(area or 64), color = self.color, dmg = self.area_dmg_m*self.dmg*(self.dot_dmg_m or 1),
character = self.character, level = self.level, parent = self}
DotArea(table.merge(t, mods))
@ -1598,14 +1696,14 @@ function Player:dot_attack(area, mods)
end
function Player:barrage(r, n)
function Player:barrage(r, n, pierce)
n = n or 8
for i = 1, n do
self.t:after((i-1)*0.075, function()
archer1:play{pitch = random:float(0.95, 1.05), volume = 0.35}
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}
local t = {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), v = 250, r = r + random:float(-math.pi/16, math.pi/16), color = self.color, dmg = self.dmg,
parent = self, character = 'barrage', level = self.level}
parent = self, character = 'barrage', level = self.level, pierce = pierce or 0}
Projectile(table.merge(t, mods or {}))
end)
end
@ -2037,26 +2135,27 @@ function Area:init(args)
local enemies = main.current.main:get_objects_in_shape(self.shape, main.current.enemies)
for _, enemy in ipairs(enemies) do
local resonance_dmg = 0
local resonance_m = (self.parent.resonance == 1 and 0.03) or (self.parent.resonance == 2 and 0.05) or (self.parent.resonance == 3 and 0.07) or 0
if self.character == 'elementor' then
if self.parent.resonance then resonance_dmg = 2*self.dmg*0.05*#enemies end
if self.parent.resonance then resonance_dmg = 2*self.dmg*resonance_m*#enemies end
enemy:hit(2*self.dmg + resonance_dmg, self)
if self.level == 3 then
enemy:slow(0.4, 6)
end
elseif self.character == 'swordsman' then
if self.parent.resonance then resonance_dmg = (self.dmg + self.dmg*0.15*#enemies)*0.05*#enemies end
if self.parent.resonance then resonance_dmg = (self.dmg + self.dmg*0.15*#enemies)*resonance_m*#enemies end
enemy:hit(self.dmg + self.dmg*0.15*#enemies + resonance_dmg, self)
elseif self.character == 'blade' and self.level == 3 then
if self.parent.resonance then resonance_dmg = (self.dmg + self.dmg*0.33*#enemies)*0.05*#enemies end
if self.parent.resonance then resonance_dmg = (self.dmg + self.dmg*0.33*#enemies)*resonance_m*#enemies end
enemy:hit(self.dmg + self.dmg*0.33*#enemies + resonance_dmg, self)
elseif self.character == 'highlander' then
if self.parent.resonance then resonance_dmg = 6*self.dmg*0.05*#enemies end
if self.parent.resonance then resonance_dmg = 6*self.dmg*resonance_m*#enemies end
enemy:hit(6*self.dmg + resonance_dmg, self)
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)
else
if self.parent.resonance then resonance_dmg = self.dmg*0.05*#enemies end
if self.parent.resonance then resonance_dmg = self.dmg*resonance_m*#enemies end
enemy:hit(self.dmg + resonance_dmg, self)
end
HitCircle{group = main.current.effects, x = enemy.x, y = enemy.y, rs = 6, color = fg[0], duration = 0.1}

67
todo
View File

@ -1,33 +1,35 @@
Item Update
New mechanics
Spend gold to level items up
* Spend gold to level items up
Block levelling for unlevellable items
Items
General:
vt Centipede - +10/20/30% movement speed
vt Ouroboros Technique R - rotating around yourself to the right releases 2/3/4 projectiles per second
vt Ouroboros Technique L - rotating around yourself to the left grants +15/25/35% defense to all units
vt Amplify - +20/35/50% AoE damage
vt Resonance - all AoE attacks deal +3/5/7% damage per unit hit
vt Ballista - +20/35/50% projectile damage
vt Call of the Void - +30/60/90% DoT damage
vt Crucio - taking damage also shares that damage across all enemies at 20/30/40% its value
* Centipede - +10/20/30% movement speed
* Ouroboros Technique R - rotating around yourself to the right releases 2/3/4 projectiles per second
* Ouroboros Technique L - rotating around yourself to the left grants +15/25/35% defense to all units
* Amplify - +20/35/50% AoE damage
* Resonance - all AoE attacks deal +3/5/7% damage per unit hit
* Ballista - +20/35/50% projectile damage
* Call of the Void - +30/60/90% DoT damage
* Crucio - taking damage also shares that damage across all enemies at 20/30/40% its value
Position:
vt Speed 3 - position 3 has +20/35/50% attack speed
vt Damage 4 - position 4 has +20/30/40% damage
vt Level 5 - position 5 is 1 level higher
vt Death 6 - position 6 takes 15% of its health as damage every 3 seconds
vt Lasting 7 - position 7 will stay alive for 10 seconds after dying
vt Defense Stance - first and last positions have +10/20/30% defense
vt Offensive Stance - first and last positions have +10/20/30% damage
* Speed 3 - position 3 has +50% attack speed
* Damage 4 - position 4 has +30% damage
* Level 5 - position 5 is 1 level higher
* Death 6 - position 6 takes 15% of its health as damage every 3 seconds
* Lasting 7 - position 7 will stay alive for 10 seconds after dying
* Defense Stance - first and last positions have +10/20/30% defense
* Offensive Stance - first and last positions have +10/20/30% damage
Death:
vt Kinetic Bomb - when a unit dies it explodes, launching enemies away
vt Porcupine Technique - when a unit dies it explodes, releasing piercing projectiles
vt Last Stand - the last unit alive is fully healed and receives a +20/30/40% bonus to all stats
* Kinetic Bomb - when a unit dies it explodes, launching enemies away
* 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
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
@ -78,12 +80,12 @@ Item Update
* Longshot
* Hex Master
* Force Push
* Call of the Void
* Spawning Pool
* Void Rift
* Blessing
* Immolation
Balance
* Changed voider DoT damage bonus to 20/40% (from 15/25%)
* Decreased shop reroll cost to 10
Decrease mercenary gold drop chance to 8/16% (from 10/20%)
QoL
@ -92,6 +94,7 @@ Item Update
Add visuals for defensive ouroboros, divine intervention, fairy buff
Options menu from buy screen
https://i.imgur.com/JJUddT3.png
https://i.imgur.com/R3YgUqk.png
Improve volcano to not look like spawn marker - https://i.imgur.com/HuS15HG.png
Add option for mouse cursor to always be visible
Add main menu
@ -110,14 +113,16 @@ Item Update
Kill enemies that go outside play area - https://i.imgur.com/QPgZbve.png
https://i.imgur.com/lCdPFZx.png
https://i.imgur.com/1CwmFYX.png
Ouroboros doesn't work with mouse controls
https://i.imgur.com/qrExpq5.png
https://i.imgur.com/DNHUST1.png
* 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 a bug where the shop would be rerolled after quitting in the arena
* Fixed multiple bugs related to locking the shop and quitting
* Fixed a bug where 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)
* Fixed a bug where mouse cursor wasn't visible on death
@ -172,7 +177,9 @@ https://steamcommunity.com/app/915310/discussions/0/4658391921156325745/ - math
Roguelite update:
Technical improvements:
Spawn tech: spawn every entity in a grid, before spawning check to see if grid position is clear, this will prevent any issues due to entities spawning inside one another
Battle stats: DPS, damage taken, etc
Battle stats: DPS, damage taken, etc (check Underlords)
Tag system: similar to PoE
Keyword explanations: similar to StS or Artifact, simply create additional text windows for keywords and what they mean
Key rebinding (for non-QWERTY keyboards)
StS-like map with nodes, node types:
Arena
@ -193,12 +200,16 @@ Roguelite update:
This unit's projectiles pierce/chain/fork/seek/split/stun/etc
This unit is a [class]
New stat system:
All stats are values from 1 to 10 (can be lower than 1 or higher than 10 due to debuffs/buffs only) that represent consistent internal values between all units
All stats are values from 1 to 10 (can be lower than 1 or higher than 10 due to debuffs/buffs) that represent consistent internal values between all units
i.e. 3 attack speed means the same internal attack rate value (like say 6 seconds) for the entire game
In general it's better if units don't have hidden internal multipliers on these stats, although sometimes that may be inevitable
Damage:
Crash - damage dealt when bumping into enemies
Projectile - damage dealt by projectiles
AoE - damage dealt in an area
DoT - damage dealt over time
Damage type:
Attack - physical attacks, decreased by the enemy's armor
Spell - magical attacks, decreased by the enemy's magic resistance
Attack type:
Crash - damage dealt when bumping into enemies
Projectile - damage dealt by projectiles
AoE - damage dealt in an area
DoT - damage dealt over time