diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index 1fb5cb51e4eb5e5fa274358577d3793a12d1c25b..7400c153caf805437b50004960385420f07d7877 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -133,6 +133,7 @@ function _M:init(t, no_default) t.stamina_rating = t.stamina_rating or 3 t.positive_negative_rating = t.positive_negative_rating or 3 t.psi_rating = t.psi_rating or 0 + t.inc_resource_multi = t.inc_resource_multi or {} t.esp = t.esp or {} t.esp_range = t.esp_range or 10 @@ -1694,7 +1695,7 @@ function _M:onTakeHit(value, src) if self:knowTalent(self.T_BACKLASH) then if src.y and src.x and not src.dead then local t = self:getTalentFromId(self.T_BACKLASH) - t.doBacklash(self, src, t) + t.doBacklash(self, src, feedback_gain, t) end end end @@ -2411,13 +2412,22 @@ function _M:levelup() end --- Notifies a change of stat value +-- Note inc_resource_multi does not auto-update and talents that use it should manually adjust the pools function _M:onStatChange(stat, v) if stat == self.STAT_CON then - self.max_life = self.max_life + 4 * v + -- life + local multi_life = 4 + (self.inc_resource_multi.life or 0) + self.max_life = self.max_life + multi_life * v elseif stat == self.STAT_WIL then - self:incMaxMana(5 * v) - self:incMaxStamina(2.5 * v) - self:incMaxPsi(1 * v) + -- mana + local multi_mana = 5 + (self.inc_resource_multi.mana or 0) + self:incMaxMana(multi_mana * v) + -- stamina + local multi_stamina = 2.5 + (self.inc_resource_multi.stamina or 0) + self:incMaxStamina(multi_stamina * v) + -- psi + local multi_psi = 1 + (self.inc_resource_multi.psi or 0) + self:incMaxPsi(multi_psi * v) elseif stat == self.STAT_STR then self:checkEncumbrance() end @@ -3216,6 +3226,7 @@ function _M:preUseTalent(ab, silent, fake) end if ab.psi and self:getPsi() < ab.psi * (100 + 2 * self:combatFatigue()) / 100 then if not silent then game.logPlayer(self, "You do not have enough energy to use %s.", ab.name) end + return false end if ab.feedback and self:getFeedback() < ab.feedback * (100 + 2 * self:combatFatigue()) / 100 then if not silent then game.logPlayer(self, "You do not have enough feedback to use %s.", ab.name) end diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index 8bdad5e15b0db75769ab0661f88029c46610d269..b558ad11ee390945895c925f89edd65f48f20a2a 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -79,6 +79,7 @@ function _M:init(t, no_default) t.rank = t.rank or 3 t.old_life = 0 t.old_air = 0 + t.old_psi = 0 t.money_value_multiplier = t.money_value_multiplier or 1 -- changes amounts in gold piles and such @@ -258,6 +259,7 @@ function _M:act() self.old_life = self.life self.old_air = self.air + self.old_psi = self.psi -- Clean log flasher -- game.flash:empty() @@ -300,7 +302,12 @@ function _M:updateMainShader() if self.air < self.max_air / 2 then game.fbo_shader:setUniform("air_warning", 1 - (self.air / self.max_air)) else game.fbo_shader:setUniform("air_warning", 0) end end - + if self:attr("solipsism_threshold") and self.psi ~= self.old_psi then + local solipsism_power = self:attr("solipsism_threshold") - self:getPsi()/self:getMaxPsi() + if solipsism_power > 0 then game.fbo_shader:setUniform("solipsism_warning", solipsism_power) + else game.fbo_shader:setUniform("solipsism_warning", 0) end + end + -- Colorize shader if self:attr("stealth") then game.fbo_shader:setUniform("colorize", {0.9,0.9,0.9,0.6}) elseif self:attr("invisible") then game.fbo_shader:setUniform("colorize", {0.3,0.4,0.9,0.8}) diff --git a/game/modules/tome/class/interface/TooltipsData.lua b/game/modules/tome/class/interface/TooltipsData.lua index 19a0b5677581bc93abc6f9799f4c192abb2562cb..aedd9d1106fa6432da4531b5d54a6044aa4cc565 100644 --- a/game/modules/tome/class/interface/TooltipsData.lua +++ b/game/modules/tome/class/interface/TooltipsData.lua @@ -295,6 +295,9 @@ TOOLTIP_SPELL_COOLDOWN = [[#GOLD#Spellcooldown#LAST# Spell cooldown represents how fast your spells will come off of cooldown. The lower it is the more often you'll be able to use your spell talents and runes. ]] +------------------------------------------------------------- +-- Mental +------------------------------------------------------------- TOOLTIP_MINDPOWER = [[#GOLD#Mindpower#LAST# Your mindpower value represents how powerful your mental abilities are. In addition, when your mental abilities inflict temporary detrimental effects, every point your opponent's relevant saving throw exceeds your mindpower will reduce the duration of the effect by 5%. @@ -304,7 +307,10 @@ Each time you deal damage with a mental attack you may have a chance to make a c Some talents allow you to increase this percentage. It is improved by Cunning. ]] - +TOOLTIP_MIND_SPEED = [[#GOLD#Mental speed#LAST# +Mental speed represents how fast you use psionic abilities compared to a normal turn. +The lower it is the faster it is. +]] ------------------------------------------------------------- -- Damage and resists ------------------------------------------------------------- diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua index 7d86b48ad7dd85a4b5caf8104dbdfb66518cc843..8cd369c24acad180b151fa23a3611fcaf3299e87 100644 --- a/game/modules/tome/data/damage_types.lua +++ b/game/modules/tome/data/damage_types.lua @@ -2099,7 +2099,8 @@ newDamageType{ if target:hasEffect(target.EFF_DISTORTION) then -- Explosive? if dam.explosion then - src:project({type="ball", target.x, target.y, radius=dam.radius}, target.x, target.y, engine.DamageType.DISTORTION, {dam=src:mindCrit(dam.explosion)}, {type="mind"}) + src:project({type="ball", target.x, target.y, radius=dam.radius}, target.x, target.y, engine.DamageType.DISTORTION, {dam=src:mindCrit(dam.explosion)}) + game.level.map:particleEmitter(target.x, target.y, dam.radius, "generic_blast", {radius=dam.radius, tx=target.x, ty=target.y, rm=255, rM=255, gm=180, gM=255, bm=180, bM=255, am=35, aM=90}) dam.explosion_done = true end -- Stun? diff --git a/game/modules/tome/data/gfx/particles/charge.lua b/game/modules/tome/data/gfx/particles/charge.lua index c944b4acd78cb1d6b7d8aa31e51ddf61ecac37d8..c2bf2d34d032f0e280275ffe66379981d1d44fd7 100644 --- a/game/modules/tome/data/gfx/particles/charge.lua +++ b/game/modules/tome/data/gfx/particles/charge.lua @@ -17,35 +17,35 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org -base_size = 32 - return { generator = function() - local life = rng.range(10, 20) - local size = rng.range(15, 20) - local angle = math.rad(rng.range(0, 360)) - local distance = engine.Map.tile_w * rng.float(2, 2.5) - local vel = distance / life + local radius = 0 + local sradius = (radius + 0.5) * (engine.Map.tile_w + engine.Map.tile_h) / 2 + local ad = rng.float(0, 360) + local a = math.rad(ad + 180) + local r = rng.float(0, sradius / 4) + local x = r * math.cos(a) + local y = r * math.sin(a) + local bx = math.floor(x / engine.Map.tile_w) + local by = math.floor(y / engine.Map.tile_h) + local static = rng.percent(40) return { trail = 1, - life = life, - size = size, sizev = 0.2, sizea = 0, + life = 2, + size = 12, sizev = 0, sizea = 0, - x = -size / 2 + distance * math.cos(angle), xv = 0, xa = 0, - y = -size / 2 + distance * math.sin(angle), yv = 0, ya = 0, - dir = angle, dirv = 0, dira = 0, - vel = -vel, velv = 0, vela = 0, + x = x, xv = 0, xa = 0, + y = y, yv = 0, ya = 0, + dir = a, dirv = 0, dira = 0, + vel = sradius / 2 / 24, velv = 0, vela = 0, - r = rng.range(200, 255) / 255, rv = 0, ra = 0, - g = rng.range(200, 255) / 255, gv = 0, ga = 0, - b = rng.range(200, 255) / 255, bv = 0, ba = 0, - a = 0.5, av = 0.01, aa = 0, + r = rng.range(255, 255)/255, rv = 0, ra = 0, + g = rng.range(180, 230)/255, gv = 0, ga = 0, + b = 0, bv = 0, ba = 0, + a = rng.range(25, 220)/255, av = 0, aa = 0, } end, }, function(self) - self.nb = (self.nb or 0) + 1 - if self.nb < 6 then - self.ps:emit(10) - end + self.ps:emit(5) end, -120 +5*2 \ No newline at end of file diff --git a/game/modules/tome/data/gfx/particles/charge_matter.lua b/game/modules/tome/data/gfx/particles/charge_matter.lua index 07cb090c326e89e29f1dcfdccf81f5d4c28c7b62..23e730639257f65e10de01a8d605b7fb0ab2eac5 100644 --- a/game/modules/tome/data/gfx/particles/charge_matter.lua +++ b/game/modules/tome/data/gfx/particles/charge_matter.lua @@ -1,4 +1,4 @@ --- ToME - Tales of Maj'Eyal +-- ToME - Tales of Middle-Earth -- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini -- -- This program is free software: you can redistribute it and/or modify @@ -17,36 +17,41 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org -base_size = 32 +local nb = 0 return { generator = function() - local life = rng.range(10, 20) - local size = rng.range(15, 20) - local angle = math.rad(rng.range(0, 360)) - local distance = engine.Map.tile_w * rng.float(2, 2.5) - local vel = distance / life - + local radius = 0 + local sradius = (radius + 0.5) * (engine.Map.tile_w + engine.Map.tile_h) / 2 + local ad = rng.float(0, 360) + local a = math.rad(ad) + local r = rng.float(0.1, sradius / 2) + local x = r * math.cos(a) + local y = r * math.sin(a) + local bx = math.floor(x / engine.Map.tile_w) + local by = math.floor(y / engine.Map.tile_h) + local static = rng.percent(40) + return { trail = 1, - life = life, - size = size, sizev = 0.2, sizea = 0, + life = 3 + 9 * (sradius - r) / sradius, + size = 3, sizev = 0, sizea = 0, + + x = x, xv = 0, xa = 0, + y = y, yv = 0, ya = 0, + dir = 0, dirv = 0, dira = 0, + vel = 0, velv = 0, vela = 0, - x = -size / 2 + distance * math.cos(angle), xv = 0, xa = 0, - y = -size / 2 + distance * math.sin(angle), yv = 0, ya = 0, - - dir = angle, dirv = 0, dira = 0, - vel = -vel, velv = 0, vela = 0, - r = rng.range(10, 110)/255, rv = 0, ra = 0, - g = rng.range(10, 50)/255, gv = 0.005, ga = 0.0005, - b = rng.range(20, 125)/255, bv = 0, ba = 0, - a = rng.range(25, 255)/255, av = static and -0.034 or 0, aa = 0.005, + r = rng.range(255, 255)/255, rv = 0.005, ra = 0.0005, + g = rng.range(180, 255)/255, gv = 0.005, ga = 0.0005, + b = rng.range(180, 255)/255, bv = 0.005, ba = 0.0005, + a = rng.range(200, 255)/255, av = static and -0.034 or 0, aa = 0.005, } end, }, function(self) - self.nb = (self.nb or 0) + 1 - if self.nb < 6 then - self.ps:emit(10) + if nb < 1 then + self.ps:emit(40) end + nb = nb + 1 end, -120 +40 diff --git a/game/modules/tome/data/gfx/particles/generic_ball.lua b/game/modules/tome/data/gfx/particles/generic_ball.lua new file mode 100644 index 0000000000000000000000000000000000000000..ac538407e87d309365ed0effc94c1b9b5328652d --- /dev/null +++ b/game/modules/tome/data/gfx/particles/generic_ball.lua @@ -0,0 +1,63 @@ +-- 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 nb = 0 +return { generator = function() + local radius = radius + local sradius = (radius + 0.5) * (engine.Map.tile_w + engine.Map.tile_h) / 2 + local ad = rng.float(0, 360) + local a = math.rad(ad) + local r = rng.float(0, sradius / 2) + local x = r * math.cos(a) + local y = r * math.sin(a) + local bx = math.floor(x / engine.Map.tile_w) + local by = math.floor(y / engine.Map.tile_h) + local static = rng.percent(40) + + return { + trail = 1, + life = 30, + size = 3, sizev = 0, sizea = 0, + + x = x, xv = 0, xa = 0, + y = y, yv = 0, ya = 0, + dir = a, dirv = 0, dira = 0, + vel = sradius / 2 / 30, velv = 0, vela = 0, + + r = rng.range(rm, rM)/255, rv = 0, ra = 0, + g = rng.range(gm, gM)/255, gv = 0, ga = 0, + b = rng.range(bm, bM)/255, bv = 0, ba = 0, + a = rng.range(am, aM)/255, av = 0.01, aa = 0, + } +end, }, +function(self) + if nb < 5 then + self.ps:emit(radius*266) + nb = nb + 1 + self.ps:emit(radius*266) + nb = nb + 1 + self.ps:emit(radius*266) + nb = nb + 1 + self.ps:emit(radius*266) + nb = nb + 1 + self.ps:emit(radius*266) + nb = nb + 1 + end +end, +5*radius*266 diff --git a/game/modules/tome/data/gfx/particles/generic_wave.lua b/game/modules/tome/data/gfx/particles/generic_wave.lua new file mode 100644 index 0000000000000000000000000000000000000000..d23851ca39b259f8b0ffb630f022db95c19eef49 --- /dev/null +++ b/game/modules/tome/data/gfx/particles/generic_wave.lua @@ -0,0 +1,63 @@ +-- 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 nb = 12 +local dir = 0 +local spread = spread or 55/2 +local radius = radius or 6 + +dir = math.deg(math.atan2(ty, tx)) + +return { generator = function() + local sradius = (radius + 0.5) * (engine.Map.tile_w + engine.Map.tile_h) / 2 + local ad = rng.float(dir - spread, dir + spread) + local a = math.rad(ad) + local r = 0 + local x = r * math.cos(a) + local y = r * math.sin(a) + local static = rng.percent(40) + local vel = sradius * ((24 - nb * 1.4) / 24) / 6 + + return { + trail = 0, + life = 6, + size = 12 - (12 - nb) * 0.7, sizev = 0, sizea = 2, + + x = x, xv = 0, xa = 0, + y = y, yv = 0, ya = 0, + dir = a, dirv = 0, dira = 0, + vel = rng.float(vel * 0.6, vel * 1.2), velv = 0, vela = 0, + + + r = rng.range(rm, rM)/255, rv = 0.005, ra = 0.0005, + g = rng.range(gm, gM)/255, gv = 0.005, ga = 0.0005, + b = rng.range(bm, bM)/255, bv = 0.005, ba = 0.0005, + a = rng.range(am, aM)/255, av = 0, aa = 0, + } +end, }, +function(self) + if nb > 0 then + local i = math.min(nb, 6) + i = (i * i) * radius + self.ps:emit(i) + nb = nb - 1 + end +end, +30*radius*7*12, +"particle_cloud" diff --git a/game/modules/tome/data/gfx/shaders/main_fbo.frag b/game/modules/tome/data/gfx/shaders/main_fbo.frag index d72f7c363eba4e476fa92ff04866910f09ce879f..d169b8d944e9da97d6dcee13ddce5ce931f61fb7 100644 --- a/game/modules/tome/data/gfx/shaders/main_fbo.frag +++ b/game/modules/tome/data/gfx/shaders/main_fbo.frag @@ -1,5 +1,6 @@ uniform float hp_warning; uniform float air_warning; +uniform float solipsism_warning; uniform float motionblur; uniform float blur; uniform float tick; @@ -121,6 +122,13 @@ void main(void) float dist = length(gl_TexCoord[0].xy - vec2(0.5)) / 2.0; gl_FragColor = mix(gl_FragColor, air_warning_color, dist); } + + if (solipsism_warning > 0.0) + { + vec4 solipsism_warning_color = vec4(solipsism_warning / 2.0, 0.0, solipsism_warning / 2.0, solipsism_warning / 1.3); + float dist = length(gl_TexCoord[0].xy - vec2(0.5)) / 2.0; + gl_FragColor = mix(gl_FragColor, solipsism_warning_color, dist); + } } /*uniform sampler2D tex; diff --git a/game/modules/tome/data/talents/chronomancy/energy.lua b/game/modules/tome/data/talents/chronomancy/energy.lua index fa797b84ba9ca3178970e1deb4ea6b434517b06a..b6fc8150f7e397de7c2732e4164fda5c3b146e4a 100644 --- a/game/modules/tome/data/talents/chronomancy/energy.lua +++ b/game/modules/tome/data/talents/chronomancy/energy.lua @@ -142,8 +142,8 @@ newTalent{ end end target:crossTierEffect(target.EFF_SPELLSHOCKED, self:combatSpellpower()) - game.level.map:particleEmitter(tx, ty, 1, "charge_matter") - game.level.map:particleEmitter(self.x, self.y, 1, "charge") + game.level.map:particleEmitter(tx, ty, 1, "generic_charge", {rm=10, rM=110, gm=10, gM=50, bm=20, bM=125, am=25, aM=255}) + game.level.map:particleEmitter(self.x, self.y, 1, "generic_charge", {rm=200, rM=255, gm=200, gM=255, bm=200, bM=255, am=125, aM=125}) game:playSoundNear(self, "talents/spell_generic") return true end, diff --git a/game/modules/tome/data/talents/chronomancy/spacetime-weaving.lua b/game/modules/tome/data/talents/chronomancy/spacetime-weaving.lua index 95ae1c406915cfb05a8fa62edb6f5ed4be89896f..29eaa632cdb4e764805776f1da76bbc48d9f6e07 100644 --- a/game/modules/tome/data/talents/chronomancy/spacetime-weaving.lua +++ b/game/modules/tome/data/talents/chronomancy/spacetime-weaving.lua @@ -243,6 +243,7 @@ newTalent{ end end, } + entrance.faction = nil game.level:addEntity(entrance) entrance:identify(true) entrance:setKnown(self, true) diff --git a/game/modules/tome/data/talents/psionic/discharge.lua b/game/modules/tome/data/talents/psionic/discharge.lua index 8b1b163a91f21984c8572b29de58047b5b00d9a5..53e0a4184ddf6c2e0b44a785fa38cb0043babf0e 100644 --- a/game/modules/tome/data/talents/psionic/discharge.lua +++ b/game/modules/tome/data/talents/psionic/discharge.lua @@ -17,7 +17,7 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org --- Edge TODO: Sounds, Particles +-- Edge TODO: Sounds newTalent{ name = "Backlash", @@ -30,24 +30,29 @@ newTalent{ target = function(self, t) return {type="hit", range=self:getTalentRange(t), talent=t} end, - doBacklash = function(self, target, t) + doBacklash = function(self, target, value, t) if core.fov.distance(self.x, self.y,target.x, target.y) > self:getTalentRange(t) then return nil end local tg = self:getTalentTarget(t) local a = game.level.map(target.x, target.y, Map.ACTOR) if not a or self:reactionToward(a) >= 0 then return nil end + local damage = math.min(value, t.getDamage(self, t)) -- Divert the Backlash? local wrath = self:hasEffect(self.EFF_FOCUSED_WRATH) - if wrath then - self:project(tg, wrath.target.x, wrath.target.y, DamageType.MIND, self:mindCrit(t.getDamage(self, t), nil, wrath.power), {type="mind", true}) -- No Martyr loops - else - self:project(tg, a.x, a.y, DamageType.MIND, self:mindCrit(t.getDamage(self, t)), {type="mind"}, true) -- No Martyr loops + if damage > 0 then + if wrath then + self:project(tg, wrath.target.x, wrath.target.y, DamageType.MIND, self:mindCrit(damage, nil, wrath.power), nil, true) -- No Martyr loops + game.level.map:particleEmitter(wrath.target.x, wrath.target.y, 1, "generic_discharge", {rm=255, rM=255, gm=180, gM=255, bm=0, bM=0, am=35, aM=90}) + else + self:project(tg, a.x, a.y, DamageType.MIND, self:mindCrit(damage), nil, true) -- No Martyr loops + game.level.map:particleEmitter(a.x, a.y, 1, "generic_discharge", {rm=255, rM=255, gm=180, gM=255, bm=0, bM=0, am=35, aM=90}) + end end end, info = function(self, t) - local damage = t.getDamage(self, t) local range = self:getTalentRange(t) - return ([[Your subconscious now retaliates when you're attacked, inflicting %0.2f mind damage to any creature within a radius of %d when the damage it deals to you results in you gaining at least one Feedback. - The damage will scale with your mindpower.]]):format(damDesc(self, DamageType.MIND, damage), range) + local damage = t.getDamage(self, t) + return ([[Your subconscious now retaliates when you take damage. If the attacker is within range (%d) you'll inflict mind damage equal to the Feedback gained from the attack or %0.2f, whichever is lower. + The damage will scale with your mindpower.]]):format(range, damDesc(self, DamageType.MIND, damage)) end, } @@ -84,10 +89,10 @@ newTalent{ cooldown = 12, tactical = { ATTACKAREA = {MIND = 2}}, requires_target = true, - proj_speed = 20, + proj_speed = 10, range = function(self, t) return 5 + math.min(5, (self:isTalentActive(self.T_MIND_STORM) and self:getTalentLevelRaw(self.T_MIND_STORM)) or 0) end, target = function(self, t) - return {type="bolt", range=self:getTalentRange(t), talent=t, friendlyfire=false, display={particle="bolt_void", trail="dust_trail"}} + return {type="bolt", range=self:getTalentRange(t), talent=t, friendlyfire=false, display={particle="discharge_bolt", trail="lighttrail"}} end, getDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 140) end, getTargetCount = function(self, t) return math.ceil(self:getTalentLevel(t)) end, @@ -142,11 +147,13 @@ newTalent{ end, activate = function(self, t) local ret = { - overcharge = 0 + overcharge = 0, + particles = self:addParticles(Particles.new("ultrashield", 1, {rm=255, rM=255, gm=180, gM=255, bm=0, bM=0, am=35, aM=90, radius=0.2, density=15, life=28, instop=10})) } return ret end, deactivate = function(self, t, p) + self:removeParticles(p.particles) return true end, info = function(self, t) @@ -188,6 +195,7 @@ newTalent{ self:setEffect(self.EFF_FOCUSED_WRATH, t.getDuration(self, t), {target=target, power=t.getCritBonus(self, t)/100}) + game.level.map:particleEmitter(self.x, self.y, 1, "generic_charge", {rm=255, rM=255, gm=180, gM=255, bm=0, bM=0, am=35, aM=90}) return true end, info = function(self, t) diff --git a/game/modules/tome/data/talents/psionic/distortion.lua b/game/modules/tome/data/talents/psionic/distortion.lua index 0906cb9e80456cbc5d05040bb3f3b2a975bfd9f1..94bc626c3f488e7f45a04428c27ebc988e648a04 100644 --- a/game/modules/tome/data/talents/psionic/distortion.lua +++ b/game/modules/tome/data/talents/psionic/distortion.lua @@ -17,7 +17,7 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org --- Edge TODO: Sounds, Particles +-- Edge TODO: Sounds local Object = require "mod.class.Object" @@ -32,10 +32,10 @@ newTalent{ range = 10, radius = function(self, t) return 1 + math.floor(self:getTalentLevel(t)/3) end, requires_target = true, - getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 100) end, + getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 150) end, getDetonateDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 200) end, target = function(self, t) - return {type="bolt", range=self:getTalentRange(t), talent=t, display={particle="bolt_void", trail="dust_trail"}} + return {type="bolt", range=self:getTalentRange(t), talent=t, display={trail="distortion_trail"}} end, action = function(self, t) local tg = self:getTalentTarget(t) @@ -49,7 +49,7 @@ newTalent{ local detonate_damage = t.getDetonateDamage(self, t) local radius = self:getTalentRadius(t) return ([[Fire a bolt of distortion that ignores resistance and inflicts %0.2f physical damage. This damage will distort affected targets, rendering them vulnerable to distortion effects. - If the bolt comes in contact with a target that's already distorted a detonation will occur, inflicting %0.2f physical damage in a %d radius. + If the bolt comes in contact with a target that's already distorted a detonation will occur, inflicting %0.2f physical damage in a radius of %d. The damage will scale with your mindpower.]]):format(damDesc(self, DamageType.PHYSICAL, damage), damDesc(self, DamageType.PHYSICAL, detonate_damage), radius) end, } @@ -75,7 +75,8 @@ newTalent{ local tg = self:getTalentTarget(t) local x, y = self:getTarget(tg) if not x or not y then return nil end - self:project(tg, x, y, DamageType.DISTORTION, {dam=self:mindCrit(t.getDamage(self, t)), knockback=t.getPower(self, t), stun=t.getPower(self, t)}, {type="mind"}) + self:project(tg, x, y, DamageType.DISTORTION, {dam=self:mindCrit(t.getDamage(self, t)), knockback=t.getPower(self, t), stun=t.getPower(self, t)}) + game.level.map:particleEmitter(self.x, self.y, tg.radius, "generic_wave", {radius=tg.radius, tx=x-self.x, ty=y-self.y, rm=255, rM=255, gm=180, gM=255, bm=180, bM=255, am=35, aM=90}) return true end, info = function(self, t) @@ -101,7 +102,7 @@ newTalent{ requires_target = true, direct_hit = true, getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 50) end, - getDuration = function(self, t) return 2 + math.ceil(self:getTalentLevel(t)) end, + getDuration = function(self, t) return 4 + math.floor(self:getTalentLevel(t)) end, target = function(self, t) return {type="hit", range=self:getTalentRange(t), talent=t} end, @@ -141,7 +142,7 @@ newTalent{ psi = 30, tactical = { ATTACK = { PHYSICAL = 2}, DISABLE = 2}, range = 10, - radius = function(self, t) return 3 end, + radius = function(self, t) return math.min(4, 1 + math.ceil(self:getTalentLevel(t)/3)) end, requires_target = true, getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 50) end, getDuration = function(self, t) return 4 + math.ceil(self:getTalentLevel(t)) end, @@ -162,7 +163,7 @@ 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"}}, + 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, always_remember = true, temporary = t.getDuration(self, t), @@ -206,7 +207,7 @@ newTalent{ summoner = self, } - e.particles = game.level.map:particleEmitter(x, y, 3, "leavestide", {only_one=true}) -- Edge TODO: Make particles for this + e.particles = game.level.map:particleEmitter(x, y, e.radius, "generic_vortex", {radius=e.radius, rm=255, rM=255, gm=180, gM=255, bm=180, bM=255, am=35, aM=90}) game.level:addEntity(e) game.level.map(x, y, Map.TERRAIN, e) game.nicer_tiles:updateAround(game.level, x, y) @@ -217,8 +218,9 @@ newTalent{ info = function(self, t) local duration = t.getDuration(self, t) local damage = t.getDamage(self, t) - return ([[Create a powerful maelstorm for %d turns. Each turn the maelstrom will pull in actors within a radius of 3 and inflict %0.2f physical damage. + local radius = self:getTalentRadius(t) + return ([[Create a powerful maelstorm for %d turns. Each turn the maelstrom will pull in actors within a radius of %d and inflict %0.2f physical damage. This damage will distort affected targets, rendering them vulnerable to distortion effects. - The damage will scale with your mindpower.]]):format(duration, damDesc(self, DamageType.PHYSICAL, damage)) + The damage will scale with your mindpower.]]):format(duration, radius, damDesc(self, DamageType.PHYSICAL, damage)) end, } \ No newline at end of file diff --git a/game/modules/tome/data/talents/psionic/dreaming.lua b/game/modules/tome/data/talents/psionic/dreaming.lua index 21bbb906cb398f2d39a9cd9f098f94fcccb977d4..71e5b4c702b884f3f37b22ee4083293e157f0c79 100644 --- a/game/modules/tome/data/talents/psionic/dreaming.lua +++ b/game/modules/tome/data/talents/psionic/dreaming.lua @@ -17,7 +17,7 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org --- Edge TODO: Sounds, Particles, +-- Edge TODO: Sounds newTalent{ name = "Sleep", @@ -64,6 +64,7 @@ newTalent{ if target then if target:canBe("sleep") then target:setEffect(target.EFF_SLEEP, t.getDuration(self, t), {src=self, power=power, waking=is_waking, insomnia=t.getInsomniaDuration(self, t), no_ct_effect=true, apply_power=self:combatMindpower()}) + game.level.map:particleEmitter(target.x, target.y, 1, "generic_charge", {rm=0, rM=0, gm=180, gM=255, bm=180, bM=255, am=35, aM=90}) else game.logSeen(self, "%s resists the sleep!", target.name:capitalize()) end @@ -152,7 +153,7 @@ newTalent{ end end - game.level.map:particleEmitter(self.x, self.y, 1, "teleport") + game.level.map:particleEmitter(x, y, 1, "generic_teleport", {rm=0, rM=0, gm=180, gM=255, bm=180, bM=255, am=35, aM=90}) -- since we're using a precise teleport we'll look for a free grid first local tx, ty = util.findFreeGrid(x, y, 5, true, {[Map.ACTOR]=true}) @@ -162,7 +163,7 @@ newTalent{ end end - game.level.map:particleEmitter(self.x, self.y, 1, "teleport") + game.level.map:particleEmitter(self.x, self.y, 1, "generic_teleport", {rm=0, rM=0, gm=180, gM=255, bm=180, bM=255, am=35, aM=90}) game:playSoundNear(self, "talents/teleport") return true @@ -194,11 +195,13 @@ newTalent{ game:playSoundNear(self, "talents/heal") local ret = { drain = self:addTemporaryValue("psi_regen", -t.getDrain(self, t)), + particles = self:addParticles(engine.Particles.new("ultrashield", 1, {rm=0, rM=0, gm=180, gM=255, bm=180, bM=255, am=70, aM=180, radius=0.8, density=60, life=14, instop=20, static=80})) } return ret end, deactivate = function(self, t, p) self:removeTemporaryValue("psi_regen", p.drain) + self:removeParticles(p.particles) return true end, info = function(self, t) diff --git a/game/modules/tome/data/talents/psionic/feedback.lua b/game/modules/tome/data/talents/psionic/feedback.lua index d6973aaaaadaa7aca47054420d60c7d276e5e3e2..0b47a699b161500b2603ddd29dc49d5b87e5b920 100644 --- a/game/modules/tome/data/talents/psionic/feedback.lua +++ b/game/modules/tome/data/talents/psionic/feedback.lua @@ -17,7 +17,7 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org --- Edge TODO: Sounds, Particles, +-- Edge TODO: Sounds newTalent{ name = "Biofeedback", @@ -112,6 +112,7 @@ newTalent{ self[inc] then self[inc](self, v) end end + game.level.map:particleEmitter(self.x, self.y, 1, "generic_charge", {rm=255, rM=255, gm=180, gM=255, bm=0, bM=0, am=35, aM=90}) return true end, info = function(self, t) diff --git a/game/modules/tome/data/talents/psionic/mentalism.lua b/game/modules/tome/data/talents/psionic/mentalism.lua index eb595b4e1bf5109486b09fe250ebc5b6f5e0f087..0f011aec9e75c197749a1c3ef10f87514621e63d 100644 --- a/game/modules/tome/data/talents/psionic/mentalism.lua +++ b/game/modules/tome/data/talents/psionic/mentalism.lua @@ -17,7 +17,7 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org --- Edge TODO: Sounds, Particles +-- Edge TODO: Sounds local Map = require "engine.Map" @@ -124,7 +124,6 @@ newTalent{ end local m = self:clone{ - shader = "shadow_simulacrum", no_drops = true, faction = self.faction, summoner = self, summoner_gain_exp=true, @@ -237,7 +236,10 @@ newTalent{ local target = game.level.map(x, y, Map.ACTOR) if not target or target == self then return end - target:setEffect(target.EFF_MIND_LINK_TARGET, 10, {power=t.getBonusDamage(self, t), src=self, range=self:getTalentRange(t)}) + target:setEffect(target.EFF_MIND_LINK_TARGET, 10, {power=t.getBonusDamage(self, t), src=self, range=self:getTalentRange(t)*2}) + + game.level.map:particleEmitter(self.x, self.y, 1, "generic_discharge", {rm=0, rM=0, gm=100, gM=180, bm=180, bM=255, am=35, aM=90}) + game.level.map:particleEmitter(target.x, target.y, 1, "generic_discharge", {rm=0, rM=0, gm=100, gM=180, bm=180, bM=255, am=35, aM=90}) local ret = { target = target, @@ -257,8 +259,9 @@ newTalent{ end, info = function(self, t) local damage = t.getBonusDamage(self, t) + local range = self:getTalentRange(t) * 2 return ([[Link minds with the target. While your minds are linked you'll inflict %d%% more mind damage to the target and gain telepathy to it's creature type. - Only one mindlink can be maintained at a time and the effect will break if the target dies or goes beyond the talent range. - The mind damage bonus will scale with your mindpower.]]):format(damage) + Only one mindlink can be maintained at a time and the effect will break if the target dies or goes beyond range (%d)). + The mind damage bonus will scale with your mindpower.]]):format(damage, range) 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 62b44b585accf215fe66c881f55ac3e5a3fc9c46..90e92826728c36a6ffbecb3014c73f44b3a9819f 100644 --- a/game/modules/tome/data/talents/psionic/nightmare.lua +++ b/game/modules/tome/data/talents/psionic/nightmare.lua @@ -17,7 +17,7 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org --- Edge TODO: Sounds, Particles, +-- Edge TODO: Sounds newTalent{ name = "Nightmare", @@ -69,6 +69,9 @@ newTalent{ end end end) + + game.level.map:particleEmitter(self.x, self.y, tg.radius, "generic_wave", {radius=tg.radius, tx=x-self.x, ty=y-self.y, rm=60, rM=130, gm=20, gM=110, bm=90, bM=130, am=35, aM=90}) + return true end, info = function(self, t) @@ -106,6 +109,7 @@ newTalent{ local m = target:clone{ shader = "shadow_simulacrum", + shader_args = { color = {0.6, 0.0, 0.3}, base = 0.3, time_factor = 2000 }, no_drops = true, faction = self.faction, summoner = self, summoner_gain_exp=true, @@ -138,6 +142,10 @@ newTalent{ m.can_talk = nil m.clone_on_hit = nil + -- Inner Demon's never flee + m.ai_tactic = m.ai_tactic or {} + m.ai_tactic.escape = 0 + -- Remove some talents local tids = {} for tid, _ in pairs(m.talents) do @@ -166,7 +174,7 @@ newTalent{ end game.zone:addEntity(game.level, m, "actor", x, y) - game.level.map:particleEmitter(x, y, 1, "shadow") + game.level.map:particleEmitter(x, y, 1, "generic_teleport", {rm=60, rM=130, gm=20, gM=110, bm=90, bM=130, am=70, aM=180}) game.logSeen(target, "#F53CBE#%s's Inner Demon manifests!", target.name:capitalize()) @@ -230,6 +238,7 @@ newTalent{ if target:attr("sleep") then chance = chance * 2 end if target:canBe("fear") then target:setEffect(target.EFF_WAKING_NIGHTMARE, t.getDuration(self, t), {src = self, chance=t.getChance(self, t), dam=self:mindCrit(t.getDamage(self, t)), apply_power=self:combatMindpower()}) + game.level.map:particleEmitter(target.x, target.y, 1, "generic_charge", {rm=60, rM=130, gm=20, gM=110, bm=90, bM=130, am=70, aM=180}) else game.logSeen(target, "%s resists the nightmare!", target.name:capitalize()) end @@ -308,7 +317,7 @@ newTalent{ m:forceLevelup(self.level) game.zone:addEntity(game.level, m, "actor", x, y) - game.level.map:particleEmitter(x, y, 1, "shadow") + game.level.map:particleEmitter(x, y, 1, "generic_teleport", {rm=60, rM=130, gm=20, gM=110, bm=90, bM=130, am=70, aM=180}) if game.party:hasMember(self) then game.party:addMember(m, { @@ -324,11 +333,13 @@ newTalent{ game:playSoundNear(self, "talents/heal") local ret = { damage = self:addTemporaryValue("night_terror", t.getDamageBonus(self, t)), + particle = self:addParticles(Particles.new("ultrashield", 1, {rm=60, rM=130, gm=20, gM=110, bm=90, bM=130, am=70, aM=180, radius=0.4, density=60, life=14, instop=20})), } return ret end, deactivate = function(self, t, p) self:removeTemporaryValue("night_terror", p.damage) + self:removeParticles(p.particle) return true end, info = function(self, t) diff --git a/game/modules/tome/data/talents/psionic/psionic.lua b/game/modules/tome/data/talents/psionic/psionic.lua index 0a03f15400522f23396559e2b194beeb14e704db..2c7c858b8701ab0ed7dc64906ece25963ac67558 100644 --- a/game/modules/tome/data/talents/psionic/psionic.lua +++ b/game/modules/tome/data/talents/psionic/psionic.lua @@ -236,11 +236,13 @@ function setupThoughtForm(self, m, x, y) m:resolve() m:resolve(nil, true) m:forceLevelup(self.level) game.zone:addEntity(game.level, m, "actor", x, y) - game.level.map:particleEmitter(x, y, 1, "summon") + game.level.map:particleEmitter(x, y, 1, "generic_teleport", {rm=225, rM=255, gm=225, gM=255, bm=225, bM=255, am=35, aM=90}) - -- Summons never flee - m.ai_tactic = m.ai_tactic or {} - m.ai_tactic.escape = 0 + -- Summons never flee... unless they're bowmen + if m.name ~= "thought-forged bowman" then + m.ai_tactic = m.ai_tactic or {} + m.ai_tactic.escape = 0 + end end load("/data/talents/psionic/absorption.lua") diff --git a/game/modules/tome/data/talents/psionic/psychic-assault.lua b/game/modules/tome/data/talents/psionic/psychic-assault.lua index cd6c9f5c7dc06568fd1943ea04d15fc0e8965492..77720f24a1673a9ddb2d6e3997383dd4a493fb55 100644 --- a/game/modules/tome/data/talents/psionic/psychic-assault.lua +++ b/game/modules/tome/data/talents/psionic/psychic-assault.lua @@ -17,7 +17,7 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org --- Edge TODO: Sounds, Particles +-- Edge TODO: Sounds newTalent{ name = "Sunder Mind", @@ -42,7 +42,7 @@ newTalent{ if not target then return end local dam =self:mindCrit(t.getDamage(self, t)) - self:project(tg, x, y, DamageType.MIND, {dam=dam, alwaysHit=true}) + self:project(tg, x, y, DamageType.MIND, {dam=dam, alwaysHit=true}, {type="mind"}) target:setEffect(target.EFF_SUNDER_MIND, 2, {power=dam/10}) return true @@ -146,7 +146,8 @@ newTalent{ getDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 200) end, action = function(self, t) local tg = self:getTalentTarget(t) - self:project(tg, self.x, self.y, DamageType.MIND, {dam=self:mindCrit(self:combatTalentMindDamage(t, 20, 200)), crossTierChance=100}, {type="mind"}) + self:project(tg, self.x, self.y, DamageType.MIND, {dam=self:mindCrit(self:combatTalentMindDamage(t, 20, 200)), crossTierChance=100} ) + game.level.map:particleEmitter(self.x, self.y, self:getTalentRadius(t), "generic_ball", {radius=self:getTalentRadius(t), rm=100, rM=125, gm=100, gM=125, bm=100, bM=125, am=200, aM=255}) game:playSoundNear(self, "talents/spell_generic") return true end, diff --git a/game/modules/tome/data/talents/psionic/slumber.lua b/game/modules/tome/data/talents/psionic/slumber.lua index bc8ae5ac1dc0a77f38701288771560dc97c1d452..01b29d2851e46bcc0fb6252043c589a94ac906ed 100644 --- a/game/modules/tome/data/talents/psionic/slumber.lua +++ b/game/modules/tome/data/talents/psionic/slumber.lua @@ -17,7 +17,7 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org --- Edge TODO: Sounds, Particles, +-- Edge TODO: Sounds newTalent{ name = "Slumber", @@ -51,6 +51,7 @@ newTalent{ local t2 = game.level.map(tx, ty, Map.ACTOR) if t2 and target_two ~= target and rng.percent(p.contagious) and t2:canBe("sleep") then t2:setEffect(t2.EFF_SLEEP, math.floor(p.dur/2), {src=self, power=p.power/10, waking=p.waking, insomnia=math.ceil(p.insomnia/2), no_ct_effect=true, apply_power=self:combatMindpower()}) + game.level.map:particleEmitter(target.x, target.y, 1, "generic_charge", {rm=0, rM=0, gm=100, gM=200, bm=200, bM=255, am=35, aM=90}) end end) end, @@ -77,6 +78,7 @@ newTalent{ local power = self:mindCrit(t.getSleepPower(self, t)) if target:canBe("sleep") then target:setEffect(target.EFF_SLUMBER, t.getDuration(self, t), {src=self, power=power, waking=is_waking, contagious=is_contagious, insomnia=t.getInsomniaDuration(self, t), no_ct_effect=true, apply_power=self:combatMindpower()}) + game.level.map:particleEmitter(target.x, target.y, 1, "generic_charge", {rm=180, rM=200, gm=100, gM=120, bm=30, bM=50, am=70, aM=180}) else game.logSeen(self, "%s resists the sleep!", target.name:capitalize()) end @@ -196,7 +198,7 @@ newTalent{ local x1, y1 = util.findFreeGrid(4, 6, 20, true, {[Map.ACTOR]=true}) if x1 then self:move(x1, y1, true) - game.level.map:particleEmitter(x1, y1, 1, "teleport") + game.level.map:particleEmitter(x1, y1, 1, "generic_teleport", {rm=0, rM=0, gm=180, gM=255, bm=180, bM=255, am=35, aM=90}) end local x2, y2 = util.findFreeGrid(8, 6, 20, true, {[Map.ACTOR]=true}) if x2 then diff --git a/game/modules/tome/data/talents/psionic/solipsism.lua b/game/modules/tome/data/talents/psionic/solipsism.lua index f15d98f521cb71e6609dd6c8d5296070bd568982..a34826e1292996686b153225244839722bf838e8 100644 --- a/game/modules/tome/data/talents/psionic/solipsism.lua +++ b/game/modules/tome/data/talents/psionic/solipsism.lua @@ -18,7 +18,7 @@ -- darkgod@te4.org --- Edge TODO: Sounds, Particles +-- Edge TODO: Sounds newTalent{ name = "Solipsism", @@ -30,15 +30,21 @@ newTalent{ getConversionRatio = function(self, t) return math.min(self:getTalentLevel(t) * 0.13, 1) end, on_learn = function(self, t) if self:getTalentLevelRaw(t) == 1 then - self.solipsism_threshold = (self.solipsism_threshold or 0) + 0.2 - self:incMaxPsi(50) + self:incMaxPsi((self:getWil()-10) * 1) + self.max_life = self.max_life - (self:getCon()-10) * 0.5 + self.inc_resource_multi.psi = (self.inc_resource_multi.psi or 0) + 1 + self.inc_resource_multi.life = (self.inc_resource_multi.life or 0) - 0.5 self.life_rating = math.ceil(self.life_rating/2) self.psi_rating = self.psi_rating + 10 + self.solipsism_threshold = (self.solipsism_threshold or 0) + 0.2 end end, on_unlearn = function(self, t) if not self:knowTalent(t) then - self:incMaxPsi(-50) + self:incMaxPsi(-(self:getWil()-10) * 1) + self.max_life = self.max_life + (self:getCon()-10) * 0.5 + self.inc_resource_multi.psi = self.inc_resource_multi.psi - 1 + self.inc_resource_multi.life = self.inc_resource_multi.life + 0.5 self.solipsism_threshold = self.solipsism_threshold - 0.2 end end, @@ -46,7 +52,8 @@ newTalent{ local conversion_ratio = t.getConversionRatio(self, t) 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 your max Psi by 50 and your solipsism threshold by 20%%, reducing global speed if your Psi falls below the threshold (currently %d%%).]]):format(conversion_ratio * 100, conversion_ratio * 100, self.solipsism_threshold * 100) + 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) end, } @@ -59,20 +66,27 @@ newTalent{ getBalanceRatio = function(self, t) return math.min(self:getTalentLevel(t) * 0.13, 1) end, on_learn = function(self, t) if self:getTalentLevelRaw(t) == 1 then - self:incMaxPsi(50) + self:incMaxPsi((self:getWil()-10) * 1) + self.max_life = self.max_life - (self:getCon()-10) * 0.5 + self.inc_resource_multi.psi = (self.inc_resource_multi.psi or 0) + 1 + self.inc_resource_multi.life = (self.inc_resource_multi.life or 0) - 0.5 self.solipsism_threshold = (self.solipsism_threshold or 0) + 0.1 end end, on_unlearn = function(self, t) if not self:knowTalent(t) then - self:incMaxPsi(-50) + self:incMaxPsi(-(self:getWil()-10) * 1) + self.max_life = self.max_life + (self:getCon()-10) * 0.5 + self.inc_resource_multi.psi = self.inc_resource_multi.psi - 1 + self.inc_resource_multi.life = self.inc_resource_multi.life + 0.5 self.solipsism_threshold = self.solipsism_threshold - 0.1 end end, info = function(self, t) local ratio = t.getBalanceRatio(self, t) * 100 return ([[You now substitute %d%% of your mental save for %d%% of your physical and spell saves throws (so at 100%% you would effectively use mental save for all saving throw rolls). - The first talent point invested will also increase your max Psi by 50 and your solipsism threshold by 10%% (currently %d%%).]]):format(ratio, ratio, self.solipsism_threshold * 100) + 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. + Learning this talent also increases your solipsism threshold by 10%% (currently %d%%).]]):format(ratio, ratio, self.solipsism_threshold * 100) end, } @@ -86,14 +100,20 @@ newTalent{ on_learn = function(self, t) self.clarity_threshold = t.getClarityThreshold(self, t) if self:getTalentLevelRaw(t) == 1 then - self:incMaxPsi(50) + self:incMaxPsi((self:getWil()-10) * 1) + self.max_life = self.max_life - (self:getCon()-10) * 0.5 + self.inc_resource_multi.psi = (self.inc_resource_multi.psi or 0) + 1 + self.inc_resource_multi.life = (self.inc_resource_multi.life or 0) - 0.5 self.solipsism_threshold = (self.solipsism_threshold or 0) + 0.1 end end, on_unlearn = function(self, t) if not self:knowTalent(t) then self.clarity_threshold = nil - self:incMaxPsi(-50) + self:incMaxPsi(-(self:getWil()-10) * 1) + self.max_life = self.max_life + (self:getCon()-10) * 0.5 + self.inc_resource_multi.psi = self.inc_resource_multi.psi - 1 + self.inc_resource_multi.life = self.inc_resource_multi.life + 0.5 self.solipsism_threshold = self.solipsism_threshold - 0.1 else self.clarity_threshold = t.getClarityThreshold(self, t) @@ -102,7 +122,8 @@ newTalent{ info = function(self, t) local threshold = t.getClarityThreshold(self, t) return ([[For every percent that your Psi pool exceeds %d%% you gain 1%% global speed (up to a maximum of 50%%). - The first talent point invested will also increase your max Psi by 50 and your solipsism threshold by 10%% (currently %d%%).]]):format(threshold * 100, self.solipsism_threshold * 100) + 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 10%% (currently %d%%).]]):format(threshold * 100, self.solipsism_threshold * 100) end, } @@ -115,21 +136,27 @@ newTalent{ getSavePercentage = function(self, t) return math.min(2, self:getTalentLevel(t)/4) end, on_learn = function(self, t) if self:getTalentLevelRaw(t) == 1 then - self:incMaxPsi(50) + self:incMaxPsi((self:getWil()-10) * 1) + self.max_life = self.max_life - (self:getCon()-10) * 0.5 + self.inc_resource_multi.psi = (self.inc_resource_multi.psi or 0) + 1 + self.inc_resource_multi.life = (self.inc_resource_multi.life or 0) - 0.5 self.solipsism_threshold = (self.solipsism_threshold or 0) + 0.1 end end, on_unlearn = function(self, t) if not self:knowTalent(t) then - self:incMaxPsi(-50) + self:incMaxPsi(-(self:getWil()-10) * 1) + self.max_life = self.max_life + (self:getCon()-10) * 0.5 + self.inc_resource_multi.psi = self.inc_resource_multi.psi - 1 + self.inc_resource_multi.life = self.inc_resource_multi.life + 0.5 self.solipsism_threshold = self.solipsism_threshold - 0.1 end end, doDismissalOnHit = function(self, value, src, t) - local saving_throw = self:mindCrit(t.getSavePercentage(self, t)) + local saving_throw = self:mindCrit(self:combatMentalResist(), t.getSavePercentage(self, t)) print("[Dismissal] ", self.name:capitalize(), " attempting to ignore ", value, "damage from ", src.name:capitalize(), "using", saving_throw, "mental save.") - if self:checkHit(math.floor(saving_throw), value) then - game.logSeen(self, "%s dismisses %s's attack!", self.name:capitalize(), src.name:capitalize()) + if self:checkHit(saving_throw, value) then + game.logSeen(self, "%s dismisses %s's damage!", self.name:capitalize(), src.name:capitalize()) return 0 else return value @@ -138,6 +165,7 @@ newTalent{ info = function(self, t) local save_percentage = t.getSavePercentage(self, t) return ([[Each time you take damage you roll %d%% of your mental save against it. If the saving throw succeeds the damage will be reduced to 0. - The first talent point invested will also increase your max Psi by 50 and your solipsism threshold by 10%% (currently %d%%).]]):format(save_percentage * 100, self.solipsism_threshold * 100) + 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 10%% (currently %d%%).]]):format(save_percentage * 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 700511fef6f478c4261082b1ec3cc33589156508..8b2bfe23a0e3ac9c402f392a16977875d8c5c632 100644 --- a/game/modules/tome/data/talents/psionic/thought-forms.lua +++ b/game/modules/tome/data/talents/psionic/thought-forms.lua @@ -17,12 +17,12 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org --- Edge TODO: Sounds, Particles, +-- Edge TODO: Sounds -- Thought Forms newTalent{ - name = "Thought-Form: Warrior", - short_name = "TF_WARRIOR", + name = "Thought-Form: Bowman", + short_name = "TF_BOWMAN", type = {"psionic/other", 1}, points = 5, require = psi_wil_req1, @@ -48,14 +48,16 @@ newTalent{ return end - -- Do our stat bonuses here so we only roll for crit once + -- Do our stat bonuses here so we only roll for crit once local stat_bonus = math.floor(self:mindCrit(t.getStatBonus(self, t))) local NPC = require "mod.class.NPC" local m = NPC.new{ - name = "thought-forged warrior", summoner = self, - desc = [[A thought-forged warrior wielding a massive hammer and clad in heavy armor. It appears ready for battle.]], - body = { INVEN = 10, MAINHAND = 1, BODY = 1, HANDS = 1, FEET = 1}, + name = "thought-forged bowman", summoner = self, + shader = "shadow_simulacrum", + shader_args = { color = {0.8, 0.8, 0.8}, base = 0.8, time_factor = 4000 }, + desc = [[A thought-forged bowman. It appears ready for battle.]], + body = { INVEN = 10, MAINHAND = 1, BODY = 1, QUIVER=1, HANDS = 1, FEET = 1}, -- Make a moddable tile resolvers.generic(function(e) if e.summoner.female then @@ -69,8 +71,8 @@ newTalent{ -- Disable our sustain when we die on_die = function(self) game:onTickEnd(function() - if self.summoner:isTalentActive(self.summoner.T_TF_WARRIOR) then - self.summoner:forceUseTalent(self.summoner.T_TF_WARRIOR, {ignore_energy=true}) + if self.summoner:isTalentActive(self.summoner.T_TF_BOWMAN) then + self.summoner:forceUseTalent(self.summoner.T_TF_BOWMAN, {ignore_energy=true}) end if self.summoner:isTalentActive(self.summoner.T_OVER_MIND) then self.summoner:forceUseTalent(self.summoner.T_OVER_MIND, {ignore_energy=true}) @@ -79,7 +81,7 @@ newTalent{ end, -- Keep them on a leash on_act = function(self) - local t = self.summoner:getTalentFromId(self.summoner.T_TF_WARRIOR) + local t = self.summoner:getTalentFromId(self.summoner.T_TF_BOWMAN) if not game.level:hasEntity(self.summoner) or core.fov.distance(self.x, self.y, self.summoner.x, self.summoner.y) > self.summoner:getTalentRange(t) then local Map = require "engine.Map" local x, y = util.findFreeGrid(self.summoner.x, self.summoner.y, 5, true, {[Map.ACTOR]=true}) @@ -89,39 +91,40 @@ newTalent{ -- Clear it's targeting on teleport self.ai_target.actor = nil self:move(x, y, true) - game.level.map:particleEmitter(x, y, 1, "summon") + game.level.map:particleEmitter(x, y, 1, "generic_teleport", {rm=225, rM=255, gm=225, gM=255, bm=225, bM=255, am=35, aM=90}) end end, - + ai = "summoned", ai_real = "tactical", ai_state = { ai_move="move_dmap", talent_in=3, ally_compassion=10 }, - ai_tactic = resolvers.tactic("melee"), + ai_tactic = resolvers.tactic("ranged"), max_life = resolvers.rngavg(100,110), - life_rating = 15, + life_rating = 12, combat_armor = 0, combat_def = 0, inc_stats = { - str = stat_bonus, - dex = stat_bonus / 2, + str = stat_bonus / 2, + dex = stat_bonus, con = stat_bonus / 2, }, resolvers.talents{ - [Talents.T_ARMOUR_TRAINING]= 3, + [Talents.T_HEAVE]= math.ceil(self.level/10), [Talents.T_WEAPON_COMBAT]= math.ceil(self.level/10), - [Talents.T_WEAPONS_MASTERY]= math.ceil(self.level/10), + [Talents.T_BOW_MASTERY]= math.ceil(self.level/10), + + [Talents.T_STEADY_SHOT]= math.ceil(self.level/10), + [Talents.T_RAPID_SHOT]= math.ceil(self.level/10), - [Talents.T_RUSH]= math.ceil(self.level/10), - [Talents.T_DEATH_DANCE]= math.ceil(self.level/10), - [Talents.T_BERSERKER]= math.ceil(self.level/10), [Talents.T_PSYCHOMETRY]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)), [Talents.T_BIOFEEDBACK]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)), [Talents.T_LUCID_DREAMER]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)), }, resolvers.equip{ - {type="weapon", subtype="greatmaul", autoreq=true, forbid_power_source={arcane=true, technique=true} }, - {type="armor", subtype="heavy", autoreq=true, forbid_power_source={arcane=true, technique=true} }, + {type="weapon", subtype="longbow", autoreq=true, forbid_power_source={arcane=true, technique=true} }, + {type="ammo", subtype="arrow", autoreq=true, forbid_power_source={arcane=true, technique=true} }, + {type="armor", subtype="light", autoreq=true, forbid_power_source={arcane=true, technique=true} }, {type="armor", subtype="hands", autoreq=true, forbid_power_source={arcane=true, technique=true} }, {type="armor", subtype="feet", autoreq=true, forbid_power_source={arcane=true, technique=true} }, }, @@ -137,25 +140,25 @@ newTalent{ } if self:knowTalent(self.T_TF_UNITY) then local t = self:getTalentFromId(self.T_TF_UNITY) - ret.power = self:addTemporaryValue("combat_mindpower", t.getOffensePower(self, t)) + ret.speed = self:addTemporaryValue("combat_mindspeed", t.getSpeedPower(self, t)/100) end return ret end, deactivate = function(self, t, p) p.summon:die(p.summon) - if p.power then self:removeTemporaryValue("combat_mindpower", p.power) end + if p.speed then self:removeTemporaryValue("combat_mindspeed", p.speed) end return true end, info = function(self, t) local stat = t.getStatBonus(self, t) - return ([[Forge a warrior wielding a greatmaul from your thoughts. The warrior learns weapon mastery, combat accuracy, berserker, death dance, and rush as it levels up and has %d improved strength, %d dexterity, and %d constitution. - The stat bonuses will improve with your mindpower.]]):format(stat, stat/2, stat/2) + return ([[Forge a bowman clad in leather armor from your thoughts. The bowman learns heave, bow mastery, combat accuracy, steady shot, and rapid shot as it levels up and has %d improved strength, %d dexterity, and %d constitution. + The stat bonuses will improve with your mindpower.]]):format(stat/2, stat, stat/2) end, } newTalent{ - name = "Thought-Form: Defender", - short_name = "TF_DEFENDER", + name = "Thought-Form: Warrior", + short_name = "TF_WARRIOR", type = {"psionic/other", 1}, points = 5, require = psi_wil_req1, @@ -181,14 +184,16 @@ newTalent{ return end - -- Do our stat bonuses here so we only roll for crit once + -- Do our stat bonuses here so we only roll for crit once local stat_bonus = math.floor(self:mindCrit(t.getStatBonus(self, t))) local NPC = require "mod.class.NPC" local m = NPC.new{ - name = "thought-forged defender", summoner = self, - desc = [[A thought-forged defender clad in massive armor. It wields a sword and shield and appears ready for battle.]], - body = { INVEN = 10, MAINHAND = 1, OFFHAND = 1, BODY = 1, HANDS = 1, FEET = 1}, + name = "thought-forged warrior", summoner = self, + shader = "shadow_simulacrum", + shader_args = { color = {0.8, 0.8, 0.8}, base = 0.8, time_factor = 4000 }, + desc = [[A thought-forged warrior wielding a massive hammer and clad in heavy armor. It appears ready for battle.]], + body = { INVEN = 10, MAINHAND = 1, BODY = 1, HANDS = 1, FEET = 1}, -- Make a moddable tile resolvers.generic(function(e) if e.summoner.female then @@ -202,8 +207,8 @@ newTalent{ -- Disable our sustain when we die on_die = function(self) game:onTickEnd(function() - if self.summoner:isTalentActive(self.summoner.T_TF_DEFENDER) then - self.summoner:forceUseTalent(self.summoner.T_TF_DEFENDER, {ignore_energy=true}) + if self.summoner:isTalentActive(self.summoner.T_TF_WARRIOR) then + self.summoner:forceUseTalent(self.summoner.T_TF_WARRIOR, {ignore_energy=true}) end if self.summoner:isTalentActive(self.summoner.T_OVER_MIND) then self.summoner:forceUseTalent(self.summoner.T_OVER_MIND, {ignore_energy=true}) @@ -212,7 +217,7 @@ newTalent{ end, -- Keep them on a leash on_act = function(self) - local t = self.summoner:getTalentFromId(self.summoner.T_TF_DEFENDER) + local t = self.summoner:getTalentFromId(self.summoner.T_TF_WARRIOR) if not game.level:hasEntity(self.summoner) or core.fov.distance(self.x, self.y, self.summoner.x, self.summoner.y) > self.summoner:getTalentRange(t) then local Map = require "engine.Map" local x, y = util.findFreeGrid(self.summoner.x, self.summoner.y, 5, true, {[Map.ACTOR]=true}) @@ -222,41 +227,39 @@ newTalent{ -- Clear it's targeting on teleport self.ai_target.actor = nil self:move(x, y, true) - game.level.map:particleEmitter(x, y, 1, "summon") + game.level.map:particleEmitter(x, y, 1, "generic_teleport", {rm=225, rM=255, gm=225, gM=255, bm=225, bM=255, am=35, aM=90}) end - end, + end, ai = "summoned", ai_real = "tactical", ai_state = { ai_move="move_dmap", talent_in=3, ally_compassion=10 }, - ai_tactic = resolvers.tactic("tank"), + ai_tactic = resolvers.tactic("melee"), max_life = resolvers.rngavg(100,110), life_rating = 15, combat_armor = 0, combat_def = 0, inc_stats = { - str = stat_bonus / 2, + str = stat_bonus, dex = stat_bonus / 2, - con = stat_bonus, + con = stat_bonus / 2, }, resolvers.talents{ - [Talents.T_ARMOUR_TRAINING]= 3 + math.ceil(self.level/10), + [Talents.T_ARMOUR_TRAINING]= 3, [Talents.T_WEAPON_COMBAT]= math.ceil(self.level/10), [Talents.T_WEAPONS_MASTERY]= math.ceil(self.level/10), - [Talents.T_SHIELD_PUMMEL]= math.ceil(self.level/10), - [Talents.T_SHIELD_WALL]= math.ceil(self.level/10), - + [Talents.T_RUSH]= math.ceil(self.level/10), + [Talents.T_DEATH_DANCE]= math.ceil(self.level/10), + [Talents.T_BERSERKER]= math.ceil(self.level/10), [Talents.T_PSYCHOMETRY]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)), [Talents.T_BIOFEEDBACK]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)), [Talents.T_LUCID_DREAMER]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)), - }, resolvers.equip{ - {type="weapon", subtype="longsword", autoreq=true, forbid_power_source={arcane=true, technique=true} }, - {type="armor", subtype="shield", autoreq=true, forbid_power_source={arcane=true, technique=true} }, - {type="armor", subtype="massive", autoreq=true, forbid_power_source={arcane=true, technique=true} }, + {type="weapon", subtype="battleaxe", autoreq=true, forbid_power_source={arcane=true, technique=true} }, + {type="armor", subtype="heavy", autoreq=true, forbid_power_source={arcane=true, technique=true} }, {type="armor", subtype="hands", autoreq=true, forbid_power_source={arcane=true, technique=true} }, {type="armor", subtype="feet", autoreq=true, forbid_power_source={arcane=true, technique=true} }, }, @@ -272,25 +275,25 @@ newTalent{ } if self:knowTalent(self.T_TF_UNITY) then local t = self:getTalentFromId(self.T_TF_UNITY) - ret.resist = self:addTemporaryValue("resists", {all= t.getDefensePower(self, t)}) + ret.power = self:addTemporaryValue("combat_mindpower", t.getOffensePower(self, t)) end return ret end, deactivate = function(self, t, p) p.summon:die(p.summon) - if p.resist then self:removeTemporaryValue("resists", p.resist) end + if p.power then self:removeTemporaryValue("combat_mindpower", p.power) end return true end, info = function(self, t) local stat = t.getStatBonus(self, t) - return ([[Forge a defender wielding a sword and shield from your thoughts. The solider learns armor training, weapon mastery, combat accuracy, shield pummel, and shield wall as it levels up and has %d improved strength, %d dexterity, and %d constitution. - The stat bonuses will improve with your mindpower.]]):format(stat/2, stat/2, stat) + return ([[Forge a warrior wielding a battle-axe from your thoughts. The warrior learns weapon mastery, combat accuracy, berserker, death dance, and rush as it levels up and has %d improved strength, %d dexterity, and %d constitution. + The stat bonuses will improve with your mindpower.]]):format(stat, stat/2, stat/2) end, } newTalent{ - name = "Thought-Form: Bowman", - short_name = "TF_BOWMAN", + name = "Thought-Form: Defender", + short_name = "TF_DEFENDER", type = {"psionic/other", 1}, points = 5, require = psi_wil_req1, @@ -321,9 +324,11 @@ newTalent{ local NPC = require "mod.class.NPC" local m = NPC.new{ - name = "thought-forged bowman", summoner = self, - desc = [[A thought-forged bowman. It appears ready for battle.]], - body = { INVEN = 10, MAINHAND = 1, BODY = 1, QUIVER=1, HANDS = 1, FEET = 1}, + name = "thought-forged defender", summoner = self, + shader = "shadow_simulacrum", + shader_args = { color = {0.8, 0.8, 0.8}, base = 0.8, time_factor = 4000 }, + desc = [[A thought-forged defender clad in massive armor. It wields a sword and shield and appears ready for battle.]], + body = { INVEN = 10, MAINHAND = 1, OFFHAND = 1, BODY = 1, HANDS = 1, FEET = 1}, -- Make a moddable tile resolvers.generic(function(e) if e.summoner.female then @@ -337,8 +342,8 @@ newTalent{ -- Disable our sustain when we die on_die = function(self) game:onTickEnd(function() - if self.summoner:isTalentActive(self.summoner.T_TF_BOWMAN) then - self.summoner:forceUseTalent(self.summoner.T_TF_BOWMAN, {ignore_energy=true}) + if self.summoner:isTalentActive(self.summoner.T_TF_DEFENDER) then + self.summoner:forceUseTalent(self.summoner.T_TF_DEFENDER, {ignore_energy=true}) end if self.summoner:isTalentActive(self.summoner.T_OVER_MIND) then self.summoner:forceUseTalent(self.summoner.T_OVER_MIND, {ignore_energy=true}) @@ -347,7 +352,7 @@ newTalent{ end, -- Keep them on a leash on_act = function(self) - local t = self.summoner:getTalentFromId(self.summoner.T_TF_BOWMAN) + local t = self.summoner:getTalentFromId(self.summoner.T_TF_DEFENDER) if not game.level:hasEntity(self.summoner) or core.fov.distance(self.x, self.y, self.summoner.x, self.summoner.y) > self.summoner:getTalentRange(t) then local Map = require "engine.Map" local x, y = util.findFreeGrid(self.summoner.x, self.summoner.y, 5, true, {[Map.ACTOR]=true}) @@ -357,40 +362,41 @@ newTalent{ -- Clear it's targeting on teleport self.ai_target.actor = nil self:move(x, y, true) - game.level.map:particleEmitter(x, y, 1, "summon") + game.level.map:particleEmitter(x, y, 1, "generic_teleport", {rm=225, rM=255, gm=225, gM=255, bm=225, bM=255, am=35, aM=90}) end - end, - + end, + ai = "summoned", ai_real = "tactical", ai_state = { ai_move="move_dmap", talent_in=3, ally_compassion=10 }, - ai_tactic = resolvers.tactic("ranged"), + ai_tactic = resolvers.tactic("tank"), max_life = resolvers.rngavg(100,110), - life_rating = 12, + life_rating = 15, combat_armor = 0, combat_def = 0, inc_stats = { str = stat_bonus / 2, - dex = stat_bonus, - con = stat_bonus / 2, + dex = stat_bonus / 2, + con = stat_bonus, }, resolvers.talents{ - [Talents.T_HEAVE]= math.ceil(self.level/10), + [Talents.T_ARMOUR_TRAINING]= 3 + math.ceil(self.level/10), [Talents.T_WEAPON_COMBAT]= math.ceil(self.level/10), - [Talents.T_BOW_MASTERY]= math.ceil(self.level/10), + [Talents.T_WEAPONS_MASTERY]= math.ceil(self.level/10), - [Talents.T_STEADY_SHOT]= math.ceil(self.level/10), - [Talents.T_RAPID_SHOT]= math.ceil(self.level/10), + [Talents.T_SHIELD_PUMMEL]= math.ceil(self.level/10), + [Talents.T_SHIELD_WALL]= math.ceil(self.level/10), [Talents.T_PSYCHOMETRY]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)), [Talents.T_BIOFEEDBACK]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)), [Talents.T_LUCID_DREAMER]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)), + }, resolvers.equip{ - {type="weapon", subtype="longbow", autoreq=true, forbid_power_source={arcane=true, technique=true} }, - {type="ammo", subtype="arrow", autoreq=true, forbid_power_source={arcane=true, technique=true} }, - {type="armor", subtype="light", autoreq=true, forbid_power_source={arcane=true, technique=true} }, + {type="weapon", subtype="longsword", autoreq=true, forbid_power_source={arcane=true, technique=true} }, + {type="armor", subtype="shield", autoreq=true, forbid_power_source={arcane=true, technique=true} }, + {type="armor", subtype="massive", autoreq=true, forbid_power_source={arcane=true, technique=true} }, {type="armor", subtype="hands", autoreq=true, forbid_power_source={arcane=true, technique=true} }, {type="armor", subtype="feet", autoreq=true, forbid_power_source={arcane=true, technique=true} }, }, @@ -406,19 +412,19 @@ newTalent{ } if self:knowTalent(self.T_TF_UNITY) then local t = self:getTalentFromId(self.T_TF_UNITY) - ret.speed = self:addTemporaryValue("combat_mindspeed", t.getSpeedPower(self, t)/100) + ret.resist = self:addTemporaryValue("resists", {all= t.getDefensePower(self, t)}) end return ret end, deactivate = function(self, t, p) p.summon:die(p.summon) - if p.speed then self:removeTemporaryValue("combat_mindspeed", p.speed) end + if p.resist then self:removeTemporaryValue("resists", p.resist) end return true end, info = function(self, t) local stat = t.getStatBonus(self, t) - return ([[Forge a bowman clad in leather armor from your thoughts. The bowman learns disengage, bow mastery, combat accuracy, steady shot, and rapid shot as it levels up and has %d improved strength, %d dexterity, and %d constitution. - The stat bonuses will improve with your mindpower.]]):format(stat/2, stat, stat/2) + return ([[Forge a defender wielding a sword and shield from your thoughts. The solider learns armor training, weapon mastery, combat accuracy, shield pummel, and shield wall as it levels up and has %d improved strength, %d dexterity, and %d constitution. + The stat bonuses will improve with your mindpower.]]):format(stat/2, stat/2, stat) end, } @@ -435,32 +441,32 @@ newTalent{ end, getStatBonus = function(self, t) return self:combatTalentMindDamage(t, 5, 50) end, on_learn = function(self, t) - if self:getTalentLevel(t) >= 1 and not self:knowTalent(self.T_TF_WARRIOR) then + if self:getTalentLevel(t) >= 1 and not self:knowTalent(self.T_TF_BOWMAN) then + self:learnTalent(self.T_TF_BOWMAN, true) + end + if self:getTalentLevel(t) >= 3 and not self:knowTalent(self.T_TF_WARRIOR) then self:learnTalent(self.T_TF_WARRIOR, true) end - if self:getTalentLevel(t) >= 3 and not self:knowTalent(self.T_TF_DEFENDER) then + if self:getTalentLevel(t) >= 5 and not self:knowTalent(self.T_TF_DEFENDER) then self:learnTalent(self.T_TF_DEFENDER, true) end - if self:getTalentLevel(t) >= 5 and not self:knowTalent(self.T_TF_BOWMAN) then - self:learnTalent(self.T_TF_BOWMAN, true) - end end, on_unlearn = function(self, t) - if self:getTalentLevel(t) < 1 and self:knowTalent(self.T_TF_WARRIOR) then + if self:getTalentLevel(t) < 1 and self:knowTalent(self.T_TF_BOWMAN) then + self:unlearnTalent(self.T_TF_BOWMAN) + end + if self:getTalentLevel(t) < 3 and self:knowTalent(self.T_TF_WARRIOR) then self:unlearnTalent(self.T_TF_WARRIOR) end - if self:getTalentLevel(t) < 3 and self:knowTalent(self.T_TF_DEFENDER) then + if self:getTalentLevel(t) < 5 and self:knowTalent(self.T_TF_DEFENDER) then self:unlearnTalent(self.T_TF_DEFENDER) end - if self:getTalentLevel(t) < 5 and self:knowTalent(self.T_TF_BOWMAN) then - self:unlearnTalent(self.T_TF_BOWMAN) - end end, 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. - At talent level one you may forge a powerful warrior wielding a two-handed weapon, at talent level 3 you may forge a strong defender using a sword and shield, and at talent level 5 a mighty bowman clad in leather armor. + 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, and at talent level 5 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) end, @@ -505,6 +511,7 @@ newTalent{ -- Switch on TickEnd so every thing applies correctly game:onTickEnd(function() + game.level.map:particleEmitter(self.x, self.y, 1, "generic_discharge", {rm=225, rM=255, gm=225, gM=255, bm=225, bM=255, am=35, aM=90}) game.party:hasMember(target).on_control = function(self) self.summoner.over_mind_ai = self.summoner.ai self.summoner.ai = "none" @@ -516,6 +523,7 @@ newTalent{ self.summoner:forceUseTalent(self.summoner.T_OVER_MIND, {ignore_energy=true}) end end + game.level.map:particleEmitter(target.x, target.y, 1, "generic_discharge", {rm=225, rM=255, gm=225, gM=255, bm=225, bM=255, am=35, aM=90}) game.party:setPlayer(target) self:resetCanSeeCache() end) @@ -558,15 +566,15 @@ newTalent{ points = 5, require = psi_wil_req4, mode = "passive", + getSpeedPower = function(self, t) return self:combatTalentMindDamage(t, 5, 15) end, getOffensePower = function(self, t) return self:combatTalentMindDamage(t, 10, 30) end, getDefensePower = function(self, t) return self:combatTalentMindDamage(t, 5, 15) end, - getSpeedPower = function(self, t) return self:combatTalentMindDamage(t, 5, 15) end, info = function(self, t) local offense = t.getOffensePower(self, t) local defense = t.getDefensePower(self, t) local speed = t.getSpeedPower(self, t) - return([[You now gain a %d bonus to mind power while Thought-Form: Warrior is active, a %d%% bonus to resist all while Thought-Form: Defender is active, and a %d%% bonus to mind speed while Thought-Form: Bowman is active. - At talent level one any Feedback your Thought-Forms gain will be given to you as well, at talent level three your Thought-Forms gain a bonus to all saves equal to your mental save, and at talent level five they gain a bonus to all damage equal to your bonus mind damage. - These bonuses scale with your mindpower.]]):format(offense, defense, speed) + return([[You now gain a %d%% bonus to mind speed while Thought-Form: Bowman is active, a %d bonus to mind power while Thought-Form: Warrior is active, and a %d%% bonus to resist all while Thought-Form: Defender is active. + At talent level one any Feedback your Thought-Forms gain will be given to you as well, at level three your Thought-Forms gain a bonus to all saves equal to your mental save, and at level five they gain a bonus to all damage equal to your bonus mind damage. + These bonuses scale with your mindpower.]]):format(speed, offense, defense, speed) end, } \ No newline at end of file diff --git a/game/modules/tome/data/timed_effects/mental.lua b/game/modules/tome/data/timed_effects/mental.lua index 983a819b56b84456205f150537d6b765ed13267c..be3e286dd8c598f12c7a39e907a2da1fbdfa527f 100644 --- a/game/modules/tome/data/timed_effects/mental.lua +++ b/game/modules/tome/data/timed_effects/mental.lua @@ -2272,16 +2272,17 @@ newEffect{ on_lose = function(self, err) return "#Target#'s regains it's senses.", "-Lobotomized" end, parameters = { power=1, dam=1 }, activate = function(self, eff) - DamageType:get(DamageType.MIND).projector(eff.src or self, self.x, self.y, DamageType.MIND, eff.src:mindCrit(eff.dam)) eff.power = math.max(eff.power - (self:attr("confusion_immune") or 0) * 100, 10) eff.tmpid = self:addTemporaryValue("confused", eff.power) eff.cid = self:addTemporaryValue("inc_stats", {[Stats.STAT_CUN]=-eff.power/2}) if eff.power <= 0 then eff.dur = 0 end + eff.particles = self:addParticles(engine.Particles.new("generic_power", 1, {rm=100, rM=125, gm=100, gM=125, bm=100, bM=125, am=200, aM=255})) end, deactivate = function(self, eff) self:removeTemporaryValue("confused", eff.tmpid) self:removeTemporaryValue("inc_stats", eff.cid) + self:removeParticles(eff.particles) if self == game.player and self.updateMainShader then self:updateMainShader() end end, } @@ -2325,9 +2326,11 @@ newEffect{ parameters = { power=2 }, activate = function(self, eff) self.mental_negative_status_effect_immune = eff.power + eff.particles = self:addParticles(engine.Particles.new("generic_power", 1, {rm=0, rM=0, gm=100, gM=180, bm=180, bM=255, am=200, aM=255})) end, deactivate = function(self, eff) self.mental_negative_status_effect_immune = nil + self:removeParticles(eff.particles) end, } @@ -2343,7 +2346,7 @@ newEffect{ on_lose = function(self, err) return "The psychic field around #target# crumbles.", "-Resonance Shield" end, activate = function(self, eff) self.resonance_field_absorb = eff.power - eff.particle = self:addParticles(Particles.new("damage_shield", 1)) + eff.particle = self:addParticles(engine.Particles.new("ultrashield", 1, {rm=255, rM=255, gm=180, gM=255, bm=0, bM=0, am=70, aM=180, radius=0.4, density=60, life=14, instop=1, static=100})) eff.sid = self:addTemporaryValue("resonance_field", eff.power) end, deactivate = function(self, eff) @@ -2383,6 +2386,12 @@ newEffect{ parameters = { power = 1 }, on_gain = function(self, err) return "#Target# is gaining feedback.", "+Feedback Loop" end, on_lose = function(self, err) return "#Target# is no longer gaining feedback.", "-Feedback Loop" end, + activate = function(self, eff) + eff.particle = self:addParticles(Particles.new("ultrashield", 1, {rm=255, rM=255, gm=180, gM=255, bm=0, bM=0, am=35, aM=90, radius=0.2, density=15, life=28, instop=40})) + end, + deactivate = function(self, eff) + self:removeParticles(eff.particle) + end, } newEffect{ @@ -2422,6 +2431,11 @@ newEffect{ end if dream_prison then eff.dur = eff.dur + 1 + if not eff.particle then + eff.particle = self:addParticles(engine.Particles.new("ultrashield", 1, {rm=0, rM=0, gm=180, gM=255, bm=180, bM=255, am=70, aM=180, radius=0.4, density=60, life=14, instop=1, static=100})) + end + elseif eff.particle then + self:removeParticles(eff.particle) end end, activate = function(self, eff) @@ -2434,6 +2448,10 @@ newEffect{ end if not self:attr("sleep") and eff.waking > 0 then DamageType:get(DamageType.MIND).projector(eff.src or self, self.x, self.y, DamageType.MIND, eff.src:mindCrit(eff.waking)) + game.level.map:particleEmitter(self.x, self.y, 1, "generic_discharge", {rm=180, rM=200, gm=100, gM=120, bm=30, bM=50, am=70, aM=180}) + end + if eff.particle then + self:removeParticles(eff.particle) end end, } @@ -2458,10 +2476,16 @@ newEffect{ end if dream_prison then eff.dur = eff.dur + 1 + if not eff.particle then + eff.particle = self:addParticles(engine.Particles.new("ultrashield", 1, {rm=0, rM=0, gm=180, gM=255, bm=180, bM=255, am=70, aM=180, radius=0.4, density=60, life=14, instop=1, static=100})) + end elseif eff.contagious > 0 and eff.dur > 1 then local t = eff.src:getTalentFromId(eff.src.T_SLUMBER) t.doContagiousSlumber(eff.src, self, eff, t) end + if eff.particle and not dream_prison then + self:removeParticles(eff.particle) + end end, activate = function(self, eff) eff.sid = self:addTemporaryValue("sleep", eff.power) @@ -2473,6 +2497,10 @@ newEffect{ end if not self:attr("sleep") and eff.waking > 0 then DamageType:get(DamageType.MIND).projector(eff.src or self, self.x, self.y, DamageType.MIND, eff.src:mindCrit(eff.waking)) + game.level.map:particleEmitter(self.x, self.y, 1, "generic_discharge", {rm=180, rM=200, gm=100, gM=120, bm=30, bM=50, am=70, aM=180}) + end + if eff.particle then + self:removeParticles(eff.particle) end end, } @@ -2497,6 +2525,9 @@ newEffect{ end if dream_prison then eff.dur = eff.dur + 1 + if not eff.particle then + eff.particle = self:addParticles(engine.Particles.new("ultrashield", 1, {rm=0, rM=0, gm=180, gM=255, bm=180, bM=255, am=70, aM=180, radius=0.4, density=60, life=14, instop=1, static=100})) + end else -- Store the power for later local real_power = eff.power @@ -2506,6 +2537,9 @@ newEffect{ -- Set the power back to its baseline eff.power = real_power end + if eff.particle and not dream_prison then + self:removeParticles(eff.particle) + end end, activate = function(self, eff) eff.sid = self:addTemporaryValue("sleep", eff.power) @@ -2517,6 +2551,10 @@ newEffect{ end if not self:attr("sleep") and eff.waking > 0 then DamageType:get(DamageType.MIND).projector(eff.src or self, self.x, self.y, DamageType.MIND, eff.src:mindCrit(eff.waking)) + game.level.map:particleEmitter(self.x, self.y, 1, "generic_discharge", {rm=180, rM=200, gm=100, gM=120, bm=30, bM=50, am=70, aM=180}) + end + if eff.particle then + self:removeParticles(eff.particle) end end, } diff --git a/game/modules/tome/data/timed_effects/other.lua b/game/modules/tome/data/timed_effects/other.lua index 55bc69c3884771e5a302e49095705d2488e15e57..3e5e127155e0e2f748824daf3d8bf834439f72ac 100644 --- a/game/modules/tome/data/timed_effects/other.lua +++ b/game/modules/tome/data/timed_effects/other.lua @@ -1604,6 +1604,7 @@ newEffect{ -- Create a clone for later spawning local m = require("mod.class.NPC").new(eff.target:clone{ shader = "shadow_simulacrum", + shader_args = { color = {0.0, 0.4, 0.8}, base = 0.6 }, no_drops = true, faction = eff.target.faction, summoner = eff.target, summoner_gain_exp=true, @@ -1651,7 +1652,7 @@ newEffect{ end game.zone:addEntity(game.level, m, "actor", x, y) - game.level.map:particleEmitter(x, y, 1, "shadow") + game.level.map:particleEmitter(x, y, 1, "generic_teleport", {rm=0, rM=0, gm=180, gM=255, bm=180, bM=255, am=35, aM=90}) if game.party:hasMember(eff.target) then game.party:addMember(m, { @@ -1673,7 +1674,7 @@ newEffect{ eff.sid = eff.target:addTemporaryValue("time_prison", 1) eff.tid = eff.target:addTemporaryValue("no_timeflow", 1) eff.imid = eff.target:addTemporaryValue("status_effect_immune", 1) - eff.particle = eff.target:addParticles(Particles.new("time_prison", 1)) + eff.particle = eff.target:addParticles(engine.Particles.new("ultrashield", 1, {rm=0, rM=0, gm=180, gM=255, bm=180, bM=255, am=70, aM=180, radius=0.4, density=60, life=14, instop=1, static=100})) eff.target.energy.value = 0 -- Make the invader deadly eff.pid = self:addTemporaryValue("inc_damage", {all=eff.power}) @@ -1719,7 +1720,7 @@ newEffect{ if not self.dead then self:move(x1, y1, true) self.on_die, self.dream_plane_on_die = self.dream_plane_on_die, nil - game.level.map:particleEmitter(x1, y1, 1, "teleport") + game.level.map:particleEmitter(x1, y1, 1, "generic_teleport", {rm=0, rM=0, gm=180, gM=255, bm=180, bM=255, am=35, aM=90}) else self.x, self.y = x1, y1 end diff --git a/game/modules/tome/data/timed_effects/physical.lua b/game/modules/tome/data/timed_effects/physical.lua index 7eb46714af0fcdb695481d4b0d6a9e72a6540746..c8985fa829b1716e146f7631302164a114eab53e 100644 --- a/game/modules/tome/data/timed_effects/physical.lua +++ b/game/modules/tome/data/timed_effects/physical.lua @@ -1835,5 +1835,9 @@ newEffect{ game.logSeen(self, "#LIGHT_RED#%s is being ravaged by distortion!", self.name:capitalize()) eff.dam = eff.dam * 1.5 end + eff.particle = self:addParticles(Particles.new("ultrashield", 1, {rm=255, rM=255, gm=180, gM=255, bm=220, bM=255, am=35, aM=90, radius=0.2, density=15, life=28, instop=40})) + end, + deactivate = function(self, eff) + self:removeParticles(eff.particle) end, } diff --git a/game/modules/tome/data/zones/dreamscape-talent/zone.lua b/game/modules/tome/data/zones/dreamscape-talent/zone.lua index fd6e7db185223a8fe3c329eb2f09510f13ad0a93..7244509c64c0ffc68dd1e0948fe852eccf2cb24c 100644 --- a/game/modules/tome/data/zones/dreamscape-talent/zone.lua +++ b/game/modules/tome/data/zones/dreamscape-talent/zone.lua @@ -46,7 +46,7 @@ return { }, }, post_process = function(level) - game.state:makeWeather(level, 6, {max_nb=7, chance=1, dir=120, speed={0.1, 0.9}, alpha={0.2, 0.4}, particle_name="weather/grey_cloud_%02d"}) + game.state:makeWeather(level, 6, {max_nb=2, chance=1, dir=120, speed={0.1, 0.9}, alpha={0.2, 0.4}, particle_name="weather/grey_cloud_%02d"}) end, foreground = function(level, dx, dx, nb_keyframes) local tick = core.game.getTime() diff --git a/game/modules/tome/dialogs/CharacterSheet.lua b/game/modules/tome/dialogs/CharacterSheet.lua index 814412ba9d9e2ae56f636f5ca403cdb007f332c7..0bdba23318bb917e311c6181994a484f9ea8442d 100644 --- a/game/modules/tome/dialogs/CharacterSheet.lua +++ b/game/modules/tome/dialogs/CharacterSheet.lua @@ -655,7 +655,7 @@ function _M:drawDialog(kind, actor_to_compare) text = compare_fields(player, actor_to_compare, function(actor, ...) return actor:combatMindCrit() end, "%d%%", "%+.0f%%") self:mouseTooltip(self.TOOLTIP_MIND_CRIT, s:drawColorStringBlended(self.font, ("Crit. chance: #00ff00#%s"):format(text), w, h, 255, 255, 255, true)) h = h + self.font_h text = compare_fields(player, actor_to_compare, function(actor, ...) return actor:combatMindSpeed() end, "%.2f%%", "%+.2f%%", 100) - self:mouseTooltip(self.TOOLTIP_SPELL_SPEED, s:drawColorStringBlended(self.font, ("Mind speed : #00ff00#%s"):format(text), w, h, 255, 255, 255, true)) h = h + self.font_h + self:mouseTooltip(self.TOOLTIP_MIND_SPEED, s:drawColorStringBlended(self.font, ("Mind speed : #00ff00#%s"):format(text), w, h, 255, 255, 255, true)) h = h + self.font_h h = 0 w = self.w * 0.5 diff --git a/game/modules/tome/dialogs/LevelupDialog.lua b/game/modules/tome/dialogs/LevelupDialog.lua index 4204552fbf433a1ce52ef67d23562e65dfcda059..d6d8fa7b59291fc6c21d31bb3e2845f7a2dec8fe 100644 --- a/game/modules/tome/dialogs/LevelupDialog.lua +++ b/game/modules/tome/dialogs/LevelupDialog.lua @@ -672,17 +672,21 @@ function _M:getStatDesc(item) text:add({"color", "LIGHT_BLUE"}, "Stat gives:", dc, true) if stat_id == self.actor.STAT_CON then - text:add("Max life: ", color, ("%0.2f"):format(diff * 4), dc, true) + local multi_life = 4 + (self.actor.inc_resource_multi.life or 0) + text:add("Max life: ", color, ("%0.2f"):format(diff * multi_life), dc, true) text:add("Physical save: ", color, ("%0.2f"):format(diff * 0.35), dc, true) elseif stat_id == self.actor.STAT_WIL then if self.actor:knowTalent(self.actor.T_MANA_POOL) then - text:add("Max mana: ", color, ("%0.2f"):format(diff * 5), dc, true) + local multi_mana = 5 + (self.actor.inc_resource_multi.mana or 0) + text:add("Max mana: ", color, ("%0.2f"):format(diff * multi_mana), dc, true) end if self.actor:knowTalent(self.actor.T_STAMINA_POOL) then - text:add("Max stamina: ", color, ("%0.2f"):format(diff * 2.5), dc, true) + local multi_stamina = 2.5 + (self.actor.inc_resource_multi.stamina or 0) + text:add("Max stamina: ", color, ("%0.2f"):format(diff * multi_stamina), dc, true) end if self.actor:knowTalent(self.actor.T_PSI_POOL) then - text:add("Max psi: ", color, ("%0.2f"):format(diff * 1), dc, true) + local multi_psi = 1 + (self.actor.inc_resource_multi.psi or 0) + text:add("Max psi: ", color, ("%0.2f"):format(diff * multi_psi), dc, true) end text:add("Mindpower: ", color, ("%0.2f"):format(diff * 0.7), dc, true) text:add("Mental save: ", color, ("%0.2f"):format(diff * 0.35), dc, true)