Skip to content
Snippets Groups Projects
Commit c9bfe87c authored by dg's avatar dg
Browse files

more

git-svn-id: http://svn.net-core.org/repos/t-engine4@5423 51575b47-30f0-44d4-a5cc-537603b46e54
parent 0f193e62
No related branches found
No related tags found
No related merge requests found
Showing
with 651 additions and 6 deletions
...@@ -493,6 +493,12 @@ function _M:actBase() ...@@ -493,6 +493,12 @@ function _M:actBase()
t.doMindStorm(self, t, p) t.doMindStorm(self, t, p)
end end
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"} self:triggerHook{"Actor:actBase:Effects"}
end end
...@@ -2937,7 +2943,7 @@ function _M:learnPool(t) ...@@ -2937,7 +2943,7 @@ function _M:learnPool(t)
self:learnTalent(self.T_PSI_POOL, true) 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 self.resource_pool_refs[self.T_PSI_POOL] = (self.resource_pool_refs[self.T_PSI_POOL] or 0) + 1
end 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) self:learnTalent(self.T_FEEDBACK_POOL, true)
end end
-- If we learn an archery talent, also learn to shoot -- If we learn an archery talent, also learn to shoot
......
...@@ -361,6 +361,8 @@ local function archery_projectile(tx, ty, tg, self, tmp) ...@@ -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("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("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("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 -- Resource regen on hit
if hitted and self:attr("stamina_regen_on_hit") then self:incStamina(self.stamina_regen_on_hit) end if hitted and self:attr("stamina_regen_on_hit") then self:incStamina(self.stamina_regen_on_hit) end
......
...@@ -169,6 +169,7 @@ newBirthDescriptor{ ...@@ -169,6 +169,7 @@ newBirthDescriptor{
talents_types = { talents_types = {
-- class -- class
["psionic/distortion"]={true, 0.3}, ["psionic/distortion"]={true, 0.3},
["psionic/dream-smith"]={true, 0.3},
["psionic/psychic-assault"]={true, 0.3}, ["psionic/psychic-assault"]={true, 0.3},
["psionic/slumber"]={true, 0.3}, ["psionic/slumber"]={true, 0.3},
["psionic/solipsism"]={true, 0.3}, ["psionic/solipsism"]={true, 0.3},
...@@ -182,6 +183,7 @@ newBirthDescriptor{ ...@@ -182,6 +183,7 @@ newBirthDescriptor{
-- locked trees -- locked trees
["psionic/discharge"]={false, 0.3}, ["psionic/discharge"]={false, 0.3},
["psionic/dream-forge"]={false, 0.3},
["psionic/nightmare"]={false, 0.3}, ["psionic/nightmare"]={false, 0.3},
}, },
talents = { talents = {
......
...@@ -56,6 +56,10 @@ setDefaultProjector(function(src, x, y, type, dam, tmp, no_martyr) ...@@ -56,6 +56,10 @@ setDefaultProjector(function(src, x, y, type, dam, tmp, no_martyr)
local e = target.tempeffect_def[target.EFF_BLOCKING] local e = target.tempeffect_def[target.EFF_BLOCKING]
dam = e.do_block(type, dam, target.tmp[target.EFF_BLOCKING], target, src) dam = e.do_block(type, dam, target.tmp[target.EFF_BLOCKING], target, src)
end 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 -- Increases damage
local mind_linked = false local mind_linked = false
...@@ -2138,4 +2142,48 @@ newDamageType{ ...@@ -2138,4 +2142,48 @@ newDamageType{
end end
end 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
game/modules/tome/data/gfx/effects/broken_dream.png

2.57 KiB

-- 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
game/modules/tome/data/gfx/shockbolt/object/dream_hammer.png

3.77 KiB

game/modules/tome/data/gfx/talents/dream_crusher.png

3.95 KiB

game/modules/tome/data/gfx/talents/dream_hammer.png

3.16 KiB

game/modules/tome/data/gfx/talents/dreamforge.png

1.66 KiB

game/modules/tome/data/gfx/talents/forge_armor.png

3.19 KiB

game/modules/tome/data/gfx/talents/forge_bellows.png

3.65 KiB

game/modules/tome/data/gfx/talents/forge_echoes.png

3.95 KiB

game/modules/tome/data/gfx/talents/forge_shield.png

4.3 KiB

game/modules/tome/data/gfx/talents/hammer_toss.png

3.07 KiB

...@@ -64,7 +64,7 @@ newTalent{ ...@@ -64,7 +64,7 @@ newTalent{
info = function(self, t) info = function(self, t)
local range = self:getTalentRange(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. 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, end,
} }
......
...@@ -152,7 +152,6 @@ newTalent{ ...@@ -152,7 +152,6 @@ newTalent{
target = function(self, t) target = function(self, t)
return {type="hit", range=self:getTalentRange(t), nolock=true, talent=t} return {type="hit", range=self:getTalentRange(t), nolock=true, talent=t}
end, end,
tactical = { ATTACKAREA = { PHYSICAL = 2 }, DISABLE = 1 },
action = function(self, t) action = function(self, t)
local tg = self:getTalentTarget(t) local tg = self:getTalentTarget(t)
local x, y = self:getTarget(tg) local x, y = self:getTarget(tg)
...@@ -166,8 +165,8 @@ newTalent{ ...@@ -166,8 +165,8 @@ newTalent{
local e = Object.new{ local e = Object.new{
old_feat = oe, old_feat = oe,
type = oe.type, subtype = oe.subtype, type = oe.type, subtype = oe.subtype,
name = "maelstrom", image = oe.image, --add_mos = {{image = "terrain/wormhole.png"}}, name = "maelstrom", image = oe.image,
display = '&', color_r=255, color_g=255, color_b=255, back_color=colors.STEEL_BLUE, display = oe.display, color=oe.color, back_color=oe.back_color,
always_remember = true, always_remember = true,
temporary = t.getDuration(self, t), temporary = t.getDuration(self, t),
is_maelstrom = true, is_maelstrom = true,
......
-- 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,
}
-- 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
...@@ -107,7 +107,7 @@ newTalent{ ...@@ -107,7 +107,7 @@ newTalent{
local m = target:clone{ local m = target:clone{
shader = "shadow_simulacrum", 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, no_drops = true,
faction = self.faction, faction = self.faction,
summoner = self, summoner_gain_exp=true, summoner = self, summoner_gain_exp=true,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment