Shop update 3/5
parent
f808b0452f
commit
8f2caf7109
54
arena.lua
54
arena.lua
|
@ -24,7 +24,7 @@ function Arena:on_enter(from, level, units, passives)
|
|||
steam.friends.setRichPresence('text', 'Arena - Level ' .. self.level)
|
||||
|
||||
self.floor = Group()
|
||||
self.main = Group():set_as_physics_world(32, 0, 0, {'player', 'enemy', 'projectile', 'enemy_projectile', 'force_field'})
|
||||
self.main = Group():set_as_physics_world(32, 0, 0, {'player', 'enemy', 'projectile', 'enemy_projectile', 'force_field', 'ghost'})
|
||||
self.post_main = Group()
|
||||
self.effects = Group()
|
||||
self.ui = Group()
|
||||
|
@ -39,10 +39,19 @@ function Arena:on_enter(from, level, units, passives)
|
|||
self.main:disable_collision_between('enemy_projectile', 'enemy_projectile')
|
||||
self.main:disable_collision_between('player', 'force_field')
|
||||
self.main:disable_collision_between('projectile', 'force_field')
|
||||
self.main:disable_collision_between('ghost', 'player')
|
||||
self.main:disable_collision_between('ghost', 'projectile')
|
||||
self.main:disable_collision_between('ghost', 'enemy')
|
||||
self.main:disable_collision_between('ghost', 'enemy_projectile')
|
||||
self.main:disable_collision_between('ghost', 'ghost')
|
||||
self.main:disable_collision_between('ghost', 'force_field')
|
||||
self.main:enable_trigger_between('projectile', 'enemy')
|
||||
self.main:enable_trigger_between('enemy_projectile', 'player')
|
||||
self.main:enable_trigger_between('player', 'enemy_projectile')
|
||||
self.main:enable_trigger_between('player', 'ghost')
|
||||
self.main:enable_trigger_between('ghost', 'player')
|
||||
|
||||
self.gold_picked_up = 0
|
||||
self.damage_dealt = 0
|
||||
self.damage_taken = 0
|
||||
self.main_slow_amount = 1
|
||||
|
@ -257,6 +266,7 @@ function Arena:on_enter(from, level, units, passives)
|
|||
self.psyker_level = class_levels.psyker
|
||||
self.conjurer_level = class_levels.conjurer
|
||||
self.sorcerer_level = class_levels.sorcerer
|
||||
self.mercenary_level = class_levels.mercenary
|
||||
|
||||
self.t:every(0.375, function()
|
||||
local p = random:table(star_positions)
|
||||
|
@ -348,12 +358,9 @@ function Arena:update(dt)
|
|||
trigger:tween(0.25, _G, {slow_amount = 1}, math.linear, function()
|
||||
slow_amount = 1
|
||||
self.paused = false
|
||||
self.paused_t1.dead = true
|
||||
self.paused_t2.dead = true
|
||||
self.paused_t1 = nil
|
||||
self.paused_t2 = nil
|
||||
self.ng_t.dead = true
|
||||
self.ng_t = nil
|
||||
if self.paused_t1 then self.paused_t1.dead = true; self.paused_t1 = nil end
|
||||
if self.paused_t2 then self.paused_t2.dead = true; self.paused_t2 = nil end
|
||||
if self.ng_t then self.ng_t.dead = true; self.ng_t = nil end
|
||||
if self.resume_button then self.resume_button.dead = true; self.resume_button = nil end
|
||||
if self.restart_button then self.restart_button.dead = true; self.restart_button = nil end
|
||||
if self.mouse_button then self.mouse_button.dead = true; self.mouse_button = nil end
|
||||
|
@ -527,12 +534,9 @@ function Arena:update(dt)
|
|||
trigger:tween(0.25, _G, {slow_amount = 1}, math.linear, function()
|
||||
slow_amount = 1
|
||||
self.paused = false
|
||||
self.paused_t1.dead = true
|
||||
self.paused_t2.dead = true
|
||||
self.paused_t1 = nil
|
||||
self.paused_t2 = nil
|
||||
self.ng_t.dead = true
|
||||
self.ng_t = nil
|
||||
if self.paused_t1 then self.paused_t1.dead = true; self.paused_t1 = nil end
|
||||
if self.paused_t2 then self.paused_t2.dead = true; self.paused_t2 = nil end
|
||||
if self.ng_t then self.ng_t.dead = true; self.ng_t = nil end
|
||||
if self.resume_button then self.resume_button.dead = true; self.resume_button = nil end
|
||||
if self.restart_button then self.restart_button.dead = true; self.restart_button = nil end
|
||||
if self.mouse_button then self.mouse_button.dead = true; self.mouse_button = nil end
|
||||
|
@ -608,6 +612,7 @@ function Arena:quit()
|
|||
self.quitting = true
|
||||
if self.level == 25 then
|
||||
if not self.win_text and not self.win_text2 then
|
||||
input:set_mouse_visible(true)
|
||||
self.won = true
|
||||
locked_state = nil
|
||||
system.save_run()
|
||||
|
@ -800,6 +805,13 @@ function Arena:quit()
|
|||
steam.userStats.storeStats()
|
||||
end
|
||||
|
||||
if self.mercenary_level >= 2 then
|
||||
state.achievement_mercenaries_win = true
|
||||
system.save_state()
|
||||
steam.userStats.setAchievement('MERCENARIES_WIN')
|
||||
steam.userStats.storeStats()
|
||||
end
|
||||
|
||||
local units = self.player:get_all_units()
|
||||
local all_units_level_2 = true
|
||||
for _, unit in ipairs(units) do
|
||||
|
@ -836,6 +848,7 @@ function Arena:quit()
|
|||
self:gain_gold()
|
||||
self.t:after(3, function()
|
||||
if self.level % 3 == 0 then
|
||||
input:set_mouse_visible(true)
|
||||
self.arena_clear_text.dead = true
|
||||
trigger:tween(1, _G, {slow_amount = 0}, math.linear, function() slow_amount = 0 end, 'slow_amount')
|
||||
trigger:tween(4, camera, {x = gw/2, y = gh/2, r = 0}, math.linear, function() camera.x, camera.y, camera.r = gw/2, gh/2, 0 end)
|
||||
|
@ -1058,9 +1071,10 @@ end
|
|||
|
||||
|
||||
function Arena:gain_gold()
|
||||
local merchant = self.player:get_unit'merchant'
|
||||
self.gold_gained = random:int(level_to_gold_gained[self.level][1], level_to_gold_gained[self.level][2])
|
||||
self.interest = math.min(math.floor(gold/5), 5)
|
||||
gold = gold + self.gold_gained + self.interest
|
||||
self.interest = math.min(math.floor(gold/5), 5) + (merchant and math.floor(gold/10) or 0)
|
||||
gold = gold + self.gold_gained + self.gold_picked_up + self.interest
|
||||
end
|
||||
|
||||
|
||||
|
@ -1074,30 +1088,30 @@ function Arena:transition()
|
|||
main:go_to('buy_screen', self.level, self.units, self.passives)
|
||||
t.t:after(0.1, function()
|
||||
t.text:set_text({
|
||||
{text = '[nudge_down, bg]gold gained: ' .. tostring(self.gold_gained or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
|
||||
{text = '[nudge_down, bg]gold gained: ' .. tostring(self.gold_gained or 0) .. ' + ' .. tostring(self.gold_picked_up or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
|
||||
{text = '[wavy_lower, bg]interest: 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5},
|
||||
{text = '[wavy_lower, bg]total: 0', font = pixul_font, alignment = 'center'}
|
||||
})
|
||||
_G[random:table{'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
t.t:after(0.2, function()
|
||||
t.text:set_text({
|
||||
{text = '[wavy_lower, bg]gold gained: ' .. tostring(self.gold_gained or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
|
||||
{text = '[wavy_lower, bg]gold gained: ' .. tostring(self.gold_gained or 0) .. ' + ' .. tostring(self.gold_picked_up or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
|
||||
{text = '[nudge_down, bg]interest: ' .. tostring(self.interest or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
|
||||
{text = '[wavy_lower, bg]total: 0', font = pixul_font, alignment = 'center'}
|
||||
})
|
||||
_G[random:table{'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
t.t:after(0.2, function()
|
||||
t.text:set_text({
|
||||
{text = '[wavy_lower, bg]gold gained: ' .. tostring(self.gold_gained or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
|
||||
{text = '[wavy_lower, bg]gold gained: ' .. tostring(self.gold_gained or 0) .. ' + ' .. tostring(self.gold_picked_up or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
|
||||
{text = '[wavy_lower, bg]interest: ' .. tostring(self.interest or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
|
||||
{text = '[nudge_down, bg]total: ' .. tostring((self.gold_gained or 0) + (self.interest or 0)), font = pixul_font, alignment = 'center'}
|
||||
{text = '[nudge_down, bg]total: ' .. tostring((self.gold_gained or 0) + (self.interest or 0) + (self.gold_picked_up or 0)), font = pixul_font, alignment = 'center'}
|
||||
})
|
||||
_G[random:table{'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end, text = Text({
|
||||
{text = '[wavy_lower, bg]gold gained: 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5},
|
||||
{text = '[wavy_lower, bg]gold gained: 0 + 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5},
|
||||
{text = '[wavy_lower, bg]interest: 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5},
|
||||
{text = '[wavy_lower, bg]total: 0', font = pixul_font, alignment = 'center'}
|
||||
}, global_text_tags)}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 434 B |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -781,7 +781,8 @@ function RerollButton:init(args)
|
|||
self.text = Text({{text = '[bg10]reroll: [yellow]2', font = pixul_font, alignment = 'center'}}, global_text_tags)
|
||||
elseif self.parent:is(Arena) then
|
||||
self.shape = Rectangle(self.x, self.y, 60, 16)
|
||||
if self.parent.level == 3 then
|
||||
local merchant = self.parent.player:get_unit'merchant'
|
||||
if self.parent.level == 3 or (merchant and merchant.level == 3) then
|
||||
self.free_reroll = true
|
||||
self.text = Text({{text = '[bg10]reroll: [yellow]0', font = pixul_font, alignment = 'center'}}, global_text_tags)
|
||||
else
|
||||
|
@ -847,7 +848,11 @@ end
|
|||
|
||||
function RerollButton:draw()
|
||||
graphics.push(self.x, self.y, 0, self.spring.x, self.spring.y)
|
||||
if self.parent:is(Arena) then
|
||||
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 4, 4, self.selected and fg[0] or bg[-2])
|
||||
else
|
||||
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 4, 4, self.selected and fg[0] or bg[1])
|
||||
end
|
||||
self.text:draw(self.x, self.y + 1)
|
||||
graphics.pop()
|
||||
end
|
||||
|
@ -1077,6 +1082,7 @@ end
|
|||
|
||||
|
||||
function CharacterPart:get_sale_price()
|
||||
if not character_tiers[self.character] then return 0 end
|
||||
local total = 0
|
||||
total = total + ((self.level == 1 and character_tiers[self.character]) or (self.level == 2 and 2*character_tiers[self.character]) or (self.level == 3 and 6*character_tiers[self.character]) or 0)
|
||||
if self.reserve then
|
||||
|
|
30
enemies.lua
30
enemies.lua
|
@ -253,6 +253,8 @@ function Seeker:init(args)
|
|||
if player and player.temporal_chains then
|
||||
self.temporal_chains_mvspd_m = 0.8
|
||||
end
|
||||
|
||||
self.usurer_count = 0
|
||||
end
|
||||
|
||||
|
||||
|
@ -435,6 +437,14 @@ function Seeker:hit(damage, projectile)
|
|||
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 12}:scale_down(0.3):change_color(0.5, self.color)
|
||||
_G[random:table{'enemy_die1', 'enemy_die2'}]:play{pitch = random:float(0.9, 1.1), volume = 0.5}
|
||||
|
||||
if main.current.mercenary_level > 0 then
|
||||
if random:bool((main.current.mercenary_level == 2 and 20) or (main.current.mercenary_level == 1 and 10) or 0) then
|
||||
trigger:after(0.01, function()
|
||||
Gold{group = main.current.main, x = self.x, y = self.y}
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
if self.boss then
|
||||
slow(0.25, 1)
|
||||
magic_die1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
|
@ -594,6 +604,17 @@ function Seeker:curse(curse, duration, arg1, arg2, arg3)
|
|||
elseif curse == 'silencer' then
|
||||
self.silenced = true
|
||||
self.t:after(duration*curse_m, function() self.silenced = false end, 'silencer_curse')
|
||||
elseif curse == 'usurer' then
|
||||
if arg1 then
|
||||
self.usurer_count = self.usurer_count + 1
|
||||
if self.usurer_count == 3 then
|
||||
usurer1:play{pitch = random:float(0.95, 1.05), volume = 1}
|
||||
rogue_crit1:play{pitch = random:float(0.95, 1.05), volume = 1}
|
||||
camera:shake(4, 0.4)
|
||||
self.usurer_count = 0
|
||||
self:hit(50*arg2.dmg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -628,6 +649,7 @@ function EnemyCritter:init(args)
|
|||
self:push(args.v, args.r)
|
||||
self.invulnerable_to = args.projectile
|
||||
self.t:after(0.5, function() self.invulnerable_to = false end)
|
||||
self.usurer_count = 0
|
||||
end
|
||||
|
||||
|
||||
|
@ -778,6 +800,14 @@ function EnemyCritter:curse(curse, duration, arg1, arg2, arg3)
|
|||
elseif curse == 'silencer' then
|
||||
self.silenced = true
|
||||
self.t:after(duration*curse_m, function() self.silenced = false end, 'silencer_curse')
|
||||
elseif curse == 'usurer' then
|
||||
if arg1 then
|
||||
self.usurer_count = self.usurer_count + 1
|
||||
if self.usurer_count == 3 then
|
||||
self.usurer_count = 0
|
||||
self:hit(10*arg2.dmg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -418,6 +418,16 @@ function table.first(t, n)
|
|||
end
|
||||
|
||||
|
||||
function table.first2(t, n)
|
||||
if n == 1 then return {t[1]} end
|
||||
local out = {}
|
||||
for i = 1, (n or 1) do
|
||||
table.push(out, t[i])
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
|
||||
-- Returns the last n values, same as tail
|
||||
-- t = {4, 3, 2, 1}
|
||||
-- table.last(t) -> 1
|
||||
|
|
120
main.lua
120
main.lua
|
@ -9,7 +9,6 @@ require 'media'
|
|||
|
||||
|
||||
function init()
|
||||
print('Initializing engine...')
|
||||
shared_init()
|
||||
|
||||
input:bind('move_left', {'a', 'left', 'dpleft', 'm1'})
|
||||
|
@ -18,8 +17,11 @@ function init()
|
|||
input:bind('move_down', {'s', 'down', 'dpdown'})
|
||||
input:bind('enter', {'space', 'return', 'fleft', 'fdown', 'fright'})
|
||||
|
||||
print('Loading sounds...')
|
||||
local s = {tags = {sfx}}
|
||||
gambler1 = Sound('Collect 5.ogg', s)
|
||||
usurer1 = Sound('Shadow Punch 2.ogg', s)
|
||||
gold1 = Sound('Collect 5.ogg', s)
|
||||
gold2 = Sound('Coins - Gears - Slot.ogg', s)
|
||||
psychic1 = Sound('Magical Impact 13.ogg', s)
|
||||
fire1 = Sound('Fire bolt 3.ogg', s)
|
||||
fire2 = Sound('Fire bolt 5.ogg', s)
|
||||
|
@ -111,7 +113,6 @@ function init()
|
|||
rogue_crit1 = Sound('Dagger Stab (Flesh) 4.ogg', s)
|
||||
rogue_crit2 = Sound('Sword hits another sword 6.ogg', s)
|
||||
|
||||
print('Loading songs...')
|
||||
song1 = Sound('Kubbi - Ember - 01 Pathfinder.ogg', {tags = {music}})
|
||||
song2 = Sound('Kubbi - Ember - 02 Ember.ogg', {tags = {music}})
|
||||
song3 = Sound('Kubbi - Ember - 03 Firelight.ogg', {tags = {music}})
|
||||
|
@ -119,7 +120,6 @@ function init()
|
|||
song5 = Sound('Kubbi - Ember - 05 Compass.ogg', {tags = {music}})
|
||||
death_song = Sound('Kubbi - Ember - 09 Formed by Glaciers.ogg', {tags = {music}})
|
||||
|
||||
print('Loading images...')
|
||||
lock_image = Image('lock')
|
||||
speed_booster_elite = Image('speed_booster_elite')
|
||||
exploder_elite = Image('exploder_elite')
|
||||
|
@ -140,6 +140,7 @@ function init()
|
|||
swarmer = Image('swarmer')
|
||||
voider = Image('voider')
|
||||
sorcerer = Image('sorcerer')
|
||||
mercenary = Image('mercenary')
|
||||
ouroboros_technique_r = Image('ouroboros_technique_r')
|
||||
ouroboros_technique_l = Image('ouroboros_technique_l')
|
||||
wall_echo = Image('wall_echo')
|
||||
|
@ -185,7 +186,6 @@ function init()
|
|||
star = Image('star')
|
||||
arrow = Image('arrow')
|
||||
|
||||
print('Initializing game...')
|
||||
class_colors = {
|
||||
['warrior'] = yellow[0],
|
||||
['ranger'] = green[0],
|
||||
|
@ -201,6 +201,7 @@ function init()
|
|||
['swarmer'] = orange[0],
|
||||
['voider'] = purple[0],
|
||||
['sorcerer'] = blue2[0],
|
||||
['mercenary'] = yellow2[0],
|
||||
}
|
||||
|
||||
class_color_strings = {
|
||||
|
@ -218,6 +219,7 @@ function init()
|
|||
['swarmer'] = 'orange',
|
||||
['voider'] = 'purple',
|
||||
['sorcerer'] = 'blue2',
|
||||
['mercenary'] = 'yellow2',
|
||||
}
|
||||
|
||||
character_names = {
|
||||
|
@ -270,6 +272,11 @@ function init()
|
|||
['vulcanist'] = 'Vulcanist',
|
||||
['warden'] = 'Warden',
|
||||
['psychic'] = 'Psychic',
|
||||
['treasure_hunter'] = 'Treasure Hunter',
|
||||
['merchant'] = 'Merchant',
|
||||
['usurer'] = 'Usurer',
|
||||
['gambler'] = 'Gambler',
|
||||
['thief'] = 'Thief',
|
||||
}
|
||||
|
||||
character_colors = {
|
||||
|
@ -322,6 +329,11 @@ function init()
|
|||
['vulcanist'] = red[0],
|
||||
['warden'] = yellow[0],
|
||||
['psychic'] = fg[0],
|
||||
['treasure_hunter'] = yellow2[0],
|
||||
['merchant'] = yellow2[0],
|
||||
['usurer'] = purple[0],
|
||||
['gambler'] = yellow2[0],
|
||||
['thief'] = red[0],
|
||||
}
|
||||
|
||||
character_color_strings = {
|
||||
|
@ -374,6 +386,11 @@ function init()
|
|||
['vulcanist'] = 'red',
|
||||
['warden'] = 'yellow',
|
||||
['psychic'] = 'fg',
|
||||
['treasure_hunter'] = 'yellow2',
|
||||
['merchant'] = 'yellow2',
|
||||
['usurer'] = 'purple',
|
||||
['gambler'] = 'yellow2',
|
||||
['thief'] = 'red',
|
||||
}
|
||||
|
||||
character_classes = {
|
||||
|
@ -426,6 +443,11 @@ function init()
|
|||
['vulcanist'] = {'sorcerer', 'nuker'},
|
||||
['warden'] = {'sorcerer', 'forcer'},
|
||||
['psychic'] = {'sorcerer', 'psyker'},
|
||||
['treasure_hunter'] = {'mercenary'},
|
||||
['merchant'] = {'mercenary'},
|
||||
['usurer'] = {'curser', 'mercenary', 'voider'},
|
||||
['gambler'] = {'mercenary', 'sorcerer'},
|
||||
['thief'] = {'rogue', 'mercenary'},
|
||||
}
|
||||
|
||||
character_class_strings = {
|
||||
|
@ -478,6 +500,11 @@ function init()
|
|||
['vulcanist'] = '[blue2]Sorcerer, [red]Nuker',
|
||||
['warden'] = '[blue2]Sorcerer, [yellow]Forcer',
|
||||
['psychic'] = '[blue2]Sorcerer, [fg]Psyker',
|
||||
['treasure_hunter'] = '[yellow2]Mercenary',
|
||||
['merchant'] = '[yellow2]Mercenary',
|
||||
['usurer'] = '[purple]Curser, [yellow2]Mercenary, [purple]Curser',
|
||||
['gambler'] = '[yellow2]Mercenary, [blue2]Sorcerer',
|
||||
['thief'] = '[red]Rogue, [yellow2]Mercenary',
|
||||
}
|
||||
|
||||
get_character_stat_string = function(character, level)
|
||||
|
@ -547,6 +574,11 @@ function init()
|
|||
['vulcanist'] = function(lvl) return '[fg]creates a volcano that explodes the nearby area [yellow]4[fg] times, dealing [yellow]' .. get_character_stat('vulcanist', lvl, 'dmg') .. ' AoE [fg]damage' end,
|
||||
['warden'] = function(lvl) return '[fg]creates a force field around a random unit that prevents enemies from entering' end,
|
||||
['psychic'] = function(lvl) return '[fg]creates a small area that deals [yellow]' .. get_character_stat('psychic', lvl, 'dmg') .. ' AoE[fg] damage' end,
|
||||
['treasure_hunter'] = function(lvl) return '[fg]picking up gold releases [yellow]4[fg] homing projectiles that each deal [yellow]' .. get_character_stat('treasure_hunter', 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,
|
||||
['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,
|
||||
}
|
||||
|
||||
character_effect_names = {
|
||||
|
@ -598,7 +630,12 @@ function init()
|
|||
['silencer'] = '[blue2]Arcane Curse',
|
||||
['vulcanist'] = '[red]Lava Burst',
|
||||
['warden'] = '[yellow]Magnetic Field',
|
||||
['psychic'] = '[fg]Mental Strike'
|
||||
['psychic'] = '[fg]Mental Strike',
|
||||
['treasure_hunter'] = '[yellow2]Golden Bolts',
|
||||
['merchant'] = '[yellow2]Item Shop',
|
||||
['usurer'] = '[purple]Bankruptcy',
|
||||
['gambler'] = '[yellow2]Multicast',
|
||||
['thief'] = '[red]Ultrakill',
|
||||
}
|
||||
|
||||
character_effect_names_gray = {
|
||||
|
@ -650,7 +687,12 @@ function init()
|
|||
['silencer'] = '[light_bg]Arcane Curse',
|
||||
['vulcanist'] = '[light_bg]Lava Burst',
|
||||
['warden'] = '[light_bg]Magnetic Field',
|
||||
['psychic'] = '[light_bg]Mental Strike'
|
||||
['psychic'] = '[light_bg]Mental Strike',
|
||||
['treasure_hunter'] = '[light_bg]Golden Bolts',
|
||||
['merchant'] = '[light_bg]Item Shop',
|
||||
['usurer'] = '[light_bg]Bankruptcy',
|
||||
['gambler'] = '[light_bg]Multicast',
|
||||
['thief'] = '[light_bg]Ultrakill',
|
||||
}
|
||||
|
||||
character_effect_descriptions = {
|
||||
|
@ -703,6 +745,11 @@ function init()
|
|||
['vulcanist'] = function() return '[fg]the number and speed of explosions is [yellow]doubled[fg]' end,
|
||||
['warden'] = function() return '[fg]creates the force field around [yellow]2[fg] units' end,
|
||||
['psychic'] = function() return '[fg]the attack can happen from any distance and repeats once' end,
|
||||
['treasure_hunter'] = function() return '[fg]release [yellow]8[fg] homing projectiles instead and they pierce twice' end,
|
||||
['merchant'] = function() return '[fg]your first item reroll is always free' end,
|
||||
['usurer'] = function() return '[fg]if the same enemy is cursed [yellow]3[fg] times it takes [yellow]' .. 10*get_character_stat('usurer', 3, 'dmg') .. '[fg] damage' end,
|
||||
['gambler'] = function() return '[yellow]60/40/20%[fg] chance to cast the attack [yellow]2/3/4[fg] times' end,
|
||||
['thief'] = function() return '[fg]if the knife crits it deals [yellow]' .. 10*get_character_stat('thief', 3, 'dmg') .. '[fg] damage, chains [yellow]10[fg] times and grants [yellow]1[fg] gold' end,
|
||||
}
|
||||
|
||||
character_effect_descriptions_gray = {
|
||||
|
@ -755,6 +802,11 @@ function init()
|
|||
['vulcanist'] = function() return '[light_bg]the number and speed of explosions is doubled' end,
|
||||
['warden'] = function() return '[light_bg]creates the force field around 2 units' end,
|
||||
['psychic'] = function() return '[light_bg]the attack can happen from any distance and repeats once' end,
|
||||
['treasure_hunter'] = function() return '[light_bg]release 8 homing projectiles instead and they pierce twice' end,
|
||||
['merchant'] = function() return '[light_bg]your first item reroll is always free' end,
|
||||
['usurer'] = function() return '[light_bg]if the same enemy is cursed 3 times it takes ' .. 10*get_character_stat('usurer', 3, 'dmg') .. ' damage' end,
|
||||
['gambler'] = function() return '[light_bg]60/40/20% chance to cast the attack 2/3/4 times' end,
|
||||
['thief'] = function() return '[light_bg]if the coin crits it deals ' .. 10*get_character_stat('thief', 3, 'dmg') .. ' damage, chains 10 times and grants 1 gold' end,
|
||||
}
|
||||
|
||||
character_stats = {
|
||||
|
@ -807,6 +859,11 @@ function init()
|
|||
['vulcanist'] = function(lvl) return get_character_stat_string('vulcanist', lvl) end,
|
||||
['warden'] = function(lvl) return get_character_stat_string('warden', lvl) end,
|
||||
['psychic'] = function(lvl) return get_character_stat_string('psychic', lvl) end,
|
||||
['treasure_hunter'] = function(lvl) return get_character_stat_string('treasure_hunter', lvl) end,
|
||||
['merchant'] = function(lvl) return get_character_stat_string('merchant', lvl) end,
|
||||
['usurer'] = function(lvl) return get_character_stat_string('usurer', lvl) end,
|
||||
['gambler'] = function(lvl) return get_character_stat_string('gambler', lvl) end,
|
||||
['thief'] = function(lvl) return get_character_stat_string('thief', lvl) end,
|
||||
}
|
||||
|
||||
class_stat_multipliers = {
|
||||
|
@ -824,6 +881,7 @@ function init()
|
|||
['swarmer'] = {hp = 1.2, dmg = 1, aspd = 1.25, area_dmg = 1, area_size = 1, def = 0.75, mvspd = 0.75},
|
||||
['voider'] = {hp = 0.75, dmg = 1.3, aspd = 1, area_dmg = 0.8, area_size = 0.75, def = 0.6, mvspd = 0.8},
|
||||
['sorcerer'] = {hp = 0.8, dmg = 1.3, aspd = 1, area_dmg = 1.2, area_size = 1, def = 0.8, mvspd = 1},
|
||||
['mercenary'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 1},
|
||||
['seeker'] = {hp = 0.5, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 0.3},
|
||||
['mini_boss'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 0.3},
|
||||
['enemy_critter'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 0.5},
|
||||
|
@ -862,17 +920,18 @@ function init()
|
|||
['sorcerer'] = function(lvl)
|
||||
return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4[' .. ylb3(lvl) .. ']/6 [fg]- sorcerers repeat their attacks once every [' .. ylb1(lvl) .. ']4/[' .. ylb2(lvl) .. ']3/[' .. ylb3(lvl) .. ']2[fg] attacks'
|
||||
end,
|
||||
['mercenary'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4 [fg]- [' .. ylb1(lvl) .. ']+10%[' .. ylb2(lvl) .. ']/+20% [fg]chance for enemies to drop gold on death' end,
|
||||
}
|
||||
|
||||
tier_to_characters = {
|
||||
[1] = {'vagrant', 'swordsman', 'magician', 'archer', 'scout', 'cleric', 'arcanist'},
|
||||
[2] = {'wizard', 'saboteur', 'sage', 'squire', 'dual_gunner', 'hunter', 'chronomancer', 'barbarian', 'cryomancer', 'beastmaster', 'launcher', 'jester', 'carver', 'psychic', 'witch', 'silencer', 'outlaw'},
|
||||
[3] = {'elementor', 'stormweaver', 'spellblade', 'psykeeper', 'engineer', 'juggernaut', 'pyromancer', 'host', 'assassin', 'bane', 'barrager', 'infestor', 'flagellant', 'illusionist'},
|
||||
[4] = {'priest', 'highlander', 'psykino', 'fairy', 'blade', 'plague_doctor', 'cannoneer', 'vulcanist', 'warden', 'corruptor'},
|
||||
[1] = {'vagrant', 'swordsman', 'magician', 'archer', 'scout', 'cleric', 'arcanist', 'treasure_hunter'},
|
||||
[2] = {'wizard', 'saboteur', 'sage', 'squire', 'dual_gunner', 'hunter', 'chronomancer', 'barbarian', 'cryomancer', 'beastmaster', 'launcher', 'jester', 'carver', 'psychic', 'witch', 'silencer', 'outlaw', 'merchant'},
|
||||
[3] = {'elementor', 'stormweaver', 'spellblade', 'psykeeper', 'engineer', 'juggernaut', 'pyromancer', 'host', 'assassin', 'bane', 'barrager', 'infestor', 'flagellant', 'illusionist', 'usurer', 'gambler'},
|
||||
[4] = {'priest', 'highlander', 'psykino', 'fairy', 'blade', 'plague_doctor', 'cannoneer', 'vulcanist', 'warden', 'corruptor', 'thief'},
|
||||
}
|
||||
|
||||
non_attacking_characters = {'cleric', 'stormweaver', 'squire', 'chronomancer', 'sage', 'psykeeper', 'bane', 'carver', 'fairy', 'priest', 'flagellant'}
|
||||
non_cooldown_characters = {'squire', 'chronomancer', 'psykeeper'}
|
||||
non_attacking_characters = {'cleric', 'stormweaver', 'squire', 'chronomancer', 'sage', 'psykeeper', 'bane', 'carver', 'fairy', 'priest', 'flagellant', 'merchant', 'treasure_hunter'}
|
||||
non_cooldown_characters = {'squire', 'chronomancer', 'psykeeper', 'merchant', 'treasure_hunter'}
|
||||
|
||||
character_tiers = {
|
||||
['vagrant'] = 1,
|
||||
|
@ -881,7 +940,6 @@ function init()
|
|||
['archer'] = 1,
|
||||
['scout'] = 1,
|
||||
['cleric'] = 1,
|
||||
['arcanist'] = 1,
|
||||
['outlaw'] = 2,
|
||||
['blade'] = 4,
|
||||
['elementor'] = 3,
|
||||
|
@ -918,12 +976,18 @@ function init()
|
|||
['priest'] = 4,
|
||||
['infestor'] = 3,
|
||||
['flagellant'] = 3,
|
||||
['psychic'] = 2,
|
||||
['arcanist'] = 1,
|
||||
['illusionist'] = 3,
|
||||
['witch'] = 2,
|
||||
['silencer'] = 2,
|
||||
['illusionist'] = 3,
|
||||
['warden'] = 4,
|
||||
['vulcanist'] = 4,
|
||||
['warden'] = 4,
|
||||
['psychic'] = 2,
|
||||
['treasure_hunter'] = 1,
|
||||
['merchant'] = 2,
|
||||
['usurer'] = 3,
|
||||
['gambler'] = 3,
|
||||
['thief'] = 4,
|
||||
}
|
||||
|
||||
get_number_of_units_per_class = function(units)
|
||||
|
@ -941,6 +1005,7 @@ function init()
|
|||
local swarmers = 0
|
||||
local voiders = 0
|
||||
local sorcerers = 0
|
||||
local mercenaries = 0
|
||||
for _, unit in ipairs(units) do
|
||||
for _, unit_class in ipairs(character_classes[unit.character]) do
|
||||
if unit_class == 'ranger' then rangers = rangers + 1 end
|
||||
|
@ -957,10 +1022,11 @@ function init()
|
|||
if unit_class == 'swarmer' then swarmers = swarmers + 1 end
|
||||
if unit_class == 'voider' then voiders = voiders + 1 end
|
||||
if unit_class == 'sorcerer' then sorcerers = sorcerers + 1 end
|
||||
if unit_class == 'mercenary' then mercenaries = mercenaries + 1 end
|
||||
end
|
||||
end
|
||||
return {ranger = rangers, warrior = warriors, healer = healers, mage = mages, nuker = nukers, conjurer = conjurers, rogue = rogues,
|
||||
enchanter = enchanters, psyker = psykers, curser = cursers, forcer = forcers, swarmer = swarmers, voider = voiders, sorcerer = sorcerers}
|
||||
enchanter = enchanters, psyker = psykers, curser = cursers, forcer = forcers, swarmer = swarmers, voider = voiders, sorcerer = sorcerers, mercenary = mercenaries}
|
||||
end
|
||||
|
||||
get_class_levels = function(units)
|
||||
|
@ -970,7 +1036,7 @@ function init()
|
|||
if number_of_units >= 6 then return 2
|
||||
elseif number_of_units >= 3 then return 1
|
||||
else return 0 end
|
||||
elseif class == 'healer' or class == 'conjurer' or class == 'enchanter' or class == 'psyker' or class == 'curser' or class == 'forcer' or class == 'swarmer' or class == 'voider' then
|
||||
elseif class == 'healer' or class == 'conjurer' or class == 'enchanter' or class == 'psyker' or class == 'curser' or class == 'forcer' or class == 'swarmer' or class == 'voider' or class == 'mercenary' then
|
||||
if number_of_units >= 4 then return 2
|
||||
elseif number_of_units >= 2 then return 1
|
||||
else return 0 end
|
||||
|
@ -996,6 +1062,7 @@ function init()
|
|||
swarmer = units_to_class_level(units_per_class.swarmer, 'swarmer'),
|
||||
voider = units_to_class_level(units_per_class.voider, 'voider'),
|
||||
sorcerer = units_to_class_level(units_per_class.sorcerer, 'sorcerer'),
|
||||
mercenary = units_to_class_level(units_per_class.mercenary, 'mercenary'),
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -1022,6 +1089,7 @@ function init()
|
|||
['swarmer'] = function(units) return 2, 4, nil, get_number_of_units_per_class(units).swarmer end,
|
||||
['voider'] = function(units) return 2, 4, nil, get_number_of_units_per_class(units).voider end,
|
||||
['sorcerer'] = function(units) return 2, 4, 6, get_number_of_units_per_class(units).sorcerer end,
|
||||
['mercenary'] = function(units) return 2, 4, nil, get_number_of_units_per_class(units).mercenary end,
|
||||
}
|
||||
|
||||
passive_names = {
|
||||
|
@ -1323,22 +1391,16 @@ function init()
|
|||
end
|
||||
-- main_song_instance = _G[random:table{'song1', 'song2', 'song3', 'song4', 'song5'}]:play{volume = 0.5}
|
||||
|
||||
|
||||
main:add(BuyScreen'buy_screen')
|
||||
main:go_to('buy_screen', run.level or 0, run.units or {}, passives)
|
||||
-- main:go_to('buy_screen', 7, run.units or {}, {'unleash'})
|
||||
|
||||
--[[
|
||||
main:add(Arena'arena')
|
||||
main:go_to('arena', 17, {
|
||||
{character = 'arcanist', level = 2},
|
||||
{character = 'silencer', level = 2},
|
||||
{character = 'warden', level = 3},
|
||||
{character = 'chronomancer', level = 1},
|
||||
{character = 'witch', level = 3},
|
||||
{character = 'illusionist', level = 3},
|
||||
{character = 'psychic', level = 2},
|
||||
{character = 'vulcanist', level = 3},
|
||||
main:go_to('arena', 13, {
|
||||
{character = 'thief', level = 3},
|
||||
{character = 'scout', level = 1},
|
||||
{character = 'beastmaster', level = 1},
|
||||
}, passives)
|
||||
]]--
|
||||
|
||||
|
|
217
player.lua
217
player.lua
|
@ -47,7 +47,6 @@ function Player:init(args)
|
|||
self:attack(32, {x = enemy.x, y = enemy.y})
|
||||
end
|
||||
end, nil, nil, 'attack')
|
||||
|
||||
if self.level == 3 then
|
||||
self.t:every(12, function()
|
||||
self.magician_invulnerable = true
|
||||
|
@ -55,6 +54,60 @@ function Player:init(args)
|
|||
end)
|
||||
end
|
||||
|
||||
elseif self.character == 'gambler' then
|
||||
self.sorcerer_count = 0
|
||||
local cast = function(pitch_a)
|
||||
local enemy = table.shuffle(main.current.main:get_objects_by_classes(main.current.enemies))[1]
|
||||
if enemy then
|
||||
gambler1:play{pitch = pitch_a, volume = math.remap(gold, 0, 50, 0, 0.8)}
|
||||
enemy:hit(2*gold)
|
||||
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_count = 0
|
||||
self.t:after(0.25, function()
|
||||
local enemy = table.shuffle(main.current.main:get_objects_by_classes(main.current.enemies))[1]
|
||||
if enemy then
|
||||
gambler1:play{pitch = pitch_a + 0.05, volume = math.remap(gold, 0, 50, 0, 0.8)}
|
||||
enemy:hit(2*gold)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
self.t:every(2, function()
|
||||
cast(1)
|
||||
if self.level == 3 then
|
||||
if random:bool(60) then
|
||||
if random:bool(40) then
|
||||
if random:bool(20) then
|
||||
self.t:after(0.25, function()
|
||||
cast(1.1)
|
||||
self.t:after(0.25, function()
|
||||
cast(1.2)
|
||||
self.t:after(0.25, function()
|
||||
cast(1.3)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
else
|
||||
self.t:after(0.25, function()
|
||||
cast(1.1)
|
||||
self.t:after(0.25, function()
|
||||
cast(1.2)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
else
|
||||
self.t:after(0.25, function()
|
||||
cast(1.1)
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end, nil, nil, 'attack')
|
||||
|
||||
elseif self.character == 'archer' then
|
||||
self.attack_sensor = Circle(self.x, self.y, 160)
|
||||
self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
|
||||
|
@ -73,6 +126,15 @@ function Player:init(args)
|
|||
end
|
||||
end, nil, nil, 'shoot')
|
||||
|
||||
elseif self.character == 'thief' then
|
||||
self.attack_sensor = Circle(self.x, self.y, 64)
|
||||
self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
|
||||
local closest_enemy = self:get_closest_object_in_shape(self.attack_sensor, main.current.enemies)
|
||||
if closest_enemy then
|
||||
self:shoot(self:angle_to_object(closest_enemy), {chain = (self.level == 3 and 10 or 5)})
|
||||
end
|
||||
end, nil, nil, 'shoot')
|
||||
|
||||
elseif self.character == 'cleric' then
|
||||
self.t:every(6, function()
|
||||
local all_units = self:get_all_units()
|
||||
|
@ -261,12 +323,12 @@ function Player:init(args)
|
|||
if x == 0 and y == 0 then x, y = gw/2, gh/2 end
|
||||
x, y = x + self.x, y + self.y
|
||||
x, y = x/2, y/2
|
||||
trigger:every_immediate(0.1, function()
|
||||
main.current.t:every_immediate(0.1, function()
|
||||
local check_circle = Circle(x, y, 2)
|
||||
local objects = main.current.main:get_objects_in_shape(check_circle, {Player, Seeker, EnemyCritter, Critter, Illusion, Saboteur, Pet, Turret})
|
||||
if #objects == 0 then
|
||||
Volcano{group = main.current.main, x = x, y = y, color = self.color, parent = self, rs = 24, level = self.level}
|
||||
trigger:cancel('volcano_spawn')
|
||||
main.current.t:cancel('volcano_spawn')
|
||||
end
|
||||
end, nil, nil, 'volcano_spawn')
|
||||
end
|
||||
|
@ -431,9 +493,10 @@ function Player:init(args)
|
|||
|
||||
elseif self.character == 'jester' then
|
||||
self.attack_sensor = Circle(self.x, self.y, 96)
|
||||
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(main.current.main:get_objects_by_classes(main.current.enemies)), 6)
|
||||
local enemies = table.first(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 6)
|
||||
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)
|
||||
|
@ -443,15 +506,29 @@ function Player:init(args)
|
|||
end
|
||||
end, nil, nil, 'attack')
|
||||
|
||||
elseif self.character == 'usurer' then
|
||||
self.attack_sensor = Circle(self.x, self.y, 96)
|
||||
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)
|
||||
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)
|
||||
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = purple[0], duration = 0.1}
|
||||
LightningLine{group = main.current.effects, src = self, dst = enemy, color = purple[0]}
|
||||
end
|
||||
end, nil, nil, 'attack')
|
||||
|
||||
elseif self.character == 'silencer' then
|
||||
self.sorcerer_count = 0
|
||||
self.attack_sensor = Circle(self.x, self.y, 96)
|
||||
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()
|
||||
local curse = function()
|
||||
buff1:play{pitch = random:float(0.9, 1.1), volume = 0.5}
|
||||
local enemies = table.first(table.shuffle(main.current.main:get_objects_by_classes(main.current.enemies)), 6)
|
||||
local enemies = table.first(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 6)
|
||||
for _, enemy in ipairs(enemies) do
|
||||
if self:distance_to_object(enemy) < 128 then
|
||||
enemy:curse('silencer', 6*(self.hex_duration_m or 1), self.level == 3, self)
|
||||
if self.level == 3 then
|
||||
local curse_m = 1
|
||||
|
@ -464,7 +541,6 @@ function Player:init(args)
|
|||
LightningLine{group = main.current.effects, src = self, dst = enemy, color = blue2[0]}
|
||||
end
|
||||
end
|
||||
end
|
||||
curse()
|
||||
if main.current.sorcerer_level > 0 then
|
||||
self.sorcerer_count = self.sorcerer_count + 1
|
||||
|
@ -508,16 +584,15 @@ function Player:init(args)
|
|||
|
||||
elseif self.character == 'bane' then
|
||||
self.attack_sensor = Circle(self.x, self.y, 96)
|
||||
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(main.current.main:get_objects_by_classes(main.current.enemies)), 6)
|
||||
local enemies = table.first(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 6)
|
||||
for _, enemy in ipairs(enemies) do
|
||||
if self:distance_to_object(enemy) < 128 then
|
||||
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}
|
||||
LightningLine{group = main.current.effects, src = self, dst = enemy, color = purple[0]}
|
||||
end
|
||||
end
|
||||
end, nil, nil, 'attack')
|
||||
|
||||
elseif self.character == 'psykino' then
|
||||
|
@ -603,24 +678,24 @@ function Player:init(args)
|
|||
local unit_2 = random:table_remove(units)
|
||||
if unit_1 then
|
||||
illusion1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
trigger:every_immediate(0.1, function()
|
||||
main.current.t:every_immediate(0.1, function()
|
||||
local check_circle = Circle(unit_1.x, unit_1.y, 6)
|
||||
local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter})
|
||||
if #objects == 0 then
|
||||
ForceField{group = main.current.main, x = unit_1.x, y = unit_1.y, parent = unit_1}
|
||||
trigger:cancel('warden_force_field_1')
|
||||
main.current.t:cancel('warden_force_field_1')
|
||||
end
|
||||
end, nil, nil, 'warden_force_field_1')
|
||||
end
|
||||
if unit_2 then
|
||||
illusion1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
ForceField{group = main.current.main, x = unit_2.x, y = unit_2.y, parent = unit_2}
|
||||
trigger:every_immediate(0.1, function()
|
||||
main.current.t:every_immediate(0.1, function()
|
||||
local check_circle = Circle(unit_2.x, unit_2.y, 6)
|
||||
local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter})
|
||||
if #objects == 0 then
|
||||
ForceField{group = main.current.main, x = unit_2.x, y = unit_2.y, parent = unit_2}
|
||||
trigger:cancel('warden_force_field_2')
|
||||
main.current.t:cancel('warden_force_field_2')
|
||||
end
|
||||
end, nil, nil, 'warden_force_field_2')
|
||||
end
|
||||
|
@ -628,12 +703,12 @@ function Player:init(args)
|
|||
local unit = random:table(self:get_all_units())
|
||||
if unit then
|
||||
illusion1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
trigger:every_immediate(0.1, function()
|
||||
main.current.t:every_immediate(0.1, function()
|
||||
local check_circle = Circle(unit.x, unit.y, 6)
|
||||
local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter})
|
||||
if #objects == 0 then
|
||||
ForceField{group = main.current.main, x = unit.x, y = unit.y, parent = unit}
|
||||
trigger:cancel('warden_force_field_0')
|
||||
main.current.t:cancel('warden_force_field_0')
|
||||
end
|
||||
end, nil, nil, 'warden_force_field_0')
|
||||
end
|
||||
|
@ -671,17 +746,16 @@ function Player:init(args)
|
|||
end, nil, nil, 'heal')
|
||||
|
||||
elseif self.character == 'infestor' then
|
||||
self.attack_sensor = Circle(self.x, self.y, 128)
|
||||
self.attack_sensor = Circle(self.x, self.y, 96)
|
||||
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(main.current.main:get_objects_by_classes(main.current.enemies)), 8)
|
||||
local enemies = table.first(table.shuffle(self:get_objects_in_shape(self.wide_attack_sensor, main.current.enemies)), 8)
|
||||
for _, enemy in ipairs(enemies) do
|
||||
if self:distance_to_object(enemy) < 128 then
|
||||
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}
|
||||
LightningLine{group = main.current.effects, src = self, dst = enemy, color = orange[0]}
|
||||
end
|
||||
end
|
||||
end, nil, nil, 'attack')
|
||||
|
||||
elseif self.character == 'flagellant' then
|
||||
|
@ -923,6 +997,7 @@ function Player:update(dt)
|
|||
if class_levels.swarmer >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if class_levels.voider >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if class_levels.sorcerer >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if class_levels.mercenary >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
self.vagrant_dmg_m = 1 + 0.1*number_of_active_sets
|
||||
self.vagrant_aspd_m = 1 + 0.1*number_of_active_sets
|
||||
end
|
||||
|
@ -988,6 +1063,7 @@ function Player:update(dt)
|
|||
if class_levels.swarmer >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if class_levels.voider >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if class_levels.sorcerer >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if class_levels.mercenary >= 1 then number_of_active_sets = number_of_active_sets + 1 end
|
||||
if main.current.psyker_level == 2 then
|
||||
self.psyker_dmg_m = 1 + 0.2*number_of_active_sets
|
||||
self.psyker_aspd_m = 1 + 0.2*number_of_active_sets
|
||||
|
@ -1039,6 +1115,7 @@ function Player:update(dt)
|
|||
self:calculate_stats()
|
||||
|
||||
if self.attack_sensor then self.attack_sensor:move_to(self.x, self.y) end
|
||||
if self.wide_attack_sensor then self.wide_attack_sensor:move_to(self.x, self.y) end
|
||||
if self.gun_kata_sensor then self.gun_kata_sensor:move_to(self.x, self.y) end
|
||||
self.t:set_every_multiplier('shoot', self.aspd_m)
|
||||
self.t:set_every_multiplier('attack', self.aspd_m)
|
||||
|
@ -1371,6 +1448,14 @@ function Player:shoot(r, mods)
|
|||
end
|
||||
end
|
||||
|
||||
if self.character == 'thief' then
|
||||
dmg_m = dmg_m*2
|
||||
if self.level == 3 and crit then
|
||||
dmg_m = dmg_m*10
|
||||
main.current.gold_picked_up = main.current.gold_picked_up + 1
|
||||
end
|
||||
end
|
||||
|
||||
if crit and mods.spawn_critters_on_crit then
|
||||
critter1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
trigger:after(0.01, function()
|
||||
|
@ -1450,7 +1535,8 @@ function Player:shoot(r, mods)
|
|||
archer1:play{pitch = random:float(0.95, 1.05), volume = 0.35}
|
||||
elseif self.character == 'wizard' or self.character == 'lich' or self.character == 'arcanist' then
|
||||
wizard1:play{pitch = random:float(0.95, 1.05), volume = 0.15}
|
||||
elseif self.character == 'scout' or self.character == 'outlaw' or self.character == 'blade' or self.character == 'spellblade' or self.character == 'jester' or self.character == 'assassin' or self.character == 'beastmaster' then
|
||||
elseif self.character == 'scout' or self.character == 'outlaw' or self.character == 'blade' or self.character == 'spellblade' or self.character == 'jester' or self.character == 'assassin' or self.character == 'beastmaster' or
|
||||
self.character == 'thief' then
|
||||
_G[random:table{'scout1', 'scout2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.35}
|
||||
if self.character == 'spellblade' then
|
||||
wizard1:play{pitch = random:float(0.95, 1.05), volume = 0.15}
|
||||
|
@ -1609,6 +1695,12 @@ function Projectile:init(args)
|
|||
|
||||
elseif self.character == 'witch' and self.level == 3 then
|
||||
self.chain = 1
|
||||
|
||||
elseif self.character == 'treasure_hunter' then
|
||||
self.homing = true
|
||||
if self.level == 3 then
|
||||
self.pierce = 2
|
||||
end
|
||||
end
|
||||
|
||||
if self.parent.divine_machine_arrow and table.any(self.parent.classes, function(v) return v == 'ranger' end) then
|
||||
|
@ -1764,7 +1856,8 @@ function Projectile:on_collision_enter(other, contact)
|
|||
self.ricochet = self.ricochet - 1
|
||||
end
|
||||
_G[random:table{'arrow_hit_wall1', 'arrow_hit_wall2'}]:play{pitch = random:float(0.9, 1.1), volume = 0.2}
|
||||
elseif self.character == 'scout' or self.character == 'outlaw' or self.character == 'blade' or self.character == 'spellblade' or self.character == 'jester' or self.character == 'beastmaster' or self.character == 'witch' then
|
||||
elseif self.character == 'scout' or self.character == 'outlaw' or self.character == 'blade' or self.character == 'spellblade' or self.character == 'jester' or self.character == 'beastmaster' or self.character == 'witch' or
|
||||
self.character == 'thief' then
|
||||
self:die(x, y, r, 0)
|
||||
knife_hit_wall1:play{pitch = random:float(0.9, 1.1), volume = 0.2}
|
||||
local r = Unit.bounce(self, nx, ny)
|
||||
|
@ -1789,7 +1882,7 @@ function Projectile:on_collision_enter(other, contact)
|
|||
elseif self.character == 'cannoneer' then
|
||||
self:die(x, y, r, random:int(2, 3))
|
||||
cannon_hit_wall1:play{pitch = random:float(0.95, 1.05), volume = 0.1}
|
||||
elseif self.character == 'engineer' or self.character == 'dual_gunner' then
|
||||
elseif self.character == 'engineer' or self.character == 'dual_gunner' or self.character == 'treasure_hunter' then
|
||||
self:die(x, y, r, random:int(2, 3))
|
||||
_G[random:table{'turret_hit_wall1', 'turret_hit_wall2'}]:play{pitch = random:float(0.9, 1.1), volume = 0.2}
|
||||
else
|
||||
|
@ -1838,7 +1931,7 @@ function Projectile:on_trigger_enter(other, contact)
|
|||
end
|
||||
|
||||
if self.character == 'archer' or self.character == 'scout' or self.character == 'outlaw' or self.character == 'blade' or self.character == 'hunter' or self.character == 'spellblade' or self.character == 'engineer' or
|
||||
self.character == 'jester' or self.character == 'assassin' or self.character == 'barrager' or self.character == 'beastmaster' or self.character == 'witch' then
|
||||
self.character == 'jester' or self.character == 'assassin' or self.character == 'barrager' or self.character == 'beastmaster' or self.character == 'witch' or self.character == 'treasure_hunter' or self.character == 'thief' then
|
||||
hit2:play{pitch = random:float(0.95, 1.05), volume = 0.35}
|
||||
if self.character == 'spellblade' then
|
||||
magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.15}
|
||||
|
@ -2427,6 +2520,7 @@ Volcano:implement(GameObject)
|
|||
Volcano:implement(Physics)
|
||||
function Volcano:init(args)
|
||||
self:init_game_object(args)
|
||||
if not self.group.world then self.dead = true; return end
|
||||
self:set_as_rectangle(9, 9, 'static', 'player')
|
||||
self:set_restitution(0.5)
|
||||
self.hfx:add('hit', 1)
|
||||
|
@ -2777,6 +2871,81 @@ function Illusion:draw()
|
|||
end
|
||||
|
||||
|
||||
Gold = Object:extend()
|
||||
Gold:implement(GameObject)
|
||||
Gold:implement(Physics)
|
||||
function Gold:init(args)
|
||||
self:init_game_object(args)
|
||||
self:set_as_rectangle(3, 3, 'dynamic', 'ghost')
|
||||
self:set_restitution(0.5)
|
||||
local r = random:float(0, 2*math.pi)
|
||||
local f = random:float(2, 4)
|
||||
self:apply_impulse(f*math.cos(r), f*math.sin(r))
|
||||
self:apply_angular_impulse(random:table{random:float(-6*math.pi, -2*math.pi), random:float(2*math.pi, 6*math.pi)})
|
||||
self:set_damping(2.5)
|
||||
self:set_angular_damping(5)
|
||||
self.color = yellow2[0]
|
||||
self.hfx:add('hit', 1)
|
||||
gold1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
end
|
||||
|
||||
|
||||
function Gold:update(dt)
|
||||
self:update_game_object(dt)
|
||||
self.r = self:get_angle()
|
||||
end
|
||||
|
||||
|
||||
function Gold:draw()
|
||||
graphics.push(self.x, self.y, self.r, self.hfx.hit.x, self.hfx.hit.x)
|
||||
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 1, 1, self.hfx.hit.f and fg[0] or self.color)
|
||||
graphics.pop()
|
||||
end
|
||||
|
||||
function Gold:on_trigger_enter(other, contact)
|
||||
if other:is(Player) then
|
||||
main.current.gold_picked_up = main.current.gold_picked_up + 1
|
||||
self.dead = true
|
||||
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 4, color = fg[0], duration = 0.1}
|
||||
for i = 1, 2 do HitParticle{group = main.current.effects, x = self.x, y = self.y, color = self.color} end
|
||||
_G[random:table{'gold2', 'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.9, 1.1), volume = 0.3}
|
||||
|
||||
local units = other:get_all_units()
|
||||
local th
|
||||
for _, unit in ipairs(units) do
|
||||
if unit.character == 'treasure_hunter' then
|
||||
th = unit
|
||||
end
|
||||
end
|
||||
if th then
|
||||
if th.level == 3 then
|
||||
trigger:after(0.01, function()
|
||||
_G[random:table{'scout1', 'scout2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.35}
|
||||
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6}
|
||||
local r = random:float(0, 2*math.pi)
|
||||
for i = 1, 8 do
|
||||
local t = {group = main.current.main, x = self.x + 8*math.cos(r), y = self.y + 8*math.sin(r), v = 250, r = r, color = yellow2[0], dmg = th.dmg, character = th.character, parent = th, level = th.level}
|
||||
Projectile(table.merge(t, mods or {}))
|
||||
r = r + math.pi/4
|
||||
end
|
||||
end)
|
||||
else
|
||||
trigger:after(0.01, function()
|
||||
_G[random:table{'scout1', 'scout2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.35}
|
||||
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6}
|
||||
local r = random:float(0, 2*math.pi)
|
||||
for i = 1, 4 do
|
||||
local t = {group = main.current.main, x = self.x + 8*math.cos(r), y = self.y + 8*math.sin(r), v = 250, r = r, color = yellow2[0], dmg = th.dmg, character = th.character, parent = th, level = th.level}
|
||||
Projectile(table.merge(t, mods or {}))
|
||||
r = r + 2*math.pi/4
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
Critter = Object:extend()
|
||||
|
|
|
@ -13,6 +13,7 @@ function shared_init()
|
|||
red = ColorRamp(Color'#e91d39', 0.025),
|
||||
purple = ColorRamp(Color'#8e559e', 0.025),
|
||||
blue2 = ColorRamp(Color'#4778ba', 0.025),
|
||||
yellow2 = ColorRamp(Color'#f59f10', 0.025),
|
||||
}
|
||||
for name, color in pairs(colors) do
|
||||
_G[name] = color
|
||||
|
@ -494,6 +495,7 @@ global_text_tags = {
|
|||
red = TextTag{draw = function(c, i, text) graphics.set_color(red[0]) end},
|
||||
orange = TextTag{draw = function(c, i, text) graphics.set_color(orange[0]) end},
|
||||
yellow = TextTag{draw = function(c, i, text) graphics.set_color(yellow[0]) end},
|
||||
yellow2 = TextTag{draw = function(c, i, text) graphics.set_color(yellow2[0]) end},
|
||||
green = TextTag{draw = function(c, i, text) graphics.set_color(green[0]) end},
|
||||
purple = TextTag{draw = function(c, i, text) graphics.set_color(purple[0]) end},
|
||||
blue = TextTag{draw = function(c, i, text) graphics.set_color(blue[0]) end},
|
||||
|
@ -501,6 +503,7 @@ global_text_tags = {
|
|||
bg = TextTag{draw = function(c, i, text) graphics.set_color(bg[0]) end},
|
||||
bg3 = TextTag{draw = function(c, i, text) graphics.set_color(bg[3]) end},
|
||||
bg10 = TextTag{draw = function(c, i, text) graphics.set_color(bg[10]) end},
|
||||
bgm2 = TextTag{draw = function(c, i, text) graphics.set_color(bg[-2]) end},
|
||||
light_bg = TextTag{draw = function(c, i, text) graphics.set_color(bg[5]) end},
|
||||
fg = TextTag{draw = function(c, i, text) graphics.set_color(fg[0]) end},
|
||||
fgm5 = TextTag{draw = function(c, i, text) graphics.set_color(fg[-5]) end},
|
||||
|
@ -511,6 +514,8 @@ global_text_tags = {
|
|||
bluem5 = TextTag{draw = function(c, i, text) graphics.set_color(blue[-5]) end},
|
||||
blue25 = TextTag{draw = function(c, i, text) graphics.set_color(blue2[5]) end},
|
||||
blue2m5 = TextTag{draw = function(c, i, text) graphics.set_color(blue2[-5]) end},
|
||||
yellow25 = TextTag{draw = function(c, i, text) graphics.set_color(yellow2[5]) end},
|
||||
yellow2m5 = TextTag{draw = function(c, i, text) graphics.set_color(yellow2[-5]) end},
|
||||
redm5 = TextTag{draw = function(c, i, text) graphics.set_color(red[-5]) end},
|
||||
orangem5 = TextTag{draw = function(c, i, text) graphics.set_color(orange[-5]) end},
|
||||
purplem5 = TextTag{draw = function(c, i, text) graphics.set_color(purple[-5]) end},
|
||||
|
|
78
todo
78
todo
|
@ -1,24 +1,24 @@
|
|||
Shop Update
|
||||
New units
|
||||
Assists (2/4) - +25/50% assist buff effectiveness
|
||||
Ringmaster (tier 4 assist, nuker)
|
||||
Absorber (tier 2 assist, warrior)
|
||||
Pardoner (tier 3 assist, mercenary)
|
||||
Oracle (tier 1 assist)
|
||||
Seraph (tier 2 assist, healer)
|
||||
Mercenaries (3/3) - enemies occasionally drop pieces of gold
|
||||
Treasure Hunter (tier 1 mercenary)
|
||||
Merchant (tier 2 mercenary)
|
||||
Pardoner (tier 3 assist, mercenary)
|
||||
Gambler (tier 4 mercenary, rogue)
|
||||
* Mercenaries (2/4) - +10/20% chance for enemies to drop gold on death
|
||||
* Treasure Hunter (tier 1 mercenary) - picking up gold releases 4 homing projectiles that deal X damage, Lv.3 - release 8 homing projectiles instead and they pierce twice
|
||||
* Merchant (tier 2 mercenary) - gain +1 interest for every 10 gold, Lv.3 - your first item reroll is always free
|
||||
* Usurer (tier 3 curser, mercenary, voider) - curses 3 nearby enemies indefinitely with debt, dealing X damage over time, Lv.3 - if the same enemy is cursed 3 times it takes 50X damage
|
||||
* Gambler (tier 3 mercenary, sorcerer) - deal 2X damage to a single random enemy where X is how much gold you have, Lv.3 effect - 60%/40%/20% chance to cast the attack 2/3/4 times
|
||||
* Thief (tier 4 mercenary, rogue) - throws a knife that deals 2X damage and chains 5 times, Lv.3 - if the knife crits it deals 10X damage, chains 10 times and grants 1 gold
|
||||
|
||||
Shop changes
|
||||
Owned units highlighted in shop
|
||||
Fix highlight colors and highlight reserve
|
||||
Shop level up
|
||||
Remove level 3 units from rotation
|
||||
|
||||
Item changes
|
||||
Sorcerer items
|
||||
Mercenary items
|
||||
|
||||
Unit changes
|
||||
Launcher - remove
|
||||
Beastmaster
|
||||
|
||||
QoL
|
||||
* Added sorcerer achievement
|
||||
|
@ -28,7 +28,7 @@ Shop Update
|
|||
* Added mouse follow control mode
|
||||
* The cursor is now invisible during waves, unless mouse follow mode is enabled
|
||||
Options menu from buy screen
|
||||
Add visuals for defensive ouroboros, divine intervention, fairy buff
|
||||
Add visuals for tank attack
|
||||
|
||||
Balance
|
||||
* Decreased level 25 boss movement speed
|
||||
|
@ -38,34 +38,43 @@ Shop Update
|
|||
* Fixed a bug where enemy critters would sometimes be unkillable
|
||||
* Fixed a rare crash involving broken enemy critter state
|
||||
* Fixed text for the illusionist's Lv.3 effect going outside the screen
|
||||
* Fixed a rare crash when hovering over your owned in the shop
|
||||
* Fixed a crash when hovering over the Lich in the shop due to playing with a save before the sorcerer update
|
||||
* Fixed a crash when warden's force field would spawn on top of enemies
|
||||
* Fixed a crash when a volcano would spawn on top of enemies
|
||||
* Fixed a crash when a pet would spawn on top of enemies
|
||||
* Fixed a bug where the maximum number of units would be wrong on certain conditions
|
||||
* Fixed a crash when clicking too fast after unpausing the game
|
||||
Fix bug where quitting on level 2 arena goes back to level 1 shop
|
||||
Fix fullscreen with different resolutions that don't scale properly
|
||||
Fix enemies still spawning after arena clear (this happens with the extra enemy spawns that were blocked earlier)
|
||||
https://i.imgur.com/ieVqYNI.png
|
||||
https://i.imgur.com/3JCeFuZ.png
|
||||
https://i.imgur.com/cvC1TBz.png
|
||||
|
||||
Sacrifice Update
|
||||
New mechanics
|
||||
Sacrifice units to level items up
|
||||
New items
|
||||
https://steamcommunity.com/app/915310/discussions/0/3106901028662504698/
|
||||
Reworked items
|
||||
Items shouldn't just be more powerful versions of other items
|
||||
Items should have drawbacks
|
||||
Items that apply to a position on the snake (a good middle step between applying them to individual units like in Underlords)
|
||||
New units
|
||||
Nocturnals/Darks/??? (3/6)
|
||||
Shadowmancer
|
||||
Necromancer
|
||||
Demonologist
|
||||
Demon
|
||||
Lich
|
||||
Lifestealer
|
||||
Zombie
|
||||
QoL
|
||||
Current items visible on item selection screen
|
||||
Endless mode
|
||||
Volume slider
|
||||
Add visuals for defensive ouroboros, divine intervention, fairy buff
|
||||
|
||||
Melee Update
|
||||
New Units
|
||||
Guardians - https://i.imgur.com/Ynu5Cdw.png
|
||||
Assists (2/4) -
|
||||
Ringmaster (tier 4 assist, nuker) - +15% to all stats to adjacent units, Lv.3 effect - create a cross that deals AoE damage 5 times for 10 seconds
|
||||
Absorber (tier 2 assist, warrior) - absorbs 50% damage from adjacent units, Lv.3 effect - absorbs 75% damage from adjacent units and gives the absorber +25% defense
|
||||
Pardoner (tier 3 assist, mercenary) -
|
||||
Oracle (tier 1 assist) - +10% dodge chance to adjacent units, Lv.3 effect - +20% dodge chance to adjacent units
|
||||
Seraph (tier 2 assist, healer) - periodically chooses 1 random unit and gives it +100% defense for 6 seconds, Lv.3 - choose 2 units instead
|
||||
|
||||
|
||||
---
|
||||
|
@ -83,14 +92,15 @@ Hexblaster? - curser that consumes curses to deal damage
|
|||
Bench? - https://i.imgur.com/B1gNVKk.png
|
||||
Balance option for when there are more sets - https://i.imgur.com/JMynwbL.png
|
||||
Negative effect: colliding with yourself kills one of your units
|
||||
Go through this later https://i.imgur.com/4t7NA32.png <- lots of good improvements
|
||||
https://i.imgur.com/bxfvA7g.png
|
||||
|
||||
|
||||
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
|
||||
Key rebinding (for non-QWERTY keyboards)
|
||||
StS-like map with nodes, node types:
|
||||
StS-like map with nodes, node types:
|
||||
Arena
|
||||
Elite
|
||||
Boss
|
||||
|
@ -100,8 +110,18 @@ StS-like map with nodes, node types:
|
|||
Text + reward
|
||||
Training grounds (upgrade unit)
|
||||
Tavern (heal units)
|
||||
|
||||
Units die permanently when they die (dead units can be stored in bench to be revived later)
|
||||
Units can have items attached to them like in Underlords
|
||||
Unit item ideas:
|
||||
Units die permanently when they die (dead units can be stored in bench to be revived later)
|
||||
Units can have items attached to them like in Underlords
|
||||
Unit item ideas:
|
||||
This unit's projectiles pierce/chain/fork/seek/split/stun/etc
|
||||
This unit is a [class]
|
||||
New stat system:
|
||||
All stats are values from 1 to 10 (can be lower than 1 or higher than due to debuffs/buffs only) that represent consistent internal values between all units
|
||||
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
|
||||
|
||||
|
|
Loading…
Reference in New Issue