From 97416c5d78b4771efe2478f169ce6c494cb3fb1e Mon Sep 17 00:00:00 2001 From: a327ex Date: Fri, 25 Jun 2021 01:21:07 -0300 Subject: [PATCH] Orb update 3/4 --- arena.lua | 4 +- assets/images/blessing.png | Bin 0 -> 278 bytes assets/images/divine_barrage.png | Bin 0 -> 465 bytes assets/images/explorer.png | Bin 0 -> 392 bytes assets/images/haste.png | Bin 0 -> 480 bytes assets/images/orbitism.png | Bin 0 -> 470 bytes assets/images/psychosense.png | Bin 0 -> 524 bytes assets/images/psychosink.png | Bin 0 -> 512 bytes assets/images/psyker_orbs.png | Bin 0 -> 446 bytes assets/images/rearm.png | Bin 0 -> 468 bytes assets/images/summon_instability.png | Bin 0 -> 376 bytes assets/images/taunt.png | Bin 0 -> 439 bytes buy_screen.lua | 18 ++- enemies.lua | 10 +- main.lua | 104 +++++++++---- player.lua | 221 +++++++++++++++++++++++---- todo | 110 ++++++------- 17 files changed, 348 insertions(+), 119 deletions(-) create mode 100644 assets/images/blessing.png create mode 100644 assets/images/divine_barrage.png create mode 100644 assets/images/explorer.png create mode 100644 assets/images/haste.png create mode 100644 assets/images/orbitism.png create mode 100644 assets/images/psychosense.png create mode 100644 assets/images/psychosink.png create mode 100644 assets/images/psyker_orbs.png create mode 100644 assets/images/rearm.png create mode 100644 assets/images/summon_instability.png create mode 100644 assets/images/taunt.png diff --git a/arena.lua b/arena.lua index 25b32d4..b9f71fb 100644 --- a/arena.lua +++ b/arena.lua @@ -377,7 +377,7 @@ function Arena:update(dt) 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom', 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', - 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' + 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance', 'blessing', 'haste', 'divine_barrage', 'orbitism', 'psyker_orbs', 'psychosense', 'rearm', 'taunt', 'summon_instability', } max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') @@ -798,7 +798,7 @@ function Arena:die() 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom', 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', - 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' + 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance', 'blessing', 'haste', 'divine_barrage', 'orbitism', 'psyker_orbs', 'psychosense', 'rearm', 'taunt', 'summon_instability', } max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') diff --git a/assets/images/blessing.png b/assets/images/blessing.png new file mode 100644 index 0000000000000000000000000000000000000000..c54ee4c0341fe4dee44ca4470495636a24554ba7 GIT binary patch literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^8bEBr!3HEncK&z(q!^2X+?^QKos)S9a~60+7BevL9R^{>VM4R<%s^Y1!yz)(xIXtt_f^rees;+|H_ zn#?PoGViYo{9jhjE%SZjXR~JAoU|C>K1tSdeA1T1gX literal 0 HcmV?d00001 diff --git a/assets/images/divine_barrage.png b/assets/images/divine_barrage.png new file mode 100644 index 0000000000000000000000000000000000000000..8ce2303f6c42146fabd456be7c527b3e42f22fc4 GIT binary patch literal 465 zcmV;?0WSWDP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0cJ@=K~!i%?V5`U zgD?z5b^rg*ZUF_YNqdvtJ{UbP1flWtCY8aqAIGuH%;&sL%Mz@mr=SeGd*FKs-o;#! zJp?r&SaReHLXzu{{MgT{Mlr>e;7K^eo(bk8O%OrZA^chhV%9GS-WM_?-6`e-HKCSC zsv?X{JChA zAdQxSlv!j5Hf?<>NIiiJ&;+9?Rd1LzgU#C9@{mwif*GLsoH4=2Jg*klf(o)<;BdWE zaL6~78?Wb&XtAps9zk}SAvD2Un=MJ}ep)NHN%gsr7I#h35-c5-h@?9`A(tRiGMswp zr?7Bg2iYJ>GgwNomSTP6khGG7>Y}HZEeY2{1qGI*tByxdkm5C>?zLXQi-=@sV^P6w z)ChVK36I5JCnzAvgwqok35tLwVcmDJ{+3e960Bu%!EO5jxnnhKh3BqG00000NkvXX Hu0mjfpJTsd literal 0 HcmV?d00001 diff --git a/assets/images/explorer.png b/assets/images/explorer.png new file mode 100644 index 0000000000000000000000000000000000000000..a9bab31f985c19d04530835b72fecd250a860797 GIT binary patch literal 392 zcmV;30eAk1P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0Ub$1K~!i%?Ud~j zf*=q@wfBGL5{GTl*slxA(6r}|mU8bA&@D-lBw3ri9$}sb^|Z-;P){MC!I~5YBI_D} zirw*unr<8=cE=*B-Vh~6Xp-W^XgNZXWG{H+xPlQGa4;9hfo6XF5g|t)*)Bm;?2f17 z@?(Y^VeNX<XU-mB=~QPhO0HnZR%fskB0RWA%SY>7b`O&HDX2X~BwEMvZ*dCt zl7hXYU@xK|_kA3R)^Q5X_#k^Br{CX$k;`n!zAUXYVDvVyb}hfeU$Zh}7Cjv`&; zvYSN_l4vGdVhJQT*%2AyEO-if;N%LTU?Eykk}If!g(yi)u3!=*Mu}R)2$vv%ih9Hd mNbnO)7LiJlBuSFLVcT9I?yEW5KJ35%0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0d+}4K~!i%?V5qA z!Y~X)=llPEo^N19vn9E?H|k(LPy|`p)0-Aycw5(XIWvEc&(ksmRW2#G-MTSkx&^J2 zEZHg8l9;7SFp`tRzjaAy$qqquaY|AZl-h@&2r_cz8dgwAu2lPpOLBXR78pS^fk+Zg zu_~BNTuBa+tOzo4nQ$tJ3M$D}Qr*#UNf3ePnQ-%nAaqtl+%+;mrL`8S)sbMQ+@RcQ zPw*3R2)lKeOOmB9hDT|0M}o}cM^dchTOE_2B@$sJpBxE#g-72<0xWOqcnMk=XtxfP z6nE<=FORB))F#<8$n1(rf)S)6|EFAA70edc+L*PnBv}zet&Ol}yrwP0*8jr6OsceG&asPtHxiP~J4s z;;nd$4(vSPyzCiNfj9jtL6|A1G6hwppvn|fxr|`?lf`nW7TXkCQk{S7Q8~HbvfKd_ WW=m$hM(#KO0000a~60+7BevL9R^{>_8Ws1_I1n!+J zQNIm?b$s8izcF_Ui|%D_*2{^GZv;(`E}as($*U#7SIy;<;p~(MC6?@Nn6ZFdbvU2n@3Zkzs!kuU&LptyjgmB!L@U&OEdEnHLu#l%9$VC8`N@1c@3wV z$E>V^rl2ks(;doPcgkPJdIwBa2?#8axgGrbC$FZAqp3hHuaak#V70>RB}z$U~)a{m<6Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0ij7mK~!i%<&+DK z!!QU1)87Bi*;18V!p8gz#BE24qEv1?en4*fzHcjYf8Cd5c|onjp8DTj_f(_=z0C>h z(;K>?#Ho@a!Sp1eeB~6U4$G_{$WWp5Nj?*d^dA>ZC-GM^X3nxNEQrHA5z zl1RxAXq+X;MJ!@vDUM1EQg~g8wFi-QVXvS>Ntq*pttnLi}J3$~d#R@?H zBvV9Z1TAHr7OhH<6Bg|f3^OAbNyPo1sNhsz31BPyzQ3ZxFg(%#jSk0ue?DgmQn8ee z`Bg)5DC2`ss_BBJO$q9niUeU(iyR`ZjS8mpmxY-GTO?-$J!K42(Sv6|+IYE$3R=@U zlX8hh1SL7#+$AB=RbmPp(A>XXK`lKEvlwzkf>xdf_6W|VXXVhpToC)iQwooqwDur| zP(dz5pFP4FR05^`i6JN$6&Su)L6o9sJqY5N>A69{ND|TXTxbbi4i)qy0&82!A5D;o zl}cunxJ;4@wluznw;B>;sZY*qf*@Af79&AvQPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0hLKaK~!i%?U;?K z!!QU&+r9rg_u{A}wTVB`MhEvm*w~i!&-Imr|Y;Kn@-^1-2PiIt4iErI^2w)bb4GNL?%e3W+Web zGD$?ZW@M$o2d3SGkY;FyOiMVG#PM$sbWZ_A)$PydX*q|PlWey zA=h(Gko!_C^uiL4&(Hi=&~Bh&+`i!Gvm0k;H)bx2wyu@G@i&{A3|6PD_z2Q{T#LNCEGasU-9B?q*E<>UbE6sO1mD9ELk zCI@H}Oalc+DW#?dvqf*Ob-@i+x`GCqE%JDy;D#C0000a~60+7BevL9R^{>E zJYH1LG_hAcbA`xEp~+VYw<>ckTCM;3&C}UOtoYMTX{7d7Pn((fzVWKD$Lup*;>o-H zuPkieztd**@AJwL8#a3yY41N$!Z~f~Q}OkZT8pdiSFvios7bZ#&YTplH=CzIRGJ+vdB8 g2N5dD9UF7?`Rn`wekhi40>hla)78&qol`;+06ojM3IG5A literal 0 HcmV?d00001 diff --git a/assets/images/rearm.png b/assets/images/rearm.png new file mode 100644 index 0000000000000000000000000000000000000000..8dcefa90883281679e652f0b0b229c5306df3dc3 GIT binary patch literal 468 zcmeAS@N?(olHy`uVBq!ia0vp^8bEBr!3HEncK&z(q!^2X+?^QKos)S9a~60+7BevL9R^{>3(E4!K`~T-k`7Htt z`8+F9+m=u#kZ5}H`3=2&=RVuayL12f&yBeXx7jxR$&woPDX0STUtc+-jZTfH|ogx^>jz?+d6 zrf`>k{$94-6O_-~*U*)_KKPy9BmtBt(j%n1XU2!w~PG`>^f7|oB**2bN zu46|nT!xY;!UlvLz zbjd}{wcvHJsA1E19KaqRwNTC`L_Hv@(Nnu&E!bVQG8HoU+m)?K-*~zT0b_!})78&q Iol`;+0AgIn1^@s6 literal 0 HcmV?d00001 diff --git a/assets/images/summon_instability.png b/assets/images/summon_instability.png new file mode 100644 index 0000000000000000000000000000000000000000..3afe65ff47e021dc9c23644de747f7f48d5f4428 GIT binary patch literal 376 zcmV-;0f+vHP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0S!q+K~!i%?U;cI z!ypVq+x`DPJA^t$Xf(;)SiyTBh0ez3>DsMlYwdV4uj}|&B#6Qk?3;Ns8Z1F8MU&im z4^mRxIzb8&M3Eqh1W_c2B0&_E;CUS_@DGMxC+LZX*=i5kwBYnQ`d^HK2=?eB@sEC` zrK$+p!Da*7&(e}vL2rP&^O?Rb8Nu}I8AJsua_2MA=4g`oKrnYKd)%lvMS85JiF*$MFW~ WPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0Zd6mK~!i%?U>OH zf-nq4!Thv9>ow*YE$TUF`S^oy1%=8Ye>QyecTj>TayJ-!6K=OUUCK* zNqBSW8H^@`#VXl9`H#UUp_chfqLNiXD~Qx;MUYtt%Q7u4V(hNqwWuH~))J0`2xiGu zLh+)4*>V*(Ze&QJa%Tgeto@L2A1uLp39QdTc!E|1kmTOA-8>l;911JQwhdlq2}Tci z7N_}`3bNI!Kqn>C?0wSvn0cDm?0^_Sy6cHqyL+^gpB*(P^O^D h6jYglDmNEgmN(@SPEO{&>@ffU002ovPDHLkV1h6^wTS=# literal 0 HcmV?d00001 diff --git a/buy_screen.lua b/buy_screen.lua index ea90511..f6d5402 100644 --- a/buy_screen.lua +++ b/buy_screen.lua @@ -144,7 +144,7 @@ function BuyScreen:on_enter(from, level, units, passives, shop_level, shop_xp) 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom', 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', - 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' + 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance', 'blessing', 'haste', 'divine_barrage', 'orbitism', 'psyker_orbs', 'psychosense', 'rearm', 'taunt', 'summon_instability', } max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') @@ -547,7 +547,7 @@ function RestartButton:update(dt) 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom', 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', - 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' + 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance', 'blessing', 'haste', 'divine_barrage', 'orbitism', 'psyker_orbs', 'psychosense', 'rearm', 'taunt', 'summon_instability', } system.save_state() main:add(BuyScreen'buy_screen') @@ -1836,7 +1836,19 @@ function ClassIcon:draw() graphics.rectangle(self.x, self.y, 16, 24, 4, 4, self.highlighted and fg[0] or ((n >= i) and class_colors[self.class] or bg[3])) _G[self.class]:draw(self.x, self.y, 0, 0.3, 0.3, 0, 0, self.highlighted and fg[-5] or ((n >= i) and _G[class_color_strings[self.class]][-5] or bg[10])) graphics.rectangle(self.x, self.y + 26, 16, 16, 3, 3, self.highlighted and fg[0] or bg[3]) - if i == 2 and not k then + if i == 1 then + if self.highlighted then + graphics.rectangle(self.x, self.y + 26, 3, 9, nil, nil, (n >= 1) and fg[-5] or fg[-10]) + else + graphics.rectangle(self.x, self.y + 26, 3, 9, nil, nil, (n >= 1) and class_colors[self.class] or bg[10]) + end + if next_n then + if next_n == 1 then + graphics.rectangle(self.x, self.y + 26, 3, 9, nil, nil, self.flash and class_colors[self.class] or bg[10]) + end + end + + elseif i == 2 and not k then if self.highlighted then graphics.line(self.x - 3, self.y + 20, self.x - 3, self.y + 25, (n >= 1) and fg[-5] or fg[-10], 3) graphics.line(self.x - 3, self.y + 27, self.x - 3, self.y + 32, (n >= 2) and fg[-5] or fg[-10], 3) diff --git a/enemies.lua b/enemies.lua index 5b09a6a..cd9e10b 100644 --- a/enemies.lua +++ b/enemies.lua @@ -307,11 +307,13 @@ function Seeker:update(dt) self:set_angular_damping(0) end else + local target = main.current.player + if self.taunted then target = self.taunted end + if self.taunted and self.taunted.dead then target = main.current.player; self.taunted = nil end if self.headbutt_charging or self.shooting then self:set_damping(10) - self:rotate_towards_object(main.current.player, 0.5) + self:rotate_towards_object(target, 0.5) elseif not self.headbutting then - local player = main.current.player if self.boss then local enemies = main.current.main:get_objects_by_classes(main.current.enemies) local x, y = 0, 0 @@ -323,12 +325,12 @@ function Seeker:update(dt) x = x/#enemies y = y/#enemies else - x, y = player.x, player.y + x, y = target.x, target.y end self:seek_point(x, y) self:wander(10, 250, 3) else - self:seek_point(player.x, player.y) + self:seek_point(target.x, target.y) self:wander(50, 100, 20) end self:steering_separate(16, main.current.enemies) diff --git a/main.lua b/main.lua index 2d55e73..cb9a782 100644 --- a/main.lua +++ b/main.lua @@ -146,6 +146,7 @@ function init() voider = Image('voider') sorcerer = Image('sorcerer') mercenary = Image('mercenary') + explorer = Image('explorer') star = Image('star') arrow = Image('arrow') centipede = Image('centipede') @@ -202,6 +203,15 @@ function init() berserking = Image('berserking') unwavering_stance = Image('unwavering_stance') unrelenting_stance = Image('unrelenting_stance') + blessing = Image('blessing') + haste = Image('haste') + divine_barrage = Image('divine_barrage') + orbitism = Image('orbitism') + psyker_orbs = Image('psyker_orbs') + psychosense = Image('psychosense') + rearm = Image('rearm') + taunt = Image('taunt') + summon_instability = Image('summon_instability') class_colors = { ['warrior'] = yellow[0], @@ -219,6 +229,7 @@ function init() ['voider'] = purple[0], ['sorcerer'] = blue2[0], ['mercenary'] = yellow2[0], + ['explorer'] = fg[0], } class_color_strings = { @@ -237,6 +248,7 @@ function init() ['voider'] = 'purple', ['sorcerer'] = 'blue2', ['mercenary'] = 'yellow2', + ['explorer'] = 'fg', } character_names = { @@ -411,7 +423,7 @@ function init() } character_classes = { - ['vagrant'] = {'psyker', 'ranger', 'warrior'}, + ['vagrant'] = {'explorer', 'psyker'}, ['swordsman'] = {'warrior'}, ['wizard'] = {'mage', 'nuker'}, ['magician'] = {'mage'}, @@ -468,7 +480,7 @@ function init() } character_class_strings = { - ['vagrant'] = '[fg]Psyker, [green]Ranger, [yellow]Warrior', + ['vagrant'] = '[fg]Explorer, Psyker', ['swordsman'] = '[yellow]Warrior', ['wizard'] = '[blue]Mage, [red]Nuker', ['magician'] = '[blue]Mage', @@ -560,7 +572,7 @@ function init() ['hunter'] = function(lvl) return '[fg]shoots an arrow that deals [yellow]' .. get_character_stat('hunter', lvl, 'dmg') .. '[fg] damage and has a [yellow]20%[fg] chance to summon a pet' end, ['chronomancer'] = function(lvl) return '[yellow]+20%[fg] attack speed to all allies' end, ['spellblade'] = function(lvl) return '[fg]throws knives that deal [yellow]' .. get_character_stat('spellblade', lvl, 'dmg') .. '[fg] damage, pierce and spiral outwards' end, - ['psykeeper'] = function(lvl) return '[fg]all damage taken is stored up to [yellow]50%[fg] max HP and distributed as healing to all allies' end, + ['psykeeper'] = function(lvl) return '[fg]creates [yellow]1[fg] healing orb every time the psykeeper takes [yellow]20%[fg] of its max HP in damage' end, ['engineer'] = function(lvl) return '[fg]drops sentries that shoot bursts of projectiles, each dealing [yellow]' .. get_character_stat('engineer', lvl, 'dmg') .. '[fg] damage' end, ['plague_doctor'] = function(lvl) return '[fg]creates an area that deals [yellow]' .. get_character_stat('plague_doctor', lvl, 'dmg') .. '[fg] damage per second' end, ['barbarian'] = function(lvl) return '[fg]deals [yellow]' .. get_character_stat('barbarian', lvl, 'dmg') .. '[fg] AoE damage and stuns enemies hit for [yellow]4[fg] seconds' end, @@ -599,7 +611,7 @@ function init() } character_effect_names = { - ['vagrant'] = '[fg]Champion', + ['vagrant'] = '[fg]Experience', ['swordsman'] = '[yellow]Cleave', ['wizard'] = '[blue]Magic Missile', ['magician'] = '[blue]Ethereal Form', @@ -656,7 +668,7 @@ function init() } character_effect_names_gray = { - ['vagrant'] = '[light_bg]Champion', + ['vagrant'] = '[light_bg]Experience', ['swordsman'] = '[light_bg]Cleave', ['wizard'] = '[light_bg]Magic Missile', ['magician'] = '[light_bg]Ethereal Form', @@ -732,7 +744,7 @@ function init() ['hunter'] = function() return '[fg]summons [yellow]3[fg] pets and the pets ricochet off walls once' 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, + ['psykeeper'] = function() return '[fg]deal [yellow]double[fg] the damage taken by the psykeeper to all enemies' end, ['engineer'] = function() return '[fg]drops [yellow]2[fg] additional turrets and grants all turrets [yellow]+50%[fg] damage and attack speed' end, ['plague_doctor'] = function() return '[fg]nearby enemies take an additional [yellow]' .. get_character_stat('plague_doctor', 3, 'dmg') .. '[fg] damage per second' end, ['barbarian'] = function() return '[fg]stunned enemies also take [yellow]100%[fg] increased damage' end, @@ -789,7 +801,7 @@ function init() ['hunter'] = function() return '[light_bg]summons 3 pets and the pets ricochet off walls once' 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, + ['psykeeper'] = function() return '[light_bg]deal double the damage taken by the psykeeper to all enemies' end, ['engineer'] = function() return '[light_bg]drops 2 additional turrets and grants all turrets +50% damage and attack speed' end, ['plague_doctor'] = function() return '[light_bg]nearby enemies take an additional ' .. get_character_stat('plague_doctor', 3, 'dmg') .. ' damage per second' end, ['barbarian'] = function() return '[light_bg]stunned enemies also take 100% increased damage' end, @@ -899,6 +911,7 @@ function init() ['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}, + ['explorer'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 1.25}, ['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}, @@ -929,7 +942,7 @@ function init() ['enchanter'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+15%[light_bg]/[' .. ylb2(lvl) .. ']+25% [fg]damage to all allies' end, ['nuker'] = function(lvl) return '[' .. ylb1(lvl) .. ']3[light_bg]/[' .. ylb2(lvl) .. ']6 [fg]- [' .. ylb1(lvl) .. ']+15%[light_bg]/[' .. ylb2(lvl) .. ']+25% [fg]area damage and size to allied nukers' end, ['conjurer'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+25%[light_bg]/[' .. ylb2(lvl) .. ']+50% [fg]summon damage and duration' end, - ['psyker'] = function(lvl) return '[fg]create a piercing, damaging orb around each psyker, it inherits damage from its target' end, + ['psyker'] = function(lvl) return '[fg]create a piercing, damaging orb around each psyker' end, ['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, @@ -939,6 +952,7 @@ function init() ylb1(lvl) .. ']4[light_bg]/[' .. ylb2(lvl) .. ']3[light_bg]/[' .. ylb3(lvl) .. ']2[fg] attacks' end, ['mercenary'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+8%[light_bg]/[' .. ylb2(lvl) .. ']+16% [fg]chance for enemies to drop gold on death' end, + ['explorer'] = function(lvl) return '[yellow]+15%[fg] attack speed and damage per active set to allied explorers' end, } tier_to_characters = { @@ -1030,6 +1044,7 @@ function init() local voiders = 0 local sorcerers = 0 local mercenaries = 0 + local explorers = 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 @@ -1047,10 +1062,11 @@ function init() 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 + if unit_class == 'explorer' then explorers = explorers + 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, mercenary = mercenaries} + enchanter = enchanters, psyker = psykers, curser = cursers, forcer = forcers, swarmer = swarmers, voider = voiders, sorcerer = sorcerers, mercenary = mercenaries, explorer = explorers} end get_class_levels = function(units) @@ -1060,7 +1076,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' or class == 'mercenary' then + elseif class == 'healer' or class == 'conjurer' or class == 'enchanter' 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 @@ -1069,6 +1085,9 @@ function init() elseif number_of_units >= 4 then return 2 elseif number_of_units >= 2 then return 1 else return 0 end + elseif class == 'explorer' or class == 'psyker' then + if number_of_units >= 1 then return 1 + else return 0 end end end return { @@ -1087,6 +1106,7 @@ function init() 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'), + explorer = units_to_class_level(units_per_class.explorer, 'explorer'), } end @@ -1107,13 +1127,14 @@ function init() ['healer'] = function(units) return 2, 4, nil, get_number_of_units_per_class(units).healer end, ['conjurer'] = function(units) return 2, 4, nil, get_number_of_units_per_class(units).conjurer end, ['enchanter'] = function(units) return 2, 4, nil, get_number_of_units_per_class(units).enchanter end, - ['psyker'] = function(units) return 2, 4, nil, get_number_of_units_per_class(units).psyker end, + ['psyker'] = function(units) return 1, 1, nil, get_number_of_units_per_class(units).psyker end, ['curser'] = function(units) return 2, 4, nil, get_number_of_units_per_class(units).curser end, ['forcer'] = function(units) return 2, 4, nil, get_number_of_units_per_class(units).forcer end, ['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, + ['explorer'] = function(units) return 1, 1, nil, get_number_of_units_per_class(units).explorer end, } passive_names = { @@ -1171,6 +1192,15 @@ function init() ['berserking'] = 'Berserking', ['unwavering_stance'] = 'Unwavering Stance', ['unrelenting_stance'] = 'Unrelenting Stance', + ['blessing'] = 'Blessing', + ['haste'] = 'Haste', + ['divine_barrage'] = 'Divine Barrage', + ['orbitism'] = 'Orbitism', + ['psyker_orbs'] = 'Psyker Orbs', + ['psychosense'] = 'Psychosense', + ['rearm'] = 'Rearm', + ['taunt'] = 'Taunt', + ['summon_instability'] = 'Summon Instability', } passive_descriptions = { @@ -1216,9 +1246,9 @@ function init() ['magnify'] = '[yellow]+20/35/50%[fg] area size', ['echo_barrage'] = '[yellow]10/20/30%[fg] chance to create [yellow]1/2/3[fg] secondary AoEs on AoE hit', ['unleash'] = '[fg]all nukers gain [yellow]+1%[fg] area size and damage every second', - ['reinforce'] = '[yellow]+10/20/30%[fg] damage, defense and aspd to all allies with at least one enchanter', + ['reinforce'] = '[yellow]+10/20/30%[fg] damage, defense and aspd to all allies if you have >=1 enchanter', ['payback'] = '[yellow]+2/5/8%[fg] damage to all allies whenever an enchanter is hit', - ['enchanted'] = '[yellow]+10/20/30%[fg] attack speed to a random unit with at least two enchanters', + ['enchanted'] = '[yellow]+33/66/99%[fg] attack speed to a random unit if you have >=2 enchanters', ['freezing_field'] = '[fg]creates an area that slows enemies by [yellow]50%[fg] for [yellow]2[fg] seconds on sorcerer spell repeat', ['burning_field'] = '[fg]creates an area that deals [yellow]30[fg] dps for [yellow]2[fg] seconds on sorcerer spell repeat', ['gravity_field'] = '[fg]creates an area that pulls enemies in for [yellow]1[fg] seconds on sorcerer spell repeat', @@ -1228,6 +1258,15 @@ function init() ['berserking'] = '[fg]all warriors have up to [yellow]+50/75/100%[fg] attack speed based on missing HP', ['unwavering_stance'] = '[fg]all warriors gain [yellow]+4/8/12%[fg] defense every [yellow]5[fg] seconds', ['unrelenting_stance'] = '[yellow]+2/5/8%[fg] defense to all allies whenever a warrior is hit', + ['blessing'] = '[yellow]+10/20/30%[fg] healing effectiveness', + ['haste'] = '[yellow]+50%[fg] movement speed that decays over [yellow]4[fg] seconds on healing orb pick up', + ['divine_barrage'] = '[yellow]20/40/60%[fg] chance to release a ricocheting barrage on healing orb pick up', + ['orbitism'] = '[yellow]+33/66/99%[fg] orb movement speed', + ['psyker_orbs'] = '[yellow]+1/2/3[fg] psyker orbs', + ['psychosense'] = '[yellow]+33/66/99%[fg] orb range', + ['rearm'] = '[fg]summons repeat their attacks once', + ['taunt'] = '[yellow]10/20/30% chance for summons to taunt nearby enemies on attack', + ['summon_instability'] = '[fg]summons explode when disappearing, dealing [yellow]100/150/200%[fg] damage', } local ts = function(lvl, a, b, c) return '[' .. ylb1(lvl) .. ']' .. tostring(a) .. '[light_bg]/[' .. ylb2(lvl) .. ']' .. tostring(b) .. '[light_bg]/[' .. ylb3(lvl) .. ']' .. tostring(c) .. '[fg]' end @@ -1274,9 +1313,9 @@ function init() ['magnify'] = function(lvl) return ts(lvl, '+20%', '35%', '50%') .. ' area size' end, ['echo_barrage'] = function(lvl) return ts(lvl, '10%', '20%', '30%') .. ' chance to create ' .. ts(lvl, '1', '2', '3') .. ' secondary AoEs on AoE hit' end, ['unleash'] = function(lvl) return '[fg]all nukers gain [yellow]+1%[fg] area size and damage every second' end, - ['reinforce'] = function(lvl) return ts(lvl, '+10%', '20%', '30%') .. ' damage, defense and aspd to all allies with at least one enchanter' end, + ['reinforce'] = function(lvl) return ts(lvl, '+10%', '20%', '30%') .. ' damage, defense and aspd to all allies if you have >=1 enchanter' end, ['payback'] = function(lvl) return ts(lvl, '+2%', '5%', '8%') .. ' damage to all allies whenever an enchanter is hit' end, - ['enchanted'] = function(lvl) return ts(lvl, '+10%', '20%', '30%') .. ' attack speed to a random unit with at least two enchanters' end, + ['enchanted'] = function(lvl) return ts(lvl, '+33%', '66%', '99%') .. ' attack speed to a random unit if you have >=2 enchanters' end, ['freezing_field'] = function(lvl) return '[fg]creates an area that slows enemies by [yellow]50%[fg] for [yellow]2[fg] seconds on sorcerer spell repeat' end, ['burning_field'] = function(lvl) return '[fg]creates an area that deals [yellow]30[fg] dps for [yellow]2[fg] seconds on sorcerer spell repeat' end, ['gravity_field'] = function(lvl) return '[fg]creates an area that pulls enemies in for [yellow]1[fg] seconds on sorcerer spell repeat' end, @@ -1286,6 +1325,15 @@ function init() ['berserking'] = function(lvl) return '[fg]all warriors have up to ' .. ts(lvl, '+50%', '75%', '100%') .. ' attack speed based on missing HP' end, ['unwavering_stance'] = function(lvl) return '[fg]all warriors gain ' .. ts(lvl, '+4%', '8%', '12%') .. ' defense every [yellow]5[fg] seconds' end, ['unrelenting_stance'] = function(lvl) return ts(lvl, '+2%', '5%', '8%') .. ' defense to all allies whenever a warrior is hit' end, + ['blessing'] = function(lvl) return ts(lvl, '+10%', '20%', '30%') .. ' healing effectiveness' end, + ['haste'] = function(lvl) return '[yellow]+50%[fg] movement speed that decays over [yellow]4[fg] seconds on healing orb pick up' end, + ['divine_barrage'] = function(lvl) return ts(lvl, '20%', '40%', '60%') .. ' chance to release a ricocheting barrage on healing orb pick up' end, + ['orbitism'] = function(lvl) return ts(lvl, '+33%', '66%', '99%') .. ' orb movement speed' end, + ['psyker_orbs'] = function(lvl) return ts(lvl, '+1', '2', '3') .. ' psyker orbs' end, + ['psychosense'] = function(lvl) return ts(lvl, '+33%', '66%', '99%') .. ' orb range' end, + ['rearm'] = function(lvl) return '[fg]summons repeat their attacks once' end, + ['taunt'] = function(lvl) return ts(lvl, '10%', '20%', '30%') .. ' chance for summons to taunt nearby enemies on attack' end, + ['summon_instability'] = function(lvl) return '[fg]summons explode when disappearing, dealing [yellow]100/150/200%[fg] damage' end, } level_to_tier_weights = { @@ -1473,7 +1521,7 @@ function init() unlevellable_items = { 'speed_3', 'damage_4', 'shoot_5', 'death_6', 'lasting_7', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'annihilation', 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'divine_punishment', 'unleash', 'freezing_field', 'burning_field', 'gravity_field', - 'magnetism', 'insurance', 'dividends' + 'magnetism', 'insurance', 'dividends', 'haste', 'rearm', } steam.userStats.requestCurrentStats() @@ -1486,10 +1534,8 @@ function init() main_song_instance = _G[random:table{'song1', 'song2', 'song3', 'song4', 'song5'}]:play{volume = 0.5} main = Main() - --[[ main:add(MainMenu'mainmenu') main:go_to('mainmenu') - ]]-- --[[ main:add(BuyScreen'buy_screen') @@ -1497,18 +1543,16 @@ function init() ]]-- -- main:go_to('buy_screen', 7, run.units or {}, {'unleash'}) + --[[ main:add(Arena'arena') - main:go_to('arena', 4, { - {character = 'psykeeper', level = 3}, - {character = 'vagrant', level = 1}, - {character = 'psychic', level = 1}, - {character = 'flagellant', level = 1}, - --[[ - {character = 'priest', level = 1}, - {character = 'cleric', level = 1}, - {character = 'fairy', level = 1}, - ]]-- - }, {}) + main:go_to('arena', 10, { + {character = 'illusionist', level = 2}, + -- {character = 'carver', level = 2}, + {character = 'engineer', level = 2}, + -- {character = 'saboteur', level = 2}, + -- {character = 'hunter', level = 2}, + }, {{passive = 'summon_instability', level = 3}}) + ]]-- --[[ main:add(Media'media') @@ -1678,7 +1722,7 @@ function open_options(self) 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom', 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', - 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' + 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance', 'blessing', 'haste', 'divine_barrage', 'orbitism', 'psyker_orbs', 'psychosense', 'rearm', 'taunt', 'summon_instability', } max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') diff --git a/player.lua b/player.lua index 7008da7..2d32abe 100644 --- a/player.lua +++ b/player.lua @@ -1002,7 +1002,7 @@ function Player:init(args) if enchanter_amount >= 2 then local unit = random:table(units) - unit.enchanted_aspd_m = (self.enchanted == 1 and 1.1) or (self.enchanted == 2 and 1.2) or (self.enchanted == 3 and 1.3) + unit.enchanted_aspd_m = (self.enchanted == 1 and 1.33) or (self.enchanted == 2 and 1.66) or (self.enchanted == 3 and 1.99) end end) @@ -1076,7 +1076,14 @@ function Player:init(args) self.t:after(0.5, function() local units = self:get_all_units() for _, unit in ipairs(units) do - if table.any(self.classes, function(v) return v == 'psyker' end) then + if table.any(unit.classes, function(v) return v == 'psyker' end) then + Projectile{group = main.current.main, x = unit.x + 24*math.cos(unit.r), y = unit.y + 24*math.sin(unit.r), color = fg[0], v = 200, dmg = unit.dmg, character = 'psyker', parent = unit} + end + end + + if self.psyker_orbs then + for i = 1, self.psyker_orbs do + local unit = random:table(units) Projectile{group = main.current.main, x = unit.x + 24*math.cos(unit.r), y = unit.y + 24*math.sin(unit.r), color = fg[0], v = 200, dmg = unit.dmg, character = 'psyker', parent = unit} end end @@ -1132,6 +1139,7 @@ function Player:update(dt) 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 class_levels.explorer >= 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 @@ -1156,10 +1164,8 @@ function Player:update(dt) elseif main.current.warrior_level == 0 then self.warrior_def_a = 0 end end - if main.current.healer_level == 2 then self.heal_effect_m = 1.3 - elseif main.current.healer_level == 1 then self.heal_effect_m = 1.15 - else self.heal_effect_m = 1 end - if self.blessing then self.heal_effect_m = self.heal_effect_m*1.2 end + self.heal_effect_m = 1 + if self.blessing then self.heal_effect_m = self.heal_effect_m*((self.blessing == 1 and 1.1) or (self.blessing == 2 and 1.2) or (self.blessing == 3 and 1.3)) end if table.any(self.classes, function(v) return v == 'nuker' end) then if main.current.nuker_level == 2 then self.nuker_area_size_m = 1.25; self.nuker_area_dmg_m = 1.25 @@ -1181,8 +1187,7 @@ function Player:update(dt) elseif main.current.enchanter_level == 1 then self.enchanter_dmg_m = 1.15 else self.enchanter_dmg_m = 1 end - --[[ - if table.any(self.classes, function(v) return v == 'psyker' end) then + if table.any(self.classes, function(v) return v == 'explorer' end) then local class_levels = get_class_levels(self:get_all_units()) local number_of_active_sets = 0 if class_levels.ranger >= 1 then number_of_active_sets = number_of_active_sets + 1 end @@ -1200,18 +1205,10 @@ function Player:update(dt) 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 - elseif main.current.psyker_level == 1 then - self.psyker_dmg_m = 1 + 0.10*number_of_active_sets - self.psyker_aspd_m = 1 + 0.10*number_of_active_sets - else - self.psyker_dmg_m = 1 - self.psyker_aspd_m = 1 - end + if class_levels.explorer >= 1 then number_of_active_sets = number_of_active_sets + 1 end + self.explorer_dmg_m = 1 + 0.15*number_of_active_sets + self.explorer_aspd_m = 1 + 0.15*number_of_active_sets end - ]]-- if main.current.forcer_level == 2 then self.knockback_m = 1.5 elseif main.current.forcer_level == 1 then self.knockback_m = 1.25 @@ -1283,13 +1280,19 @@ function Player:update(dt) self.flagellant_hp_m = 2 end + if self.haste then + if self.hasted then + self.haste_mvspd_m = math.remap(love.timer.getTime() - self.hasted, 0, 4, 1.5, 1) + else self.haste_mvspd_m = 1 end + end + self.buff_def_a = (self.warrior_def_a or 0) - self.buff_aspd_m = (self.chronomancer_aspd_m or 1)*(self.vagrant_aspd_m or 1)*(self.outlaw_aspd_m or 1)*(self.fairy_aspd_m or 1)*(self.psyker_aspd_m or 1)*(self.chronomancy_aspd_m or 1)*(self.awakening_aspd_m or 1)*(self.berserking_aspd_m or 1)*(self.reinforce_aspd_m or 1)*(self.squire_aspd_m or 1)*(self.speed_3_aspd_m or 1)*(self.last_stand_aspd_m or 1)*(self.enchanted_aspd_m or 1) - self.buff_dmg_m = (self.squire_dmg_m or 1)*(self.vagrant_dmg_m or 1)*(self.enchanter_dmg_m or 1)*(self.swordsman_dmg_m or 1)*(self.flagellant_dmg_m or 1)*(self.psyker_dmg_m or 1)*(self.ballista_dmg_m or 1)*(self.awakening_dmg_m or 1)*(self.reinforce_dmg_m or 1)*(self.payback_dmg_m or 1)*(self.immolation_dmg_m or 1)*(self.damage_4_dmg_m or 1)*(self.offensive_stance_dmg_m or 1)*(self.last_stand_dmg_m or 1)*(self.dividends_dmg_m or 1) + self.buff_aspd_m = (self.chronomancer_aspd_m or 1)*(self.vagrant_aspd_m or 1)*(self.outlaw_aspd_m or 1)*(self.fairy_aspd_m or 1)*(self.psyker_aspd_m or 1)*(self.chronomancy_aspd_m or 1)*(self.awakening_aspd_m or 1)*(self.berserking_aspd_m or 1)*(self.reinforce_aspd_m or 1)*(self.squire_aspd_m or 1)*(self.speed_3_aspd_m or 1)*(self.last_stand_aspd_m or 1)*(self.enchanted_aspd_m or 1)*(self.explorer_aspd_m or 1) + self.buff_dmg_m = (self.squire_dmg_m or 1)*(self.vagrant_dmg_m or 1)*(self.enchanter_dmg_m or 1)*(self.swordsman_dmg_m or 1)*(self.flagellant_dmg_m or 1)*(self.psyker_dmg_m or 1)*(self.ballista_dmg_m or 1)*(self.awakening_dmg_m or 1)*(self.reinforce_dmg_m or 1)*(self.payback_dmg_m or 1)*(self.immolation_dmg_m or 1)*(self.damage_4_dmg_m or 1)*(self.offensive_stance_dmg_m or 1)*(self.last_stand_dmg_m or 1)*(self.dividends_dmg_m or 1)*(self.explorer_dmg_m or 1) self.buff_def_m = (self.squire_def_m or 1)*(self.ouroboros_def_m or 1)*(self.unwavering_stance_def_m or 1)*(self.reinforce_def_m or 1)*(self.defensive_stance_def_m or 1)*(self.last_stand_def_m or 1)*(self.unrelenting_stance_def_m or 1) self.buff_area_size_m = (self.nuker_area_size_m or 1)*(self.magnify_area_size_m or 1)*(self.unleash_area_size_m or 1)*(self.last_stand_area_size_m or 1) self.buff_area_dmg_m = (self.nuker_area_dmg_m or 1)*(self.amplify_area_dmg_m or 1)*(self.unleash_area_dmg_m or 1)*(self.last_stand_area_dmg_m or 1) - self.buff_mvspd_m = (self.wall_rider_mvspd_m or 1)*(self.centipede_mvspd_m or 1)*(self.squire_mvspd_m or 1)*(self.last_stand_mvspd_m or 1) + 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.haste_mvspd_m or 1) self.buff_hp_m = (self.flagellant_hp_m or 1) self:calculate_stats() @@ -1879,14 +1882,14 @@ function Player:dot_attack(area, mods) end -function Player:barrage(r, n, pierce) +function Player:barrage(r, n, pierce, ricochet) 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, pierce = pierce or 0} + parent = self, character = 'barrage', level = self.level, pierce = pierce or 0, ricochet = ricochet or 0} Projectile(table.merge(t, mods or {})) end) end @@ -1956,8 +1959,8 @@ function Projectile:init(args) elseif self.character == 'psyker' then self.pierce = 10000 - self.orbit_distance = random:float(28, 36) - self.orbit_speed = random:float(4, 6) + self.orbit_distance = random:float(32, 40)*((self.parent.psychosense == 1 and 1.33) or (self.parent.psychosense == 2 and 1.66) or (self.parent.psychosense == 3 and 1.99) or 1) + self.orbit_speed = random:float(4, 6)*((self.parent.orbitism == 1 and 1.33) or (self.parent.orbitism == 2 and 1.66) or (self.parent.orbitism == 3 and 1.99) or 1) self.orbit_offset = random:float(0, 2*math.pi) elseif self.character == 'lich' then @@ -2751,16 +2754,73 @@ function Tree:init(args) LightningLine{group = main.current.effects, src = self, dst = unit_2, color = green[0]} end HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = green[0], duration = 0.1} + + if self.parent.rearm then + self.t:after(1, function() + heal1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + local unit_1 = random:table_remove(units) + local unit_2 = random:table_remove(units) + if unit_1 then + unit_1:heal(0.2*unit_1.max_hp*(self.heal_effect_m or 1)) + LightningLine{group = main.current.effects, src = self, dst = unit_1, color = green[0]} + end + if unit_2 then + unit_2:heal(0.2*unit_2.max_hp*(self.heal_effect_m or 1)) + LightningLine{group = main.current.effects, src = self, dst = unit_2, color = green[0]} + end + HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = green[0], duration = 0.1} + end) + end + + if self.parent.taunt and random:bool((self.parent.taunt == 1 and 10) or (self.parent.taunt == 2 and 20) or (self.parent.taunt == 3 and 30)) then + local enemies = self:get_objects_in_shape(Circle(self.x, self.y, 96), main.current.enemies) + if #enemies > 0 then + for _, enemy in ipairs(enemies) do + enemy.taunted = self + enemy.t:after(4, function() enemy.taunted = false end, 'taunt') + end + end + end + else local unit = random:table(units) unit:heal(0.2*unit.max_hp*(self.heal_effect_m or 1)) HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = green[0], duration = 0.1} LightningLine{group = main.current.effects, src = self, dst = unit, color = green[0]} + + if self.parent.rearm then + self.t:after(1, function() + heal1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + local unit = random:table(units) + unit:heal(0.2*unit.max_hp*(self.heal_effect_m or 1)) + HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = green[0], duration = 0.1} + LightningLine{group = main.current.effects, src = self, dst = unit, color = green[0]} + end) + end + + if self.parent.taunt and random:bool((self.parent.taunt == 1 and 10) or (self.parent.taunt == 2 and 20) or (self.parent.taunt == 3 and 30)) then + local enemies = self:get_objects_in_shape(Circle(self.x, self.y, 96), main.current.enemies) + if #enemies > 0 then + for _, enemy in ipairs(enemies) do + enemy.taunted = self + enemy.t:after(4, function() enemy.taunted = false end, 'taunt') + end + end + end end end) self.t:after(10*(self.parent.conjurer_buff_m or 1), function() - self.t:every_immediate(0.05, function() self.hidden = not self.hidden end, 7, function() self.dead = true end) + self.t:every_immediate(0.05, function() self.hidden = not self.hidden end, 7, function() + self.dead = true + + if self.parent.summon_instability then + camera:shake(2, 0.5) + local n = (self.parent.summon_instability == 1 and 1) or (self.parent.summon_instability == 2 and 1.5) or (self.parent.summon_instability == 3 and 2) or 1 + Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*48, color = self.color, dmg = n*self.parent.dmg*self.parent.area_dmg_m, parent = self.parent} + _G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} + end + end) end) end @@ -2930,6 +2990,40 @@ function Turret:init(args) turret1:play{pitch = random:float(0.95, 1.05), volume = 0.35} turret2:play{pitch = random:float(0.95, 1.05), volume = 0.35} end, 3) + + if self.parent.taunt and random:bool((self.parent.taunt == 1 and 10) or (self.parent.taunt == 2 and 20) or (self.parent.taunt == 3 and 30)) then + local enemies = self:get_objects_in_shape(Circle(self.x, self.y, 96), main.current.enemies) + if #enemies > 0 then + for _, enemy in ipairs(enemies) do + enemy.taunted = self + enemy.t:after(4, function() enemy.taunted = false end, 'taunt') + end + end + end + + if self.parent.rearm then + self.t:after(1, function() + self.t:every({0.1, 0.2}, function() + self.hfx:use('hit', 0.25, 200, 10) + HitCircle{group = main.current.effects, x = self.x + 0.8*self.shape.w*math.cos(self.r), y = self.y + 0.8*self.shape.w*math.sin(self.r), rs = 6} + local t = {group = main.current.main, x = self.x + 1.6*self.shape.w*math.cos(self.r), y = self.y + 1.6*self.shape.w*math.sin(self.r), v = 200, r = self.r, color = self.color, + dmg = self.parent.dmg*(self.parent.conjurer_buff_m or 1)*self.upgrade_dmg_m, character = self.parent.character, parent = self.parent} + Projectile(table.merge(t, mods or {})) + turret1:play{pitch = random:float(0.95, 1.05), volume = 0.35} + turret2:play{pitch = random:float(0.95, 1.05), volume = 0.35} + end, 3) + + if self.parent.taunt and random:bool((self.parent.taunt == 1 and 10) or (self.parent.taunt == 2 and 20) or (self.parent.taunt == 3 and 30)) then + local enemies = self:get_objects_in_shape(Circle(self.x, self.y, 96), main.current.enemies) + if #enemies > 0 then + for _, enemy in ipairs(enemies) do + enemy.taunted = self + enemy.t:after(4, function() enemy.taunted = false end, 'taunt') + end + end + end + end) + end end, nil, nil, 'shoot') self.t:after(24*(self.parent.conjurer_buff_m or 1), function() @@ -2937,6 +3031,13 @@ function Turret:init(args) for i = 1, n do HitParticle{group = main.current.effects, x = self.x, y = self.y, r = random:float(0, 2*math.pi), color = self.color} end HitCircle{group = main.current.effects, x = self.x, y = self.y}:scale_down() self.dead = true + + if self.parent.summon_instability then + camera:shake(2, 0.5) + local n = (self.parent.summon_instability == 1 and 1) or (self.parent.summon_instability == 2 and 1.5) or (self.parent.summon_instability == 3 and 2) or 1 + Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*48, color = self.color, dmg = n*self.parent.dmg*self.parent.area_dmg_m, parent = self.parent} + _G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} + end end) self.upgrade_dmg_m = 1 @@ -3027,6 +3128,13 @@ function Pet:on_collision_enter(other, contact) self.ricochet = self.ricochet - 1 else self.dead = true + + if self.parent.summon_instability then + camera:shake(2, 0.5) + local n = (self.parent.summon_instability == 1 and 1) or (self.parent.summon_instability == 2 and 1.5) or (self.parent.summon_instability == 3 and 2) or 1 + Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*48, color = self.color, dmg = n*self.parent.dmg*self.parent.area_dmg_m, parent = self.parent} + _G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} + end end end end @@ -3117,7 +3225,18 @@ function Saboteur:on_collision_enter(other, contact) local t = {group = main.current.effects, x = self.x, y = self.y, r = self.r, w = (self.crit and 1.5 or 1)*self.area_size_m*64, color = self.color, dmg = (self.crit and 2 or 1)*self.area_dmg_m*self.actual_dmg*(self.conjurer_buff_m or 1), character = self.character, parent = self.parent} Area(table.merge(t, mods or {})) - self.dead = true + + if self.parent.summon_instability then + self.t:after(0.25, function() + camera:shake(2, 0.5) + local n = (self.parent.summon_instability == 1 and 1) or (self.parent.summon_instability == 2 and 1.5) or (self.parent.summon_instability == 3 and 2) or 1 + Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*48, color = self.color, dmg = n*self.parent.dmg*self.parent.area_dmg_m, parent = self.parent} + _G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} + self.dead = true + end) + else + self.dead = true + end end end @@ -3150,6 +3269,30 @@ function Illusion:init(args) parent = self.parent, level = self.parent.level} Projectile(table.merge(t, mods or {})) end + + if self.parent.rearm then + self.t:after(0.25, function() + local closest_enemy = self:get_closest_object_in_shape(self.attack_sensor, main.current.enemies) + if closest_enemy then + wizard1:play{pitch = random:float(0.95, 1.05), volume = 0.05} + local r = self:angle_to_object(closest_enemy) + 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.parent.color, dmg = self.parent.dmg, character = 'illusionist', + parent = self.parent, level = self.parent.level} + Projectile(table.merge(t, mods or {})) + end + end) + end + + if self.parent.taunt and random:bool((self.parent.taunt == 1 and 10) or (self.parent.taunt == 2 and 20) or (self.parent.taunt == 3 and 30)) then + local enemies = self:get_objects_in_shape(Circle(self.x, self.y, 96), main.current.enemies) + if #enemies > 0 then + for _, enemy in ipairs(enemies) do + enemy.taunted = self + enemy.t:after(4, function() enemy.taunted = false end, 'taunt') + end + end + end end, nil, nil, 'shoot') self.t:after(12*(self.parent.conjurer_buff_m or 1), function() @@ -3165,6 +3308,13 @@ function Illusion:init(args) parent = self.parent, level = self.parent.level, pierce = 1, ricochet = 1} end end + + if self.parent.summon_instability then + camera:shake(2, 0.5) + local n = (self.parent.summon_instability == 1 and 1) or (self.parent.summon_instability == 2 and 1.5) or (self.parent.summon_instability == 3 and 2) or 1 + Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*48, color = self.color, dmg = n*self.parent.dmg*self.parent.area_dmg_m, parent = self.parent} + _G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} + end end) end @@ -3381,8 +3531,21 @@ function HealingOrb:on_trigger_enter(other, contact) end if lowest_unit then lowest_unit:heal(0.1*lowest_unit.max_hp*(lowest_unit.heal_effect_m or 1)) - else + end + if main.current.player.haste then + local units = other:get_all_units() + for _, unit in ipairs(units) do + unit.hasted = love.timer.getTime() + unit.t:after(4, function() unit.hasted = false end, 'haste') + end + end + + if main.current.player.divine_barrage and random:bool((main.current.player.divine_barrage == 1 and 20) or (main.current.player.divine_barrage == 2 and 40) or (main.current.player.divine_barrage == 3 and 60)) then + trigger:after(0.01, function() + if not main.current.main.world then return end + main.current.player:barrage(main.current.player.r, 5, nil, 3) + end) end end end diff --git a/todo b/todo index b51954e..3f5359b 100644 --- a/todo +++ b/todo @@ -1,4 +1,59 @@ -Healer & Psyker Update +Orb Update + New items: + Healer: + * Blessing - +10/20/30% healing effectiveness + * Haste - +50% movement speed that decays over 4 seconds on healing orb pick up + * Divine Barrage - 10/20/30% chance to release a ricocheting barrage when picking up a healing orb + Psyker: + * Orbitism - 33/66/99% faster orb speed + * Psyker Orbs - +1/2/3 psyker orbs + * Psychosense - 33/66/99% increased orb range + Conjurer: + * Rearm - summons repeat their attacks once + * Taunt - 10/20/30% chance for summons to taunt nearby enemies on attack + * Summon Instability - summons explode when disappearing, dealing 100/150/200% damage + Changes: + * Magnetism - also attracts healing orbs + * Enchanted - 33/66/99% + Explorer: + * +15% attack speed and damage per active set to allied explorers + Healer rework: + * Enemies have a 8/16% chance to spawn healing orbs on death, orbs prioritize healing low health allies + * Cleric: creates 1 healing orb, Lv.3: creates 4 healing orbs + * Priest: creates 5 healing orbs + * Fairy: grants a random unit 100% attack speed for 6 seconds and creates 1 healing orb + Psyker rework: + * Create a piercing, damaging orb around each psyker, it inherits damage from its target + * Flagellant - Lv.3: 2X flagellant max HP and +12% damage to all allies per cast + * Psykeeper - creates a healing orb every time the psykeeper takes 20% of its max HP in damage, Lv.3: deal double the damage taken by the psykeeper to all enemies + Balance + Change cursers to add more curse targets as set bonuses + Decrease reroll cost to 5 + * Increased sage's attack speed + Increase spawn marker time + Decrease range and thrown speed for forcers + Decrease damage for blue and white on higher NG + Increase gold rewards at higher NG + Prevent orange from killing multiple units at once + Slightly decrease probability of special spawn at levels above 20 + QoL + Lowered sound effect for gambler + Show cooldown on elite attack + * Options menu from buy screen + * Add main menu + * Title + * Snake DVD + * Arena run button + * Options button + * Quit button + * Soundtrack button + * Volume slider + https://i.imgur.com/4hOt5uX.png "party 7/9" + https://i.imgur.com/dlGbx0k.png lvl 3 effect on shop card + Add visuals divine intervention, fairy buff + Change text for enchanted to "if you have >= 2 enchanters" and change text for reinforce to "if you have >= 1 enchanter" + +Loop Update New items: General: Intimidation - enemies spawn with -10/20/30% max HP @@ -17,67 +72,20 @@ Healer & Psyker Update Warping Shots - X/Y/Z% chance for projectiles to ignore wall collisions and warp around the screen 1/2/3 times Culling Strike - instantly kill elites below 10/20/30% max HP Lightning Strike - X/Y/Z% chance for attacks to create chain lightning, dealing 60/80/100% damage and hitting 2/3/4 enemies - Healer: - Blessing - +10/20/30% healing effectiveness - Divine Favor - healing over maximum HP provides a shield that prevents damage once - Divine Barrage - 10/20/30% chance to release a homing barrage when picking up a healing orb - Psyker: - Orbitism - 33/66/99% faster orb speed - Psychosink - orbs move faster based on the amount of damage all psykers have taken recently - Psychosense - 20/40/60% increased orb range - Conjurer: - Rearm - summons repeat their attacks once - Taunt - 10/20/30% chance for summons to taunt nearby enemies on attack - Summon Instability - summons explode when disappearing, dealing 100/150/200% damage - https://i.imgur.com/yzCVMah.png - Changes: - * Magnetism - also attracts healing orbs - Enchanted - 33/66/99% - Healer rework: - * Enemies have a 8/16% chance to spawn healing orbs on death, orbs prioritize healing low health allies - * Cleric: creates 1 healing orb, Lv.3: creates 4 healing orbs - * Priest: creates 5 healing orbs - * Fairy: grants a random unit 100% attack speed for 6 seconds and creates 1 healing orb - Psyker rework: - * Create a piercing, damaging orb around each psyker, it inherits damage from its target - * Flagellant - Lv.3: 4X flagellant max HP and +12% damage to all allies per cast - * Psykeeper - creates a healing orb every time the psykeeper takes 20% of its max HP in damage, Lv.3: deal double the damage taken by the psykeeper to all enemies Looping Change end screen Loop button on end screen Looping lets you continue with the current snake until you die Difficulty is increased according to the formula for levels 25+ Snake size goes up by 1 every loop, up to 12 - Balance - Change cursers to add more curse targets as set bonuses - Decrease reroll cost to 5 - * Increased sage's attack speed - Increase spawn marker time - Decrease range and thrown speed for forcers - Decrease damage for blue and white on higher NG - Increase gold rewards at higher NG + Conjurer rework: QoL - Lowered sound effect for gambler Selling items - Show cooldown on elite attack - * Options menu from buy screen - * Add main menu - * Title - * Snake DVD - * Arena run button - * Options button - * Quit button - * Soundtrack button - https://i.imgur.com/4hOt5uX.png "party 7/9" - https://i.imgur.com/dlGbx0k.png lvl 3 effect on shop card - * Volume slider Your party + items on end, death and passive screens - https://i.imgur.com/JJUddT3.png Add option for mouse cursor to always be visible - Add visuals divine intervention, fairy buff - Change text for enchanted to "if you have >= 2 enchanters" and change text for reinforce to "if you have >= 1 enchanter" Bug fixes - Fix barbarian stun just slowing and not stunning * Fixed fullscreen button and general resolution issues + Fix barbarian stun just slowing and not stunning Fixed a series of crashes that happened rarely right before changing from the arena back to the shop https://i.imgur.com/Rk6qbDD.png - merchant doesnt give reroll if dies https://i.imgur.com/1soUUdk.png - 5th position stops shooting when 1-4 die @@ -85,7 +93,6 @@ Healer & Psyker Update https://i.imgur.com/8he1WDm.png - infinite money https://i.imgur.com/0wZ5wma.png - max unit bugged when changing ng mid run, https://i.imgur.com/qrExpq5.png - --- 30 refresh rate makes enemies faster?!?! @@ -132,6 +139,7 @@ Draft mode Enemy ideas - https://steamcommunity.com/app/915310/discussions/0/3069747783691890511/ Unit ideas - https://i.imgur.com/VNMS2YV.png Unit ideas - https://steamcommunity.com/app/915310/discussions/0/3069747783693969554/ +Unit ideas - https://steamcommunity.com/app/915310/discussions/0/3046104336668792953/ --