Commit 90c99f932621293b1d53954c594fa02d55ebc763

Authored by Chris Davidson
1 parent bb74a081

Significantly revise Defiler talents

Revise Defiler birth properties
... ... @@ -2022,7 +2022,11 @@ function _M:tooltip(x, y, seen_by)
2022 2022 if e.type == "physical" then
2023 2023 effphysical:add(true, "- ", {"color", "LIGHT_RED"}, desceffect(e, p, dur), {"color", "WHITE"} )
2024 2024 elseif e.type == "magical" then
2025   - effmagical:add(true, "- ", {"color", "DARK_ORCHID"}, desceffect(e, p, dur), {"color", "WHITE"} )
  2025 + if e.subtype and e.subtype.disease then
  2026 + effmagical:add(true, "- ", {"color", "DARK_GREEN"}, desceffect(e, p, dur), {"color", "WHITE"} )
  2027 + else
  2028 + effmagical:add(true, "- ", {"color", "DARK_ORCHID"}, desceffect(e, p, dur), {"color", "WHITE"} )
  2029 + end
2026 2030 elseif e.type == "mental" then
2027 2031 effmental:add(true, "- ", {"color", "YELLOW"}, desceffect(e, p, dur), {"color", "WHITE"} )
2028 2032 elseif e.type == "other" then
... ... @@ -2579,7 +2583,7 @@ function _M:onTakeHit(value, src, death_note)
2579 2583 end
2580 2584
2581 2585 -- Bloodlust!
2582   - if value > 0 and src and src.knowTalent and src:knowTalent(src.T_BLOODLUST) then
  2586 + if value > 0 and src and not (src == self) and src.knowTalent and src:knowTalent(src.T_BLOODLUST) then
2583 2587 src:setEffect(src.EFF_BLOODLUST, 1, {})
2584 2588 end
2585 2589
... ... @@ -2718,7 +2722,7 @@ function _M:onTakeHit(value, src, death_note)
2718 2722 local vt = self:getTalentFromId(self.T_LEECH)
2719 2723 self:incVim(vt.getVim(self, vt))
2720 2724 self:heal(vt.getHeal(self, vt), src)
2721   - if self.player then src:logCombat(src, "#AQUAMARINE#You leech a part of #Target#'s vim.") end
  2725 + --if self.player then src:logCombat(src, "#AQUAMARINE#You leech a part of #Target#'s vim.") end
2722 2726 end
2723 2727
2724 2728 -- Invisible on hit
... ... @@ -5204,9 +5208,10 @@ end
5204 5208 local previous_incVim = _M.incVim
5205 5209 function _M:incVim(v)
5206 5210 if v < 0 and self:attr("bloodcasting") then
  5211 + local mult = self:attr("bloodcasting") / 100
5207 5212 local cost = math.abs(v)
5208 5213 if self.vim - cost < 0 then
5209   - local damage = cost - (self.vim or 0)
  5214 + local damage = (cost - (self.vim or 0)) * mult
5210 5215 self:incVim(-self.vim or 0)
5211 5216 self.life = self.life - damage
5212 5217 else
... ... @@ -5221,7 +5226,7 @@ end
5221 5226 local previous_getVim = _M.getVim
5222 5227 function _M:getVim()
5223 5228 if self:attr("bloodcasting") and self.on_preuse_checking_resources then
5224   - return self.life
  5229 + return math.max(self.vim, self.life)
5225 5230 else
5226 5231 return previous_getVim(self)
5227 5232 end
... ... @@ -5879,7 +5884,7 @@ function _M:postUseTalent(ab, ret, silent)
5879 5884 if #tgts > 0 then
5880 5885 self.turn_procs.corrupted_strength = true
5881 5886 DamageType:projectingFor(self, {project_type={talent=self:getTalentFromId(self.T_CORRUPTED_STRENGTH)}})
5882   - self:attackTarget(rng.table(tgts), DamageType.BLIGHT, self:combatTalentWeaponDamage(self.T_CORRUPTED_STRENGTH, 0.5, 1.1), true)
  5887 + self:attackTarget(rng.table(tgts), DamageType.BLIGHT, self:combatTalentWeaponDamage(self.T_CORRUPTED_STRENGTH, 0.2, 0.7), true)
