From c9bfe87ccbd1c56cb853bae47e08e56d71c51112 Mon Sep 17 00:00:00 2001 From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54> Date: Thu, 9 Aug 2012 22:36:54 +0000 Subject: [PATCH] more git-svn-id: http://svn.net-core.org/repos/t-engine4@5423 51575b47-30f0-44d4-a5cc-537603b46e54 --- game/modules/tome/class/Actor.lua | 8 +- game/modules/tome/class/interface/Archery.lua | 2 + .../tome/data/birth/classes/psionic.lua | 2 + game/modules/tome/data/damage_types.lua | 48 +++ .../tome/data/gfx/effects/broken_dream.png | Bin 0 -> 2635 bytes .../tome/data/gfx/particles/dreamhammer.lua | 45 +++ .../gfx/shockbolt/object/dream_hammer.png | Bin 0 -> 3856 bytes .../tome/data/gfx/talents/dream_crusher.png | Bin 0 -> 4048 bytes .../tome/data/gfx/talents/dream_hammer.png | Bin 0 -> 3234 bytes .../tome/data/gfx/talents/dreamforge.png | Bin 0 -> 1701 bytes .../tome/data/gfx/talents/forge_armor.png | Bin 0 -> 3268 bytes .../tome/data/gfx/talents/forge_bellows.png | Bin 0 -> 3738 bytes .../tome/data/gfx/talents/forge_echoes.png | Bin 0 -> 4047 bytes .../tome/data/gfx/talents/forge_shield.png | Bin 0 -> 4402 bytes .../tome/data/gfx/talents/hammer_toss.png | Bin 0 -> 3146 bytes .../talents/chronomancy/spacetime-weaving.lua | 2 +- .../tome/data/talents/psionic/distortion.lua | 5 +- .../tome/data/talents/psionic/dream-forge.lua | 267 +++++++++++++++++ .../tome/data/talents/psionic/dream-smith.lua | 276 ++++++++++++++++++ .../tome/data/talents/psionic/nightmare.lua | 2 +- .../tome/data/talents/psionic/psionic.lua | 7 +- .../tome/data/talents/psionic/solipsism.lua | 2 +- .../data/talents/psionic/thought-forms.lua | 5 +- .../tome/data/timed_effects/mental.lua | 69 ++++- 24 files changed, 728 insertions(+), 12 deletions(-) create mode 100644 game/modules/tome/data/gfx/effects/broken_dream.png create mode 100644 game/modules/tome/data/gfx/particles/dreamhammer.lua create mode 100644 game/modules/tome/data/gfx/shockbolt/object/dream_hammer.png create mode 100644 game/modules/tome/data/gfx/talents/dream_crusher.png create mode 100644 game/modules/tome/data/gfx/talents/dream_hammer.png create mode 100644 game/modules/tome/data/gfx/talents/dreamforge.png create mode 100644 game/modules/tome/data/gfx/talents/forge_armor.png create mode 100644 game/modules/tome/data/gfx/talents/forge_bellows.png create mode 100644 game/modules/tome/data/gfx/talents/forge_echoes.png create mode 100644 game/modules/tome/data/gfx/talents/forge_shield.png create mode 100644 game/modules/tome/data/gfx/talents/hammer_toss.png create mode 100644 game/modules/tome/data/talents/psionic/dream-forge.lua create mode 100644 game/modules/tome/data/talents/psionic/dream-smith.lua diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index 9e98c806a1..096f55f2a1 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -493,6 +493,12 @@ function _M:actBase() t.doMindStorm(self, t, p) end end + + if self:isTalentActive(self.T_DREAMFORGE) then + local t, p = self:getTalentFromId(self.T_DREAMFORGE), self:isTalentActive(self.T_DREAMFORGE) + t.doForgeStrike(self, t, p) + end + self:triggerHook{"Actor:actBase:Effects"} end @@ -2937,7 +2943,7 @@ function _M:learnPool(t) self:learnTalent(self.T_PSI_POOL, true) self.resource_pool_refs[self.T_PSI_POOL] = (self.resource_pool_refs[self.T_PSI_POOL] or 0) + 1 end - if t.type[1]:find("^psionic/feedback") or t.type[1]:find("^psionic/discharge")and not self:knowTalent(self.T_FEEDBACK_POOL) then + if t.type[1]:find("^psionic/feedback") or t.type[1]:find("^psionic/discharge") and not self:knowTalent(self.T_FEEDBACK_POOL) then self:learnTalent(self.T_FEEDBACK_POOL, true) end -- If we learn an archery talent, also learn to shoot diff --git a/game/modules/tome/class/interface/Archery.lua b/game/modules/tome/class/interface/Archery.lua index 57e60fbc56..621452a0e0 100644 --- a/game/modules/tome/class/interface/Archery.lua +++ b/game/modules/tome/class/interface/Archery.lua @@ -361,6 +361,8 @@ local function archery_projectile(tx, ty, tg, self, tmp) if hitted and not target.dead and target:attr("stamina_regen_when_hit") then target:incStamina(target.stamina_regen_when_hit) end if hitted and not target.dead and target:attr("mana_regen_when_hit") then target:incMana(target.mana_regen_when_hit) end if hitted and not target.dead and target:attr("equilibrium_regen_when_hit") then target:incEquilibrium(-target.equilibrium_regen_when_hit) end + if hitted and not target.dead and target:attr("psi_regen_when_hit") then target:incPsi(target.psi_regen_when_hit) end + if hitted and not target.dead and target:attr("hate_regen_when_hit") then target:incHate(target.hate_regen_when_hit) end -- Resource regen on hit if hitted and self:attr("stamina_regen_on_hit") then self:incStamina(self.stamina_regen_on_hit) end diff --git a/game/modules/tome/data/birth/classes/psionic.lua b/game/modules/tome/data/birth/classes/psionic.lua index 0212f663ec..6b6e15aa1c 100644 --- a/game/modules/tome/data/birth/classes/psionic.lua +++ b/game/modules/tome/data/birth/classes/psionic.lua @@ -169,6 +169,7 @@ newBirthDescriptor{ talents_types = { -- class ["psionic/distortion"]={true, 0.3}, + ["psionic/dream-smith"]={true, 0.3}, ["psionic/psychic-assault"]={true, 0.3}, ["psionic/slumber"]={true, 0.3}, ["psionic/solipsism"]={true, 0.3}, @@ -182,6 +183,7 @@ newBirthDescriptor{ -- locked trees ["psionic/discharge"]={false, 0.3}, + ["psionic/dream-forge"]={false, 0.3}, ["psionic/nightmare"]={false, 0.3}, }, talents = { diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua index 855058ba67..88edc4e73e 100644 --- a/game/modules/tome/data/damage_types.lua +++ b/game/modules/tome/data/damage_types.lua @@ -56,6 +56,10 @@ setDefaultProjector(function(src, x, y, type, dam, tmp, no_martyr) local e = target.tempeffect_def[target.EFF_BLOCKING] dam = e.do_block(type, dam, target.tmp[target.EFF_BLOCKING], target, src) end + if target.isTalentActive and target:isTalentActive(target.T_FORGE_SHIELD) then + local t = target:getTalentFromId(target.T_FORGE_SHIELD) + dam = t.doForgeShield(type, dam, t, target, src) + end -- Increases damage local mind_linked = false @@ -2138,4 +2142,48 @@ newDamageType{ end end end, +} + +-- Mind/Fire damage with lots of parameter options +newDamageType{ + name = "dreamforge", type = "DREAMFORGE", + projector = function(src, x, y, type, dam, tmp) + local target = game.level.map(x, y, Map.ACTOR) + if not target then return end + local power, dur, dist, do_particles + tmp = tmp or {} + if _G.type(dam) == "table" then dam, power, dur, dist, do_particles = dam.dam, dam.power, dam.dur, dam.dist, dam.do_particles end + if target and not tmp[target] then + if src:checkHit(src:combatMindpower(), target:combatMentalResist(), 0, 95) then + DamageType:get(DamageType.MIND).projector(src, x, y, DamageType.MIND, {dam=dam/2, alwaysHit=true}) + DamageType:get(DamageType.FIREBURN).projector(src, x, y, DamageType.FIREBURN, dam/2) + if power and power > 0 then + local silent = true and target:hasEffect(target.EFF_BROKEN_DREAM) or false + target:setEffect(target.EFF_BROKEN_DREAM, dur, {power=power}, silent) + target:crossTierEffect(target.EFF_BRAINLOCKED, src:combatMindpower()) + end + -- Do knockback + if dist then + if target:canBe("knockback") then + target:knockback(src.x, src.y, dist) + target:crossTierEffect(target.EFF_OFFBALANCE, src:combatMindpower()) + game.logSeen(target, "%s is knocked back!", target.name:capitalize()) + else + game.logSeen(target, "%s resists the forge bellow!", target.name:capitalize()) + end + end + if do_particles then + if rng.percent(50) then + game.level.map:particleEmitter(target.x, target.y, 1, "generic_discharge", {rm=225, rM=255, gm=160, gM=160, bm=0, bM=0, am=35, aM=90}) + elseif hit then + game.level.map:particleEmitter(target.x, target.y, 1, "generic_discharge", {rm=225, rM=255, gm=225, gM=255, bm=255, bM=255, am=35, aM=90}) + end + end + else -- Save for half damage + DamageType:get(DamageType.MIND).projector(src, x, y, DamageType.MIND, {dam=dam/4, alwaysHit=true}) + DamageType:get(DamageType.FIREBURN).projector(src, x, y, DamageType.FIREBURN, dam/4) + game.logSeen(target, "%s resists the dream forge!", target.name:capitalize()) + end + end + end, } \ No newline at end of file diff --git a/game/modules/tome/data/gfx/effects/broken_dream.png b/game/modules/tome/data/gfx/effects/broken_dream.png new file mode 100644 index 0000000000000000000000000000000000000000..6572d17912c49fe4276e15650e7d3cf75421fdf8 GIT binary patch literal 2635 zcmV-R3bgf!P)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF00001b5ch_0Itp) z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01ejw01ejxLMWSf00007bV*G`2iyn= z01`FI7sgKj013-UL_t(|+U1*TY#h}U$A5QbAKr%_N&MQ_u@i6}jxm%sZXhAhghxdP z2va~p2&njws;ycI6j~KN0BUKADz&H|5N!cb=tCwTp#(|{#SJusgw{3W0gi){II-h6 zi8p@k?wo#@UGL0#*1`7f+7U+@?arOKbMN`z^Z4JhI|>lK!lLmN7gw$a{QAXizOlkZ z-BO*>60@!6D75W~@%F!>eDF~ur}I&{aDhCZ;_)8@`TkvATzSB#m_u7f)&x9?=n(wo zPs9B5=>bMY<je=);rj}B^8SFSv~?sUpj7f)QXJC_5B+k0r=AU;nE(X*8rxqiqjsSS zjJSqMfk=GRxD}B67&kKwK536~$(=n64jE?-0M#KkyI-!vs|yO1R8XwSN^)qWk{87e zh#(9{Vacss9PEzFegNi|csTe<H5hT_Q&-r!`YJxOSlmI4j}M{*K{3Da3%ZX*W-kCi zzs`}D7UOqgUwP75faP4Q)-YZK;nb)Qy1ku&q1fyMVAnItSX$;z>L4j2Ikk_ix+P8^ zAj;l14#KC0Bb>8gZ^i)7fyXlOpkLoz%?))0sHhGR1u-2A1u@P19@Wh6k@#ogFjVqd zREL;~e`@A;BmO<Ap<+6vem8-jn}7VLfA(0wl8OL(o~no8nBD9JyI-fq1F^5L%@RbV zScT<YuSU%e+i33^oE-q{ef%P7=EO~3EWykg(3C}~bZO5P8{+q;21RAM!tUM(%YU+S z=BaSwMdd6G`eDRDk#WQad#V$MK8e*9Nr@54W<<4x9@bx2%Elc%Giw1|KU+z8o{mz= zL7{|FsiVXdRVkTaT+p=ULc1#nLf2rF%Ez|OoCU0_3lY+NFf0~7X8a0U{o5K3Qk1f% zMGJVTz+rNX3b%)E)|K(bC*3mxz>hCoj11}K9359bah~vhv9~#~L`fx1mJ4Ec6G3?J zvYMFzAXFHjVO}u|MePcuuA-Ath&?FUGJ#V+akLNxtSl?0INwiicrdpB+_Q8coKhez zXJ1xKzyu|Y$ve<yTYpK(779k;-sRQ&V%x6V2EjeI-N=%>yp#wosnpGx31Zz1inB|k z?H_lA_|8%k>>e0m`Jdm&odp#5d@S)4!e}(jY)PN*r*co)`^8L&d2<Nl<uNckoST~9 zb)gW%Vh%G)IV8<tSdQ2vk7(k+q|i|fMuclaq1+WkubDp|F{V+VP?<PX5@*BU+WGTy z2f*dU#U}BYC8CsK#k_gBivf!Z3n4PTFd-r+O#@x$*yt$x!eRO%5!@o2RZzgfU=Sja z@mbNDAlz;`!eRD@!;C7$T(_IE^YfYO@jxtw7=|PGwR7g=27u~<0!T4`5ka}#Z0_pf zx%PHmJ9v<&13*gGxu>RvXD+w^PkiMP{YOODuyZGWY;SjnFW`2&S-)Tb->#`)ZFxBo ziP(WK3@Qo=IMm-iX>XiV8oa8qk}a!NnJFl)#Jk6i@vW8?dIkmnSW{U^sn^S^2M#be zIy$~!>h;ol^UZkU3Je+s#Z65NJKP)edbzQ(k|V>zY&moYfbw9Fzg}?#SInK8+%#z# zS2j2E&#tcQT0oWGKQ^e+G#+Se<yWn($*R!$^(+en%##%>Xn6BY{@rb-sske<Jkr|A z)90NBz(cLAj>=yi3emD=jcE}|(bnHj{p+uD<kTrvZra2n=bz6Lb#<mi8U_pe{_F?A zDxYr*fS>Q#V^jV|_4O=E03?D$BD}h4mE&`I<4U0vy$;F)ytZ;B5{a14GYrlN2KioH z-PrXfKmM4fKl^NqSXJc$fI`0?lp>-O4{zUYyH=l{Zzpd`QSS5EYjC>G-&U{Yg^Mpn z3<EI?UTJ9H<twi=1L)YyH0I{z+5B99`ocon^X}ia4MWoqr6@`nD=PpbFmCGX9Cz)# zzP=Q;E9|xerONz#PBb=hOL;lOVko6d1!FO83xzn|*hnbhK88U@IE+{dBT6aW>+Kyk z?#6=$QGid=atFXwWo5j(b}hfX^inP<F9+bc-Me|Mrw3dv&@_gC>zkVaDE9f-ziu6Y zxY;`-a|$$#{p;2-Cod0xwav|pC<U4ZE*F3A>f*({W<|Im6yll7F5}&`Ygt)bYzEg{ zY=-{O(7@e`7THsvuCuA9hwI;Z3xJCJe9F9Dc3M`e{id5(lw#73^?woe4h^wv<HoVJ z3yX{C8X4hm*!-RFt!u7fO-Tt7x1xkR+tI;&AAFEq3m9}@VHgJ26&LfD)vEzG6b{>z zzjx_U&hq)b6nj)ku{03i&c%zz+IIBzjw%1@)mO7--aK$1M1xacr;`R?D4zeF<krec zmOD_=N9*e+WoBX+JX&8ruKjBzC9F@w`2`#~N5%o@85lr`vpN!u@?dSPt!+_J5et02 zN$q--Qk)$KP*G4|Yk#n|7Kuik`-pHf7u(^^fdMlprI~nRRh6ynhKdSDYI|CV#ke75 zwQs4aO7BLRX3i}q08HR(eqCp7AQ_KWl$1=V<Rrj~($cZ>^89?<6ZyDO9LNO#pN7K| z0)PnTTFA;dg@sII<E-L+6LM~0;kZp$Dgd8^!`TPm<lrENOt7YgLAAvKDyKkC6SBa< z?5cx7`>#bQGHMtM3=QR`AhP4ci3u&B-0Mx&4?UhK12E45K$*ugApkp$AJ1JysQJi| zw388~C<_Kts=w2h@?bE%>xuAAcX#dpc=Pb#^qBz2PfS$TGgkHrP6VW`n{&z)0Pl2l znS4Kucr1Y_Q=(7wEKTFRNftt;1pp#!Iegf*Q=9%nPczYU{~Z#U^6F1(t}k?Sq$MTU zs2J;M+({|Li~IJ?008an>3uv40BGs<`nt|bGXVgG!3+EMr*(szhzQShbWAJLOv_!L zXlp~cTr&rN%f*vzZPT-?>2%(E{5V^BdS=85M1;-V-Rzr)lw}(LfDPNX&xjQ$x0~;L z_~G<p%XA;Gx37<vzW5?zjPJ|({_`Cj(_a0IrR=-5ZbdXL=?aov(~l{|-CMV2<arqZ zAQp>peM?Ky6;$>RP%anOwzN#|=lN`qw#}WL{Jy>2vLncj{O<G5dHcYD%q5acPHw~d z?^8F$0?3yski65^$9E@L_Rg6FBxKd5O?-UvWX1vb=;TSR+Ppa{z-G^3T`uH~J0MLZ z_q5`6qn>|0s|h8$FHRZ;==zk1l8B_OIh;`doYmCCNB#X^O_QfnT-Vvw-_OFPrtA|c za`f)-`K6^iuxuH(S5=w2MZ>VaClm+h<<3r?+O>=S9zB{HM#&7kJY7>%M14^aCGm=J t&)^{cJ8^>c3^2Ph0)W{hU-`Gk{||Me)L_@xz)}DJ002ovPDHLkV1jg{0!sh@ literal 0 HcmV?d00001 diff --git a/game/modules/tome/data/gfx/particles/dreamhammer.lua b/game/modules/tome/data/gfx/particles/dreamhammer.lua new file mode 100644 index 0000000000..abc535e905 --- /dev/null +++ b/game/modules/tome/data/gfx/particles/dreamhammer.lua @@ -0,0 +1,45 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + +base_size = 64 +local nb = 1 + +return { + system_rotation = 225 + math.deg(math.atan2(ty-sy, tx-sx)), system_rotationv = 0, + + base = 1000, + + angle = { 0, 0 }, anglev = { 0, 0 }, anglea = { 0, 0 }, + + life = { 10, 10 }, + size = { 64, 64 }, sizev = {0, 0}, sizea = {0, 0}, + + r = {255, 255}, rv = {0, 0}, ra = {0, 0}, + g = {255, 255}, gv = {0, 0}, ga = {0, 0}, + b = {255, 255}, bv = {0, 0}, ba = {0, 0}, + a = {255, 255}, av = {0, 0}, aa = {0, 0}, + +}, + function(self) + if nb == 1 then + self.ps:emit(1) + nb = nb -1 + end +end, + 1, tile, true diff --git a/game/modules/tome/data/gfx/shockbolt/object/dream_hammer.png b/game/modules/tome/data/gfx/shockbolt/object/dream_hammer.png new file mode 100644 index 0000000000000000000000000000000000000000..9ccdd24db274fefd3266cf729cd7658d54dee77b GIT binary patch literal 3856 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 S<7SQk0000<MNUMnLSTZ<z+*xH literal 0 HcmV?d00001 diff --git a/game/modules/tome/data/gfx/talents/dream_crusher.png b/game/modules/tome/data/gfx/talents/dream_crusher.png new file mode 100644 index 0000000000000000000000000000000000000000..add18a553e091451f9b0426284993276009e5e57 GIT binary patch literal 4048 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 C42|Ug literal 0 HcmV?d00001 diff --git a/game/modules/tome/data/gfx/talents/dream_hammer.png b/game/modules/tome/data/gfx/talents/dream_hammer.png new file mode 100644 index 0000000000000000000000000000000000000000..6d9e3f2c187a075350ef06255bef83e05cfdd9ce GIT binary patch literal 3234 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 US01Lt1poj507*qoM6N<$g4!_u82|tP literal 0 HcmV?d00001 diff --git a/game/modules/tome/data/gfx/talents/dreamforge.png b/game/modules/tome/data/gfx/talents/dreamforge.png new file mode 100644 index 0000000000000000000000000000000000000000..7c8e1259d52dd00222199b41a3183bd8d44a90d1 GIT binary patch literal 1701 zcmV;W23q-vP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF00001b5ch_0Itp) z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01ejw01ejxLMWSf00007bV*G`2iyn< z1voN=Z#qf<00t#VL_t(|+U;6hh*eb-{`Ow`3U`cQ=w)y!B&>(4p$rU0LBmX$6O2!S z6a+#EA%#>5SEDHEp_iG$dJWRhK~Z}MvcM99(2DM$587OOFzCq#b4Jh?^SXLC=iIY@ z*1q>TKQ_~x1H;_A&%W#I^{t=1)_1l7z*xqY#xlPO015yK015yK015yK015yK015yK z0G8)v<|<%ps1GZllBP22D;2vvCZ}Ui={TqJRX#r(&V{%#{ic<}FINDJpS^Z}0eF=R z9s~<bb*3Qa`rHMeIj#ifdOJ5+03efZ0s9LW<FoaE!NE0nqzh0SS)gTAW?<rnKa(#+ z$$(?LY_4(zDbKpOdsx=y{CCWO2nVcSp=$Oa(7TdwSRq%&S!8I5i6$_VK9}X6F-vF) z%CVz+@;eI{Em)qtXQ(+O!Q<aw#&sevnZ&A^lK<If>wAMJmp}xN2FT>|ntwW%L1fMG z=9BiGmEM=ebvmxeTW2Z{K&e#1Z<|(Q+osj`mIL0<gd<`+`qqRC0JH2dnGohMxrv_T zg$B0@m1sr;Gh-te90TL#$QtZo#=%op+HZqLzqyDDn!ruejo<+$8E;A;*9#nL+18}+ zzdesEPw+j-@gC!OmCo0sJ<rsHl|(o|gbOb`j_&U6_PfBdKmCR4&pn#%T!Ll&jBJNP z7T4@&b_K9b?|I&({G_JxZL;~O%<`PbiX}t)a|(t^Z>$G!<C#7TT<yc;WIbL8O;1l_ z(=<V4o}m3apk1ZOj&<Ya4kEx9FJ28`e7VNW57}7Yfu83mA>a79DV3M$Q+tRoGP1UH zC3yPu@7O^W2!0~7AEZ6SwdBHrYdgtSdkNFXp!)_f#tJKPL%@Dc3b3L?pQB~dz7YEI z$gjBl^3ynE7jn{-fgx3K_PCSJr2XC7{~;tsr_PW<6LM&#G8w>C0BgRhcUB1=o;Zj4 zzyQv!En`It02_5lSy5r3CJ0L64ywf<f3Uo+^t#B54JRhS)^66e8LHK4=$bf(6KOnh z5NpQD13Haw<GHqRGrG32w)XdWBkTZD7-(U>33dTa=N=%!`r|c6`Hp*mMx%jkU!6gv zQo;VGR$;T_0a`9eosyd6GQoCj$E~eOF;-*5nk1(_0sc|I)@jDcljr8%3{6c<VPt9w zJv}|H2Lx{D2RMhIh{aVTG<=y&Ojwwghrnk5-ahnmVD&k7gEKQTt_O&gQnGT91}k0> zM!bNt&Qb;5z|45y>q*?Yb!*|<Vb=p9NC)1*9hA0_dn{zhEOb;JvYjYDPXLhM+HI7Q zVmL4|w<JGW19%?^ksDekTS=3g@T?TLyb>6p7WqH|CfEX#2{&i4eud(IL_vx!_%$>% zgfj!Ha2p-Qy)gbafWA+UElmJ+KKU>hj1@kW)spmdlj$l2tXsDZmo8meS|Ly>mGGh_ zsAg+x<hGfF&d$2eny_a}|I*6=@9y0mGB{e`8YSMrVt*77UeN?&%+dnjgMcG2E`3HM zSl#5LsM9zRKH9r|=>YJ_hdbqt>ezW|Nzpo_2V}cZkr{)wTEm=<V&rZr{qyHra%< zyUzyM-;LWgAFOU)`~aMK>!qAK(56jqFXRUwIEyCRMug$v;l&HUo;|y<UMC!!%n1sl zhmM2>g=4G<C!c=;rBZ3mYn}H}xKgR$j~!cb20Kbz*sr)e+B??2Tf_=0pvH`i`}Qv$ z0LtYuu6_I_%D(bVuFz+C(4J3pD#Nf1{sO>j)$zpvz~#^1!($96Nu<=rJLd%?&p<~s zSoP{%jE#-`x215kT18zG>MT)Wf?}!_0~F%}IP?lIHuq`#*x!%y=g$}IaM2DgbO?-& zj^f*`gRNO$k-~~}eJmZU5Y7p;JUXL9icG!!{`>=Q=gyt{txG@zbDN_qHfHPskevdN zGQLBB3Hc>@K4GDfAd!{OG6hulYOB?DC++XSebw6H0a*7A!t4O>-@9={Sw!CTDQ^E} zM{;|oR`BTc=o;o30Hsv=ZcxSF;`$b|(}Y*i1vP<+oB(419gY?X3kN{GUdO%*8_;Mp v{ujGIQ3ovdI-mfc0H6S%0H6S1IbZ(*R<)+xNvZ{{00000NkvXXu0mjf!IL1G literal 0 HcmV?d00001 diff --git a/game/modules/tome/data/gfx/talents/forge_armor.png b/game/modules/tome/data/gfx/talents/forge_armor.png new file mode 100644 index 0000000000000000000000000000000000000000..d48f3267c71b19d02eafe914b8b842e2aa66a0c6 GIT binary patch literal 3268 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 Cd>j7& literal 0 HcmV?d00001 diff --git a/game/modules/tome/data/gfx/talents/forge_bellows.png b/game/modules/tome/data/gfx/talents/forge_bellows.png new file mode 100644 index 0000000000000000000000000000000000000000..ac33b3c0a1ad2edd2106f3c3ff7ea4c9041ba1f7 GIT binary patch literal 3738 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 Ef*3~|O8@`> literal 0 HcmV?d00001 diff --git a/game/modules/tome/data/gfx/talents/forge_echoes.png b/game/modules/tome/data/gfx/talents/forge_echoes.png new file mode 100644 index 0000000000000000000000000000000000000000..a6fdb221643b3795358acf28494570dcfa85c21e GIT binary patch literal 4047 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 BZ2ABI literal 0 HcmV?d00001 diff --git a/game/modules/tome/data/gfx/talents/forge_shield.png b/game/modules/tome/data/gfx/talents/forge_shield.png new file mode 100644 index 0000000000000000000000000000000000000000..52e0bd13d8366377d0186a41ad5d9e3bcbe71fbd GIT binary patch literal 4402 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 literal 0 HcmV?d00001 diff --git a/game/modules/tome/data/gfx/talents/hammer_toss.png b/game/modules/tome/data/gfx/talents/hammer_toss.png new file mode 100644 index 0000000000000000000000000000000000000000..73e08ef8ab95ab66682a33524c08a9276f8f0f66 GIT binary patch literal 3146 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 literal 0 HcmV?d00001 diff --git a/game/modules/tome/data/talents/chronomancy/spacetime-weaving.lua b/game/modules/tome/data/talents/chronomancy/spacetime-weaving.lua index 29eaa632cd..b71b453e2f 100644 --- a/game/modules/tome/data/talents/chronomancy/spacetime-weaving.lua +++ b/game/modules/tome/data/talents/chronomancy/spacetime-weaving.lua @@ -64,7 +64,7 @@ newTalent{ info = function(self, t) local range = self:getTalentRange(t) return ([[Teleports you to up to %d tiles away to a targeted location in line of sight. Additional talent points increase the range. - This spell takes no time to cast..]]):format(range) + This spell takes no time to cast.]]):format(range) end, } diff --git a/game/modules/tome/data/talents/psionic/distortion.lua b/game/modules/tome/data/talents/psionic/distortion.lua index e11c835d71..e693b315cb 100644 --- a/game/modules/tome/data/talents/psionic/distortion.lua +++ b/game/modules/tome/data/talents/psionic/distortion.lua @@ -152,7 +152,6 @@ newTalent{ target = function(self, t) return {type="hit", range=self:getTalentRange(t), nolock=true, talent=t} end, - tactical = { ATTACKAREA = { PHYSICAL = 2 }, DISABLE = 1 }, action = function(self, t) local tg = self:getTalentTarget(t) local x, y = self:getTarget(tg) @@ -166,8 +165,8 @@ newTalent{ local e = Object.new{ old_feat = oe, type = oe.type, subtype = oe.subtype, - name = "maelstrom", image = oe.image, --add_mos = {{image = "terrain/wormhole.png"}}, - display = '&', color_r=255, color_g=255, color_b=255, back_color=colors.STEEL_BLUE, + name = "maelstrom", image = oe.image, + display = oe.display, color=oe.color, back_color=oe.back_color, always_remember = true, temporary = t.getDuration(self, t), is_maelstrom = true, diff --git a/game/modules/tome/data/talents/psionic/dream-forge.lua b/game/modules/tome/data/talents/psionic/dream-forge.lua new file mode 100644 index 0000000000..dd68a6e9c1 --- /dev/null +++ b/game/modules/tome/data/talents/psionic/dream-forge.lua @@ -0,0 +1,267 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + +local Object = require "mod.class.Object" + +newTalent{ + name = "Forge Shield", + type = {"psionic/dream-forge", 1}, + points = 5, + require = psi_wil_high1, + cooldown = 24, + sustain_psi = 25, + mode = "sustained", + tactical = { DEFEND = 2, }, + getPower = function(self, t) return self:combatTalentMindDamage(t, 15, 150) end, + doForgeShield = function(type, dam, t, self, src) + -- Grab our damage threshold + local dam_threshold = self.max_life * 0.08 + if self:knowTalent(self.T_SOLIPSISM) then + local t = self:getTalentFromId(self.T_SOLIPSISM) + local ratio = t.getConversionRatio(self, t) + local psi_percent = self:getMaxPsi() * t.getConversionRatio(self, t) + dam_threshold = (self.max_life * (1 - ratio) + psi_percent) * 0.08 + end + + local dur = self:getTalentLevel(t) >= 5 and 2 or 1 + local blocked + local amt = dam + local eff = self:hasEffect(self.EFF_FORGE_SHIELD) + if not eff and dam > dam_threshold then + self:setEffect(self.EFF_FORGE_SHIELD, dur, {power=t.getPower(self, t), number=1, d_types={[type]=true}}) + amt = util.bound(dam - t.getPower(self, t), 0, dam) + blocked = t.getPower(self, t) + game.logSeen(self, "#ORANGE#%s forges a dream shield to block the attack!", self.name:capitalize()) + elseif eff and eff.d_types[type] then + amt = util.bound(dam - eff.power, 0, dam) + blocked = eff.power + elseif eff and dam > dam_threshold * (1 + eff.number) then + eff.number = eff.number + 1 + eff.d_types[type] = true + amt = util.bound(dam - eff.power, 0, dam) + blocked = eff.power + game.logSeen(self, "#ORANGE#%s's dream shield has been strengthened by the attack!", self.name:capitalize()) + end + + if blocked then + print("[Forge Shield] blocked", math.min(blocked, dam), DamageType.dam_def[type].name, "damage") + end + + if amt == 0 and src.life then src:setEffect(src.EFF_COUNTERSTRIKE, 1, {power=t.getPower(self, t), no_ct_effect=true, src=self, nb=1}) end + return amt + end, + activate = function(self, t) + game:playSoundNear(self, "talents/spell_generic") + local ret ={ + } + if self:knowTalent(self.T_FORGE_ARMOR) then + local t = self:getTalentFromId(self.T_FORGE_ARMOR) + ret.def = self:addTemporaryValue("combat_def", t.getDefense(self, t)) + ret.armor = self:addTemporaryValue("combat_armor", t.getArmor(self, t)) + ret.psi = self:addTemporaryValue("psi_regen_when_hit", t.getPsiRegen(self, t)) + end + return ret + end, + deactivate = function(self, t, p) + if p.def then self:removeTemporaryValue("combat_def", p.def) end + if p.armor then self:removeTemporaryValue("combat_armor", p.armor) end + if p.psi then self:removeTemporaryValue("psi_regen_when_hit", p.psi) end + + return true + end, + info = function(self, t) + local power = t.getPower(self, t) + return ([[When an attack would deal 8%% or more of your effective health you forge the Dream Shield to protect yourself, reducing the damage of all attacks of that type by %0.2f for the next turn. + You may block multiple damage types at one time but the base damage threshold increases by 8%% per damage type the shield is already blocking. + If you block all of an attack's damage, the attacker will be vulnerable to a deadly counterstrike (a normal attack will instead deal 200%% damage) for one turn. + At talent level five the block effect will last two turns. + This talent scales with your mindpower.]]):format(power) + end, +} + +newTalent{ + name = "Forge Bellows", + type = {"psionic/dream-forge", 2}, + points = 5, + require = psi_wil_high2, + cooldown = 24, + psi = 30, + tactical = { ATTACKAREA = { FIRE = 2, MIND = 2}, ESCAPE = 2, }, + range = 0, + radius = function(self, t) return math.min(10, 3 + math.ceil(self:getTalentLevel(t)/2)) end, + requires_target = true, + target = function(self, t) + return {type="cone", range=self:getTalentRange(t), friendlyfire=false, radius = self:getTalentRadius(t), talent=t} + end, + getDuration = function(self, t) return 5 + math.floor(self:getTalentLevel(t)) end, + getBlastDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 200) end, + getForgeDamage = function(self, t) return self:combatTalentMindDamage(t, 0, 25) end, + action = function(self, t) + local tg = self:getTalentTarget(t) + local x, y = self:getTarget(tg) + if not x or not y then return nil end + + local blast_damage = self:mindCrit(t.getBlastDamage(self, t)) + local forge_damage = self:mindCrit(t.getForgeDamage(self, t)) + + -- Do our blast first + self:project(tg, x, y, DamageType.DREAMFORGE, {dam=blast_damage, dist=math.ceil(tg.radius/2)}) + + -- Now build our Barrier + self:project(tg, x, y, function(px, py, tg, self) + local oe = game.level.map(px, py, Map.TERRAIN) + if rng.percent(50) or not oe or oe.is_forgebarrier or game.level.map:checkAllEntities(px, py, "block_move") then return end + + local e = Object.new{ + old_feat = oe, + type = oe.type, subtype = oe.subtype, + name = "forge barrier", image = "terrain/lava/lava_mountain5.png", + display = '#', color=colors.RED, back_color=colors.DARK_GREY, + shader = "shadow_simulacrum", + shader_args = { color = {0.6, 0.0, 0.0}, base = 0.9, time_factor = 1500 }, + always_remember = true, + can_pass = {pass_wall=1}, + block_move = true, + block_sight = true, + temporary = t.getDuration(self, t), + is_forgebarrier = true, + x = px, y = py, + canAct = false, + dam = forge_damage, + radius = self:getTalentRadius(t), + act = function(self) + local tg = {type="ball", range=0, friendlyfire=false, radius = 1, talent=t, x=self.x, y=self.y,} + self.summoner:project(tg, self.x, self.y, engine.DamageType.DREAMFORGE, self.dam) + + self:useEnergy() + self.temporary = self.temporary - 1 + if self.temporary <= 0 then + game.level.map(self.x, self.y, engine.Map.TERRAIN, self.old_feat) + game.level:removeEntity(self) + game.level.map:updateMap(self.x, self.y) + end + end, + summoner_gain_exp = true, + summoner = self, + } + + game.level:addEntity(e) + game.level.map(px, py, Map.TERRAIN, e) + game.nicer_tiles:updateAround(game.level, px, py) + game.level.map:updateMap(px, py) + end) + game:playSoundNear(self, "talents/fireflash") + return true + end, + info = function(self, t) + local blast_damage = t.getBlastDamage(self, t) + local radius = self:getTalentRadius(t) + local duration = t.getDuration(self, t) + local forge_damage = t.getForgeDamage(self, t) + return ([[Release the bellows of the forge upon your surroundings, inflicting %0.2f mind damage, %0.2f burning damage, and knocking back your enemies in a radius %d cone. + Affected terrain may be changed (50%% chance) for %d turns into forge walls that block movement and inflict %0.2f mind and %0.2f fire damage on nearby enemies. + The damage and knockback chance will scale with your mindpower.]]): + format(damDesc(self, DamageType.MIND, blast_damage), damDesc(self, DamageType.FIRE, blast_damage), radius, duration, damDesc(self, DamageType.MIND, forge_damage), damDesc(self, DamageType.FIRE, forge_damage)) + end, +} + +newTalent{ + name = "Forge Armor", + type = {"psionic/dream-forge", 3}, + points = 5, + require = psi_wil_high3, + mode = "passive", + getArmor = function(self, t) return self:combatTalentMindDamage(t, 5, 50) end, + getDefense = function(self, t) return self:combatTalentMindDamage(t, 5, 25) end, + getPsiRegen = function(self, t) return self:combatTalentMindDamage(t, 1, 5) end, + info = function(self, t) + local armor = t.getArmor(self, t) + local defense = t.getDefense(self, t) + local psi = t.getPsiRegen(self, t) + return([[Your Forge Shield talent now increses your armor by %d, your defense by %d, and gives you %0.2f psi when you're hit by a melee or ranged attack. + The bonuses will scale with your mindpower.]]):format(armor, defense, psi) + end, +} + +newTalent{ + name = "Dreamforge", + type = {"psionic/dream-forge", 4}, + points = 5, + require = psi_wil_high4, + cooldown = 24, + sustain_psi = 50, + mode = "sustained", + no_sustain_autoreset = true, + tactical = { ATTACKAREA = { FIRE = 2, MIND = 2}, DEBUFF = 2, }, + range = 0, + radius = function(self, t) return math.min(5, 1 + math.ceil(self:getTalentLevel(t)/2)) end, + target = function(self, t) + return {type="ball", range=self:getTalentRange(t), friendlyfire=false, radius = self:getTalentRadius(t), talent=t} + end, + getDamage = function(self, t) return math.ceil(self:combatTalentMindDamage(t, 10, 100)) end, + getPower = function(self, t) return math.floor(self:combatTalentMindDamage(t, 5, 50)) end, + getDuration = function(self, t) return 1 + math.floor(self:getTalentLevel(t)/2) end, + doForgeStrike = function(self, t, p) + -- If we moved reset the forge + if self.x ~= p.x or self.y ~= p.y or p.new then + p.x = self.x; p.y=self.y; p.radius=0; p.damage=0; p.power=0; p.new = nil; + -- Otherwise we strike the forge + elseif not self.resting then + local max_radius = self:getTalentRadius(t) + local max_damage = t.getDamage(self, t) + local power = t.getPower(self, t) + local dur = 0 + p.radius = math.min(p.radius + 1, max_radius) + + if p.damage < max_damage then + p.radius = math.min(p.radius + 1, max_radius) + p.damage = math.min(max_damage/4 + p.damage, max_damage) + game.logSeen(self, "#GOLD#%s strikes the dreamforge!", self.name:capitalize()) + elseif p.power == 0 then + p.power = power + dur = t.getDuration(self, t) + game.logSeen(self, "#GOLD#%s begins breaking dreams!", self.name:capitalize()) + game:playSoundNear(self, "talents/lightning_loud") + end + local tg = {type="ball", range=self:getTalentRange(t), friendlyfire=false, radius=p.radius, talent=t} + self:project(tg, self.x, self.y, engine.DamageType.DREAMFORGE, {dam=self:combatMindCrit(p.damage), power=p.power, dur=dur, do_particles=true }) + end + end, + activate = function(self, t) + local ret ={ + x = self.x, y=self.y, radius=0, damage=0, power=0, new = true, + } + game:playSoundNear(self, "talents/devouringflame") + return ret + end, + deactivate = function(self, t, p) + return true + end, + info = function(self, t) + local radius = self:getTalentRadius(t) + local damage = t.getDamage(self, t) + local power = t.getPower(self, t) + local duration = t.getDuration(self, t) + return ([[The pounding forge of thought in your mind is released upon your surroundings. Each turn that you remain stationary you'll strike the dreamforge, inflicting mind and burning damage on enemies around you. + The effect will build over five turns, until it reaches a maximum radius of %d, maximum mind damage of %0.2f, and maximum burning damage of %0.2f. + At this point you'll begin breaking the dreams of enemies who hear the forge, reducing their mental save by %d and giving them a %d%% chance of spell failure due too the tremendous echo in their minds for %d turns. + The damage and dream breaking effect will scale with your mindpower.]]): + format(radius, damDesc(self, DamageType.MIND, damage), damDesc(self, DamageType.FIRE, damage), power, power, duration) + end, +} diff --git a/game/modules/tome/data/talents/psionic/dream-smith.lua b/game/modules/tome/data/talents/psionic/dream-smith.lua new file mode 100644 index 0000000000..03ad7e0d5d --- /dev/null +++ b/game/modules/tome/data/talents/psionic/dream-smith.lua @@ -0,0 +1,276 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + +-- Dream-Forge Hammer +function useDreamHammer(self) + local combat = { + talented = "dream", + sound = {"actions/melee", pitch=0.6, vol=1.2}, sound_miss = {"actions/melee", pitch=0.6, vol=1.2}, + + wil_attack = true, + damrange = 1.5, + physspeed = 1, + dam = 16, + apr = 0, + atk = 0, + physcrit = 0, + dammod = {wil=1.2}, + melee_project = {}, + } + if self:knowTalent(self.T_DREAM_HAMMER) then + local t = self:getTalentFromId(self.T_DREAM_HAMMER) + combat.dam = 16 + t.getBaseDamage(self, t) + combat.apr = 0 + t.getBaseApr(self, t) + combat.physcrit = 0 + t.getBaseCrit(self, t) + combat.atk = 0 + t.getBaseAtk(self, t) + end + if self:knowTalent(self.T_HAMMER_TOSS) then + local t = self:getTalentFromId(self.T_HAMMER_TOSS) + combat.atk = t.getAttackTotal(self, t) + end + if self:knowTalent(self.T_FORGE_ECHOES) then + local t = self:getTalentFromId(self.T_FORGE_ECHOES) + combat.melee_project = { [engine.DamageType.DREAMFORGE] = t.getProject(self, t) } + end + return combat +end + +newTalent{ + name = "Dream Smith's Hammer", + short_name = "DREAM_HAMMER", + type = {"psionic/dream-smith", 1}, + points = 5, + require = psi_wil_req1, + cooldown = 6, + psi = 5, + requires_target = true, + tactical = { ATTACK = { weapon = 2 } }, + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1.4, 2.1) end, + getBaseDamage = function(self, t) return self:combatTalentMindDamage(t, 0, 60) end, + getBaseAtk = function(self, t) return self:combatTalentMindDamage(t, 0, 20) end, + getBaseApr = function(self, t) return self:combatTalentMindDamage(t, 0, 20) end, + getBaseCrit = function(self, t) return self:combatTalentMindDamage(t, 0, 20) end, + action = function(self, t) + local tg = {type="hit", range=self:getTalentRange(t)} + local x, y, target = self:getTarget(tg) + if not x or not y or not target then return nil end + if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end + local speed, hit = self:attackTargetWith(target, useDreamHammer(self), nil, t.getDamage(self, t)) + game.level.map:particleEmitter(target.x, target.y, 1, "dreamhammer", {tile="shockbolt/object/dream_hammer", tx=target.x, ty=target.y, sx=self.x, sy=self.y}) + + -- Reset Dream Smith talents + if hit then + for tid, cd in pairs(self.talents_cd) do + local tt = self:getTalentFromId(tid) + if tt.type[1]=="psionic/dream-smith" then + self.talents_cd[tid] = 0 + end + end + if rng.percent(50) then + game.level.map:particleEmitter(self.x, self.y, 1, "generic_charge", {rm=225, rM=255, gm=0, gM=0, bm=0, bM=0, am=35, aM=90}) + elseif hit then + game.level.map:particleEmitter(self.x, self.y, 1, "generic_charge", {rm=225, rM=255, gm=225, gM=255, bm=0, bM=0, am=35, aM=90}) + end + game:playSoundNear(self, "talents/heal") + end + + return true + end, + info = function(self, t) + local damage = t.getDamage(self, t) + local weapon_damage = useDreamHammer(self).dam + local weapon_range = useDreamHammer(self).dam * useDreamHammer(self).damrange + local weapon_atk = useDreamHammer(self).atk + local weapon_apr = useDreamHammer(self).apr + local weapon_crit = useDreamHammer(self).physcrit + return ([[Smith a hammer from the dream forge and strike a nearby foe, inflicting %d%% weapon damage. If the attack hits it will bring all Dream Smith talents off cooldown. + The base power, accuracy, armour penetration, and critical strike chance of the weapon will scale with your mindpower. + + Current Dream Hammer Stats + Base Power: %0.2f - %0.2f + Uses Stats: 120%% Wil + Damage Type: Physical + Accuracy is based on willpower for this weapon. + Accuracy Bonus: +%d + Armour Penetration: +%d + Physical Crit. Chance: +%d]]):format(damage * 100, weapon_damage, weapon_range, weapon_atk, weapon_apr, weapon_crit) + end, +} + +newTalent{ + name = "Hammer Toss", + type = {"psionic/dream-smith", 2}, + points = 5, + require = psi_wil_req2, + cooldown = 8, + psi = 10, + tactical = { ATTACKAREA = { weapon = 2 } }, + range = function(self, t) return 5 + self:getTalentLevelRaw(t) end, + requires_target = true, + proj_speed = 10, + target = function(self, t) + return {type="beam", range=self:getTalentRange(t), selffire=false, talent=t, display={display='', particle="arrow", particle_args={tile="shockbolt/object/dream_hammer"}, trail="firetrail"}} + end, + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1, 1.5) end, + getAttack = function(self, t) return self:getTalentLevel(t) * 10 end, -- Used for the talent display + getAttackTotal = function(self, t) + local base_atk = 0 + if self:knowTalent(self.T_DREAM_HAMMER) then + local t = self:getTalentFromId(self.T_DREAM_HAMMER) + base_atk = 0 + t.getBaseAtk(self, t) + end + return base_atk + t.getAttack(self, t) + end, + getDreamHammer = function(self, t) return useDreamHammer(self) end, -- To prevent upvalue issues + action = function(self, t) + local tg = self:getTalentTarget(t) + local x, y = self:getTarget(tg) + if not x or not y then return nil end + local _ _, x, y = self:canProject(tg, x, y) + + print("[Dream Hammer Throw] Projection from", self.x, self.y, "to", x, y) + self:projectile(tg, x, y, function(px, py, tg, self) + local tmp_target = game.level.map(px, py, engine.Map.ACTOR) + if tmp_target and tmp_target ~= self then + local t = self:getTalentFromId(self.T_HAMMER_TOSS) + self:attackTargetWith(tmp_target, t.getDreamHammer(self, t), nil, t.getDamage(self, t)) + end + if x == px and y == py and self and self.x and self.y then + print("[Dream Hammer Return] Projection from", x, y, "to", self.x, self.y) + local tgr = tg + tgr.x, tgr.y = px, py + self:projectile(tgr, self.x, self.y, function(px, py, tgr, self) + local tmp_target = game.level.map(px, py, engine.Map.ACTOR) + local t = self:getTalentFromId(self.T_HAMMER_TOSS) + if tmp_target and tmp_target ~= self then + self:attackTargetWith(tmp_target, t.getDreamHammer(self, t), nil, t.getDamage(self, t)) + end + end) + end + end) + + game:playSoundNear(self, "talents/warp") + return true + end, + info = function(self, t) + local damage = t.getDamage(self, t) + local attack_bonus = t.getAttack(self, t) + return ([[Throw your Dream Hammer at a distant target, inflicting %d%% weapon damage on all creatures between you and it. After reaching it's destination the Dream Hammer will return, potentially hitting creatures a second time. + Learning this talent increases the accuracy of your Dream Hammer by %d.]]):format(damage * 100, attack_bonus) + end, +} + +newTalent{ + name = "Dream Crusher", + type = {"psionic/dream-smith", 3}, + points = 5, + require = psi_wil_req3, + cooldown = 12, + psi = 10, + requires_target = true, + tactical = { ATTACK = { weapon = 2 }, DISABLE = { stun = 2 } }, + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1, 1.5) end, + getMasteryDamage = function(self, t) return self:getTalentLevel(t) * 10 end, + getPercentInc = function(self, t) return math.sqrt(self:getTalentLevel(t) / 5) / 2 end, + getStun = function(self, t) return 2 + math.floor(self:getTalentLevel(t)) end, + action = function(self, t) + local tg = {type="hit", range=self:getTalentRange(t)} + local x, y, target = self:getTarget(tg) + if not x or not y or not target then return nil end + if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end + local speed, hit = self:attackTargetWith(target, useDreamHammer(self), nil, t.getDamage(self, t)) + game.level.map:particleEmitter(target.x, target.y, 1, "dreamhammer", {tile="shockbolt/object/dream_hammer", tx=target.x, ty=target.y, sx=self.x, sy=self.y}) + + -- Try to stun ! + if hit then + if target:canBe("stun") then + target:setEffect(target.EFF_STUNNED, t.getStun(self, t), {apply_power=self:combatMindpower()}) + else + game.logSeen(target, "%s resists the stunning blow!", target.name:capitalize()) + end + if rng.percent(50) then + game.level.map:particleEmitter(target.x, target.y, 1, "generic_discharge", {rm=225, rM=255, gm=0, gM=0, bm=0, bM=0, am=35, aM=90}) + elseif hit then + game.level.map:particleEmitter(target.x, target.y, 1, "generic_discharge", {rm=225, rM=255, gm=225, gM=255, bm=0, bM=0, am=35, aM=90}) + end + game:playSoundNear(self, "talents/lightning_loud") + end + return true + end, + info = function(self, t) + local damage = t.getDamage(self, t) + local power = t.getMasteryDamage(self, t) + local percent = t.getPercentInc(self, t) + local stun = t.getStun(self, t) + return ([[Crush your enemy with your Dream Hammer, inflicting %d%% of weapon damage. If the attack hits, the target is stunned for %d turns. + Stun chance improves with your mindpower. Learning this talent increases your Physical Power for Dream Hammer damage calculations by %d and all damage with Dream Hammer attacks by %d%%. + ]]):format(damage * 100, stun, power, percent * 100) + end, +} + +newTalent{ + name = "Forge Echoes", + type = {"psionic/dream-smith", 4}, + points = 5, + require = psi_wil_req4, + cooldown = 24, + psi = 20, + tactical = { ATTACKAREA = { weapon = 3 } }, + radius = function(self, t) return 1 + math.floor(self:getTalentLevel(t)/2) end, + requires_target = true, + target = function(self, t) + return {type="ball", range=self:getTalentRange(t), radius=self:getTalentRadius(t), friendlyfire=false } + end, + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1, 1.5) end, + getProject = function(self, t) return self:combatTalentMindDamage(t, 10, 50) end, + action = function(self, t) + local tg = {type="hit", range=self:getTalentRange(t)} + local x, y, target = self:getTarget(tg) + if not x or not y or not target then return nil end + if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end + local speed, hit = self:attackTargetWith(target, useDreamHammer(self), nil, t.getDamage(self, t)) + game.level.map:particleEmitter(target.x, target.y, 1, "dreamhammer", {tile="shockbolt/object/dream_hammer", tx=target.x, ty=target.y, sx=self.x, sy=self.y}) + + -- Forge Echoe + if hit then + local tg = self:getTalentTarget(t) + self:project(tg, target.x, target.y, function(px, py, tg, self) + local tmp_target = game.level.map(px, py, Map.ACTOR) + if tmp_target and tmp_target ~= self and tmp_target ~= target then + local hit = self:attackTargetWith(tmp_target, useDreamHammer(self), nil, t.getDamage(self, t)) + if hit and rng.percent(50) then + game.level.map:particleEmitter(tmp_target.x, tmp_target.y, 1, "generic_discharge", {rm=225, rM=255, gm=0, gM=0, bm=0, bM=0, am=35, aM=90}) + elseif hit then + game.level.map:particleEmitter(tmp_target.x, tmp_target.y, 1, "generic_discharge", {rm=225, rM=255, gm=225, gM=255, bm=0, bM=0, am=35, aM=90}) + end + end + end) + game:playSoundNear(self, "talents/echo") + end + return true + end, + info = function(self, t) + local damage = t.getDamage(self, t) + local radius = self:getTalentRadius(t) + local project = t.getProject(self, t) + return ([[Strike the target with a mighty blow from the forge, inflicting %d%% weapon damage. If the attack hits the echo of the attack will lash out at all enemies in a %d radius. + Learning this talent adds %0.2f mind damage and %0.2f burning damage to your Dream Hammer strikes. + The mind and fire damage will scale with your mindpower.]]):format(damage * 100, radius, damDesc(self, DamageType.MIND, project), damDesc(self, DamageType.FIRE, project)) + end, +} \ No newline at end of file diff --git a/game/modules/tome/data/talents/psionic/nightmare.lua b/game/modules/tome/data/talents/psionic/nightmare.lua index 7f62378656..62212ba64c 100644 --- a/game/modules/tome/data/talents/psionic/nightmare.lua +++ b/game/modules/tome/data/talents/psionic/nightmare.lua @@ -107,7 +107,7 @@ newTalent{ local m = target:clone{ shader = "shadow_simulacrum", - shader_args = { color = {0.6, 0.0, 0.3}, base = 0.3, time_factor = 2000 }, + shader_args = { color = {0.6, 0.0, 0.3}, base = 0.6, time_factor = 1500 }, no_drops = true, faction = self.faction, summoner = self, summoner_gain_exp=true, diff --git a/game/modules/tome/data/talents/psionic/psionic.lua b/game/modules/tome/data/talents/psionic/psionic.lua index 2dc38987f8..f9ea48e1ae 100644 --- a/game/modules/tome/data/talents/psionic/psionic.lua +++ b/game/modules/tome/data/talents/psionic/psionic.lua @@ -34,10 +34,11 @@ newTalentType{ allow_random=true, type="psionic/psi-archery", name = "psi-archer newTalentType{ allow_random=true, type="psionic/greater-psi-fighting", name = "greater psi-fighting", description = "Elevate psi-fighting prowess to epic levels." } newTalentType{ allow_random=true, type="psionic/brainstorm", name = "brainstorm", description = "Focus your telekinetic powers in ways undreamed of by most mindslayers." } --- Secret Project... -- Solipsist Talent Trees newTalentType{ allow_random=true, type="psionic/discharge", name = "discharge", description = "Project feedback on the world around you." } newTalentType{ allow_random=true, type="psionic/distortion", name = "distortion", description = "Distort reality with your mental energy." } +newTalentType{ allow_random=true, type="psionic/dream-forge", name = "Dream Forge", description = "Master the dream forge to create powerful armor and effects." } +newTalentType{ allow_random=true, type="psionic/dream-smith", name = "Dream Smith", description = "Call the dream-forge hammer to smite your foes." } newTalentType{ allow_random=true, type="psionic/nightmare", name = "nightmare", description = "Manifest your enemies nightmares." } newTalentType{ allow_random=true, type="psionic/psychic-assault", name = "Psychic Assault", description = "Directly attack your opponents minds." } newTalentType{ allow_random=true, type="psionic/slumber", name = "slumber", description = "Force enemies into a deep sleep." } @@ -261,6 +262,8 @@ load("/data/talents/psionic/grip.lua") -- Solipsist load("/data/talents/psionic/discharge.lua") load("/data/talents/psionic/distortion.lua") +load("/data/talents/psionic/dream-forge.lua") +load("/data/talents/psionic/dream-smith.lua") load("/data/talents/psionic/dreaming.lua") load("/data/talents/psionic/mentalism.lua") load("/data/talents/psionic/feedback.lua") @@ -269,7 +272,7 @@ load("/data/talents/psionic/psychic-assault.lua") load("/data/talents/psionic/slumber.lua") load("/data/talents/psionic/solipsism.lua") load("/data/talents/psionic/thought-forms.lua") -load("/data/talents/psionic/trance.lua") +--load("/data/talents/psionic/trance.lua") load("/data/talents/psionic/possession.lua") diff --git a/game/modules/tome/data/talents/psionic/solipsism.lua b/game/modules/tome/data/talents/psionic/solipsism.lua index 19faccb98b..ff332a191b 100644 --- a/game/modules/tome/data/talents/psionic/solipsism.lua +++ b/game/modules/tome/data/talents/psionic/solipsism.lua @@ -56,7 +56,7 @@ newTalent{ return ([[You believe that your mind is the center of everything. Permanently increases the amount of psi you gain per level by 10 and reduces your life rating (affects life at level up) by 50%% (one time only adjustment). You also have learned to overcome damage with your mind alone and convert %d%% of all damage into Psi damage and %d%% of your healing and life regen now recovers Psi instead of life. The first talent point invested will also increase the amount of Psi you gain from willpower by 1 but reduce the amount of life you gain from constitution by 0.5. - The first talent point also increases your solipsism threshold by 20%% (currently %d%%).]]):format(conversion_ratio * 100, conversion_ratio * 100, self.solipsism_threshold * 100) + The first talent point also increases your solipsism threshold by 20%% (currently %d%%), reducing your global speed by 1%% for each percentage your current Psi falls below this threshold.]]):format(conversion_ratio * 100, conversion_ratio * 100, self.solipsism_threshold * 100) end, } diff --git a/game/modules/tome/data/talents/psionic/thought-forms.lua b/game/modules/tome/data/talents/psionic/thought-forms.lua index 24d8fdc0ea..6473a17d3c 100644 --- a/game/modules/tome/data/talents/psionic/thought-forms.lua +++ b/game/modules/tome/data/talents/psionic/thought-forms.lua @@ -103,6 +103,7 @@ newTalent{ max_life = resolvers.rngavg(100,110), life_rating = 12, combat_armor = 0, combat_def = 0, + stats = { mag=self:getMag(), wil=self:getWil(), cun=self:getCun()}, inc_stats = { str = stat_bonus / 2, dex = stat_bonus, @@ -244,6 +245,7 @@ newTalent{ max_life = resolvers.rngavg(100,110), life_rating = 15, combat_armor = 0, combat_def = 0, + stats = { mag=self:getMag(), wil=self:getWil(), cun=self:getCun()}, inc_stats = { str = stat_bonus, dex = stat_bonus / 2, @@ -384,6 +386,7 @@ newTalent{ max_life = resolvers.rngavg(100,110), life_rating = 15, combat_armor = 0, combat_def = 0, + stats = { mag=self:getMag(), wil=self:getWil(), cun=self:getCun()}, inc_stats = { str = stat_bonus / 2, dex = stat_bonus / 2, @@ -478,7 +481,7 @@ newTalent{ info = function(self, t) local bonus = t.getStatBonus(self, t) local range = self:getTalentRange(t) - return([[Forge a guardian from your thoughts alone. Your guardian's primary stat will be improved by %d and it's two secondary stats by %d. + return([[Forge a guardian from your thoughts alone. Your guardian's primary stat will be improved by %d, it's two secondary stats by %d, and it will have magic, cunning, and willpower equal to your own. At talent level one you may forge a mighty bowman clad in leather armor, at level three a powerful warrior wielding a two-handed weapon, and at level five a strong defender using a sword and shield. Thought forms can only be maintained up to a range of %d and will rematerialize next to you if this range is exceeded. Only one thought-form may be active at a time and the stat bonuses will improve with your mindpower.]]):format(bonus, bonus/2, range) diff --git a/game/modules/tome/data/timed_effects/mental.lua b/game/modules/tome/data/timed_effects/mental.lua index bceca9ef3b..02b97478bf 100644 --- a/game/modules/tome/data/timed_effects/mental.lua +++ b/game/modules/tome/data/timed_effects/mental.lua @@ -2640,8 +2640,8 @@ newEffect{ type = "mental", subtype = { psionic=true }, status = "detrimental", - on_gain = function(self, err) return "#Target# mental functions have been impaired.", "+Sundered Mind" end, - on_lose = function(self, err) return "#Target#'s regains it's senses.", "-Sundered Mind" end, + on_gain = function(self, err) return "#Target#'s mental functions have been impaired.", "+Sundered Mind" end, + on_lose = function(self, err) return "#Target# regains it's senses.", "-Sundered Mind" end, parameters = { power=10 }, on_merge = function(self, old_eff, new_eff) self:removeTemporaryValue("combat_mentalresist", old_eff.sunder) @@ -2658,4 +2658,69 @@ newEffect{ deactivate = function(self, eff) self:removeTemporaryValue("combat_mentalresist", eff.sunder) end, +} + +newEffect{ + name = "BROKEN_DREAM", image = "effects/broken_dream.png", + desc = "Broken Dream", + long_desc = function(self, eff) return ("The target's dreams have been broken by the dreamforge, reducing it's mental save by %d and reducing it's chance of successfully casting a spell by %d%%."):format(eff.power, eff.power) end, + type = "mental", + subtype = { psionic=true, morale=true }, + status = "detrimental", + on_gain = function(self, err) return "#Target#'s dreams have been broken.", "+Broken Dream" end, + on_lose = function(self, err) return "#Target# regains hope.", "-Broken Dream" end, + parameters = { power=10 }, + activate = function(self, eff) + eff.silence = self:addTemporaryValue("spell_failure", eff.power) + eff.sunder = self:addTemporaryValue("combat_mentalresist", -eff.power) + end, + deactivate = function(self, eff) + self:removeTemporaryValue("spell_failure", eff.silence) + self:removeTemporaryValue("combat_mentalresist", eff.sunder) + end, +} + +newEffect{ + name = "FORGE_SHIELD", image = "talents/block.png", + desc = "Forge Shield", + long_desc = function(self, eff) + local e_string = "" + if eff.number == 1 then + e_string = DamageType.dam_def[next(eff.d_types)].name + else + local list = table.keys(eff.d_types) + for i = 1, #list do + list[i] = DamageType.dam_def[list[i]].name + end + e_string = table.concat(list, ", ") + end + local function tchelper(first, rest) + return first:upper()..rest:lower() + end + return ("Absorbs %d damage from the next blockable attack. Currently Blocking: %s."):format(eff.power, e_string:gsub("(%a)([%w_']*)", tchelper)) + end, + type = "mental", + subtype = { psionic=true }, + status = "beneficial", + parameters = { power=1 }, + on_gain = function(self, eff) return nil, nil end, + on_lose = function(self, eff) return nil, nil end, + damage_feedback = function(self, eff, src, value) + if eff.particle and eff.particle._shader and eff.particle._shader.shad and src and src.x and src.y then + local r = -rng.float(0.2, 0.4) + local a = math.atan2(src.y - self.y, src.x - self.x) + eff.particle._shader:setUniform("impact", {math.cos(a) * r, math.sin(a) * r}) + eff.particle._shader:setUniform("impact_tick", core.game.getTime()) + end + end, + activate = function(self, eff) + if core.shader.active() then + eff.particle = self:addParticles(Particles.new("shader_shield", 1, {img="shield2", size_factor=1}, {type="shield", time_factor=12000, color={1.0, 0.5, 0}})) + else + eff.particle = self:addParticles(Particles.new("time_shield_bubble", 1)) + end + end, + deactivate = function(self, eff) + self:removeParticles(eff.particle) + end, } \ No newline at end of file -- GitLab