hymns.lua
21.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
-- ToME - Tales of Maj'Eyal
-- Copyright (C) 2009 - 2019 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
--- general tactical function accounting for Hymn Acolyte and Hymn Incantor
-- uses t.base_tactical and t.adept_deac_tactical
local hymn_tactical = function(self, t, aitarget)
local bt_type, tacs = type(t.base_tactical)
if bt_type == "function" then
tacs = t.base_tactical(self, t, aitarget)
elseif bt_type == "table" then
tacs = table.clone(t.base_tactical)
end
tacs = tacs or {}
local lvl = self:getTalentLevel(self.T_HYMN_INCANTOR)
if lvl > 0 then
tacs.buff = (tacs.buff or 0) + 2*lvl/(lvl + 5)
end
lvl = self:getTalentLevel(self.T_HYMN_ADEPT)
if lvl > 0 and self:isTalentActive(t.id) then
if t.adept_deac_tactical then
table.mergeAdd(tacs, t.adept_deac_tactical)
end
tacs.special = (tacs.special or 0) + 0.01 -- forces some "inertia" in toggling hymns
end
return tacs
end
newTalent{
name = "Hymn of Shadows",
type = {"celestial/hymns-hymns", 1},
mode = "sustained",
hide = true,
require = divi_req1,
points = 5,
cooldown = 12,
sustain_negative = 20,
no_energy = true,
dont_provide_pool = true,
tactical = hymn_tactical,
base_tactical = { buff=1, defend=0.5, escape=1 , closein=1},
adept_deac_tactical = {escape = -0.5, closein = -0.5}, -- adept tactic adjustments when deactivating (negated)
range = 0,
moveSpeed = function(self, t) return self:combatTalentSpellDamage(t, 20, 50) end,
castSpeed = function(self, t) return self:combatTalentSpellDamage(t, 7, 20) end,
callbackOnActBase = function(self, t)
if self:isTalentActive(self.T_HYMN_NOCTURNALIST) then
local t2 = self:getTalentFromId(self.T_HYMN_NOCTURNALIST)
t2.do_beams(self, t2)
end
end,
sustain_slots = 'celestial_hymn',
activate = function(self, t)
game:playSoundNear(self, "talents/spell_generic2")
local ret = {}
self:talentTemporaryValue(ret, "movement_speed", t.moveSpeed(self, t)/100)
self:talentTemporaryValue(ret, "combat_spellspeed", t.castSpeed(self, t)/100)
ret.particle = self:addParticles(Particles.new("darkness_shield", 1))
if self:knowTalent(self.T_HYMN_INCANTOR) then
local t2 = self:getTalentFromId(self.T_HYMN_INCANTOR)
self:talentTemporaryValue(ret, "on_melee_hit", {[DamageType.DARKNESS]=t2.getDamageOnMeleeHit(self, t2)})
self:talentTemporaryValue(ret, "inc_damage", {[DamageType.DARKNESS] = t2.getDarkDamageIncrease(self, t2)})
end
if self:knowTalent(self.T_HYMN_ADEPT) then
local t2 = self:getTalentFromId(self.T_HYMN_ADEPT)
self:talentTemporaryValue(ret, "infravision", t2.getBonusInfravision(self, t2))
end
if self:isTalentActive(self.T_HYMN_NOCTURNALIST) then
local t2 = self:getTalentFromId(self.T_HYMN_NOCTURNALIST)
end
return ret
end,
deactivate = function(self, t, p)
self:removeParticles(p.particle)
if self.turn_procs.resetting_talents then return true end
if self:knowTalent(self.T_HYMN_ADEPT) then
local t2 = self:getTalentFromId(self.T_HYMN_ADEPT)
game:onTickEnd(function() self:setEffect(self.EFF_WILD_SPEED, 1, {power=t2.getSpeed(self, t2), no_talents=0}) end)
end
return true
end,
info = function(self, t)
return ([[Chant the glory of the Moons, gaining the agility of shadows.
This increases your movement speed by %d%% and your spell speed by %d%%.
You may only have one Hymn active at once.
The effects will increase with your Spellpower.]]):
tformat(t.moveSpeed(self, t), t.castSpeed(self, t))
end,
}
newTalent{
name = "Hymn of Detection",
type = {"celestial/hymns-hymns", 1},
mode = "sustained",
hide = true,
require = divi_req1,
points = 5,
cooldown = 12,
sustain_negative = 20,
no_energy = true,
dont_provide_pool = true,
tactical = hymn_tactical,
adept_deac_tactical = {escape = -0.5}, -- adept tactic adjustments when deactivating (negated)
base_tactical = function(self, t, aitarget) -- buff tactic up to +3 depending on how much the talent helps to see a stealthed/invisible target or a target that is out of sense range
local buff, max_buff = 0, 4
if not aitarget or not self.aiSeeTargetPos then -- out of combat, stay vigilant for enemies
buff = max_buff
else
if self:attr("blind") or self:attr("esp_all") then return end -- target automatically seen or unseen
local ax, ay = self:aiSeeTargetPos(aitarget)
local dist = core.fov.distance(self.x, self.y, ax, ay)
if dist <= self.sight then -- target within sight range
local is_active = self:isTalentActive(t.id)
local see, see_chance = self:canSeeNoCache(aitarget)
if see_chance and see_chance < 100 then -- detecting hidden is useful (rules out esp, etc.)
local tgt_inv = aitarget:attr("invisible")
if tgt_inv then -- buff value increases depending on relative invisibility detection
local base_det = self:combatSeeInvisible() - (is_active and self.compute_vals[is_active.invis] or 0)
if base_det <= 0 then return {buff = max_buff} end -- cannot see at all with no detection ability
local need_det = tgt_inv - base_det
buff = buff + math.max(0, max_buff*(0.5 + need_det/(math.abs(need_det) + 20))) -- adds 0 (need_det = -20) to max_buff (need_det = +20)
end
local tgt_stealth = aitarget:attr("stealth")
if tgt_stealth then -- buff value increases depending on relative stealth detection
tgt_stealth = tgt_stealth + (aitarget:attr("inc_stealth") or 0)
local base_det = is_active and is_active.base_see_stealth or self:combatSeeStealth()
local need_det = tgt_stealth - base_det
buff = buff + math.max(0, max_buff*(0.5 + need_det/(math.abs(need_det) + 20))) -- adds 0 (need_det = -20) to max_buff (need_det = +20)
end
end
end
end
buff=math.min(buff, max_buff)
return {buff=buff + 0.25, special = buff/2}
end,
range = 0,
sustain_slots = 'celestial_hymn',
getSeeInvisible = function(self, t) return self:combatTalentSpellDamage(t, 2, 25) end,
getSeeStealth = function(self, t) return self:combatTalentSpellDamage(t, 2, 25) end,
critPower = function(self, t) return self:combatTalentSpellDamage(t, 10, 50) end,
callbackOnActBase = function(self, t)
if self:isTalentActive(self.T_HYMN_NOCTURNALIST) then
local t2 = self:getTalentFromId(self.T_HYMN_NOCTURNALIST)
t2.do_beams(self, t2)
end
end,
activate = function(self, t)
game:playSoundNear(self, "talents/spell_generic2")
-- base_see_stealth = self:combatSeeStealth(),
local ret = {}
self:talentTemporaryValue(ret, "see_invisible", t.getSeeInvisible(self, t))
self:talentTemporaryValue(ret, "see_stealth", t.getSeeStealth(self, t))
self:talentTemporaryValue(ret, "blindfight", 1)
self:talentTemporaryValue(ret, "combat_critical_power", t.critPower(self, t))
ret.particle = self:addParticles(Particles.new("darkness_shield", 1))
if self:knowTalent(self.T_HYMN_INCANTOR) then
local t2 = self:getTalentFromId(self.T_HYMN_INCANTOR)
self:talentTemporaryValue(ret, "on_melee_hit", {[DamageType.DARKNESS]=t2.getDamageOnMeleeHit(self, t2)})
self:talentTemporaryValue(ret, "inc_damage", {[DamageType.DARKNESS] = t2.getDarkDamageIncrease(self, t2)})
end
if self:knowTalent(self.T_HYMN_ADEPT) then
local t2 = self:getTalentFromId(self.T_HYMN_ADEPT)
self:talentTemporaryValue(ret, "infravision", t2.getBonusInfravision(self, t2))
end
if self:isTalentActive(self.T_HYMN_NOCTURNALIST) then
local t2 = self:getTalentFromId(self.T_HYMN_NOCTURNALIST)
end
return ret
end,
deactivate = function(self, t, p)
self:removeParticles(p.particle)
if self.turn_procs.resetting_talents then return true end
if self:knowTalent(self.T_HYMN_ADEPT) then
local t2 = self:getTalentFromId(self.T_HYMN_ADEPT)
self:setEffect(self.EFF_INVISIBILITY, t2.invisDur(self, t2), {power=t2.invisPower(self, t2), penalty=0.4})
end
return true
end,
info = function(self, t)
local invis = t.getSeeInvisible(self, t)
local stealth = t.getSeeStealth(self, t)
return ([[Chant the glory of the Moons, granting you stealth detection (+%d power), and invisibility detection (+%d power).
You may also attack creatures you cannot see without penalty and your critical hits do %d%% more damage.
You may only have one Hymn active at once.
The stealth and invisibility detection will increase with your Spellpower.]]):
tformat(stealth, invis, t.critPower(self, t))
end,
}
newTalent{
name = "Hymn of Perseverance",
type = {"celestial/hymns-hymns",1},
mode = "sustained",
hide = true,
require = divi_req1,
points = 5,
cooldown = 12,
sustain_negative = 20,
no_energy = true,
dont_provide_pool = true,
tactical = hymn_tactical,
base_tactical = {defend=1}, -- could check base immunities here
adept_deac_tactical = {defend = -0.5}, -- adept tactic adjustments when deactivating (negated)
range = 10,
getImmunities = function(self, t) return self:combatTalentLimit(t, 1, 0.2, 0.45) end, -- Limit < 100%
callbackOnActBase = function(self, t)
if self:isTalentActive(self.T_HYMN_NOCTURNALIST) then
local t2 = self:getTalentFromId(self.T_HYMN_NOCTURNALIST)
t2.do_beams(self, t2)
end
end,
sustain_slots = 'celestial_hymn',
activate = function(self, t)
game:playSoundNear(self, "talents/spell_generic2")
local ret = {}
self:talentTemporaryValue(ret, "stun_immune", t.getImmunities(self, t))
self:talentTemporaryValue(ret, "confusion_immune", t.getImmunities(self, t))
self:talentTemporaryValue(ret, "blind_immune", t.getImmunities(self, t))
ret.particle = self:addParticles(Particles.new("darkness_shield", 1))
if self:knowTalent(self.T_HYMN_INCANTOR) then
local t2 = self:getTalentFromId(self.T_HYMN_INCANTOR)
self:talentTemporaryValue(ret, "on_melee_hit", {[DamageType.DARKNESS]=t2.getDamageOnMeleeHit(self, t2)})
self:talentTemporaryValue(ret, "inc_damage", {[DamageType.DARKNESS] = t2.getDarkDamageIncrease(self, t2)})
end
if self:knowTalent(self.T_HYMN_ADEPT) then
local t2 = self:getTalentFromId(self.T_HYMN_ADEPT)
self:talentTemporaryValue(ret, "infravision", t2.getBonusInfravision(self, t2))
end
if self:isTalentActive(self.T_HYMN_NOCTURNALIST) then
local t2 = self:getTalentFromId(self.T_HYMN_NOCTURNALIST)
end
return ret
end,
deactivate = function(self, t, p)
self:removeParticles(p.particle)
if self.turn_procs.resetting_talents then return true end
if self:knowTalent(self.T_HYMN_ADEPT) then
local t2 = self:getTalentFromId(self.T_HYMN_ADEPT)
self:setEffect(self.EFF_DAMAGE_SHIELD, t2.shieldDur(self, t2), {power=t2.shieldPower(self, t2)})
end
return true
end,
info = function(self, t)
local immunities = t.getImmunities(self, t)
return ([[Chant the glory of the Moons, granting you %d%% stun, blindness and confusion resistance.
You may only have one Hymn active at once.]]):
tformat(100 * (immunities))
end,
}
-- Depreciated, but retained for compatability.
newTalent{
name = "Hymn of Moonlight",
type = {"celestial/hymns-hymns",1},
mode = "sustained",
require = divi_req4,
points = 5,
cooldown = 12,
sustain_negative = 20,
no_energy = true,
dont_provide_pool = true,
tactical = { ATTACKAREA = { DARKNESS = 1 },
NEGATIVE = function(self, t, target)
return t.getNegativeDrain(self, t)/15 -- negated for foes
end
},
range = 5,
getDamage = function(self, t) return self:combatTalentSpellDamage(t, 7, 80) end,
getTargetCount = function(self, t) return math.floor(self:combatTalentScale(t, 1, 5)) end,
getNegativeDrain = function(self, t) return self:combatTalentLimit(t, 0, 7, 3) end, -- Limit > 0, no regen at high levels
target = function(self, t) -- for AI only
return {type="ball", friendlyfire=false, friendlyblock=false, radius=self:getTalentRange(t), range=0, talent=t}
end,
callbackOnActBase = function(self, t)
local drain = t.getNegativeDrain(self, t)
if self:getNegative() < drain then return end
local tgts = {}
local grids = core.fov.circle_grids(self.x, self.y, 5, true)
for x, yy in pairs(grids) do for y, _ in pairs(grids[x]) do
local a = game.level.map(x, y, Map.ACTOR)
if a and self:reactionToward(a) < 0 then
tgts[#tgts+1] = a
end
end end
local drain = t.getNegativeDrain(self, t)
-- Randomly take targets
local tg = {type="hit", range=self:getTalentRange(t), talent=t}
for i = 1, t.getTargetCount(self, t) do
if #tgts <= 0 then break end
if self:getNegative() - 1 < drain then break end
local a, id = rng.table(tgts)
table.remove(tgts, id)
self:project(tg, a.x, a.y, DamageType.DARKNESS, rng.avg(1, self:spellCrit(t.getDamage(self, t)), 3))
game.level.map:particleEmitter(self.x, self.y, math.max(math.abs(a.x-self.x), math.abs(a.y-self.y)), "shadow_beam", {tx=a.x-self.x, ty=a.y-self.y})
game:playSoundNear(self, "talents/spell_generic")
self:incNegative(-drain)
end
end,
sustain_slots = 'celestial_hymn',
activate = function(self, t)
game:playSoundNear(self, "talents/spell_generic")
game.logSeen(self, "#DARK_GREY#A shroud of shadow dances around %s!", self:getName())
return { name=("%s's %s"):tformat(self:getName():capitalize(), t.name)
}
end,
deactivate = function(self, t, p)
game.logSeen(self, "#DARK_GREY#The shroud of shadows around %s disappears.", self:getName())
return true
end,
info = function(self, t)
local targetcount = t.getTargetCount(self, t)
local damage = t.getDamage(self, t)
local drain = t.getNegativeDrain(self, t)
return ([[Chant the glory of the Moons, conjuring a shroud of dancing shadows that follows you as long as this spell is active.
Each turn, a shadowy beam will hit up to %d of your foes within radius 5 for 1 to %0.2f damage.
This powerful spell will drain %0.1f negative energy for each beam; no beam will fire if your negative energy is too low.
You may only have one Hymn active at once.
The damage will increase with your Spellpower.]]):
tformat(targetcount, damDesc(self, DamageType.DARKNESS, damage), drain)
end,
}
newTalent{
name = "Hymn Acolyte",
type = {"celestial/hymns", 1},
require = divi_req1,
points = 5,
mode = "passive",
negative = 0, -- forces learning of Negative pool
no_difficulty_boost = true, -- avoid double boost from difficulty
passives = function(self, t)
self:setTalentTypeMastery("celestial/hymns-hymns", self:getTalentMastery(t))
end,
on_learn = function(self, t)
self:learnTalent(self.T_HYMN_OF_SHADOWS, true, nil, {no_unlearn=true})
self:learnTalent(self.T_HYMN_OF_DETECTION, true, nil, {no_unlearn=true})
self:learnTalent(self.T_HYMN_OF_PERSEVERANCE, true, nil, {no_unlearn=true})
end,
on_unlearn = function(self, t)
self:unlearnTalent(self.T_HYMN_OF_SHADOWS)
self:unlearnTalent(self.T_HYMN_OF_DETECTION)
self:unlearnTalent(self.T_HYMN_OF_PERSEVERANCE)
end,
info = function(self, t)
local ret = ""
local old1 = self.talents[self.T_HYMN_OF_SHADOWS]
local old2 = self.talents[self.T_HYMN_OF_DETECTION]
local old3 = self.talents[self.T_HYMN_OF_PERSEVERANCE]
self.talents[self.T_HYMN_OF_SHADOWS] = (self.talents[t.id] or 0)
self.talents[self.T_HYMN_OF_DETECTION] = (self.talents[t.id] or 0)
self.talents[self.T_HYMN_OF_PERSEVERANCE] = (self.talents[t.id] or 0)
pcall(function() -- Be very paranoid, even if some addon or whatever manage to make that crash, we still restore values
local t1 = self:getTalentFromId(self.T_HYMN_OF_SHADOWS)
local t2 = self:getTalentFromId(self.T_HYMN_OF_DETECTION)
local t3 = self:getTalentFromId(self.T_HYMN_OF_PERSEVERANCE)
ret = ([[You have learned to sing the praises of the Moons, in the form of three defensive Hymns:
Hymn of Shadows: Increases your movement speed by %d%% and your spell casting speed by %d%%.
Hymn of Detection: Increases your ability to see stealthy creatures by %d and invisible creatures by %d, and increases your critical power by %d%%.
Hymn of Perseverance: Increases your resistance to stun, confusion and blinding by %d%%.
You may only have one Hymn active at a time.]]):
tformat(t1.moveSpeed(self, t1), t1.castSpeed(self, t1), t2.getSeeStealth(self, t2), t2.getSeeInvisible(self, t2), t2.critPower(self, t2), t3.getImmunities(self, t3)*100)
end)
self.talents[self.T_HYMN_OF_SHADOWS] = old1
self.talents[self.T_HYMN_OF_DETECTION] = old2
self.talents[self.T_HYMN_OF_PERSEVERANCE] = old3
return ret
end,
}
newTalent{
name = "Hymn Incantor",
type = {"celestial/hymns", 2},
require = divi_req2,
points = 5,
mode = "passive",
getDamageOnMeleeHit = function(self, t) return self:combatTalentSpellDamage(t, 10, 30) end,
getDarkDamageIncrease = function(self, t) return self:combatTalentSpellDamage(t, 10, 30) end,
info = function(self, t)
return ([[Your Hymns now focus darkness near you, which increases your darkness damage by %d%% and does %0.2f darkness damage to anyone who hits you in melee.
These values scale with your Spellpower.]]):tformat(t.getDarkDamageIncrease(self, t), damDesc(self, DamageType.DARKNESS, t.getDamageOnMeleeHit(self, t)))
end,
}
-- Remember that Hymns can be swapped instantly.
newTalent{
name = "Hymn Adept",
type = {"celestial/hymns", 3},
require = divi_req3,
points = 5,
mode = "passive",
getBonusInfravision = function(self, t) return math.floor(self:combatTalentScale(t, 0.75, 3.5, 0.75)) end,
getSpeed = function(self, t) return self:combatTalentSpellDamage(t, 300, 600) end,
shieldDur = function(self, t) return self:combatTalentSpellDamage(t, 5, 10) end,
shieldPower = function(self, t) return self:combatTalentSpellDamage(t, 50, 500) end,
invisDur = function(self, t) return self:combatTalentSpellDamage(t, 5, 10) end,
invisPower = function(self, t) return math.ceil(self:combatTalentSpellDamage(t, 20, 30)) end,
info = function(self, t)
return ([[Your skill in Hymns now improves your sight in darkness, increasing your infravision radius by %d.
Also, when you end a Hymn, you will gain a buff of a type based on which Hymn you ended.
Hymn of Shadows increases your movement speed by %d%% for one turn.
Hymn of Detection makes you invisible (power %d) for %d turns.
Hymn of Perseverance grants a damage shield (power %d) for %d turns.]]):tformat(t.getBonusInfravision(self, t), t.getSpeed(self, t), t.invisPower(self, t), t.invisDur(self, t), self:getShieldAmount(t.shieldPower(self, t)), self:getShieldDuration(t.shieldDur(self, t)))
end,
}
newTalent{
name = "Hymn Nocturnalist",
type = {"celestial/hymns", 4},
require = divi_req4,
points = 5,
mode = "sustained",
cooldown = 10,
sustain_negative = 5,
range = 5,
tactical = { SELF = {NEGATIVE = 0.5}, -- this assumes a Hymn is active
ATTACKAREA = { DARKNESS = 1 },
DISABLE = { blind = 0.5},
NEGATIVE = function(self, t, target)
return t.getNegativeDrain(self, t)/15 -- negated for foes
end
},
target = function(self, t) -- for AI only
return {type="ball", friendlyfire=false, friendlyblock=false, radius=self:getTalentRange(t), range=0, talent=t}
end,
getDamage = function(self, t) return self:combatTalentSpellDamage(t, 1, 50) end,
getTargetCount = function(self, t) return math.floor(self:combatTalentScale(t, 1, 5)) end,
getNegativeDrain = function(self, t) return 5 end,
do_beams = function(self, t)
if self:getNegative() < t.getNegativeDrain(self, t) then return end
local tgts = {}
local grids = core.fov.circle_grids(self.x, self.y, 5, true)
for x, yy in pairs(grids) do for y, _ in pairs(grids[x]) do
local a = game.level.map(x, y, Map.ACTOR)
if a and self:reactionToward(a) < 0 then
tgts[#tgts+1] = a
end
end end
if #tgts <= 0 then return end
local drain = t.getNegativeDrain(self, t)
self:incNegative(-drain) -- Make sure to pay before Corona procs
local dam = self:spellCrit(t.getDamage(self, t))
-- Randomly take targets
local tg = {type="hit", range=self:getTalentRange(t), talent=t}
for i = 1, t.getTargetCount(self, t) do
if #tgts <= 0 then break end
local a, id = rng.table(tgts)
table.remove(tgts, id)
self:project(tg, a.x, a.y, DamageType.DARKNESS_BLIND, dam)
game.level.map:particleEmitter(self.x, self.y, math.max(math.abs(a.x-self.x), math.abs(a.y-self.y)), "shadow_beam", {tx=a.x-self.x, ty=a.y-self.y})
game:playSoundNear(self, "talents/spell_generic")
end
end,
activate = function(self, t)
game:onTickEnd(function()
self.turn_procs.resetting_talents = true
local hymn_id = self.sustain_slots and self.sustain_slots.celestial_hymn
if self:isTalentActive(hymn_id) then
self:forceUseTalent(hymn_id, {ignore_energy=true, ignore_cd=true, no_talent_fail=true, silent=true})
self:forceUseTalent(hymn_id, {ignore_energy=true, ignore_cd=true, no_talent_fail=true, silent=true})
end
self.turn_procs.resetting_talents = nil
end)
return {}
end,
deactivate = function(self, t, p)
game:onTickEnd(function()
self.turn_procs.resetting_talents = true
local hymn_id = self.sustain_slots and self.sustain_slots.celestial_hymn
if self:isTalentActive(hymn_id) then
self:forceUseTalent(hymn_id, {ignore_energy=true, ignore_cd=true, no_talent_fail=true, silent=true})
self:forceUseTalent(hymn_id, {ignore_energy=true, ignore_cd=true, no_talent_fail=true, silent=true})
end
self.turn_procs.resetting_talents = nil
end)
return true
end,
info = function(self, t)
return ([[Your passion for singing the praises of the Moons reaches its zenith.
Your Hymns now fire shadowy beams that will hit up to %d of your foes within radius 5 for %0.2f damage, with a 25%% chance of blinding.
This powerful effect will drain %0.1f negative energy each time it fires at at least 1 target; no beam will fire if your negative energy is too low.
These values scale with your Spellpower.]]):tformat(t.getTargetCount(self, t), damDesc(self, DamageType.DARKNESS, t.getDamage(self, t)), t.getNegativeDrain(self, t))
end,
}