5883 5888 DamageType:projectingFor(self, nil)
5884 5889 end
5885 5890 end
... ...
... ... @@ -64,15 +64,15 @@ newBirthDescriptor{
64 64 talents_types = {
65 65 ["technique/combat-training"]={true, 0.3},
66 66 ["cunning/survival"]={false, 0.1},
67   - ["corruption/sanguisuge"]={true, 0.3},
  67 + ["corruption/sanguisuge"]={true, 0.0},
68 68 ["corruption/reaving-combat"]={true, 0.3},
69 69 ["corruption/scourge"]={true, 0.3},
70   - ["corruption/plague"]={true, 0.3},
  70 + ["corruption/plague"]={true, 0.0},
71 71 ["corruption/hexes"]={false, 0.3},
72 72 ["corruption/curses"]={false, 0.3},
73 73 ["corruption/bone"]={true, 0.3},
74 74 ["corruption/torment"]={true, 0.3},
75   - ["corruption/vim"]={true, 0.3},
  75 + ["corruption/vim"]={true, 0.0},
76 76 ["corruption/rot"]={false, 0.3},
77 77 },
78 78 talents = {
... ... @@ -99,7 +99,7 @@ newBirthDescriptor{
99 99 },
100 100 },
101 101 copy_add = {
102   - life_rating = 2,
  102 + life_rating = 1,
103 103 },
104 104 }
105 105
... ... @@ -136,7 +136,7 @@ newBirthDescriptor{
136 136 ["corruption/blood"]={true, 0.3},
137 137 ["corruption/vim"]={true, 0.3},
138 138 ["corruption/blight"]={true, 0.3},
139   - ["corruption/torment"]={false, 0.3},
  139 + ["corruption/torment"]={true, 0.3},
140 140 },
141 141 talents = {
142 142 [ActorTalents.T_DRAIN] = 1,
... ...
... ... @@ -843,6 +843,9 @@ newDamageType{
843 843 if src and src.knowTalent and realdam > 0 and target and src:knowTalent(src.T_PESTILENT_BLIGHT) then
844 844 src:callTalent(src.T_PESTILENT_BLIGHT, "do_rot", target, realdam)
845 845 end
  846 + if src and src.knowTalent and realdam > 0 and target and src:knowTalent(src.T_VIRULENT_DISEASE) and (not state or not state.from_disease) then
  847 + src:callTalent(src.T_VIRULENT_DISEASE, "do_disease", target, realdam)
  848 + end
846 849 return realdam
847 850 end,
848 851 death_message = {"diseased", "poxed", "infected", "plagued", "debilitated by noxious blight before falling", "fouled", "tainted"},
... ...
... ... @@ -23,9 +23,8 @@ newTalent{
23 23 require = corrs_req1,
24 24 points = 5,
25 25 vim = 13,
26   - cooldown = 8,
  26 + cooldown = 10,
27 27 range = 10,
28   - random_ego = "attack",
29 28 tactical = { ATTACK = {PHYSICAL = 2} },
30 29 direct_hit = true,
31 30 requires_target = true,
... ... @@ -44,10 +43,11 @@ newTalent{
44 43 self:project(tg, x, y, function(tx, ty)
45 44 local target = game.level.map(tx, ty, Map.ACTOR)
46 45 if not target then return end
47   - local damage = dam * (1 + t.getBonus(self, t) * #self:effectsFilter({status="detrimental", type="magical"}, 10))
48   -
  46 + local effs = #target:effectsFilter({status="detrimental", type="magical"})
  47 + local damage = dam * (1 + t.getBonus(self, t) * effs)
  48 + game.log(tostring(damage)..", "..tostring(dam)..", "..tostring(effs))
49 49 DamageType:get(DamageType.PHYSICAL).projector(self, tx, ty, DamageType.PHYSICAL, damage)
50   - end, dam)
  50 + end)
51 51 local _ _, _, _, x, y = self:canProject(tg, x, y)
52 52 game.level.map:particleEmitter(self.x, self.y, tg.range, "bone_spear", {tx=x - self.x, ty=y - self.y})
53 53 game:playSoundNear(self, "talents/arcane")
... ... @@ -60,13 +60,12 @@ newTalent{
60 60 end,
61 61 }
62 62
63   --- Finish me pls
64 63 newTalent{
65 64 name = "Bone Grab",
66 65 type = {"corruption/bone", 2},
67 66 require = corrs_req2,
68 67 points = 5,
69   - vim = 28,
  68 + vim = 15,
70 69 cooldown = 15,
71 70 range = function(self, t) return math.floor(self:combatTalentLimit(t, 10, 4, 9)) end,
72 71 tactical = { DISABLE = 1, CLOSEIN = 3 },
... ... @@ -79,32 +78,55 @@ newTalent{
79 78 if not x or not y then return nil end
80 79
81 80 local dam = self:spellCrit(t.getDamage(self, t))
82   -
83 81 self:project(tg, x, y, function(px, py)
84 82 local target = game.level.map(px, py, engine.Map.ACTOR)
85 83 if not target then return end
86 84
87   - target:pull(self.x, self.y, tg.range)
88   -
89   - DamageType:get(DamageType.PHYSICAL).projector(self, target.x, target.y, DamageType.PHYSICAL, dam)
90   - if target:canBe("pin") then
91   - target:setEffect(target.EFF_BONE_GRAB, t.getDuration(self, t), {apply_power=self:combatSpellpower()})
  85 + if core.fov.distance(self.x, self.y, target.x, target.y) > 1 then
  86 + target:pull(self.x, self.y, tg.range)
  87 + DamageType:get(DamageType.PHYSICAL).projector(self, target.x, target.y, DamageType.PHYSICAL, dam)
  88 + if target:canBe("pin") then
  89 + target:setEffect(target.EFF_BONE_GRAB, t.getDuration(self, t), {apply_power=self:combatSpellpower()})
  90 + else
  91 + game.logSeen(target, "%s resists the bone!", target.name:capitalize())
  92 + end
92 93 else
93   - game.logSeen(target, "%s resists the bone!", target.name:capitalize())
  94 + local tg = {type="cone", cone_angle=25, range=0, radius=8, friendlyfire=false}
  95 +
  96 + local grids = {}
  97 + self:project(tg, x, y, function(px, py)
  98 + if core.fov.distance(target.x, target.y, px, py) > 2 then grids[#grids+1] = {px, py} end
  99 + end)
  100 +
  101 + DamageType:get(DamageType.PHYSICAL).projector(self, target.x, target.y, DamageType.PHYSICAL, dam)
  102 + if target:canBe("pin") then
  103 + target:setEffect(target.EFF_BONE_GRAB, t.getDuration(self, t), {apply_power=self:combatSpellpower()})
  104 + else
  105 + game.logSeen(target, "%s resists the bone!", target.name:capitalize())
  106 + end
  107 +
  108 + local hit = self:checkHit(self:combatSpellpower(), target:combatSpellResist() + (target:attr("continuum_destabilization") or 0))
  109 + if not target:canBe("teleport") or not hit then
  110 + game.logSeen(target, "%s resists being teleported by Bone Grab!", target.name:capitalize())
  111 + return true
  112 + end
  113 + local spot = rng.table(grids)
  114 + if not spot then return end
  115 + target:teleportRandom(spot[1], spot[2], 0)
94 116 end
95 117 end)
96   - game:playSoundNear(self, "talents/arcane")
97   -
  118 + game:playSoundNear(self, "talents/arcane")
98 119 return true
99 120 end,
100 121 info = function(self, t)
101   - return ([[Grab a target and teleport it to your side or if adjacent to a random location away from you, pinning it there with a bone rising from the ground for %d turns.
  122 + return ([[Grab a target and teleport it to your side or if adjacent to a random location at least 3 spaces away from you, pinning it there with a bone rising from the ground for %d turns.
102 123 The bone will also deal %0.2f physical damage.
103 124 The damage will increase with your Spellpower.]]):
104 125 format(t.getDuration(self, t), damDesc(self, DamageType.PHYSICAL, t.getDamage(self, t)))
105 126 end,
106 127 }
107 128
  129 +-- Fix breaking Movement
108 130 newTalent{
109 131 name = "Bone Spike",
110 132 type = {"corruption/bone", 3},
... ... @@ -112,12 +134,13 @@ newTalent{
112 134 image = "talents/bone_nova.png",
113 135 points = 5,
114 136 mode = "passive",
115   - getDamage = function(self, t) return self:combatTalentSpellDamage(t, 20, 90) end,
  137 + getDamage = function(self, t) return self:combatTalentSpellDamage(t, 10, 60) end,
116 138 radius = 10,
117 139 target = function(self, t)
118 140 return {type="ball", radius=self:getTalentRadius(t), selffire=false, friendlyfire=false, talent=t}
119 141 end,
120 142 callbackOnTalentPost = function(self, t, ab, ret, silent)
  143 + if ab.no_energy then return end
121 144 if self.turn_procs.bone_spike then return end
122 145 self.turn_procs.bone_spike = true
123 146 game:onTickEnd(function()
... ... @@ -127,20 +150,21 @@ newTalent{
127 150 self:project(tg, self.x, self.y, function(px, py)
128 151 local target = game.level.map(px, py, engine.Map.ACTOR)
129 152 if not target then return end
130   - local nb = #self:effectsFilter({status="detrimental", type="magical"})
  153 + local nb = #target:effectsFilter({status="detrimental", type="magical"})
131 154 if nb and nb < 3 then return end
132 155 self:project({type="beam", range=10, selffire=false, friendlyfire=false, talent=t}, target.x, target.y, DamageType.PHYSICAL, dam)
133 156 local _ _, _, _, x, y = self:canProject(tg, x, y)
134   - game.level.map:particleEmitter(self.x, self.y, 10, "bone_spear", {tx=target.x - self.x, ty=target.y - self.y})
  157 + game.level.map:particleEmitter(self.x, self.y, 10, "bone_spear", {speed=0.2, tx=target.x - self.x, ty=target.y - self.y})
135 158 end)
136 159 end)
137 160 end,
138 161 info = function(self, t)
139   - return ([[At the end of any turn you used a talent you launch a spear of bone at all enemies afflicted by 3 or more magical detrimental effects dealing %d to all enemies it passes through.
  162 + return ([[Whenever you use a non-instant talent you launch a spear of bone at all enemies afflicted by 3 or more magical detrimental effects dealing %d to all enemies it passes through.
140 163 The damage will increase with your Spellpower.]]):format(damDesc(self, DamageType.PHYSICAL, t.getDamage(self, t)) )
141 164 end,
142 165 }
143 166
  167 +-- Fix on clone bug
144 168 newTalent{
145 169 name = "Bone Shield",
146 170 type = {"corruption/bone", 4},
... ... @@ -151,9 +175,9 @@ newTalent{
151 175 sustain_vim = 50,
152 176 tactical = { DEFEND = 4 },
153 177 direct_hit = true,
154   - getNb = function(self, t) return math.floor(self:combatTalentScale(t, 1, 5)) end,
155   - getThreshold = function(self, t) return math.floor(self:combatStatScale(self:combatSpellpower(), 10, 120)) end,
156   - getRegen = function(self, t) return math.max(math.floor(30 / t.getNb(self, t)), 3) end,
  178 + getRegen = function(self, t) return self:combatTalentLimit(t, 3, 20, 3.5) end,
  179 + getNb = function(self, t) return math.floor(self:combatTalentScale(t, 1, 4.5)) end,
  180 + getThreshold = function(self, t) return math.floor(self:combatSpellpower()) end,
157 181 iconOverlay = function(self, t, p)
158 182 local p = self.sustain_talents[t.id]
159 183 if not p or not p.nb then return "" end
... ... @@ -165,6 +189,7 @@ newTalent{
165 189 if not p or p.nb < nb then return true end
166 190 end,
167 191 callbackOnActBase = function(self, t)
  192 + if not self:isTalentActive(t.id) then return end
168 193 local p = self.sustain_talents[t.id]
169 194 p.next_regen = (p.next_regen or 1) - 1
170 195 if p.next_regen <= 0 then
... ... @@ -185,7 +210,8 @@ newTalent{
185 210 end
186 211 end,
187 212 callbackOnHit = function(self, t, cb, src, dt)
188   - local p = self.sustain_talents[t.id]
  213 + local p = self:isTalentActive(t.id)
  214 + if not p then return end
189 215 if not p.nb or p.nb <= 0 then return end
190 216 if not cb.value or cb.value < t.getThreshold(self, t) then return end
191 217 p.nb = p.nb - 1
... ... @@ -208,6 +234,7 @@ newTalent{
208 234
209 235 local adv_gfx = core.shader.allow("adv") and true or false
210 236 local ps = {}
  237 + game.log("Bone Shield clone activate "..tostring(util.bound(nb, 0, 10)) or ".shader value is nil")
211 238 if adv_gfx then
212 239 ps[1] = self:addParticles(Particles.new("shader_ring_rotating", 1, {toback=true, a=0.5, rotation=0, radius=1.5, img="bone_shield"}, {type="boneshield"}))
213 240 ps[1]._shader.shad:resetClean()
... ... @@ -221,6 +248,7 @@ newTalent{
221 248 return {
222 249 adv_gfx = adv_gfx,
223 250 particles = ps,
  251 + clone_test = 1,
224 252 nb = nb,
225 253 next_regen = t.getRegen(self, t),
226 254 }
... ...
... ... @@ -22,7 +22,7 @@ newTalent{
22 22 type = {"corruption/curses", 1},
23 23 require = corrs_req1,
24 24 points = 5,
25   - cooldown = 20,
  25 + cooldown = 15,
26 26 vim = 20,
27 27 range = 10,
28 28 tactical = { DISABLE = 2 },
... ... @@ -103,8 +103,8 @@ newTalent{
103 103 return true
104 104 end,
105 105 info = function(self, t)
106   - return ([[Curses your target, stopping any natural healing and dealing %0.2f darkness damage each turn for 10 turns.
107   - The damage will increase with your Spellpower.]]):format(damDesc(self, DamageType.DARKNESS, self:combatTalentSpellDamage(t, 10, 70)))
  106 + return ([[Curses your target, stopping any natural healing and dealing %0.2f darkness damage over 10 turns.
  107 + The damage will increase with your Spellpower.]]):format(damDesc(self, DamageType.DARKNESS, self:combatTalentSpellDamage(t, 10, 70)*10))
108 108 end,
109 109 }
110 110
... ...
... ... @@ -38,55 +38,59 @@ local getTargetDiseases = function(self, target)
38 38 return diseases
39 39 end
40 40
  41 +-- Fix dead priority
  42 +-- Add a clear display on where the disease went
41 43 newTalent{
42 44 name = "Virulent Disease",
43 45 type = {"corruption/plague", 1},
44 46 require = corrs_req1,
45 47 points = 5,
46   - vim = 8,
47 48 cooldown = 3,
48   - random_ego = "attack",
49   - tactical = { ATTACK = {BLIGHT = {disease=2}} },
50   - requires_target = true,
51   - no_energy = true,
52   - target = function(self, t) return {type="hit", range=self:getTalentRange(t), talent=t} end,
53   - range = function(self, t) return 5 end, -- Instant cast should not do thousands of damage at long range. This is still too powerful, though
54   - action = function(self, t)
55   - local tg = self:getTalentTarget(t)
56   - local x, y = self:getTarget(tg)
57   - if not x or not y then return nil end
  49 + mode = "passive",
  50 + do_disease = function(self, t, target, val)
  51 + if self:isTalentCoolingDown(t) then return end
58 52
59   - local diseases = {{self.EFF_WEAKNESS_DISEASE, "str"}, {self.EFF_ROTTING_DISEASE, "con"}, {self.EFF_DECREPITUDE_DISEASE, "dex"}}
60   - local disease = rng.table(diseases)
61   -
62   - -- Try to rot !
63   - self:project(tg, x, y, function(px, py)
  53 + -- Grab an enemy of radius 5 of the damaged target that has the most diseases else default to the actor damaged
  54 + local disease_target = {actor=target, count=0}
  55 + if dead then disease_target.actor = "none" end
  56 + self:project({type="ball", radius=5, friendlyfire=false, selffire=false, x=target.x, y=target.y}, target.x, target.y, function(px, py)
64 57 local target = game.level.map(px, py, engine.Map.ACTOR)
65 58 if not target then return end
66   - if target:canBe("disease") then
67   - local str, dex, con = not target:hasEffect(self.EFF_WEAKNESS_DISEASE) and target:getStr() or 0, not target:hasEffect(self.EFF_DECREPITUDE_DISEASE) and target:getDex() or 0, not target:hasEffect(self.EFF_ROTTING_DISEASE) and target:getCon() or 0
  59 + local count = #target:effectsFilter(function(e) return e.subtype.disease end, 9)
  60 + if (count > 0 and disease_target.count < count) or disease_target.actor == "none" then -- If the initial target was dead then we grab a semi-random one
  61 + disease_target.actor = target
  62 + disease_target.count = count
  63 + end
  64 + end)
68 65
69   - if str >= dex and str >= con then
70   - disease = {self.EFF_WEAKNESS_DISEASE, "str"}
71   - elseif dex >= str and dex >= con then
72   - disease = {self.EFF_DECREPITUDE_DISEASE, "dex"}
73   - elseif con > 0 then
74   - disease = {self.EFF_ROTTING_DISEASE, "con"}
75   - end
  66 + if disease_target.actor == "none" then return end
  67 + target = disease_target.actor
  68 + local diseases = {{self.EFF_WEAKNESS_DISEASE, "str"}, {self.EFF_ROTTING_DISEASE, "con"}, {self.EFF_DECREPITUDE_DISEASE, "dex"}}
  69 + local disease = rng.table(diseases)
76 70
77   - target:setEffect(disease[1], 6, {src=self, dam=self:spellCrit(7 + self:combatTalentSpellDamage(t, 6, 45)), [disease[2]]=self:combatTalentSpellDamage(t, 5, 35), apply_power=self:combatSpellpower()})
78   - else
79   - game.logSeen(target, "%s resists the disease!", target.name:capitalize())
  71 + if target:canBe("disease") then
  72 + local str, dex, con = not target:hasEffect(self.EFF_WEAKNESS_DISEASE) and target:getStr() or 0, not target:hasEffect(self.EFF_DECREPITUDE_DISEASE) and target:getDex() or 0, not target:hasEffect(self.EFF_ROTTING_DISEASE) and target:getCon() or 0
  73 +
  74 + if str >= dex and str >= con then
  75 + disease = {self.EFF_WEAKNESS_DISEASE, "str"}
  76 + elseif dex >= str and dex >= con then
  77 + disease = {self.EFF_DECREPITUDE_DISEASE, "dex"}
  78 + elseif con > 0 then
  79 + disease = {self.EFF_ROTTING_DISEASE, "con"}
80 80 end
81   - game.level.map:particleEmitter(px, py, 1, "circle", {oversize=0.7, a=200, limit_life=8, appear=8, speed=-2, img="disease_circle", radius=0})
82   - end)
83   - game:playSoundNear(self, "talents/slime")
84 81
85   - return true
  82 + target:setEffect(disease[1], 6, {src=self, dam=self:spellCrit(7 + self:combatTalentSpellDamage(t, 6, 45)), [disease[2]]=self:combatTalentSpellDamage(t, 5, 35), apply_power=self:combatSpellpower()})
  83 + else
  84 + game.logSeen(target, "%s resists the disease!", target.name:capitalize())
  85 + end
  86 + self:startTalentCooldown(t)
  87 + game.level.map:particleEmitter(target.x, target.y, 1, "circle", {oversize=0.7, a=200, limit_life=8, appear=8, speed=-2, img="disease_circle", radius=0})
  88 + game:playSoundNear(self, "talents/slime")
86 89 end,
87 90 info = function(self, t)
88   - return ([[Fires a bolt of pure filth, diseasing your target with a disease doing %0.2f blight damage per turn for 6 turns, and reducing one of its physical stats (strength, constitution, dexterity) by %d. The three diseases can stack.
  91 + return ([[Whenever you dealt non-disease blight damage you apply a disease dealing %0.2f blight damage per turn for 6 turns and reducing one of its physical stats (strength, constitution, dexterity) by %d. The three diseases can stack.
89 92 Virulent Disease will always try to apply a disease the target does not currently have, and also one that will have the most debilitating effect for the target.
  93 + This disease will try to prioritize being applied to an enemy with a high disease count near the target.
90 94 The effect will increase with your Spellpower.]]):
91 95 format(damDesc(self, DamageType.BLIGHT, 7 + self:combatTalentSpellDamage(t, 6, 65)), self:combatTalentSpellDamage(t, 5, 35))
92 96 end,
... ... @@ -98,8 +102,8 @@ newTalent{
98 102 require = corrs_req2,
99 103 points = 5,
100 104 vim = 18,
101   - cooldown = 9,
102   - range = 8,
  105 + cooldown = 4,
  106 + range = 10,
103 107 radius = function(self, t) return math.floor(self:combatTalentScale(t, 1.5, 3.5)) end,
104 108 getTargetDiseases = getTargetDiseases,
105 109 tactical = function(self, t, aitarget)
... ... @@ -130,7 +134,7 @@ newTalent{
130 134 local x, y = self:getTarget(tg)
131 135 if not x or not y then return nil end
132 136
133   - local dam = self:spellCrit(self:combatTalentSpellDamage(t, 15, 85))
  137 + local dam = self:spellCrit(self:combatTalentSpellDamage(t, 15, 90))
134 138 local diseases
135 139
136 140 -- Try to rot !
... ... @@ -157,7 +161,13 @@ newTalent{
157 161 parameters.src = self
158 162 parameters.apply_power = self:combatSpellpower()
159 163 parameters.__tmpvals = nil
160   - target:setEffect(disease.id, 6, parameters)
  164 +
  165 + local dur = math.max(6, parameters.dur)
  166 + if target:canBe("disease") then
  167 + target:setEffect(disease.id, 6, parameters)
  168 + else
  169 + game.logSeen(target, "%s resists the disease!", target.name:capitalize())
  170 + end
161 171 end
162 172 end)
163 173 game.level.map:particleEmitter(x, y,self:getTalentRadius(t), "circle", {oversize=0.7, a=200, limit_life=8, appear=8, speed=-2, img="disease_circle", radius=self:getTalentRadius(t)})
... ... @@ -168,9 +178,9 @@ newTalent{
168 178 end,
169 179 info = function(self, t)
170 180 return ([[Make your target's diseases burst, doing %0.2f blight damage for each disease it is infected with.
171   - This will also spread any diseases to any nearby foes in a radius of %d.
  181 + This will also spread any diseases to any nearby foes in a radius of %d with a minimum duration of 6.
172 182 The damage will increase with your Spellpower.]]):
173   - format(damDesc(self, DamageType.BLIGHT, self:combatTalentSpellDamage(t, 15, 85)), self:getTalentRadius(t))
  183 + format(damDesc(self, DamageType.BLIGHT, self:combatTalentSpellDamage(t, 15, 115)), self:getTalentRadius(t))
174 184 end,
175 185 }
176 186
... ... @@ -282,6 +292,7 @@ newTalent{
282 292 local params = table.clone(disease.params, true)
283 293 params.__tmpvals = nil
284 294 params.src = self
  295 + params.apply_power = self:combatSpellpower()
285 296 if target:canBe("disease") then
286 297 target:setEffect(disease.id, 6, params)
287 298 else
... ...
... ... @@ -38,10 +38,11 @@ newTalent{
38 38 info = function(self, t)
39 39 return ([[Allows you to dual wield any type of one handed weapons, and increases the damage of the off-hand weapon to %d%%.
40 40 Also, casting a spell (which uses a turn) will give a free melee attack at a random target in melee range for %d%% blight damage.]]):
41   - format(100*t.getoffmult(self,t), 100 * self:combatTalentWeaponDamage(t, 0.5, 1.1))
  41 + format(100*t.getoffmult(self,t), 100 * self:combatTalentWeaponDamage(t, 0.2, 0.7))
42 42 end,
43 43 }
44 44
  45 +-- Fix display
45 46 newTalent{
46 47 name = "Bloodlust",
47 48 type = {"corruption/reaving-combat", 2},
... ... @@ -52,13 +53,13 @@ newTalent{
52 53 -- Effect is refreshed in function _M:onTakeHit(value, src) in mod\class\Actor.lua
53 54 -- getParams called in definition of EFF_BLOODLUST in data\timed_effects\magical.lua
54 55 getParams = function(self, t) -- returns maxSP per turn, max duration
55   - return self:combatTalentScale(t, 1, 5, 0.75), math.floor(self:combatTalentScale(t, 2, 6))
  56 + return self:combatTalentScale(t, 1, 8, 0.75), math.floor(self:combatTalentScale(t, 2, 6))
56 57 end,
57 58 info = function(self, t)
58 59 local SPbonus, maxDur = t.getParams(self, t)
59 60 return ([[Each time you deal damage to one of your foes, you enter a bloodlust-infused frenzy, increasing your Spellpower by 1 (maximum %d Spellpower per turn, %d Spellpower overall), and extending any current frenzy for an additional turn.
60 61 The frenzy lasts up to %d turns, and the bonus decreases by %0.1f%% of its current value each turn you don't deal damage.]]):
61   - format(SPbonus, SPbonus*6, maxDur, 100/maxDur)
  62 + format(SPbonus / 5, SPbonus*8, maxDur, 100/maxDur)
62 63 end,
63 64 }
64 65
... ...
... ... @@ -99,8 +99,8 @@ carrionworm = function(self, target, duration, x, y)
99 99 m.unused_talents_types = 0
100 100 m.no_inventory_access = true
101 101 m.no_points_on_levelup = true
  102 + m.carrion_worm = true -- This keeps the on_death effect from spamming the damage log with 0s
102 103 m.save_hotkeys = true
103   - m.ai_state = m.ai_state or {}
104 104 m.ai_state.tactic_leash = 100
105 105 -- Try to use stored AI talents to preserve tweaking over multiple summons
106 106 m.ai_talents = self.stored_ai_talents and self.stored_ai_talents[m.name] or {}
... ...
... ... @@ -32,10 +32,10 @@ newTalent{
32 32 requires_target = true,
33 33 range = function(self, t) return math.floor(self:combatTalentScale(t, 5, 9)) end,
34 34 action = function(self, t)
35   - local tg = {type="bolt", range=self:getTalentRange(t), talent=t, display={particle="bolt_slime"}}
  35 + local tg = {type="hit", range=self:getTalentRange(t), talent=t, display={particle="bolt_slime"}}
36 36 local x, y = self:getTarget(tg)
37 37 if not x or not y then return nil end
38   - self:projectile(tg, x, y, DamageType.DRAIN_VIM, self:spellCrit(self:combatTalentSpellDamage(t, 25, 200)), {type="slime"})
  38 + self:project(tg, x, y, DamageType.DRAIN_VIM, self:spellCrit(self:combatTalentSpellDamage(t, 25, 200)), {type="slime"})
39 39 game:playSoundNear(self, "talents/slime")
40 40 return true
41 41 end,
... ... @@ -47,26 +47,21 @@ newTalent{
47 47 end,
48 48 }
49 49
50   --- Finish me pls
51 50 newTalent{
52 51 name = "Bloodcasting",
53 52 type = {"corruption/sanguisuge", 2},
54 53 require = corrs_req2,
55 54 points = 5,
56   - vim = 0,
57   - cooldown = 18,
58   - no_energy = true,
59   - range = 10,
  55 + mode = "passive",
60 56 no_npc_use = true,
61   - getDuration = function(self, t) return math.floor(self:combatTalentLimit(t, 18, 3, 7)) end, --Limit duration < 18
62   - action = function(self, t)
63   - self:setEffect(self.EFF_BLOODCASTING, t.getDuration(self,t), {})
64   - game:playSoundNear(self, "talents/spell_generic2")
65   - return true
  57 + getLifeCost = function(self, t) return math.floor(self:combatTalentScale(t, 250, 100)) end,
  58 + passives = function(self, t, p)
  59 + self:talentTemporaryValue(p, "bloodcasting", t.getLifeCost(self, t))
66 60 end,
67 61 info = function(self, t)
68   - return ([[For %d turns, your corruption spells will consume health instead of vim if their cost is higher than your vim.]]):
69   - format(t.getDuration(self,t))
  62 + return ([[Your corruption spells will consume health instead of vim if their cost is higher than your vim.
  63 + The health cost is equal to %d%% of the vim cost.]]):
  64 + format(t.getLifeCost(self,t))
70 65 end,
71 66 }
72 67
... ... @@ -79,6 +74,7 @@ newTalent{
79 74 sustain_vim = 5,
80 75 cooldown = 30,
81 76 range = 10,
  77 + no_energy = true,
82 78 tactical = { BUFF = 2 },
83 79 VimOnDeath = function(self, t) return self:combatTalentScale(t, 6, 16) end,
84 80 activate = function(self, t)
... ...
... ... @@ -17,24 +17,29 @@
17 17 -- Nicolas Casalini "DarkGod"
18 18 -- darkgod@te4.org
19 19
  20 +-- Reaver gets an abnormally low number of melee strikes so its important that cooldowns and such reflect this, otherwise it encourages playing as a ranged caster
  21 +
20 22 local DamageType = require "engine.DamageType"
21 23
22 24 newTalent{
23   - name = "Rend",
  25 + name = "Virulent Strike",
  26 + short_name = "REND",
24 27 type = {"corruption/scourge", 1},
25 28 require = corrs_req1,
26 29 points = 5,
27   - vim = 9,
28   - cooldown = 6,
  30 + vim = 15,
  31 + cooldown = 4,
29 32 range = 1,
30 33 is_melee = true,
31 34 target = function(self, t) return {type="hit", range=self:getTalentRange(t)} end,
32 35 tactical = { ATTACK = {PHYSICAL = 2} },
33 36 requires_target = true,
  37 + getIncrease = function(self, t) return math.floor(self:combatTalentLimit(t, 4, 1, 3.5)) end,
  38 + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.8, 1.6) end,
34 39 action = function(self, t)
35 40 local weapon, offweapon = self:hasDualWeapon()
36 41 if not weapon then
37   - game.logPlayer(self, "You cannot use Rend without two weapons!")
  42 + game.logPlayer(self, "You cannot use Virulent Strike without two weapons!")
38 43 return nil
39 44 end
40 45
... ... @@ -43,32 +48,30 @@ newTalent{
43 48 if not target or not self:canProject(tg, x, y) then return nil end
44 49
45 50 DamageType:projectingFor(self, {project_type={talent=t}})
46   - local speed1, hit1 = self:attackTargetWith(target, weapon.combat, nil, self:combatTalentWeaponDamage(t, 0.8, 1.6))
47   - local speed2, hit2 = self:attackTargetWith(target, offweapon.combat, nil, self:getOffHandMult(offweapon.combat, self:combatTalentWeaponDamage(t, 0.8, 1.6)))
  51 + local speed1, hit1 = self:attackTargetWith(target, weapon.combat, nil, t.getDamage(self, t))
  52 + local speed2, hit2 = self:attackTargetWith(target, offweapon.combat, nil, self:getOffHandMult(offweapon.combat, t.getDamage(self, t)))
48 53 DamageType:projectingFor(self, nil)
49 54
50   - -- Try to bleed !
51 55 if hit1 then
52   - if target:canBe("cut") then
53   - target:setEffect(target.EFF_CUT, 5, {power=self:combatTalentSpellDamage(t, 5, 40), src=self, apply_power=self:combatPhysicalpower()})
54   - else
55   - game.logSeen(target, "%s resists the cut!", target.name:capitalize())
  56 + local effs = target:effectsFilter(function(e) return e.subtype.disease end, 1)
  57 + local eff2 = target:hasEffect(effs[1])
  58 + if eff2 then
  59 + eff2.dur = eff2.dur + t.getIncrease(self, t)
56 60 end
57 61 end
58 62 if hit2 then
59   - if target:canBe("cut") then
60   - target:setEffect(target.EFF_CUT, 5, {power=self:combatTalentSpellDamage(t, 5, 40), src=self, apply_power=self:combatPhysicalpower()})
61   - else
62   - game.logSeen(target, "%s resists the cut!", target.name:capitalize())
  63 + local effs = target:effectsFilter(function(e) return e.subtype.disease end, 1)
  64 + local eff2 = target:hasEffect(effs[1])
  65 + if eff2 then
  66 + eff2.dur = eff2.dur + t.getIncrease(self, t)
63 67 end
64 68 end
65 69
66 70 return true
67 71 end,
68 72 info = function(self, t)
69   - return ([[Hit the target with both weapons, doing %d%% damage with each hit. For each hit, the target will bleed for %0.2f damage each turn for 5 turns.
70   - The bleeding effect will increase with your Spellpower.]]):
71   - format(100 * self:combatTalentWeaponDamage(t, 0.8, 1.6), self:combatTalentSpellDamage(t, 5, 40))
  73 + return ([[Strike the target with both weapons dealing %d%% damage with each hit. Each strike that hits will increase the duration of a random disease effect by %d.]]):
  74 + format(100 * t.getDamage(self, t), t.getIncrease(self, t))
72 75 end,
73 76 }
74 77
... ... @@ -107,17 +110,19 @@ newTalent{
107 110 type = {"corruption/scourge", 3},
108 111 require = corrs_req3,
109 112 points = 5,
110   - vim = 18,
111   - cooldown = 12,
  113 + vim = 20,
  114 + cooldown = 8,
112 115 range = 1,
113   - radius = 1,
  116 + radius = function(self, t) return self:combatTalentLimit(t, 7, 1, 5) end,
114 117 requires_target = true,
115 118 is_melee = true,
116   - tactical = { ATTACK = {ACID = 2}, DISABLE = 1 },
  119 + tactical = { ATTACK = {ACID = 2}},
117 120 target = function(self, t)
118 121 -- Tries to simulate the acid splash
119   - return {type="ballbolt", range=1, radius=self:getTalentRadius(t), selffire=false, talent=t}
  122 + return {type="ballbolt", range=1, radius=self:getTalentRadius(t), selffire=false, friendlyfire=false, talent=t}
120 123 end,
  124 + getSplash = function(self, t) return self:combatTalentSpellDamage(t, 10, 200) end,
  125 + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.8, 1.6) end,
121 126 action = function(self, t)
122 127 local weapon, offweapon = self:hasDualWeapon()
123 128 if not weapon then
... ... @@ -130,8 +135,8 @@ newTalent{
130 135 if not target or not self:canProject(tg, x, y) then return nil end
131 136
132 137 DamageType:projectingFor(self, {project_type={talent=t}})
133   - local speed1, hit1 = self:attackTargetWith(target, weapon.combat, DamageType.ACID, self:combatTalentWeaponDamage(t, 0.8, 1.6))
134   - local speed2, hit2 = self:attackTargetWith(target, offweapon.combat, DamageType.ACID, self:getOffHandMult(offweapon.combat, self:combatTalentWeaponDamage(t, 0.8, 1.6)))
  138 + local speed1, hit1 = self:attackTargetWith(target, weapon.combat, DamageType.ACID, t.getDamage(self, t))
  139 + local speed2, hit2 = self:attackTargetWith(target, offweapon.combat, DamageType.ACID, self:getOffHandMult(offweapon.combat, t.getDamage(self, t)))
135 140 DamageType:projectingFor(self, nil)
136 141
137 142 -- Acid splash !
... ... @@ -139,35 +144,37 @@ newTalent{
139 144 local tg = self:getTalentTarget(t)
140 145 tg.x = target.x
141 146 tg.y = target.y
142   - self:project(tg, target.x, target.y, DamageType.ACID, self:spellCrit(self:combatTalentSpellDamage(t, 10, 130)))
  147 + self:project(tg, target.x, target.y, DamageType.ACID, self:spellCrit(t.getSplash(self, t)))
143 148 end
144 149
145 150 return true
146 151 end,
147 152 info = function(self, t)
148 153 return ([[Strike with each of your weapons, doing %d%% acid weapon damage with each hit.
149   - If at least one of the strikes hits, an acid splash is generated, doing %0.2f acid damage to all targets other than yourself adjacent to the foe you struck.
  154 + If at least one of the strikes hits, an acid splash is generated, doing %0.2f acid damage to all enemies in radius %d around the foe you struck.
150 155 The splash damage will increase with your Spellpower.]]):
151   - format(100 * self:combatTalentWeaponDamage(t, 0.8, 1.6), damDesc(self, DamageType.ACID, self:combatTalentSpellDamage(t, 10, 130)))
  156 + format(100 * t.getDamage(self, t), damDesc(self, DamageType.ACID, t.getSplash(self, t)), self:getTalentRadius(t))
152 157 end,
153 158 }
154 159
155 160 newTalent{
156   - name = "Dark Surprise",
  161 + name = "Corrupting Strike",
  162 + short_name = "DARK_SURPRISE",
157 163 type = {"corruption/scourge", 4},
158 164 require = corrs_req4,
159 165 points = 5,
160   - vim = 14,
  166 + vim = 30,
161 167 cooldown = 8,
162 168 range = 1,
163 169 is_melee = true,
164 170 requires_target = true,
165   - tactical = { ATTACK = {DARKNESS = 1, BLIGHT = 1}, DISABLE = 2 },
  171 + tactical = { ATTACK = {BLIGHT = 1},},
166 172 target = function(self, t) return {type="hit", range=self:getTalentRange(t)} end,
  173 + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1, 2) end,
167 174 action = function(self, t)
168 175 local weapon, offweapon = self:hasDualWeapon()
169 176 if not weapon then
170   - game.logPlayer(self, "You cannot use Dark Surprise without two weapons!")
  177 + game.logPlayer(self, "You cannot use Corrupting Strike without two weapons!")
171 178 return nil
172 179 end
173 180
... ... @@ -175,25 +182,19 @@ newTalent{
175 182 local x, y, target = self:getTarget(tg)
176 183 if not target or not self:canProject(tg, x, y) then return nil end
177 184
178   - DamageType:projectingFor(self, {project_type={talent=t}})
179   - local speed1, hit1 = self:attackTargetWith(target, weapon.combat, DamageType.DARKNESS, self:combatTalentWeaponDamage(t, 0.6, 1.4))
  185 + -- Awkward to have this happen first, but part of the point of the talent is to help guarantee any misc disease on hit effects can't be immuned
  186 + target:removeSustainsFilter(function(e) return e.is_nature end, 2)
  187 + target:setEffect(target.EFF_CORRUPTING_STRIKE, 2, {})
180 188
181   - if hit1 then
182   - self.turn_procs.auto_phys_crit = true
183   - local speed2, hit2 = self:attackTargetWith(target, offweapon.combat, DamageType.BLIGHT, self:getOffHandMult(offweapon.combat, self:combatTalentWeaponDamage(t, 0.6, 1.4)))
184   - self.turn_procs.auto_phys_crit = nil
185   - if hit2 and target:canBe("blind") then
186   - target:setEffect(target.EFF_BLINDED, 4, {apply_power=self:combatPhysicalpower()})
187   - else
188   - game.logSeen(self, "%s resists the darkness.", target.name:capitalize())
189   - end
190   - end
  189 + DamageType:projectingFor(self, {project_type={talent=t}})
  190 + local speed1, hit1 = self:attackTargetWith(target, weapon.combat, DamageType.PHYSICAL, t.getDamage(self, t))
  191 + local speed2, hit2 = self:attackTargetWith(target, offweapon.combat, DamageType.PHYSICAL, self:getOffHandMult(offweapon.combat, t.getDamage(self, t)))
191 192 DamageType:projectingFor(self, nil)
192 193
193 194 return true
194 195 end,
195 196 info = function(self, t)
196   - return ([[Hits the target with your main weapon, doing %d%% darkness weapon damage. If the attack hits you attack with your second weapon, doing %d%% blight weapon damage and granting an automatic critical. If the second attack hits, the target is blinded for 4 turns.]]):
197   - format(100 * self:combatTalentWeaponDamage(t, 0.6, 1.4), 100 * self:combatTalentWeaponDamage(t, 0.6, 1.4))
  197 + return ([[Corrupt the target reducing disease immunity by 100%% for 2 turns and stripping up to 2 nature sustains then strike with both your weapons dealing %d%% damage.]]):
  198 + format(100 * t.getDamage(self, t))
198 199 end,
199 200 }
... ...
... ... @@ -21,31 +21,11 @@ newTalent{
21 21 name = "Willful Tormenter",
22 22 type = {"corruption/torment", 1},
23 23 require = corrs_req1,
24   - mode = "sustained",
  24 + mode = "passive",
25 25 points = 5,
26   - cooldown = 20,
27   - tactical = { BUFF = 2 },
28   - VimBonus = function(self, t) return self:combatTalentScale(t, 20, 75, 0.75) end,
29   - activate = function(self, t)
30   - game:playSoundNear(self, "talents/flame")
31   - return {
32   - vim = self:addTemporaryValue("max_vim", t.VimBonus(self, t)),
33   - }
34   - end,
35   - deactivate = function(self, t, p)
36   - self:removeTemporaryValue("max_vim", p.vim)
37   -
38   - while self:getMaxVim() < 0 do
39   - local l = {}
40   - for tid, _ in pairs(self.sustain_talents) do
41   - local t = self:getTalentFromId(tid)
42   - if t.sustain_vim then l[#l+1] = tid end
43   - end
44   - if #l == 0 then break end
45   - self:forceUseTalent(rng.table(l), {ignore_energy=true, no_equilibrium_fail=true, no_paradox_fail=true})
46   - end
47   -
48   - return true
  26 + VimBonus = function(self, t) return self:combatTalentScale(t, 20, 95, 0.75) end,
  27 + passives = function(self, t, p)
  28 + self:talentTemporaryValue(p, "max_vim", t.VimBonus(self, t))
49 29 end,
50 30 info = function(self, t)
51 31 return ([[You set your mind toward a single goal: the destruction of all your foes.
... ... @@ -153,7 +133,7 @@ newTalent{
153 133 end,
154 134 info = function(self, t)
155 135 local l, c = t.getPower(self, t)
156   - return ([[When you are dealt a blow that reduces your life by at least %d%%, you have a %d%% chance to reduce the remaining cooldown of all your spells by 1.
  136 + return ([[When you are dealt a blow that reduces your life by at least %d%%, you have a %d%% chance to reduce the remaining cooldown of all your talents by 1.
157 137 The chance will increase with your Spellpower.]]):
158 138 format(l, c)
159 139 end,
... ...
... ... @@ -126,7 +126,7 @@ newTalent{
126 126 points = 5,
127 127 cooldown = 15,
128 128 vim = 16,
129   - range = 5,
  129 + range = 10,
130 130 tactical = { DISABLE = 2 },
131 131 direct_hit = true,
132 132 requires_target = true,
... ... @@ -139,7 +139,7 @@ newTalent{
139 139 self:project(tg, x, y, function(tx, ty)
140 140 local target = game.level.map(tx, ty, Map.ACTOR)
141 141 if not target or target == self then return end
142   - target:setEffect(target.EFF_HEALING_INVERSION, 5, {apply_power=self:combatSpellpower(), power=t.getPower(self, t)})
  142 + target:setEffect(target.EFF_HEALING_INVERSION, 5, {src=self, apply_power=self:combatSpellpower(), power=t.getPower(self, t)})
143 143 end)
144 144 game:playSoundNear(self, "talents/slime")
145 145 return true
... ... @@ -188,13 +188,16 @@ newTalent{
188 188 local p = self.tmp[eff_id]
189 189 local e = self.tempeffect_def[eff_id]
190 190 local effectParam = self:copyEffect(eff_id)
191   - effectParam.src = self
  191 + effectParam.__tmpparticles = nil
  192 + if effectParam then
  193 + effectParam.src = self
192 194
193   - target:setEffect(eff_id, p.dur, effectParam)
194   - self:removeEffect(eff_id)
195   - local dead, val = self:takeHit(dam, self, {source_talent=t})
196   - target:heal(val, self)
197   - game:delayedLogMessage(self, target, "vile_transplant"..e.desc, ("#CRIMSON##Source# transfers an effect (%s) to #Target#!"):format(e.desc))
  195 + target:setEffect(eff_id, p.dur, effectParam)
  196 + self:removeEffect(eff_id)
  197 + local dead, val = self:takeHit(dam, self, {source_talent=t})
  198 + target:heal(val, self)
  199 + game:delayedLogMessage(self, target, "vile_transplant"..e.desc, ("#CRIMSON##Source# transfers an effect (%s) to #Target#!"):format(e.desc))
  200 + end
198 201 end
199 202 nb = nb - 1
200 203 end
... ...
... ... @@ -50,23 +50,26 @@ newTalent{
50 50 type = {"corruption/vim", 2},
51 51 require = corrs_req2,
52 52 points = 5,
53   - cooldown = 25,
54   - vim = 25,
  53 + cooldown = 15,
  54 + vim = 35,
55 55 requires_target = true,
56 56 no_npc_use = true,
57 57 getDuration = function(self, t) return math.floor(self:combatTalentScale(t, 4, 8)) end,
58   - getResistPenalty = function(self, t) return self:combatTalentSpellDamage(t, 10, 45) end, -- Consider reducing this
  58 + getResistPenalty = function(self, t) return self:combatTalentSpellDamage(t, 10, 30) end,
  59 + getSaves = function(self, t) return self:combatTalentSpellDamage(t, 8, 50) end,
59 60 action = function(self, t)
60 61 local rad = 10
61 62 self:setEffect(self.EFF_VIMSENSE_DETECT, t.getDuration(self,t), {
62 63 range = rad,
63 64 actor = 1,
64 65 VimsensePenalty = t.getResistPenalty(self,t), -- Compute resist penalty at time of activation
  66 + VimsenseSaves = t.getSaves(self,t),
  67 +
65 68 on_detect = function(self, x, y)
66 69 local a = game.level.map(x, y, engine.Map.ACTOR)
67 70 if not a or self:reactionToward(a) >= 0 then return end
68 71 a:setTarget(game.player)
69   - a:setEffect(a.EFF_VIMSENSE, 2, {power=self:hasEffect(self.EFF_VIMSENSE_DETECT).VimsensePenalty or 0})
  72 + a:setEffect(a.EFF_VIMSENSE, 2, {power=self:hasEffect(self.EFF_VIMSENSE_DETECT).VimsensePenalty or 0, saves=self:hasEffect(self.EFF_VIMSENSE_DETECT).VimsenseSaves or 0})
70 73 end,
71 74 })
72 75 game:playSoundNear(self, "talents/spell_generic")
... ... @@ -74,9 +77,9 @@ newTalent{
74 77 end,
75 78 info = function(self, t)
76 79 return ([[Feel the very existence of creatures around you for %d turns, in a radius of 10.
77   - The evil touch will reduce their blight resistance by %d%%, but also make them aware of you.
78   - The resistance reduction will improve with your Spellpower.]]):
79   - format(t.getDuration(self,t), t.getResistPenalty(self,t))
  80 + The evil touch will reduce their blight resistance by %d%% and all saves by %d, but also make them aware of you.
  81 + The resistance and save reduction will improve with your Spellpower.]]):
  82 + format(t.getDuration(self,t), t.getResistPenalty(self,t), t.getSaves(self, t))
80 83 end,
81 84 }
82 85
... ... @@ -87,8 +90,8 @@ newTalent{
87 90 mode = "passive",
88 91 points = 5,
89 92 -- called by _M:onTakeHit function in mod\class\Actor.lua
90   - getVim = function(self, t) return self:combatTalentScale(t, 3.7, 6.5, 0.75) end,
91   - getHeal = function(self, t) return self:combatTalentScale(t, 8, 20, 0.75) end,
  93 + getVim = function(self, t) return self:combatTalentScale(t, 1.7, 6.5, 0.75) end,
  94 + getHeal = function(self, t) return self:combatTalentScale(t, 4, 15, 0.75) end,
92 95 info = function(self, t)
93 96 return ([[Each time a creature affected by vimsense hurts you, you regain %0.2f vim and %0.2f health.]]):
94 97 format(t.getVim(self,t),t.getHeal(self,t))
... ... @@ -108,7 +111,7 @@ newTalent{
108 111 radius = 3,
109 112 requires_target = true,
110 113 target = function(self, t)
111   - return {type="ball", radius=self:getTalentRadius(t), range=self:getTalentRange(t), selffire=false, talent=t}
  114 + return {type="ball", radius=self:getTalentRadius(t), range=self:getTalentRange(t), selffire=false, talent=t}
112 115 end,
113 116 action = function(self, t)
114 117 local tg = self:getTalentTarget(t)
... ...
... ... @@ -253,16 +253,18 @@ newEffect{
253 253 newEffect{
254 254 name = "VIMSENSE", image = "talents/vimsense.png",
255 255 desc = "Vimsense",
256   - long_desc = function(self, eff) return ("Reduces blight resistance by %d%%."):format(eff.power) end,
  256 + long_desc = function(self, eff) return ("Reduces blight resistance by %d%% and all saves by %d."):format(eff.power, eff.saves) end,
257 257 type = "magical",
258 258 subtype = { blight=true },
259 259 status = "detrimental",
260   - parameters = { power=10 },
  260 + parameters = { power=10, saves=0 },
261 261 activate = function(self, eff)
262   - eff.tmpid = self:addTemporaryValue("resists", {[DamageType.BLIGHT]=-eff.power})
  262 + self:effectTemporaryValue(eff, "resists", {[DamageType.BLIGHT]=-eff.power})
  263 + self:effectTemporaryValue(eff, "combat_mindresist", -eff.saves)
  264 + self:effectTemporaryValue(eff, "combat_spellresist", -eff.saves)
  265 + self:effectTemporaryValue(eff, "combat_physresist", -eff.saves)
263 266 end,
264 267 deactivate = function(self, eff)
265   - self:removeTemporaryValue("resists", eff.tmpid)
266 268 end,
267 269 }
268 270
... ... @@ -973,12 +975,30 @@ newEffect{
973 975 }
974 976
975 977 newEffect{
  978 + name = "CORRUPTING_STRIKE", image = "talents/dark_surprise.png",
  979 + desc = "Corrupting Strike",
  980 + long_desc = function(self, eff) return ("The targets natural essence in corrupted reducing disease resistance by 100%%."):format() end,
  981 + type = "magical",
  982 + subtype = {blight=true},
  983 + status = "detrimental",
  984 + parameters = {},
  985 + on_gain = function(self, err) return "#Target# is completely vulnerable to disease!" end,
  986 + on_lose = function(self, err) return "#Target# no longer vulnerable to disease." end,
  987 + activate = function(self, eff)
  988 + self:effectTemporaryValue(eff, "disease_immune", -1)
  989 + end,
  990 + deactivate = function(self, eff)
  991 + end,
  992 +}
  993 +
  994 +newEffect{
976 995 name = "BLOODLUST", image = "talents/bloodlust.png",
977 996 desc = "Bloodlust",
978 997 long_desc = function(self, eff) return ("The target is in a magical frenzy, improving spellpower by %d."):format(eff.power) end,
979 998 type = "magical",
980 999 subtype = { frenzy=true },
981 1000 status = "beneficial",
  1001 + charges = function(self, eff) return math.floor(eff.power) end,
982 1002 parameters = { power=1 },
983 1003 on_timeout = function(self, eff)
984 1004 if eff.refresh_turn + 10 < game.turn then -- Decay only if it's not refreshed
... ... @@ -3105,10 +3125,9 @@ newEffect{
3105 3125 if raw_value > 0 and not eff.projecting then -- avoid feedback; it's bad to lose out on dmg but it's worse to break the game
3106 3126 eff.projecting = true
3107 3127 local dam = raw_value * eff.power / 100
3108   - local psrc = eff.src or src or self
3109   - psrc.__project_source = eff
3110   - DamageType:get(DamageType.BLIGHT).projector(psrc, self.x, self.y, DamageType.BLIGHT, dam)
3111   - psrc.__project_source = nil
  3128 + eff.src.__project_source = eff
  3129 + DamageType:get(DamageType.BLIGHT).projector(eff.src, self.x, self.y, DamageType.BLIGHT, dam)
  3130 + eff.src.__project_source = nil
3112 3131 eff.projecting = false
3113 3132 end
3114 3133 return {value=0}
... ...