Newer
Older
-- ToME - Tales of Middle-Earth
-- Copyright (C) 2009, 2010 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 function makeGolem()
return require("mod.class.NPC").new{
type = "construct", subtype = "golem",
display = 'g', color=colors.WHITE,
level_range = {1, 50},
combat = { dam=10, atk=10, apr=0, dammod={str=1} },
body = { INVEN = 50, MAINHAND=1, OFFHAND=1, BODY=1,},
infravision = 20,
rank = 3,
size_category = 4,
resolvers.talents{
[Talents.T_MASSIVE_ARMOUR_TRAINING]=1,
[Talents.T_HEAVY_ARMOUR_TRAINING]=1,
[Talents.T_WEAPON_COMBAT]=2,
},
resolvers.equip{
{type="weapon", subtype="battleaxe", autoreq=true},
{type="armor", subtype="heavy", autoreq=true}
},
autolevel = "alchemy-golem",
ai = "summoned", ai_real = "dumb_talented_simple", ai_state = { talent_in=4, ai_move="move_astar" },
energy = { mod=1 },
stats = { str=14, dex=12, mag=10, con=12 },
see_invisible = 2,
no_breath = 1,
}
end
newTalent{
name = "Refit Golem",
type = {"spell/golemancy-base", 1},
cooldown = 20,
mana = 10,
action = function(self, t)
if not self.alchemy_golem then
self.alchemy_golem = game.zone:finishEntity(game.level, "actor", makeGolem())
if not self.alchemy_golem then return end
self.alchemy_golem.faction = self.faction
self.alchemy_golem.name = "golem (servant of "..self.name..")"
self.alchemy_golem.summoner = self
self.alchemy_golem.summoner_gain_exp = true
local co = coroutine.running()
local ok = false
self:restInit(20, "refitting", "refitted", function(cnt, max)
if cnt > max then ok = true end
coroutine.resume(co)
end)
coroutine.yield()
if not ok then
game.logPlayer(self, "You have been interrupted!")
return
end
local ammo = self:hasAlchemistWeapon()
-- talk to the golem
if game.level:hasEntity(self.alchemy_golem) and self.alchemy_golem.life >= self.alchemy_golem.max_life then
local chat = Chat.new("alchemist-golem", self.alchemy_golem, self)
chat:invoke()
-- heal the golem
elseif game.level:hasEntity(self.alchemy_golem) and self.alchemy_golem.life < self.alchemy_golem.max_life then
if not ammo or ammo:getNumber() < 2 then
game.logPlayer(self, "You need to ready 2 alchemist gems in your quiver to heal your golem.")
return
end
for i = 1, 2 do self:removeObject(self:getInven("QUIVER"), 1) end
self.alchemy_golem:heal(self:combatTalentSpellDamage(t, 15, 150, (ammo.alchemist_power + self:combatSpellpower()) / 2))
-- resurrect the golem
if not ammo or ammo:getNumber() < 15 then
game.logPlayer(self, "You need to ready 15 alchemist gems in your quiver to heal your golem.")
return
end
wait()
for i = 1, 15 do self:removeObject(self:getInven("QUIVER"), 1) end
self.alchemy_golem.dead = nil
if self.alchemy_golem.life < 0 then self.alchemy_golem.life = self.alchemy_golem.max_life / 3 end
-- Find space
local x, y = util.findFreeGrid(self.x, self.y, 5, true, {[Map.ACTOR]=true})
if not x then
return
end
game.zone:addEntity(game.level, self.alchemy_golem, "actor", x, y)
end
game:playSoundNear(self, "talents/arcane")
return true
end,
info = function(self, t)
local ammo = self:hasAlchemistWeapon()
local heal = 0
if ammo then self:combatTalentSpellDamage(t, 15, 150, (ammo.alchemist_power + self:combatSpellpower()) / 2) end
return ([[Interract with your golem
- If it is destroyed you will take some time to reconstruct it (takes 15 alchemist gems).
- If it is alive you will be able to talk to it, change its weapon and armour or heal it (%d; takes 2 alchemist gems)]]):
format(heal)
name = "Golem: Taunt", short_name = "GOLEM_TAUNT",
type = {"spell/golemancy", 1},
require = spells_req1,
points = 5,
cooldown = function(self, t)
return 20 - self:getTalentLevelRaw(t) * 2
range = 10,
mana = 5,
if not game.level:hasEntity(self.alchemy_golem) then
game.logPlayer(self, "Your golem is currently inactive.")
local tg = {type="hit", range=self:getTalentRange(t)}
game.target.source_actor = self.alchemy_golem
local x, y, target = self:getTarget(tg)
game.target.source_actor = self
if not x or not y or not target then print(1) return nil end
if math.floor(core.fov.distance(self.alchemy_golem.x, self.alchemy_golem.y, x, y)) > self:getTalentRange(t) then return nil end
self.alchemy_golem:setTarget(target)
target:setTarget(self.alchemy_golem)
game.logPlayer(self, "Your golem provokes %s to attack it.", target.name:capitalize())
return ([[Orders your golem to taunt a target, forcing it to attack the golem.]]):format()
end,
}
newTalent{
name = "Golem: Knockback",
type = {"spell/golemancy", 2},
require = spells_req2,
points = 5,
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
cooldown = 10,
range = 10,
mana = 5,
action = function(self, t)
if not game.level:hasEntity(self.alchemy_golem) then
game.logPlayer(self, "Your golem is currently inactive.")
return
end
local tg = {type="hit", range=self:getTalentRange(t)}
game.target.source_actor = self.alchemy_golem
local x, y, target = self:getTarget(tg)
game.target.source_actor = self
if not x or not y or not target then return nil end
if math.floor(core.fov.distance(self.alchemy_golem.x, self.alchemy_golem.y, x, y)) > self:getTalentRange(t) then return nil end
self.alchemy_golem:setTarget(target)
local l = line.new(self.alchemy_golem.x, self.alchemy_golem.y, x, y)
local lx, ly = l()
local tx, ty = self.alchemy_golem.x, self.alchemy_golem.y
lx, ly = l()
while lx and ly do
if game.level.map:checkAllEntities(lx, ly, "block_move", self.alchemy_golem) then break end
tx, ty = lx, ly
lx, ly = l()
end
self.alchemy_golem:move(tx, ty, true)
-- Attack ?
if math.floor(core.fov.distance(self.alchemy_golem.x, self.alchemy_golem.y, x, y)) > 1 then return true end
local hit = self.alchemy_golem:attackTarget(target, nil, self.alchemy_golem:combatTalentWeaponDamage(t, 0.8, 1.6), true)
-- Try to knockback !
if hit then
if target:checkHit(self.alchemy_golem:combatAttackStr(), target:combatPhysicalResist(), 0, 95, 5 - self.alchemy_golem:getTalentLevel(t) / 2) and target:canBe("knockback") then
target:knockback(self.alchemy_golem.x, self.alchemy_golem.y, 3)
else
game.logSeen(target, "%s resists the knockback!", target.name:capitalize())
end
end
return true
end,
return ([[Your golem rushes to the target, knocking it back and doing %d%% damage.]]):format(100 * self:combatTalentWeaponDamage(t, 0.8, 1.6))
end,
}
newTalent{
name = "Golem: Crush",
type = {"spell/golemancy", 3},
require = spells_req3,
points = 5,
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
cooldown = 10,
range = 10,
mana = 5,
action = function(self, t)
if not game.level:hasEntity(self.alchemy_golem) then
game.logPlayer(self, "Your golem is currently inactive.")
return
end
local tg = {type="hit", range=self:getTalentRange(t)}
game.target.source_actor = self.alchemy_golem
local x, y, target = self:getTarget(tg)
game.target.source_actor = self
if not x or not y or not target then return nil end
if math.floor(core.fov.distance(self.alchemy_golem.x, self.alchemy_golem.y, x, y)) > self:getTalentRange(t) then return nil end
self.alchemy_golem:setTarget(target)
local l = line.new(self.alchemy_golem.x, self.alchemy_golem.y, x, y)
local lx, ly = l()
local tx, ty = self.alchemy_golem.x, self.alchemy_golem.y
lx, ly = l()
while lx and ly do
if game.level.map:checkAllEntities(lx, ly, "block_move", self.alchemy_golem) then break end
tx, ty = lx, ly
lx, ly = l()
end
self.alchemy_golem:move(tx, ty, true)
-- Attack ?
if math.floor(core.fov.distance(self.alchemy_golem.x, self.alchemy_golem.y, x, y)) > 1 then return true end
local hit = self.alchemy_golem:attackTarget(target, nil, self.alchemy_golem:combatTalentWeaponDamage(t, 0.8, 1.6), true)
-- Try to knockback !
if hit then
if target:checkHit(self.alchemy_golem:combatAttackStr(), target:combatPhysicalResist(), 0, 95, 10 - self.alchemy_golem:getTalentLevel(t) / 2) and target:canBe("stun") then
target:setEffect(target.EFF_PINNED, 2 + self.alchemy_golem:getTalentLevel(t), {})
else
game.logSeen(target, "%s resists the crushing!", target.name:capitalize())
end
end
return true
return ([[Your golem rushes to the target, crushing and doing %d%% damage.]]):format(100 * self:combatTalentWeaponDamage(t, 0.8, 1.6))
end,
}
newTalent{
name = "Invoke Golem",
type = {"spell/golemancy",4},
require = spells_req4,
points = 5,
mana = 10,
cooldown = 20,
if not game.level:hasEntity(self.alchemy_golem) then
game.logPlayer(self, "Your golem is currently inactive.")
return
end
-- Find space
local x, y = util.findFreeGrid(self.x, self.y, 5, true, {[Map.ACTOR]=true})
if not x then
game.logPlayer(self, "Not enough space to invoke!")
return
end
self.alchemy_golem:setEffect(self.alchemy_golem.EFF_MIGHTY_BLOWS, 5, {power=self:combatTalentSpellDamage(t, 15, 50)})
self.alchemy_golem:move(x, y, true)
game:playSoundNear(self, "talents/arcane")
return true
end,
info = function(self, t)
return ([[You invoke your golem to your side, granting it a temporary melee power increase of %d for 5 turns.]]):format(self:combatTalentSpellDamage(t, 15, 50))